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;
117 RecordGUI::~RecordGUI()
119 delete status_thread;
120 delete record_transport;
124 delete startover_thread;
125 delete interrupt_thread;
127 delete batch_duration;
132 void RecordGUI::create_objects()
134 int xs5 = xS(5), xs10 = xS(10), xs20 = xS(20), xs30 = xS(30);
135 int ys5 = yS(5), ys10 = yS(10);
136 char string[BCTEXTLEN];
138 Asset *asset = record->default_asset;
139 lock_window("RecordGUI::create_objects");
140 status_thread = new RecordStatusThread(mwindow, this);
141 status_thread->start();
142 set_icon(mwindow->theme->get_image("record_icon"));
144 mwindow->theme->get_recordgui_sizes(this, get_w(), get_h());
145 //printf("RecordGUI::create_objects 1\n");
146 mwindow->theme->draw_rwindow_bg(this);
152 int pad = max(BC_TextBox::calculate_h(this, MEDIUMFONT, 1, 1),
153 BC_Title::calculate_h(this, "X")) + ys5;
157 add_subwindow(title = new BC_Title(x, y, _("Path:")));
158 x1 = max(title->get_w(), x1);
160 add_subwindow(title = new BC_Title(x, y, _("Start time:")));
161 x1 = max(title->get_w(), x1);
163 add_subwindow(title = new BC_Title(x, y, _("Duration time:")));
164 x1 = max(title->get_w(), x1);
166 add_subwindow(title = new BC_Title(x, y, _("Source:")));
167 x1 = max(title->get_w(), x1);
169 add_subwindow(title = new BC_Title(x, y, _("Mode:")));
170 x1 = max(title->get_w(), x1);
172 add_subwindow(title = new BC_Title(x, y, _("Transport:")));
173 x1 = max(title->get_w(), x1);
176 button_y = max(y, button_y);
183 add_subwindow(batch_path = new RecordPath(this, x, y));
184 add_subwindow(batch_browse = new BrowseButton(mwindow->theme,
187 batch_path->get_x() + batch_path->get_w(),
190 _(PROGRAM_NAME ": Record path"),
191 _("Select a file to record to:"),
193 x2 = max(x2, batch_path->get_w() + batch_browse->get_w());
195 batch_start = new RecordStart(this, x, y);
196 batch_start->create_objects();
197 x2 = max(x2, batch_start->get_w());
199 batch_duration = new RecordDuration(this, x, y);
200 batch_duration->create_objects();
201 x2 = max(x2, batch_duration->get_w());
203 batch_source = new RecordSource(this, x, y);
204 batch_source->create_objects();
205 x2 = max(x2, batch_source->get_w());
207 batch_mode = new RecordGUIModeMenu(this, x, y, xS(200), "");
208 batch_mode->create_objects();
209 x2 = max(x2, batch_mode->get_w());
211 record_transport = new RecordTransport(mwindow,
213 record_transport->create_objects();
214 x2 = max(x2, record_transport->get_w());
219 // Compression settings
223 pad = BC_Title::calculate_h(this, "X") + ys5;
224 add_subwindow(title = new BC_Title(x, y, _("Format:")));
225 x3 = max(title->get_w(), x3);
228 if(asset->audio_data)
230 add_subwindow(title = new BC_Title(x, y, _("Audio compression:")));
231 x3 = max(title->get_w(), x3);
233 add_subwindow(title = new BC_Title(x, y, _("Samplerate:")));
234 x3 = max(title->get_w(), x3);
236 add_subwindow(title = new BC_Title(x, y, _("Clipped samples:")));
237 x3 = max(title->get_w(), x3);
241 if(asset->video_data)
243 add_subwindow(title = new BC_Title(x, y, _("Video compression:")));
244 x3 = max(title->get_w(), x3);
246 add_subwindow(title = new BC_Title(x, y, _("Framerate:")));
247 x3 = max(title->get_w(), x3);
249 add_subwindow(title = new BC_Title(x, y, _("Frames dropped:")));
250 x3 = max(title->get_w(), x3);
252 add_subwindow(title = new BC_Title(x, y, _("Frames behind:")));
253 x3 = max(title->get_w(), x3);
257 add_subwindow(title = new BC_Title(x, y, _("Position:")));
258 x3 = max(title->get_w(), x3);
260 add_subwindow(title = new BC_Title(x, y, _("Prev label:")));
261 x3 = max(title->get_w(), x3);
264 button_y = max(y, button_y);
266 x = x3 + x2 + x1 + xS(40);
268 add_subwindow(new BC_Title(x, y,
269 File::formattostr(asset->format),
271 mwindow->theme->recordgui_fixed_color));
274 if(asset->audio_data) {
275 add_subwindow(new BC_Title(x, y,
276 File::bitstostr(asset->bits),
278 mwindow->theme->recordgui_fixed_color));
281 sprintf(string, "%d", asset->sample_rate);
282 add_subwindow(new BC_Title(x, y,
284 mwindow->theme->recordgui_fixed_color));
287 add_subwindow(samples_clipped = new BC_Title(x, y,
289 mwindow->theme->recordgui_variable_color));
293 if(asset->video_data) {
294 add_subwindow(new BC_Title(x, y,
295 asset->format == FILE_MPEG ? _("File Capture") :
296 File::compressiontostr(asset->vcodec),
298 mwindow->theme->recordgui_fixed_color));
301 sprintf(string, "%0.2f", asset->frame_rate);
302 add_subwindow(framerate = new BC_Title(x, y,
304 mwindow->theme->recordgui_fixed_color));
307 add_subwindow(frames_dropped = new BC_Title(x, y,
309 mwindow->theme->recordgui_variable_color));
311 add_subwindow(frames_behind = new BC_Title(x, y,
313 mwindow->theme->recordgui_variable_color));
317 add_subwindow(position_title = new BC_Title(x, y,
319 mwindow->theme->recordgui_variable_color));
322 add_subwindow(prev_label_title = new BC_Title(x, y,
323 _("None"), MEDIUMFONT,
324 mwindow->theme->recordgui_variable_color));
327 button_y = max(y, button_y);
333 add_subwindow(title = new BC_Title(x,y, _("Batches:")));
334 int y_max = y + title->get_h(); x1 = x;
335 x += title->get_w() + xs5;
336 add_subwindow(activate_batch = new RecordGUIActivateBatch(this, x, y));
337 x += activate_batch->get_w();
338 y_max = max(y_max, y + activate_batch->get_h());
339 add_subwindow(start_batches = new RecordGUIStartBatches(this, x, y));
340 y_max = max(y_max, y + start_batches->get_h()); x2 = x;
341 x += start_batches->get_w();
342 add_subwindow(new_batch = new RecordGUINewBatch(this, x, y));
343 y_max = max(y_max, y + new_batch->get_h()); x3 = x;
344 x += new_batch->get_w(); int x4 = x;
345 add_subwindow(label_button = new RecordGUILabel(this, x, y));
346 y_max = max(y_max, y + label_button->get_h());
348 int y1 = y_max, y2 = y1 + ys5;
349 add_subwindow(title = new BC_Title(x1,y2, _("Cron:")));
350 y_max = max(y_max, y2 + title->get_h());
351 x1 += title->get_w() + xs5;
352 add_subwindow(cron_status = new BC_Title(x1,y2, _("Idle"), MEDIUMFONT,
353 mwindow->theme->recordgui_variable_color));
354 y_max = max(y_max, y2 + cron_status->get_h());
355 add_subwindow(stop_batches = new RecordGUIStopBatches(this, x2, y1));
356 y_max = max(y_max, y1 + stop_batches->get_h());
357 add_subwindow(delete_batch = new RecordGUIDeleteBatch(this, x3, y1));
358 y_max = max(y_max, y1 + delete_batch->get_h());
359 add_subwindow(clrlbls_button = new RecordGUIClearLabels(this, x4, y1));
360 y_max = max(y_max, y1 + clrlbls_button->get_h());
370 if(asset->video_data) {
371 add_subwindow(drop_frames = new RecordGUIDropFrames(this, x, y));
372 add_subwindow(fill_frames = new RecordGUIFillFrames(this, x, y1));
373 x += drop_frames->get_w() + xs5; x1 = x;
374 add_subwindow(monitor_video = new RecordGUIMonitorVideo(this, x, y));
375 x += monitor_video->get_w() + xs5;
378 if(asset->audio_data) {
379 add_subwindow(monitor_audio = new RecordGUIMonitorAudio(this, x, y));
380 x += monitor_audio->get_w() + xs5;
381 add_subwindow(meter_audio = new RecordGUIAudioMeters(this, x, y));
382 x += meter_audio->get_w() + xs5;
385 add_subwindow(power_off = new RecordGUIPowerOff(this, x1, y1));
386 x1 += power_off->get_w() + xs10;
387 add_subwindow(commercial_check = new RecordGUICommCheck(this, x1, y1));
388 x1 += commercial_check->get_w() + xs30;
389 add_subwindow(deinterlace = new RecordGUIDeinterlace(this, x1, y1));
390 deinterlace->create_objects();
391 x1 += deinterlace->get_w() + xs5;
392 add_subwindow(new BC_Title(x1, y1, _("deinterlace")));
398 y = y1 + fill_frames->get_h();
399 else if( monitor_audio )
400 y += monitor_audio->get_h();
402 int bottom_margin = max(BC_OKButton::calculate_h(),
403 LoadMode::calculate_h(this, mwindow->theme)) + ys5;
406 add_subwindow(batch_bay = new RecordGUIBatches(this, x, y,
407 get_w() - xs20, get_h() - y - bottom_margin - ys10));
408 y += batch_bay->get_h() + ys5;
409 record->record_batches.gui = batch_bay;
410 batch_bay->update_batches(-1);
413 int loadmode_w = LoadMode::calculate_w(this, mwindow->theme);
414 load_mode = new LoadMode(mwindow, this,
415 get_w() / 2 - loadmode_w / 2, y, &record->load_mode);
416 load_mode->create_objects();
417 y += load_mode->get_h() + ys5;
419 add_subwindow(new RecordGUIOK(this));
421 interrupt_thread = new EndRecordThread(this);
422 // add_subwindow(new RecordGUISave(record, this));
423 add_subwindow(new RecordGUICancel(this));
425 startover_thread = new RecordStartoverThread(this);
427 enable_batch_buttons();
428 if( batch_mode->value == RECORD_TIMED )
429 batch_duration->enable();
431 batch_duration->disable();
436 void RecordGUI::update_batches()
438 lock_window("void RecordGUI::Update_batches");
439 batch_bay->update_batches();
444 Batch *RecordGUI::get_current_batch()
446 return record->get_editing_batch();
449 Batch *RecordGUI::get_editing_batch()
451 return record->get_editing_batch();
454 void RecordGUI::update_batch_sources()
456 //printf("RecordGUI::update_batch_sources 1\n");
457 ChannelPicker *channel_picker =
458 record->record_monitor->window->channel_picker;
460 batch_source->update_list(&channel_picker->channel_listitems);
461 //printf("RecordGUI::update_batch_sources 2\n");
464 int RecordGUI::translation_event()
466 mwindow->session->rwindow_x = get_x();
467 mwindow->session->rwindow_y = get_y();
472 int RecordGUI::resize_event(int w, int h)
474 int xs20 = xS(20), ys10 = yS(10);
475 // Recompute batch list based on previous extents
476 int bottom_margin = mwindow->session->rwindow_h -
479 int mode_margin = mwindow->session->rwindow_h - load_mode->get_y();
480 mwindow->session->rwindow_x = get_x();
481 mwindow->session->rwindow_y = get_y();
482 mwindow->session->rwindow_w = w;
483 mwindow->session->rwindow_h = h;
484 mwindow->theme->get_recordgui_sizes(this, w, h);
485 mwindow->theme->draw_rwindow_bg(this);
487 int new_h = mwindow->session->rwindow_h - bottom_margin - batch_bay->get_y();
488 if(new_h < ys10) new_h = ys10;
489 batch_bay->reposition_window(batch_bay->get_x(),
491 mwindow->session->rwindow_w - xs20,
492 mwindow->session->rwindow_h - bottom_margin - batch_bay->get_y());
494 load_mode->reposition_window(mwindow->session->rwindow_w / 2 -
495 mwindow->theme->loadmode_w / 2,
496 mwindow->session->rwindow_h - mode_margin);
502 void RecordGUI::update_batch_tools()
504 lock_window("RecordGUI::update_batch_tools");
505 //printf("RecordGUI::update_batch_tools 1\n");
506 Batch *batch = get_editing_batch();
507 batch_path->update(batch->asset->path);
509 // File is open in editing batch
510 // if(current_batch() == editing_batch() && record->file)
511 // batch_path->disable();
513 // batch_path->enable();
515 batch_start->update(&batch->start_day, &batch->start_time);
516 batch_duration->update(0, &batch->duration);
517 batch_source->update(batch->get_source_text());
518 batch_mode->update(batch->record_mode);
519 if( batch_mode->value == RECORD_TIMED )
520 batch_duration->enable();
522 batch_duration->disable();
527 void RecordGUI::enable_batch_buttons()
529 lock_window("RecordGUI::enable_batch_buttons");
531 delete_batch->enable();
532 start_batches->enable();
533 stop_batches->disable();
534 activate_batch->enable();
538 void RecordGUI::disable_batch_buttons()
540 lock_window("RecordGUI::disable_batch_buttons");
541 new_batch->disable();
542 delete_batch->disable();
543 start_batches->disable();
544 stop_batches->enable();
545 activate_batch->disable();
549 RecordGUIBatches::RecordGUIBatches(RecordGUI *gui, int x, int y, int w, int h)
550 : RecordBatchesGUI(gui->record->record_batches, x, y, w, h)
555 // Do nothing for double clicks to protect active batch
556 int RecordGUIBatches::handle_event()
561 int RecordGUIBatches::selection_changed()
563 RecordBatchesGUI::selection_changed();
564 gui->update_batch_tools();
569 RecordGUISave::RecordGUISave(RecordGUI *gui)
571 gui->get_h() - BC_WindowBase::get_resources()->ok_images[0]->get_h() - yS(10),
572 BC_WindowBase::get_resources()->ok_images)
574 set_tooltip(_("Save the recording and quit."));
578 int RecordGUISave::handle_event()
584 int RecordGUISave::keypress_event()
586 // if(get_keypress() == RETURN)
594 RecordGUICancel::RecordGUICancel(RecordGUI *gui)
595 : BC_CancelButton(gui)
597 set_tooltip(_("Quit without pasting into project."));
601 int RecordGUICancel::handle_event()
603 gui->interrupt_thread->start(0);
607 int RecordGUICancel::keypress_event()
609 if(get_keypress() == ESC)
619 RecordGUIOK::RecordGUIOK(RecordGUI *gui)
622 set_tooltip(_("Quit and paste into project."));
626 int RecordGUIOK::handle_event()
628 gui->interrupt_thread->start(1);
633 RecordGUIStartOver::RecordGUIStartOver(RecordGUI *gui, int x, int y)
634 : BC_GenericButton(x, y, _("Start Over"))
636 set_tooltip(_("Rewind the current file and erase."));
639 RecordGUIStartOver::~RecordGUIStartOver()
643 int RecordGUIStartOver::handle_event()
645 if(!gui->startover_thread->running())
646 gui->startover_thread->start();
651 RecordGUIDropFrames::RecordGUIDropFrames(RecordGUI *gui, int x, int y)
652 : BC_CheckBox(x, y, gui->record->drop_overrun_frames, _("drop overrun frames"))
654 this->set_underline(0);
656 set_tooltip(_("Drop input frames when behind."));
659 int RecordGUIDropFrames::handle_event()
661 gui->record->drop_overrun_frames = get_value();
665 int RecordGUIDropFrames::keypress_event()
667 if( get_keypress() == caption[0] ) {
668 set_value(get_value() ? 0 : 1);
675 RecordGUIFillFrames::RecordGUIFillFrames(RecordGUI *gui, int x, int y)
676 : BC_CheckBox(x, y, gui->record->fill_underrun_frames, _("fill underrun frames"))
678 this->set_underline(0);
680 set_tooltip(_("Write extra frames when behind."));
683 int RecordGUIFillFrames::handle_event()
685 gui->record->fill_underrun_frames = get_value();
689 int RecordGUIFillFrames::keypress_event()
691 if( get_keypress() == caption[0] ) {
692 set_value(get_value() ? 0 : 1);
699 RecordGUIPowerOff::RecordGUIPowerOff(RecordGUI *gui, int x, int y)
700 : BC_CheckBox(x, y, gui->record->power_off, _("poweroff when done"))
702 this->set_underline(0);
704 set_tooltip(_("poweroff system when batch record done."));
707 int RecordGUIPowerOff::handle_event()
709 gui->record->power_off = get_value();
713 int RecordGUIPowerOff::keypress_event()
715 if( get_keypress() == caption[0] ) {
716 set_value(get_value() ? 0 : 1);
724 RecordGUICommCheck::RecordGUICommCheck(RecordGUI *gui, int x, int y)
725 : BC_CheckBox(x, y, gui->record->commercial_check, _("check for ads"))
727 this->set_underline(0);
729 set_tooltip(_("check for commercials."));
732 int RecordGUICommCheck::handle_event()
734 gui->record->update_skimming(get_value());
738 int RecordGUICommCheck::keypress_event()
740 if( get_keypress() == caption[0] ) {
741 set_value(get_value() ? 0 : 1);
742 gui->record->update_skimming(get_value());
750 RecordGUIDelaceItem::RecordGUIDelaceItem(RecordGUIDeinterlace *popup,
751 const char *text, int id)
757 int RecordGUIDelaceItem::handle_event()
759 popup->gui->record->deinterlace = id;
764 RecordGUIDeinterlace::RecordGUIDeinterlace(RecordGUI *gui, int x, int y)
765 : BC_PopupMenu(x, y, xS(24), "", 1, 0, xS(3))
770 void RecordGUIDeinterlace::create_objects()
772 add_item(new RecordGUIDelaceItem(this, _("None"), RECORD_LACE_NONE));
773 add_item(new RecordGUIDelaceItem(this, _("Even"), RECORD_LACE_EVEN));
774 add_item(new RecordGUIDelaceItem(this, _("Odd"), RECORD_LACE_ODD));
778 void RecordGUIDeinterlace::update()
780 int v = gui->record->deinterlace;
781 for( int i=0,n=total_items(); i<n; ++i ) {
782 RecordGUIDelaceItem *item = (RecordGUIDelaceItem *)get_item(i);
783 item->set_checked(item->id == v);
788 RecordGUIMonitorVideo::RecordGUIMonitorVideo(RecordGUI *gui, int x, int y)
789 : BC_CheckBox(x, y, gui->record->monitor_video, _("Monitor video"))
791 this->set_underline(8);
795 int RecordGUIMonitorVideo::handle_event()
797 // Video capture constitutively, just like audio, but only flash on screen if 1
798 int mode = get_value();
799 Record *record = gui->record;
800 record->set_video_monitoring(mode);
801 if(record->monitor_video) {
803 BC_Window *window = record->record_monitor->window;
804 window->lock_window("RecordGUIMonitorVideo::handle_event");
805 window->show_window();
806 window->raise_window();
808 window->unlock_window();
809 lock_window("RecordGUIMonitorVideo::handle_event");
810 record->video_window_open = 1;
816 int RecordGUIMonitorVideo::keypress_event()
818 if(get_keypress() == 'v') {
819 set_value(get_value() ? 0 : 1);
828 RecordGUIMonitorAudio::RecordGUIMonitorAudio(RecordGUI *gui, int x, int y)
829 : BC_CheckBox(x, y, gui->record->monitor_audio, _("Monitor audio"))
831 this->set_underline(8);
835 int RecordGUIMonitorAudio::handle_event()
837 int mode = get_value();
838 Record *record = gui->record;
839 record->set_audio_monitoring(mode);
840 if(record->monitor_audio) {
842 BC_Window *window = record->record_monitor->window;
843 window->lock_window("RecordGUIMonitorAudio::handle_event");
844 window->show_window();
845 window->raise_window();
847 window->unlock_window();
848 lock_window("RecordGUIMonitorAudio::handle_event");
849 record->video_window_open = 1;
854 int RecordGUIMonitorAudio::keypress_event()
856 if(get_keypress() == 'a') {
857 set_value(get_value() ? 0 : 1);
865 RecordGUIAudioMeters::RecordGUIAudioMeters(RecordGUI *gui, int x, int y)
866 : BC_CheckBox(x, y, gui->record->metering_audio, _("Audio meters"))
868 this->set_underline(6);
872 int RecordGUIAudioMeters::handle_event()
874 int mode = get_value();
875 Record *record = gui->record;
876 record->set_audio_metering(mode);
877 if(record->metering_audio) {
879 BC_Window *window = record->record_monitor->window;
880 window->lock_window("RecordGUIAudioMeters::handle_event");
881 window->show_window();
882 window->raise_window();
884 window->unlock_window();
885 lock_window("RecordGUIAudioMeters::handle_event");
886 record->video_window_open = 1;
891 int RecordGUIAudioMeters::keypress_event()
893 if(get_keypress() == 'm') {
894 set_value(get_value() ? 0 : 1);
901 RecordPath::RecordPath(RecordGUI *gui, int x, int y)
902 : RecordBatchesGUI::Path(gui->record->record_batches, x, y)
907 int RecordPath::handle_event()
909 return RecordBatchesGUI::Path::handle_event();
913 RecordStart::RecordStart(RecordGUI *gui, int x, int y)
914 : RecordBatchesGUI::StartTime(gui, gui->record->record_batches, x, y)
919 int RecordStart::handle_event()
921 return RecordBatchesGUI::StartTime::handle_event();
924 RecordDuration::RecordDuration(RecordGUI *gui, int x, int y)
925 : RecordBatchesGUI::Duration(gui, gui->record->record_batches, x, y)
930 int RecordDuration::handle_event()
932 return RecordBatchesGUI::Duration::handle_event();
936 RecordSource::RecordSource(RecordGUI *gui, int x, int y)
937 : RecordBatchesGUI::Source(gui, gui->record->record_batches, x, y)
942 int RecordSource::handle_event()
944 gui->record->set_batch_channel_no(get_number());
945 return RecordBatchesGUI::Source::handle_event();
949 RecordNews::RecordNews(RecordGUI *gui, int x, int y)
950 : RecordBatchesGUI::News(gui->record->record_batches, x, y)
955 int RecordNews::handle_event()
957 return RecordBatchesGUI::News::handle_event();
961 RecordGUINewBatch::RecordGUINewBatch(RecordGUI *gui, int x, int y)
962 : RecordBatchesGUI::NewBatch(gui->record->record_batches, x, y)
965 set_tooltip(_("Create new clip."));
967 int RecordGUINewBatch::handle_event()
969 gui->record->new_batch();
970 return RecordBatchesGUI::NewBatch::handle_event();
974 RecordGUIDeleteBatch::RecordGUIDeleteBatch(RecordGUI *gui, int x, int y)
975 : RecordBatchesGUI::DeleteBatch(gui->record->record_batches, x, y)
978 set_tooltip(_("Delete clip."));
981 int RecordGUIDeleteBatch::handle_event()
983 gui->record->delete_batch();
984 return RecordBatchesGUI::DeleteBatch::handle_event();
988 RecordGUIStartBatches::RecordGUIStartBatches(RecordGUI *gui, int x, int y)
989 : RecordBatchesGUI::StartBatches(gui->record->record_batches, x, y)
992 set_tooltip(_("Start batch recording\nfrom the current position."));
995 int RecordGUIStartBatches::handle_event()
997 Record *record = gui->record;
998 record->start_cron_thread();
999 return RecordBatchesGUI::StartBatches::handle_event();
1003 RecordGUIStopBatches::RecordGUIStopBatches(RecordGUI *gui, int x, int y)
1004 : RecordBatchesGUI::StopBatches(gui->record->record_batches, x, y)
1009 int RecordGUIStopBatches::handle_event()
1011 Record *record = gui->record;
1013 record->stop_cron_thread(_("Stopped"));
1015 return RecordBatchesGUI::StopBatches::handle_event();
1019 RecordGUIActivateBatch::RecordGUIActivateBatch(RecordGUI *gui, int x, int y)
1020 : RecordBatchesGUI::ActivateBatch(gui->record->record_batches, x, y)
1023 set_tooltip(_("Make the highlighted\nclip active."));
1025 int RecordGUIActivateBatch::handle_event()
1027 gui->record->activate_batch(gui->record->editing_batch());
1028 gui->update_cron_status(_("Idle"));
1029 return RecordBatchesGUI::ActivateBatch::handle_event();
1033 RecordGUILabel::RecordGUILabel(RecordGUI *gui, int x, int y)
1034 : BC_GenericButton(x, y, _("Label"))
1041 RecordGUILabel::~RecordGUILabel()
1045 int RecordGUILabel::handle_event()
1047 gui->record->toggle_label();
1051 int RecordGUILabel::keypress_event()
1053 if( get_keypress() == *get_text() ) {
1061 RecordGUIClearLabels::RecordGUIClearLabels(RecordGUI *gui, int x, int y)
1062 : BC_GenericButton(x, y, _("ClrLbls"))
1068 RecordGUIClearLabels::~RecordGUIClearLabels()
1072 int RecordGUIClearLabels::handle_event()
1074 gui->record->clear_labels();
1079 EndRecordThread::EndRecordThread(RecordGUI *gui)
1086 EndRecordThread::~EndRecordThread()
1088 if(Thread::running()) {
1089 window->lock_window("EndRecordThread::~EndRecordThread");
1090 window->set_done(1);
1091 window->unlock_window();
1096 void EndRecordThread::start(int is_ok)
1098 this->is_ok = is_ok;
1099 if( gui->record->writing_file ) {
1104 gui->set_done(!is_ok);
1108 void EndRecordThread::run()
1110 window = new QuestionWindow(gui->record->mwindow);
1111 window->create_objects(_("Interrupt recording in progress?"), 0);
1112 int result = window->run_window();
1114 if(result == 2) gui->set_done(!is_ok);
1118 RecordStartoverThread::RecordStartoverThread(RecordGUI *gui)
1123 RecordStartoverThread::~RecordStartoverThread()
1125 if(Thread::running()) {
1126 window->lock_window("RecordStartoverThread::~RecordStartoverThread");
1127 window->set_done(1);
1128 window->unlock_window();
1133 void RecordStartoverThread::run()
1135 Record *record = gui->record;
1136 window = new QuestionWindow(record->mwindow);
1137 window->create_objects(_("Rewind batch and overwrite?"), 0);
1138 int result = window->run_window();
1139 if(result == 2) record->start_over();
1144 int RecordGUI::set_translation(int x, int y, float z)
1146 record->video_x = x;
1147 record->video_y = y;
1148 record->video_zoom = z;
1152 void RecordGUI::reset_video()
1154 total_dropped_frames = 0;
1155 status_thread->reset_video();
1156 update_framerate(record->default_asset->frame_rate);
1159 void RecordGUI::update_dropped_frames(long value)
1161 status_thread->update_dropped_frames(value);
1164 void RecordGUI::update_frames_behind(long value)
1166 status_thread->update_frames_behind(value);
1169 void RecordGUI::update_position(double value)
1171 status_thread->update_position(value);
1174 void RecordGUI::update_framerate(double value)
1176 status_thread->update_framerate(value);
1179 void RecordGUI::update_video(int dropped, int behind)
1181 total_dropped_frames += dropped;
1182 update_dropped_frames(total_dropped_frames);
1183 update_frames_behind(behind);
1184 status_thread->update_position(record->current_display_position());
1187 void RecordGUI::reset_audio()
1189 // gui->lock_window("RecordAudio::run 2");
1191 total_clipped_samples = 0;
1192 status_thread->reset_audio();
1193 AudioDevice *adevice = record->adevice;
1194 RecordMonitorGUI *window = record->record_monitor->window;
1195 window->lock_window("RecordAudio::run 2");
1196 MeterPanel *meters = window->meters;
1198 int dmix = adevice && (adevice->get_idmix() || adevice->get_odmix());
1199 meters->init_meters(dmix);
1201 window->unlock_window();
1202 // gui->unlock_window();
1205 void RecordGUI::update_clipped_samples(long value)
1207 status_thread->update_clipped_samples(value);
1210 void RecordGUI::update_audio(int channels, double *max, int *over)
1212 // Get clipping status
1214 for( int ch=0; ch<channels && !clipped; ++ch )
1215 if( over[ch] ) clipped = 1;
1217 update_clipped_samples(++total_clipped_samples);
1219 // Update meters if monitoring
1220 if( record->metering_audio ) {
1221 RecordMonitorGUI *window = record->record_monitor->window;
1222 window->lock_window("RecordAudio::run 1");
1223 MeterPanel *meters = window->meters;
1224 int nmeters = meters->meters.total;
1225 for( int ch=0; ch<nmeters; ++ch ) {
1226 double vmax = ch < channels ? max[ch] : 0.;
1227 int vover = ch < channels ? over[ch] : 0;
1228 meters->meters.values[ch]->update(vmax, vover);
1230 window->unlock_window();
1232 // update position, if no video
1233 if( !record->default_asset->video_data )
1234 update_position(record->current_display_position());
1238 int RecordGUI::keypress_event()
1240 return record_transport->keypress_event();
1243 void RecordGUI::update_labels(double new_position)
1245 RecordLabel *prev, *next;
1247 for(prev = record->get_current_batch()->labels->last;
1249 prev = prev->previous) {
1250 if(prev->position <= new_position) break;
1253 for(next = record->get_current_batch()->labels->first;
1257 if(next->position > new_position) break;
1261 update_title(prev_label_title, prev->position);
1263 update_title(prev_label_title, -1);
1266 // update_title(next_label_title, (double)next->position / record->default_asset->sample_rate);
1268 // update_title(next_label_title, -1);
1272 int RecordGUI::update_prev_label(long new_position)
1274 update_title(prev_label_title, new_position);
1278 // int RecordGUI::update_next_label(long new_position)
1280 // update_title(next_label_title, new_position);
1283 int RecordGUI::update_title(BC_Title *title, double position)
1285 static char string[256];
1288 Units::totext(string,
1290 mwindow->edl->session->time_format,
1291 record->default_asset->sample_rate,
1292 record->default_asset->frame_rate,
1293 mwindow->edl->session->frames_per_foot);
1296 sprintf(string, "-");
1298 title->update(string);
1303 void RecordGUI::update_cron_status(const char *status)
1305 lock_window("RecordGUI::update_cron_status");
1306 cron_status->update(status);
1310 void RecordGUI::update_power_off(int value)
1312 lock_window("RecordGUI::update_power_off");
1313 power_off->update(value);
1320 // ===================================== GUI
1321 // ================================================== modes
1323 RecordGUIModeTextBox::RecordGUIModeTextBox(RecordGUIModeMenu *mode_menu,
1324 int x, int y, int w,const char *text)
1325 : BC_TextBox(x, y, w, 1, text)
1327 this->mode_menu = mode_menu;
1330 RecordGUIModeTextBox::~RecordGUIModeTextBox()
1334 int RecordGUIModeTextBox::handle_event()
1339 RecordGUIModeListBox::RecordGUIModeListBox(RecordGUIModeMenu *mode_menu)
1340 : BC_ListBox(mode_menu->textbox->get_x() + mode_menu->textbox->get_w(),
1341 mode_menu->textbox->get_y(), xS(100), yS(50), LISTBOX_TEXT,
1342 &mode_menu->modes, 0, 0, 1, 0, 1)
1344 this->mode_menu = mode_menu;
1347 RecordGUIModeListBox::~RecordGUIModeListBox()
1351 int RecordGUIModeListBox::handle_event()
1353 return mode_menu->handle_event();
1356 RecordGUIModeMenu::RecordGUIModeMenu(RecordGUI *record_gui,
1357 int x, int y, int w,const char *text)
1359 this->record_gui = record_gui;
1360 textbox = new RecordGUIModeTextBox(this,x, y, w, "");
1361 record_gui->add_subwindow(textbox);
1362 listbox = new RecordGUIModeListBox(this);
1363 record_gui->add_subwindow(listbox);
1366 RecordGUIModeMenu::~RecordGUIModeMenu()
1368 for( int i=0; i<modes.total; ++i )
1369 delete modes.values[i];
1374 void RecordGUIModeMenu::create_objects()
1376 value = RECORD_UNTIMED;
1377 modes.append(new BC_ListBoxItem(Batch::mode_to_text(RECORD_UNTIMED)));
1378 modes.append(new BC_ListBoxItem(Batch::mode_to_text(RECORD_TIMED)));
1379 textbox->update(modes.values[value]->get_text());
1382 int RecordGUIModeMenu::handle_event()
1384 value = listbox->get_selection_number(0, 0);
1385 textbox->update(modes.values[value]->get_text());
1386 textbox->handle_event();
1387 record_gui->record->set_record_mode(value);
1388 if( value == RECORD_TIMED )
1389 record_gui->batch_duration->enable();
1391 record_gui->batch_duration->disable();
1395 void RecordGUIModeMenu::update(int value)
1397 this->value = value;
1398 textbox->update(modes.values[value]->get_text());
1401 int RecordGUIModeMenu::get_w()
1403 return textbox->get_w() + listbox->get_w();
1406 int RecordGUIModeMenu::get_h()
1408 return MAX(textbox->get_h(), listbox->get_h());
1412 RecordStatusThread::RecordStatusThread(MWindow *mwindow, RecordGUI *gui)
1415 this->mwindow = mwindow;
1417 input_lock = new Condition(0, "RecordStatusThread::input_lock");
1424 RecordStatusThread::~RecordStatusThread()
1426 if(Thread::running())
1429 input_lock->unlock();
1435 void RecordStatusThread::reset_video()
1437 new_dropped_frames = 0;
1438 displayed_dropped_frames = -1;
1439 new_frames_behind = 0;
1440 displayed_frames_behind = -1;
1442 displayed_framerate = -1.;
1446 void RecordStatusThread::reset_audio()
1448 new_clipped_samples = 0;
1449 displayed_clipped_samples = -1;
1452 void RecordStatusThread::update_frames_behind(long value)
1454 if( value != displayed_frames_behind ) {
1455 new_frames_behind = value;
1456 input_lock->unlock();
1460 void RecordStatusThread::update_dropped_frames(long value)
1462 if( value != displayed_dropped_frames ) {
1463 new_dropped_frames = value;
1464 input_lock->unlock();
1468 void RecordStatusThread::update_clipped_samples(long value)
1470 if( value != displayed_clipped_samples ) {
1471 new_clipped_samples = value;
1472 input_lock->unlock();
1476 void RecordStatusThread::update_position(double value)
1478 this->new_position = value;
1479 input_lock->unlock();
1482 void RecordStatusThread::update_framerate(double value)
1484 if( value != displayed_framerate ) {
1485 new_framerate = value;
1486 input_lock->unlock();
1490 void RecordStatusThread::get_window_lock()
1492 if( !window_locked ) {
1493 gui->lock_window("RecordStatusThread::run 1");
1499 void RecordStatusThread::
1500 update_status_string(const char *fmt, T &new_value, T &displayed_value, BC_Title *widgit)
1502 if( new_value >= 0 ) {
1503 if( displayed_value != new_value ) {
1504 displayed_value = new_value;
1507 sprintf(string, fmt, displayed_value);
1509 widgit->update(string);
1516 void RecordStatusThread::run()
1519 input_lock->lock("RecordStatusThread::run");
1521 update_status_string("%d", new_dropped_frames, displayed_dropped_frames,
1522 gui->frames_dropped);
1523 update_status_string("%d", new_frames_behind, displayed_frames_behind,
1524 gui->frames_behind);
1525 update_status_string("%d", new_clipped_samples, displayed_clipped_samples,
1526 gui->samples_clipped);
1527 update_status_string("%0.2f", new_framerate, displayed_framerate,
1529 if( new_position >= 0 ) {
1531 gui->update_title(gui->position_title, new_position);
1532 gui->update_labels(new_position);
1535 if( window_locked ) {
1536 gui->unlock_window();
1543 void RecordGUI::start_flash_batch()
1545 if( batch_flash ) return;
1546 batch_flash = new RecordGUIFlash(this);
1549 void RecordGUI::stop_flash_batch()
1551 if( !batch_flash ) return;
1556 void RecordGUI::flash_batch()
1558 lock_window("void RecordGUI::flash_batch");
1559 int cur_batch = record->current_batch();
1560 if( cur_batch >= 0 && cur_batch < batch_bay->count()) {
1561 flash_color = flash_color == GREEN ? RED : GREEN;
1562 //printf("RecordGUI::flash_batch %x\n", flash_color);
1563 batch_bay->set_row_color(cur_batch, flash_color);
1564 batch_bay->update_batch_news(cur_batch);
1570 RecordGUIFlash(RecordGUI *record_gui)
1573 this->record_gui = record_gui;
1574 flash_lock = new Condition(0,"RecordGUIFlash::flash_lock");
1582 if( Thread::running() ) {
1584 flash_lock->unlock();
1591 void RecordGUIFlash::run()
1594 record_gui->flash_batch();
1603 RecordGUIDCOffset::RecordGUIDCOffset(MWindow *mwindow, int y)
1604 : BC_Button(xS(230), y, mwindow->theme->calibrate_data)
1608 RecordGUIDCOffset::~RecordGUIDCOffset() {}
1610 int RecordGUIDCOffset::handle_event()
1615 int RecordGUIDCOffset::keypress_event() { return 0; }
1617 RecordGUIDCOffsetText::RecordGUIDCOffsetText(char *text, int y, int number)
1618 : BC_TextBox(xS(30), y+yS(1), xS(67), 1, text, 0)
1620 this->number = number;
1623 RecordGUIDCOffsetText::~RecordGUIDCOffsetText()
1627 int RecordGUIDCOffsetText::handle_event()
1632 RecordGUIReset::RecordGUIReset(MWindow *mwindow, RecordGUI *gui, int y)
1633 : BC_Button(xS(400), y, mwindow->theme->over_button)
1634 { this->gui = gui; }
1636 RecordGUIReset::~RecordGUIReset()
1640 int RecordGUIReset::handle_event()
1645 RecordGUIResetTranslation::RecordGUIResetTranslation(MWindow *mwindow, RecordGUI *gui, int y)
1646 : BC_Button(xS(250), y, mwindow->theme->reset_data)
1651 RecordGUIResetTranslation::~RecordGUIResetTranslation()
1655 int RecordGUIResetTranslation::handle_event()
1657 gui->set_translation(0, 0, 1);