4 * Copyright (C) 2008-2017 Adam Williams <broadcast at earthling dot net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "bcsignals.h"
25 #include "browsebutton.h"
27 #include "channelpicker.h"
29 #include "condition.h"
32 #include "edlsession.h"
34 #include "filesystem.h"
38 #include "meterpanel.h"
41 #include "mwindowgui.h"
42 #include "preferences.h"
44 #include "recconfirmdelete.h"
45 #include "recordgui.h"
47 #include "recordlabel.h"
48 #include "recordmonitor.h"
49 #include "recordtransport.h"
50 #include "recordvideo.h"
51 #include "mainsession.h"
54 #include "videodevice.h"
61 RecordGUI::RecordGUI(MWindow *mwindow, Record *record)
62 : BC_Window(_(PROGRAM_NAME ": Recording"),
63 mwindow->session->rwindow_x, mwindow->session->rwindow_y,
64 mwindow->session->rwindow_w, mwindow->session->rwindow_h,
65 xS(10), yS(10), 1, 0, 1)
67 this->mwindow = mwindow;
68 this->record = record;
70 current_operation = 0;
100 interrupt_thread = 0;
107 monitor_video_window = 0;
108 dc_offset_button = 0;
109 for( int i=0; i<MAXCHANNELS; ++i ) {
110 dc_offset_text[i] = 0;
113 total_dropped_frames = 0;
114 total_clipped_samples = 0;
115 // *** CONTEXT_HELP ***
116 context_help_set_keyword("Record Web Media");
119 RecordGUI::~RecordGUI()
121 delete status_thread;
122 delete record_transport;
126 delete startover_thread;
127 delete interrupt_thread;
129 delete batch_duration;
134 void RecordGUI::create_objects()
136 int xs5 = xS(5), xs10 = xS(10), xs20 = xS(20), xs30 = xS(30);
137 int ys5 = yS(5), ys10 = yS(10);
138 char string[BCTEXTLEN];
140 Asset *asset = record->default_asset;
141 lock_window("RecordGUI::create_objects");
142 status_thread = new RecordStatusThread(mwindow, this);
143 status_thread->start();
144 set_icon(mwindow->theme->get_image("record_icon"));
146 mwindow->theme->get_recordgui_sizes(this, get_w(), get_h());
147 //printf("RecordGUI::create_objects 1\n");
148 mwindow->theme->draw_rwindow_bg(this);
154 int pad = max(BC_TextBox::calculate_h(this, MEDIUMFONT, 1, 1),
155 BC_Title::calculate_h(this, "X")) + ys5;
159 add_subwindow(title = new BC_Title(x, y, _("Path:")));
160 x1 = max(title->get_w(), x1);
162 add_subwindow(title = new BC_Title(x, y, _("Start time:")));
163 x1 = max(title->get_w(), x1);
165 add_subwindow(title = new BC_Title(x, y, _("Duration time:")));
166 x1 = max(title->get_w(), x1);
168 add_subwindow(title = new BC_Title(x, y, _("Source:")));
169 x1 = max(title->get_w(), x1);
171 add_subwindow(title = new BC_Title(x, y, _("Mode:")));
172 x1 = max(title->get_w(), x1);
174 add_subwindow(title = new BC_Title(x, y, _("Transport:")));
175 x1 = max(title->get_w(), x1);
178 button_y = max(y, button_y);
185 add_subwindow(batch_path = new RecordPath(this, x, y));
186 add_subwindow(batch_browse = new BrowseButton(mwindow->theme,
189 batch_path->get_x() + batch_path->get_w(),
192 _(PROGRAM_NAME ": Record path"),
193 _("Select a file to record to:"),
195 x2 = max(x2, batch_path->get_w() + batch_browse->get_w());
197 batch_start = new RecordStart(this, x, y);
198 batch_start->create_objects();
199 x2 = max(x2, batch_start->get_w());
201 batch_duration = new RecordDuration(this, x, y);
202 batch_duration->create_objects();
203 x2 = max(x2, batch_duration->get_w());
205 batch_source = new RecordSource(this, x, y);
206 batch_source->create_objects();
207 x2 = max(x2, batch_source->get_w());
209 batch_mode = new RecordGUIModeMenu(this, x, y, xS(200), "");
210 batch_mode->create_objects();
211 x2 = max(x2, batch_mode->get_w());
213 record_transport = new RecordTransport(mwindow,
215 record_transport->create_objects();
216 x2 = max(x2, record_transport->get_w());
221 // Compression settings
225 pad = BC_Title::calculate_h(this, "X") + ys5;
226 add_subwindow(title = new BC_Title(x, y, _("Format:")));
227 x3 = max(title->get_w(), x3);
230 if(asset->audio_data)
232 add_subwindow(title = new BC_Title(x, y, _("Audio compression:")));
233 x3 = max(title->get_w(), x3);
235 add_subwindow(title = new BC_Title(x, y, _("Samplerate:")));
236 x3 = max(title->get_w(), x3);
238 add_subwindow(title = new BC_Title(x, y, _("Clipped samples:")));
239 x3 = max(title->get_w(), x3);
243 if(asset->video_data)
245 add_subwindow(title = new BC_Title(x, y, _("Video compression:")));
246 x3 = max(title->get_w(), x3);
248 add_subwindow(title = new BC_Title(x, y, _("Framerate:")));
249 x3 = max(title->get_w(), x3);
251 add_subwindow(title = new BC_Title(x, y, _("Frames dropped:")));
252 x3 = max(title->get_w(), x3);
254 add_subwindow(title = new BC_Title(x, y, _("Frames behind:")));
255 x3 = max(title->get_w(), x3);
259 add_subwindow(title = new BC_Title(x, y, _("Position:")));
260 x3 = max(title->get_w(), x3);
262 add_subwindow(title = new BC_Title(x, y, _("Prev label:")));
263 x3 = max(title->get_w(), x3);
266 button_y = max(y, button_y);
268 x = x3 + x2 + x1 + xS(40);
270 add_subwindow(new BC_Title(x, y,
271 File::formattostr(asset->format),
273 mwindow->theme->recordgui_fixed_color));
276 if(asset->audio_data) {
277 add_subwindow(new BC_Title(x, y,
278 File::bitstostr(asset->bits),
280 mwindow->theme->recordgui_fixed_color));
283 sprintf(string, "%d", asset->sample_rate);
284 add_subwindow(new BC_Title(x, y,
286 mwindow->theme->recordgui_fixed_color));
289 add_subwindow(samples_clipped = new BC_Title(x, y,
291 mwindow->theme->recordgui_variable_color));
295 if(asset->video_data) {
296 add_subwindow(new BC_Title(x, y,
297 asset->format == FILE_MPEG ? _("File Capture") :
298 File::compressiontostr(asset->vcodec),
300 mwindow->theme->recordgui_fixed_color));
303 sprintf(string, "%0.2f", asset->frame_rate);
304 add_subwindow(framerate = new BC_Title(x, y,
306 mwindow->theme->recordgui_fixed_color));
309 add_subwindow(frames_dropped = new BC_Title(x, y,
311 mwindow->theme->recordgui_variable_color));
313 add_subwindow(frames_behind = new BC_Title(x, y,
315 mwindow->theme->recordgui_variable_color));
319 add_subwindow(position_title = new BC_Title(x, y,
321 mwindow->theme->recordgui_variable_color));
324 add_subwindow(prev_label_title = new BC_Title(x, y,
325 _("None"), MEDIUMFONT,
326 mwindow->theme->recordgui_variable_color));
329 button_y = max(y, button_y);
335 add_subwindow(title = new BC_Title(x,y, _("Batches:")));
336 int y_max = y + title->get_h(); x1 = x;
337 x += title->get_w() + xs5;
338 add_subwindow(activate_batch = new RecordGUIActivateBatch(this, x, y));
339 x += activate_batch->get_w();
340 y_max = max(y_max, y + activate_batch->get_h());
341 add_subwindow(start_batches = new RecordGUIStartBatches(this, x, y));
342 y_max = max(y_max, y + start_batches->get_h()); x2 = x;
343 x += start_batches->get_w();
344 add_subwindow(new_batch = new RecordGUINewBatch(this, x, y));
345 y_max = max(y_max, y + new_batch->get_h()); x3 = x;
346 x += new_batch->get_w(); int x4 = x;
347 add_subwindow(label_button = new RecordGUILabel(this, x, y));
348 y_max = max(y_max, y + label_button->get_h());
350 int y1 = y_max, y2 = y1 + ys5;
351 add_subwindow(title = new BC_Title(x1,y2, _("Cron:")));
352 y_max = max(y_max, y2 + title->get_h());
353 x1 += title->get_w() + xs5;
354 add_subwindow(cron_status = new BC_Title(x1,y2, _("Idle"), MEDIUMFONT,
355 mwindow->theme->recordgui_variable_color));
356 y_max = max(y_max, y2 + cron_status->get_h());
357 add_subwindow(stop_batches = new RecordGUIStopBatches(this, x2, y1));
358 y_max = max(y_max, y1 + stop_batches->get_h());
359 add_subwindow(delete_batch = new RecordGUIDeleteBatch(this, x3, y1));
360 y_max = max(y_max, y1 + delete_batch->get_h());
361 add_subwindow(clrlbls_button = new RecordGUIClearLabels(this, x4, y1));
362 y_max = max(y_max, y1 + clrlbls_button->get_h());
372 if(asset->video_data) {
373 add_subwindow(drop_frames = new RecordGUIDropFrames(this, x, y));
374 add_subwindow(fill_frames = new RecordGUIFillFrames(this, x, y1));
375 x += drop_frames->get_w() + xs5; x1 = x;
376 add_subwindow(monitor_video = new RecordGUIMonitorVideo(this, x, y));
377 x += monitor_video->get_w() + xs5;
380 if(asset->audio_data) {
381 add_subwindow(monitor_audio = new RecordGUIMonitorAudio(this, x, y));
382 x += monitor_audio->get_w() + xs5;
383 add_subwindow(meter_audio = new RecordGUIAudioMeters(this, x, y));
384 x += meter_audio->get_w() + xs5;
387 add_subwindow(power_off = new RecordGUIPowerOff(this, x1, y1));
388 x1 += power_off->get_w() + xs10;
389 add_subwindow(commercial_check = new RecordGUICommCheck(this, x1, y1));
390 x1 += commercial_check->get_w() + xs30;
391 add_subwindow(deinterlace = new RecordGUIDeinterlace(this, x1, y1));
392 deinterlace->create_objects();
393 x1 += deinterlace->get_w() + xs5;
394 add_subwindow(new BC_Title(x1, y1, _("deinterlace")));
400 y = y1 + fill_frames->get_h();
401 else if( monitor_audio )
402 y += monitor_audio->get_h();
404 int bottom_margin = max(BC_OKButton::calculate_h(),
405 LoadMode::calculate_h(this, mwindow->theme)) + ys5;
408 add_subwindow(batch_bay = new RecordGUIBatches(this, x, y,
409 get_w() - xs20, get_h() - y - bottom_margin - ys10));
410 y += batch_bay->get_h() + ys5;
411 record->record_batches.gui = batch_bay;
412 batch_bay->update_batches(-1);
415 int loadmode_w = LoadMode::calculate_w(this, mwindow->theme);
416 load_mode = new LoadMode(mwindow, this,
417 get_w() / 2 - loadmode_w / 2, y, &record->load_mode);
418 load_mode->create_objects();
419 y += load_mode->get_h() + ys5;
421 add_subwindow(new RecordGUIOK(this));
423 interrupt_thread = new EndRecordThread(this);
424 // add_subwindow(new RecordGUISave(record, this));
425 add_subwindow(new RecordGUICancel(this));
427 startover_thread = new RecordStartoverThread(this);
429 enable_batch_buttons();
430 if( batch_mode->value == RECORD_TIMED )
431 batch_duration->enable();
433 batch_duration->disable();
438 void RecordGUI::update_batches()
440 lock_window("void RecordGUI::Update_batches");
441 batch_bay->update_batches();
446 Batch *RecordGUI::get_current_batch()
448 return record->get_editing_batch();
451 Batch *RecordGUI::get_editing_batch()
453 return record->get_editing_batch();
456 void RecordGUI::update_batch_sources()
458 //printf("RecordGUI::update_batch_sources 1\n");
459 ChannelPicker *channel_picker =
460 record->record_monitor->window->channel_picker;
462 batch_source->update_list(&channel_picker->channel_listitems);
463 //printf("RecordGUI::update_batch_sources 2\n");
466 int RecordGUI::translation_event()
468 mwindow->session->rwindow_x = get_x();
469 mwindow->session->rwindow_y = get_y();
474 int RecordGUI::resize_event(int w, int h)
476 int xs20 = xS(20), ys10 = yS(10);
477 // Recompute batch list based on previous extents
478 int bottom_margin = mwindow->session->rwindow_h -
481 int mode_margin = mwindow->session->rwindow_h - load_mode->get_y();
482 mwindow->session->rwindow_x = get_x();
483 mwindow->session->rwindow_y = get_y();
484 mwindow->session->rwindow_w = w;
485 mwindow->session->rwindow_h = h;
486 mwindow->theme->get_recordgui_sizes(this, w, h);
487 mwindow->theme->draw_rwindow_bg(this);
489 int new_h = mwindow->session->rwindow_h - bottom_margin - batch_bay->get_y();
490 if(new_h < ys10) new_h = ys10;
491 batch_bay->reposition_window(batch_bay->get_x(),
493 mwindow->session->rwindow_w - xs20,
494 mwindow->session->rwindow_h - bottom_margin - batch_bay->get_y());
496 load_mode->reposition_window(mwindow->session->rwindow_w / 2 -
497 mwindow->theme->loadmode_w / 2,
498 mwindow->session->rwindow_h - mode_margin);
504 void RecordGUI::update_batch_tools()
506 lock_window("RecordGUI::update_batch_tools");
507 //printf("RecordGUI::update_batch_tools 1\n");
508 Batch *batch = get_editing_batch();
509 batch_path->update(batch->asset->path);
511 // File is open in editing batch
512 // if(current_batch() == editing_batch() && record->file)
513 // batch_path->disable();
515 // batch_path->enable();
517 batch_start->update(&batch->start_day, &batch->start_time);
518 batch_duration->update(0, &batch->duration);
519 batch_source->update(batch->get_source_text());
520 batch_mode->update(batch->record_mode);
521 if( batch_mode->value == RECORD_TIMED )
522 batch_duration->enable();
524 batch_duration->disable();
529 void RecordGUI::enable_batch_buttons()
531 lock_window("RecordGUI::enable_batch_buttons");
533 delete_batch->enable();
534 start_batches->enable();
535 stop_batches->disable();
536 activate_batch->enable();
540 void RecordGUI::disable_batch_buttons()
542 lock_window("RecordGUI::disable_batch_buttons");
543 new_batch->disable();
544 delete_batch->disable();
545 start_batches->disable();
546 stop_batches->enable();
547 activate_batch->disable();
551 RecordGUIBatches::RecordGUIBatches(RecordGUI *gui, int x, int y, int w, int h)
552 : RecordBatchesGUI(gui->record->record_batches, x, y, w, h)
557 // Do nothing for double clicks to protect active batch
558 int RecordGUIBatches::handle_event()
563 int RecordGUIBatches::selection_changed()
565 RecordBatchesGUI::selection_changed();
566 gui->update_batch_tools();
571 RecordGUISave::RecordGUISave(RecordGUI *gui)
573 gui->get_h() - BC_WindowBase::get_resources()->ok_images[0]->get_h() - yS(10),
574 BC_WindowBase::get_resources()->ok_images)
576 set_tooltip(_("Save the recording and quit."));
580 int RecordGUISave::handle_event()
586 int RecordGUISave::keypress_event()
588 // if(get_keypress() == RETURN)
593 return context_help_check_and_show();
596 RecordGUICancel::RecordGUICancel(RecordGUI *gui)
597 : BC_CancelButton(gui)
599 set_tooltip(_("Quit without pasting into project."));
603 int RecordGUICancel::handle_event()
605 gui->interrupt_thread->start(0);
609 int RecordGUICancel::keypress_event()
611 if(get_keypress() == ESC)
617 return context_help_check_and_show();
621 RecordGUIOK::RecordGUIOK(RecordGUI *gui)
624 set_tooltip(_("Quit and paste into project."));
628 int RecordGUIOK::handle_event()
630 gui->interrupt_thread->start(1);
635 RecordGUIStartOver::RecordGUIStartOver(RecordGUI *gui, int x, int y)
636 : BC_GenericButton(x, y, _("Start Over"))
638 set_tooltip(_("Rewind the current file and erase."));
641 RecordGUIStartOver::~RecordGUIStartOver()
645 int RecordGUIStartOver::handle_event()
647 if(!gui->startover_thread->running())
648 gui->startover_thread->start();
653 RecordGUIDropFrames::RecordGUIDropFrames(RecordGUI *gui, int x, int y)
654 : BC_CheckBox(x, y, gui->record->drop_overrun_frames, _("drop overrun frames"))
656 this->set_underline(0);
658 set_tooltip(_("Drop input frames when behind."));
661 int RecordGUIDropFrames::handle_event()
663 gui->record->drop_overrun_frames = get_value();
667 int RecordGUIDropFrames::keypress_event()
669 if( get_keypress() == caption[0] ) {
670 set_value(get_value() ? 0 : 1);
674 return context_help_check_and_show();
677 RecordGUIFillFrames::RecordGUIFillFrames(RecordGUI *gui, int x, int y)
678 : BC_CheckBox(x, y, gui->record->fill_underrun_frames, _("fill underrun frames"))
680 this->set_underline(0);
682 set_tooltip(_("Write extra frames when behind."));
685 int RecordGUIFillFrames::handle_event()
687 gui->record->fill_underrun_frames = get_value();
691 int RecordGUIFillFrames::keypress_event()
693 if( get_keypress() == caption[0] ) {
694 set_value(get_value() ? 0 : 1);
698 return context_help_check_and_show();
701 RecordGUIPowerOff::RecordGUIPowerOff(RecordGUI *gui, int x, int y)
702 : BC_CheckBox(x, y, gui->record->power_off, _("poweroff when done"))
704 this->set_underline(0);
706 set_tooltip(_("poweroff system when batch record done."));
707 // *** CONTEXT_HELP ***
708 context_help_set_keyword("Capture at some Future Time via Batch");
711 int RecordGUIPowerOff::handle_event()
713 gui->record->power_off = get_value();
717 int RecordGUIPowerOff::keypress_event()
719 if( get_keypress() == caption[0] ) {
720 set_value(get_value() ? 0 : 1);
724 return context_help_check_and_show();
728 RecordGUICommCheck::RecordGUICommCheck(RecordGUI *gui, int x, int y)
729 : BC_CheckBox(x, y, gui->record->commercial_check, _("check for ads"))
731 this->set_underline(0);
733 set_tooltip(_("check for commercials."));
734 // *** CONTEXT_HELP ***
735 context_help_set_keyword("The commercial DB");
738 int RecordGUICommCheck::handle_event()
740 gui->record->update_skimming(get_value());
744 int RecordGUICommCheck::keypress_event()
746 if( get_keypress() == caption[0] ) {
747 set_value(get_value() ? 0 : 1);
748 gui->record->update_skimming(get_value());
752 return context_help_check_and_show();
756 RecordGUIDelaceItem::RecordGUIDelaceItem(RecordGUIDeinterlace *popup,
757 const char *text, int id)
763 int RecordGUIDelaceItem::handle_event()
765 popup->gui->record->deinterlace = id;
770 RecordGUIDeinterlace::RecordGUIDeinterlace(RecordGUI *gui, int x, int y)
771 : BC_PopupMenu(x, y, xS(24), "", 1, 0, xS(3))
776 void RecordGUIDeinterlace::create_objects()
778 add_item(new RecordGUIDelaceItem(this, _("None"), RECORD_LACE_NONE));
779 add_item(new RecordGUIDelaceItem(this, _("Even"), RECORD_LACE_EVEN));
780 add_item(new RecordGUIDelaceItem(this, _("Odd"), RECORD_LACE_ODD));
784 void RecordGUIDeinterlace::update()
786 int v = gui->record->deinterlace;
787 for( int i=0,n=total_items(); i<n; ++i ) {
788 RecordGUIDelaceItem *item = (RecordGUIDelaceItem *)get_item(i);
789 item->set_checked(item->id == v);
794 RecordGUIMonitorVideo::RecordGUIMonitorVideo(RecordGUI *gui, int x, int y)
795 : BC_CheckBox(x, y, gui->record->monitor_video, _("Monitor video"))
797 this->set_underline(8);
801 int RecordGUIMonitorVideo::handle_event()
803 // Video capture constitutively, just like audio, but only flash on screen if 1
804 int mode = get_value();
805 Record *record = gui->record;
806 record->set_video_monitoring(mode);
807 if(record->monitor_video) {
809 BC_Window *window = record->record_monitor->window;
810 window->lock_window("RecordGUIMonitorVideo::handle_event");
811 window->show_window();
812 window->raise_window();
814 window->unlock_window();
815 lock_window("RecordGUIMonitorVideo::handle_event");
816 record->video_window_open = 1;
820 BC_Window *window = record->record_monitor->window;
821 window->lock_window("RecordGUIMonitorVideo::handle_event");
822 window->hide_window();
824 window->unlock_window();
825 lock_window("RecordGUIMonitorVideo::handle_event");
826 record->video_window_open = 0;
832 int RecordGUIMonitorVideo::keypress_event()
834 if(get_keypress() == 'v') {
835 set_value(get_value() ? 0 : 1);
839 return context_help_check_and_show();
844 RecordGUIMonitorAudio::RecordGUIMonitorAudio(RecordGUI *gui, int x, int y)
845 : BC_CheckBox(x, y, gui->record->monitor_audio, _("Monitor audio"))
847 this->set_underline(8);
851 int RecordGUIMonitorAudio::handle_event()
853 int mode = get_value();
854 Record *record = gui->record;
855 record->set_audio_monitoring(mode);
856 if(record->monitor_audio) {
858 BC_Window *window = record->record_monitor->window;
859 window->lock_window("RecordGUIMonitorAudio::handle_event");
860 window->show_window();
861 window->raise_window();
863 window->unlock_window();
864 lock_window("RecordGUIMonitorAudio::handle_event");
865 record->video_window_open = 1;
870 int RecordGUIMonitorAudio::keypress_event()
872 if(get_keypress() == 'a') {
873 set_value(get_value() ? 0 : 1);
877 return context_help_check_and_show();
881 RecordGUIAudioMeters::RecordGUIAudioMeters(RecordGUI *gui, int x, int y)
882 : BC_CheckBox(x, y, gui->record->metering_audio, _("Audio meters"))
884 this->set_underline(6);
886 // *** CONTEXT_HELP ***
887 context_help_set_keyword("Sound Level Meters Window");
890 int RecordGUIAudioMeters::handle_event()
892 int mode = get_value();
893 Record *record = gui->record;
894 record->set_audio_metering(mode);
895 if(record->metering_audio) {
897 BC_Window *window = record->record_monitor->window;
898 window->lock_window("RecordGUIAudioMeters::handle_event");
899 window->show_window();
900 window->raise_window();
902 window->unlock_window();
903 lock_window("RecordGUIAudioMeters::handle_event");
904 record->video_window_open = 1;
909 int RecordGUIAudioMeters::keypress_event()
911 if(get_keypress() == 'm') {
912 set_value(get_value() ? 0 : 1);
916 return context_help_check_and_show();
919 RecordPath::RecordPath(RecordGUI *gui, int x, int y)
920 : RecordBatchesGUI::Path(gui->record->record_batches, x, y)
925 int RecordPath::handle_event()
927 return RecordBatchesGUI::Path::handle_event();
931 RecordStart::RecordStart(RecordGUI *gui, int x, int y)
932 : RecordBatchesGUI::StartTime(gui, gui->record->record_batches, x, y)
937 int RecordStart::handle_event()
939 return RecordBatchesGUI::StartTime::handle_event();
942 RecordDuration::RecordDuration(RecordGUI *gui, int x, int y)
943 : RecordBatchesGUI::Duration(gui, gui->record->record_batches, x, y)
948 int RecordDuration::handle_event()
950 return RecordBatchesGUI::Duration::handle_event();
954 RecordSource::RecordSource(RecordGUI *gui, int x, int y)
955 : RecordBatchesGUI::Source(gui, gui->record->record_batches, x, y)
960 int RecordSource::handle_event()
962 gui->record->set_batch_channel_no(get_number());
963 return RecordBatchesGUI::Source::handle_event();
967 RecordNews::RecordNews(RecordGUI *gui, int x, int y)
968 : RecordBatchesGUI::News(gui->record->record_batches, x, y)
973 int RecordNews::handle_event()
975 return RecordBatchesGUI::News::handle_event();
979 RecordGUINewBatch::RecordGUINewBatch(RecordGUI *gui, int x, int y)
980 : RecordBatchesGUI::NewBatch(gui->record->record_batches, x, y)
983 set_tooltip(_("Create new clip."));
984 // *** CONTEXT_HELP ***
985 context_help_set_keyword("Capture at some Future Time via Batch");
987 int RecordGUINewBatch::handle_event()
989 gui->record->new_batch();
990 return RecordBatchesGUI::NewBatch::handle_event();
994 RecordGUIDeleteBatch::RecordGUIDeleteBatch(RecordGUI *gui, int x, int y)
995 : RecordBatchesGUI::DeleteBatch(gui->record->record_batches, x, y)
998 set_tooltip(_("Delete clip."));
999 // *** CONTEXT_HELP ***
1000 context_help_set_keyword("Capture at some Future Time via Batch");
1003 int RecordGUIDeleteBatch::handle_event()
1005 gui->record->delete_batch();
1006 return RecordBatchesGUI::DeleteBatch::handle_event();
1010 RecordGUIStartBatches::RecordGUIStartBatches(RecordGUI *gui, int x, int y)
1011 : RecordBatchesGUI::StartBatches(gui->record->record_batches, x, y)
1014 set_tooltip(_("Start batch recording\nfrom the current position."));
1015 // *** CONTEXT_HELP ***
1016 context_help_set_keyword("Capture at some Future Time via Batch");
1019 int RecordGUIStartBatches::handle_event()
1021 Record *record = gui->record;
1022 record->start_cron_thread();
1023 return RecordBatchesGUI::StartBatches::handle_event();
1027 RecordGUIStopBatches::RecordGUIStopBatches(RecordGUI *gui, int x, int y)
1028 : RecordBatchesGUI::StopBatches(gui->record->record_batches, x, y)
1031 // *** CONTEXT_HELP ***
1032 context_help_set_keyword("Capture at some Future Time via Batch");
1035 int RecordGUIStopBatches::handle_event()
1037 Record *record = gui->record;
1039 record->stop_cron_thread(_("Stopped"));
1041 return RecordBatchesGUI::StopBatches::handle_event();
1045 RecordGUIActivateBatch::RecordGUIActivateBatch(RecordGUI *gui, int x, int y)
1046 : RecordBatchesGUI::ActivateBatch(gui->record->record_batches, x, y)
1049 set_tooltip(_("Make the highlighted\nclip active."));
1050 // *** CONTEXT_HELP ***
1051 context_help_set_keyword("Capture at some Future Time via Batch");
1053 int RecordGUIActivateBatch::handle_event()
1055 gui->record->activate_batch(gui->record->editing_batch());
1056 gui->update_cron_status(_("Idle"));
1057 return RecordBatchesGUI::ActivateBatch::handle_event();
1061 RecordGUILabel::RecordGUILabel(RecordGUI *gui, int x, int y)
1062 : BC_GenericButton(x, y, _("Label"))
1066 // *** CONTEXT_HELP ***
1067 context_help_set_keyword("Capture at some Future Time via Batch");
1071 RecordGUILabel::~RecordGUILabel()
1075 int RecordGUILabel::handle_event()
1077 gui->record->toggle_label();
1081 int RecordGUILabel::keypress_event()
1083 if( get_keypress() == *get_text() ) {
1087 return context_help_check_and_show();
1091 RecordGUIClearLabels::RecordGUIClearLabels(RecordGUI *gui, int x, int y)
1092 : BC_GenericButton(x, y, _("ClrLbls"))
1095 // *** CONTEXT_HELP ***
1096 context_help_set_keyword("Capture at some Future Time via Batch");
1100 RecordGUIClearLabels::~RecordGUIClearLabels()
1104 int RecordGUIClearLabels::handle_event()
1106 gui->record->clear_labels();
1111 EndRecordThread::EndRecordThread(RecordGUI *gui)
1118 EndRecordThread::~EndRecordThread()
1120 if(Thread::running()) {
1121 window->lock_window("EndRecordThread::~EndRecordThread");
1122 window->set_done(1);
1123 window->unlock_window();
1128 void EndRecordThread::start(int is_ok)
1130 this->is_ok = is_ok;
1131 if( gui->record->writing_file ) {
1136 gui->set_done(!is_ok);
1140 void EndRecordThread::run()
1142 window = new QuestionWindow(gui->record->mwindow);
1143 window->create_objects(_("Interrupt recording in progress?"), 0);
1144 int result = window->run_window();
1146 if(result == 2) gui->set_done(!is_ok);
1150 RecordStartoverThread::RecordStartoverThread(RecordGUI *gui)
1155 RecordStartoverThread::~RecordStartoverThread()
1157 if(Thread::running()) {
1158 window->lock_window("RecordStartoverThread::~RecordStartoverThread");
1159 window->set_done(1);
1160 window->unlock_window();
1165 void RecordStartoverThread::run()
1167 Record *record = gui->record;
1168 window = new QuestionWindow(record->mwindow);
1169 window->create_objects(_("Rewind batch and overwrite?"), 0);
1170 int result = window->run_window();
1171 if(result == 2) record->start_over();
1176 int RecordGUI::set_translation(int x, int y, float z)
1178 record->video_x = x;
1179 record->video_y = y;
1180 record->video_zoom = z;
1184 void RecordGUI::reset_video()
1186 total_dropped_frames = 0;
1187 status_thread->reset_video();
1188 update_framerate(record->default_asset->frame_rate);
1191 void RecordGUI::update_dropped_frames(long value)
1193 status_thread->update_dropped_frames(value);
1196 void RecordGUI::update_frames_behind(long value)
1198 status_thread->update_frames_behind(value);
1201 void RecordGUI::update_position(double value)
1203 status_thread->update_position(value);
1206 void RecordGUI::update_framerate(double value)
1208 status_thread->update_framerate(value);
1211 void RecordGUI::update_video(int dropped, int behind)
1213 total_dropped_frames += dropped;
1214 update_dropped_frames(total_dropped_frames);
1215 update_frames_behind(behind);
1216 status_thread->update_position(record->current_display_position());
1219 void RecordGUI::reset_audio()
1221 // gui->lock_window("RecordAudio::run 2");
1223 total_clipped_samples = 0;
1224 status_thread->reset_audio();
1225 AudioDevice *adevice = record->adevice;
1226 RecordMonitorGUI *window = record->record_monitor->window;
1227 window->lock_window("RecordAudio::run 2");
1228 MeterPanel *meters = window->meters;
1230 int dmix = adevice && (adevice->get_idmix() || adevice->get_odmix());
1231 meters->init_meters(dmix);
1233 window->unlock_window();
1234 // gui->unlock_window();
1237 void RecordGUI::update_clipped_samples(long value)
1239 status_thread->update_clipped_samples(value);
1242 void RecordGUI::update_audio(int channels, double *max, int *over)
1244 // Get clipping status
1246 for( int ch=0; ch<channels && !clipped; ++ch )
1247 if( over[ch] ) clipped = 1;
1249 update_clipped_samples(++total_clipped_samples);
1251 // Update meters if monitoring
1252 if( record->metering_audio ) {
1253 RecordMonitorGUI *window = record->record_monitor->window;
1254 window->lock_window("RecordAudio::run 1");
1255 MeterPanel *meters = window->meters;
1256 int nmeters = meters->meters.total;
1257 for( int ch=0; ch<nmeters; ++ch ) {
1258 double vmax = ch < channels ? max[ch] : 0.;
1259 int vover = ch < channels ? over[ch] : 0;
1260 meters->meters.values[ch]->update(vmax, vover);
1262 window->unlock_window();
1264 // update position, if no video
1265 if( !record->default_asset->video_data )
1266 update_position(record->current_display_position());
1270 int RecordGUI::keypress_event()
1272 if (get_keypress() != 'h' || ! alt_down() ||
1273 ! is_tooltip_event_win() || ! cursor_inside())
1274 return record_transport->keypress_event();
1276 context_help_show("Record Web Media");
1280 void RecordGUI::update_labels(double new_position)
1282 RecordLabel *prev, *next;
1284 for(prev = record->get_current_batch()->labels->last;
1286 prev = prev->previous) {
1287 if(prev->position <= new_position) break;
1290 for(next = record->get_current_batch()->labels->first;
1294 if(next->position > new_position) break;
1298 update_title(prev_label_title, prev->position);
1300 update_title(prev_label_title, -1);
1303 // update_title(next_label_title, (double)next->position / record->default_asset->sample_rate);
1305 // update_title(next_label_title, -1);
1309 int RecordGUI::update_prev_label(long new_position)
1311 update_title(prev_label_title, new_position);
1315 // int RecordGUI::update_next_label(long new_position)
1317 // update_title(next_label_title, new_position);
1320 int RecordGUI::update_title(BC_Title *title, double position)
1322 static char string[256];
1325 Units::totext(string,
1327 mwindow->edl->session->time_format,
1328 record->default_asset->sample_rate,
1329 record->default_asset->frame_rate,
1330 mwindow->edl->session->frames_per_foot);
1333 sprintf(string, "-");
1335 title->update(string);
1340 void RecordGUI::update_cron_status(const char *status)
1342 lock_window("RecordGUI::update_cron_status");
1343 cron_status->update(status);
1347 void RecordGUI::update_power_off(int value)
1349 lock_window("RecordGUI::update_power_off");
1350 power_off->update(value);
1357 // ===================================== GUI
1358 // ================================================== modes
1360 RecordGUIModeTextBox::RecordGUIModeTextBox(RecordGUIModeMenu *mode_menu,
1361 int x, int y, int w,const char *text)
1362 : BC_TextBox(x, y, w, 1, text)
1364 this->mode_menu = mode_menu;
1367 RecordGUIModeTextBox::~RecordGUIModeTextBox()
1371 int RecordGUIModeTextBox::handle_event()
1376 RecordGUIModeListBox::RecordGUIModeListBox(RecordGUIModeMenu *mode_menu)
1377 : BC_ListBox(mode_menu->textbox->get_x() + mode_menu->textbox->get_w(),
1378 mode_menu->textbox->get_y(), xS(100), yS(50), LISTBOX_TEXT,
1379 &mode_menu->modes, 0, 0, 1, 0, 1)
1381 this->mode_menu = mode_menu;
1384 RecordGUIModeListBox::~RecordGUIModeListBox()
1388 int RecordGUIModeListBox::handle_event()
1390 return mode_menu->handle_event();
1393 RecordGUIModeMenu::RecordGUIModeMenu(RecordGUI *record_gui,
1394 int x, int y, int w,const char *text)
1396 this->record_gui = record_gui;
1397 textbox = new RecordGUIModeTextBox(this,x, y, w, "");
1398 record_gui->add_subwindow(textbox);
1399 listbox = new RecordGUIModeListBox(this);
1400 record_gui->add_subwindow(listbox);
1403 RecordGUIModeMenu::~RecordGUIModeMenu()
1405 for( int i=0; i<modes.total; ++i )
1406 delete modes.values[i];
1411 void RecordGUIModeMenu::create_objects()
1413 value = RECORD_UNTIMED;
1414 modes.append(new BC_ListBoxItem(Batch::mode_to_text(RECORD_UNTIMED)));
1415 modes.append(new BC_ListBoxItem(Batch::mode_to_text(RECORD_TIMED)));
1416 textbox->update(modes.values[value]->get_text());
1419 int RecordGUIModeMenu::handle_event()
1421 value = listbox->get_selection_number(0, 0);
1422 textbox->update(modes.values[value]->get_text());
1423 textbox->handle_event();
1424 record_gui->record->set_record_mode(value);
1425 if( value == RECORD_TIMED )
1426 record_gui->batch_duration->enable();
1428 record_gui->batch_duration->disable();
1432 void RecordGUIModeMenu::update(int value)
1434 this->value = value;
1435 textbox->update(modes.values[value]->get_text());
1438 int RecordGUIModeMenu::get_w()
1440 return textbox->get_w() + listbox->get_w();
1443 int RecordGUIModeMenu::get_h()
1445 return MAX(textbox->get_h(), listbox->get_h());
1449 RecordStatusThread::RecordStatusThread(MWindow *mwindow, RecordGUI *gui)
1452 this->mwindow = mwindow;
1454 input_lock = new Condition(0, "RecordStatusThread::input_lock");
1461 RecordStatusThread::~RecordStatusThread()
1463 if(Thread::running())
1466 input_lock->unlock();
1472 void RecordStatusThread::reset_video()
1474 new_dropped_frames = 0;
1475 displayed_dropped_frames = -1;
1476 new_frames_behind = 0;
1477 displayed_frames_behind = -1;
1479 displayed_framerate = -1.;
1483 void RecordStatusThread::reset_audio()
1485 new_clipped_samples = 0;
1486 displayed_clipped_samples = -1;
1489 void RecordStatusThread::update_frames_behind(long value)
1491 if( value != displayed_frames_behind ) {
1492 new_frames_behind = value;
1493 input_lock->unlock();
1497 void RecordStatusThread::update_dropped_frames(long value)
1499 if( value != displayed_dropped_frames ) {
1500 new_dropped_frames = value;
1501 input_lock->unlock();
1505 void RecordStatusThread::update_clipped_samples(long value)
1507 if( value != displayed_clipped_samples ) {
1508 new_clipped_samples = value;
1509 input_lock->unlock();
1513 void RecordStatusThread::update_position(double value)
1515 this->new_position = value;
1516 input_lock->unlock();
1519 void RecordStatusThread::update_framerate(double value)
1521 if( value != displayed_framerate ) {
1522 new_framerate = value;
1523 input_lock->unlock();
1527 void RecordStatusThread::get_window_lock()
1529 if( !window_locked ) {
1530 gui->lock_window("RecordStatusThread::run 1");
1536 void RecordStatusThread::
1537 update_status_string(const char *fmt, T &new_value, T &displayed_value, BC_Title *widgit)
1539 if( new_value >= 0 ) {
1540 if( displayed_value != new_value ) {
1541 displayed_value = new_value;
1544 sprintf(string, fmt, displayed_value);
1546 widgit->update(string);
1553 void RecordStatusThread::run()
1556 input_lock->lock("RecordStatusThread::run");
1558 update_status_string("%d", new_dropped_frames, displayed_dropped_frames,
1559 gui->frames_dropped);
1560 update_status_string("%d", new_frames_behind, displayed_frames_behind,
1561 gui->frames_behind);
1562 update_status_string("%d", new_clipped_samples, displayed_clipped_samples,
1563 gui->samples_clipped);
1564 update_status_string("%0.2f", new_framerate, displayed_framerate,
1566 if( new_position >= 0 ) {
1568 gui->update_title(gui->position_title, new_position);
1569 gui->update_labels(new_position);
1572 if( window_locked ) {
1573 gui->unlock_window();
1580 void RecordGUI::start_flash_batch()
1582 if( batch_flash ) return;
1583 batch_flash = new RecordGUIFlash(this);
1586 void RecordGUI::stop_flash_batch()
1588 if( !batch_flash ) return;
1593 void RecordGUI::flash_batch()
1595 lock_window("void RecordGUI::flash_batch");
1596 int cur_batch = record->current_batch();
1597 if( cur_batch >= 0 && cur_batch < batch_bay->count()) {
1598 flash_color = flash_color == GREEN ? RED : GREEN;
1599 //printf("RecordGUI::flash_batch %x\n", flash_color);
1600 batch_bay->set_row_color(cur_batch, flash_color);
1601 batch_bay->update_batch_news(cur_batch);
1607 RecordGUIFlash(RecordGUI *record_gui)
1610 this->record_gui = record_gui;
1611 flash_lock = new Condition(0,"RecordGUIFlash::flash_lock");
1619 if( Thread::running() ) {
1621 flash_lock->unlock();
1628 void RecordGUIFlash::run()
1631 record_gui->flash_batch();
1640 RecordGUIDCOffset::RecordGUIDCOffset(MWindow *mwindow, int y)
1641 : BC_Button(xS(230), y, mwindow->theme->calibrate_data)
1645 RecordGUIDCOffset::~RecordGUIDCOffset() {}
1647 int RecordGUIDCOffset::handle_event()
1652 int RecordGUIDCOffset::keypress_event() { return context_help_check_and_show(); }
1654 RecordGUIDCOffsetText::RecordGUIDCOffsetText(char *text, int y, int number)
1655 : BC_TextBox(xS(30), y+yS(1), xS(67), 1, text, 0)
1657 this->number = number;
1660 RecordGUIDCOffsetText::~RecordGUIDCOffsetText()
1664 int RecordGUIDCOffsetText::handle_event()
1669 RecordGUIReset::RecordGUIReset(MWindow *mwindow, RecordGUI *gui, int y)
1670 : BC_Button(xS(400), y, mwindow->theme->over_button)
1671 { this->gui = gui; }
1673 RecordGUIReset::~RecordGUIReset()
1677 int RecordGUIReset::handle_event()
1682 RecordGUIResetTranslation::RecordGUIResetTranslation(MWindow *mwindow, RecordGUI *gui, int y)
1683 : BC_Button(xS(250), y, mwindow->theme->reset_data)
1688 RecordGUIResetTranslation::~RecordGUIResetTranslation()
1692 int RecordGUIResetTranslation::handle_event()
1694 gui->set_translation(0, 0, 1);