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;
814 BC_Window *window = record->record_monitor->window;
815 window->lock_window("RecordGUIMonitorVideo::handle_event");
816 window->hide_window();
818 window->unlock_window();
819 lock_window("RecordGUIMonitorVideo::handle_event");
820 record->video_window_open = 0;
826 int RecordGUIMonitorVideo::keypress_event()
828 if(get_keypress() == 'v') {
829 set_value(get_value() ? 0 : 1);
838 RecordGUIMonitorAudio::RecordGUIMonitorAudio(RecordGUI *gui, int x, int y)
839 : BC_CheckBox(x, y, gui->record->monitor_audio, _("Monitor audio"))
841 this->set_underline(8);
845 int RecordGUIMonitorAudio::handle_event()
847 int mode = get_value();
848 Record *record = gui->record;
849 record->set_audio_monitoring(mode);
850 if(record->monitor_audio) {
852 BC_Window *window = record->record_monitor->window;
853 window->lock_window("RecordGUIMonitorAudio::handle_event");
854 window->show_window();
855 window->raise_window();
857 window->unlock_window();
858 lock_window("RecordGUIMonitorAudio::handle_event");
859 record->video_window_open = 1;
864 int RecordGUIMonitorAudio::keypress_event()
866 if(get_keypress() == 'a') {
867 set_value(get_value() ? 0 : 1);
875 RecordGUIAudioMeters::RecordGUIAudioMeters(RecordGUI *gui, int x, int y)
876 : BC_CheckBox(x, y, gui->record->metering_audio, _("Audio meters"))
878 this->set_underline(6);
882 int RecordGUIAudioMeters::handle_event()
884 int mode = get_value();
885 Record *record = gui->record;
886 record->set_audio_metering(mode);
887 if(record->metering_audio) {
889 BC_Window *window = record->record_monitor->window;
890 window->lock_window("RecordGUIAudioMeters::handle_event");
891 window->show_window();
892 window->raise_window();
894 window->unlock_window();
895 lock_window("RecordGUIAudioMeters::handle_event");
896 record->video_window_open = 1;
901 int RecordGUIAudioMeters::keypress_event()
903 if(get_keypress() == 'm') {
904 set_value(get_value() ? 0 : 1);
911 RecordPath::RecordPath(RecordGUI *gui, int x, int y)
912 : RecordBatchesGUI::Path(gui->record->record_batches, x, y)
917 int RecordPath::handle_event()
919 return RecordBatchesGUI::Path::handle_event();
923 RecordStart::RecordStart(RecordGUI *gui, int x, int y)
924 : RecordBatchesGUI::StartTime(gui, gui->record->record_batches, x, y)
929 int RecordStart::handle_event()
931 return RecordBatchesGUI::StartTime::handle_event();
934 RecordDuration::RecordDuration(RecordGUI *gui, int x, int y)
935 : RecordBatchesGUI::Duration(gui, gui->record->record_batches, x, y)
940 int RecordDuration::handle_event()
942 return RecordBatchesGUI::Duration::handle_event();
946 RecordSource::RecordSource(RecordGUI *gui, int x, int y)
947 : RecordBatchesGUI::Source(gui, gui->record->record_batches, x, y)
952 int RecordSource::handle_event()
954 gui->record->set_batch_channel_no(get_number());
955 return RecordBatchesGUI::Source::handle_event();
959 RecordNews::RecordNews(RecordGUI *gui, int x, int y)
960 : RecordBatchesGUI::News(gui->record->record_batches, x, y)
965 int RecordNews::handle_event()
967 return RecordBatchesGUI::News::handle_event();
971 RecordGUINewBatch::RecordGUINewBatch(RecordGUI *gui, int x, int y)
972 : RecordBatchesGUI::NewBatch(gui->record->record_batches, x, y)
975 set_tooltip(_("Create new clip."));
977 int RecordGUINewBatch::handle_event()
979 gui->record->new_batch();
980 return RecordBatchesGUI::NewBatch::handle_event();
984 RecordGUIDeleteBatch::RecordGUIDeleteBatch(RecordGUI *gui, int x, int y)
985 : RecordBatchesGUI::DeleteBatch(gui->record->record_batches, x, y)
988 set_tooltip(_("Delete clip."));
991 int RecordGUIDeleteBatch::handle_event()
993 gui->record->delete_batch();
994 return RecordBatchesGUI::DeleteBatch::handle_event();
998 RecordGUIStartBatches::RecordGUIStartBatches(RecordGUI *gui, int x, int y)
999 : RecordBatchesGUI::StartBatches(gui->record->record_batches, x, y)
1002 set_tooltip(_("Start batch recording\nfrom the current position."));
1005 int RecordGUIStartBatches::handle_event()
1007 Record *record = gui->record;
1008 record->start_cron_thread();
1009 return RecordBatchesGUI::StartBatches::handle_event();
1013 RecordGUIStopBatches::RecordGUIStopBatches(RecordGUI *gui, int x, int y)
1014 : RecordBatchesGUI::StopBatches(gui->record->record_batches, x, y)
1019 int RecordGUIStopBatches::handle_event()
1021 Record *record = gui->record;
1023 record->stop_cron_thread(_("Stopped"));
1025 return RecordBatchesGUI::StopBatches::handle_event();
1029 RecordGUIActivateBatch::RecordGUIActivateBatch(RecordGUI *gui, int x, int y)
1030 : RecordBatchesGUI::ActivateBatch(gui->record->record_batches, x, y)
1033 set_tooltip(_("Make the highlighted\nclip active."));
1035 int RecordGUIActivateBatch::handle_event()
1037 gui->record->activate_batch(gui->record->editing_batch());
1038 gui->update_cron_status(_("Idle"));
1039 return RecordBatchesGUI::ActivateBatch::handle_event();
1043 RecordGUILabel::RecordGUILabel(RecordGUI *gui, int x, int y)
1044 : BC_GenericButton(x, y, _("Label"))
1051 RecordGUILabel::~RecordGUILabel()
1055 int RecordGUILabel::handle_event()
1057 gui->record->toggle_label();
1061 int RecordGUILabel::keypress_event()
1063 if( get_keypress() == *get_text() ) {
1071 RecordGUIClearLabels::RecordGUIClearLabels(RecordGUI *gui, int x, int y)
1072 : BC_GenericButton(x, y, _("ClrLbls"))
1078 RecordGUIClearLabels::~RecordGUIClearLabels()
1082 int RecordGUIClearLabels::handle_event()
1084 gui->record->clear_labels();
1089 EndRecordThread::EndRecordThread(RecordGUI *gui)
1096 EndRecordThread::~EndRecordThread()
1098 if(Thread::running()) {
1099 window->lock_window("EndRecordThread::~EndRecordThread");
1100 window->set_done(1);
1101 window->unlock_window();
1106 void EndRecordThread::start(int is_ok)
1108 this->is_ok = is_ok;
1109 if( gui->record->writing_file ) {
1114 gui->set_done(!is_ok);
1118 void EndRecordThread::run()
1120 window = new QuestionWindow(gui->record->mwindow);
1121 window->create_objects(_("Interrupt recording in progress?"), 0);
1122 int result = window->run_window();
1124 if(result == 2) gui->set_done(!is_ok);
1128 RecordStartoverThread::RecordStartoverThread(RecordGUI *gui)
1133 RecordStartoverThread::~RecordStartoverThread()
1135 if(Thread::running()) {
1136 window->lock_window("RecordStartoverThread::~RecordStartoverThread");
1137 window->set_done(1);
1138 window->unlock_window();
1143 void RecordStartoverThread::run()
1145 Record *record = gui->record;
1146 window = new QuestionWindow(record->mwindow);
1147 window->create_objects(_("Rewind batch and overwrite?"), 0);
1148 int result = window->run_window();
1149 if(result == 2) record->start_over();
1154 int RecordGUI::set_translation(int x, int y, float z)
1156 record->video_x = x;
1157 record->video_y = y;
1158 record->video_zoom = z;
1162 void RecordGUI::reset_video()
1164 total_dropped_frames = 0;
1165 status_thread->reset_video();
1166 update_framerate(record->default_asset->frame_rate);
1169 void RecordGUI::update_dropped_frames(long value)
1171 status_thread->update_dropped_frames(value);
1174 void RecordGUI::update_frames_behind(long value)
1176 status_thread->update_frames_behind(value);
1179 void RecordGUI::update_position(double value)
1181 status_thread->update_position(value);
1184 void RecordGUI::update_framerate(double value)
1186 status_thread->update_framerate(value);
1189 void RecordGUI::update_video(int dropped, int behind)
1191 total_dropped_frames += dropped;
1192 update_dropped_frames(total_dropped_frames);
1193 update_frames_behind(behind);
1194 status_thread->update_position(record->current_display_position());
1197 void RecordGUI::reset_audio()
1199 // gui->lock_window("RecordAudio::run 2");
1201 total_clipped_samples = 0;
1202 status_thread->reset_audio();
1203 AudioDevice *adevice = record->adevice;
1204 RecordMonitorGUI *window = record->record_monitor->window;
1205 window->lock_window("RecordAudio::run 2");
1206 MeterPanel *meters = window->meters;
1208 int dmix = adevice && (adevice->get_idmix() || adevice->get_odmix());
1209 meters->init_meters(dmix);
1211 window->unlock_window();
1212 // gui->unlock_window();
1215 void RecordGUI::update_clipped_samples(long value)
1217 status_thread->update_clipped_samples(value);
1220 void RecordGUI::update_audio(int channels, double *max, int *over)
1222 // Get clipping status
1224 for( int ch=0; ch<channels && !clipped; ++ch )
1225 if( over[ch] ) clipped = 1;
1227 update_clipped_samples(++total_clipped_samples);
1229 // Update meters if monitoring
1230 if( record->metering_audio ) {
1231 RecordMonitorGUI *window = record->record_monitor->window;
1232 window->lock_window("RecordAudio::run 1");
1233 MeterPanel *meters = window->meters;
1234 int nmeters = meters->meters.total;
1235 for( int ch=0; ch<nmeters; ++ch ) {
1236 double vmax = ch < channels ? max[ch] : 0.;
1237 int vover = ch < channels ? over[ch] : 0;
1238 meters->meters.values[ch]->update(vmax, vover);
1240 window->unlock_window();
1242 // update position, if no video
1243 if( !record->default_asset->video_data )
1244 update_position(record->current_display_position());
1248 int RecordGUI::keypress_event()
1250 return record_transport->keypress_event();
1253 void RecordGUI::update_labels(double new_position)
1255 RecordLabel *prev, *next;
1257 for(prev = record->get_current_batch()->labels->last;
1259 prev = prev->previous) {
1260 if(prev->position <= new_position) break;
1263 for(next = record->get_current_batch()->labels->first;
1267 if(next->position > new_position) break;
1271 update_title(prev_label_title, prev->position);
1273 update_title(prev_label_title, -1);
1276 // update_title(next_label_title, (double)next->position / record->default_asset->sample_rate);
1278 // update_title(next_label_title, -1);
1282 int RecordGUI::update_prev_label(long new_position)
1284 update_title(prev_label_title, new_position);
1288 // int RecordGUI::update_next_label(long new_position)
1290 // update_title(next_label_title, new_position);
1293 int RecordGUI::update_title(BC_Title *title, double position)
1295 static char string[256];
1298 Units::totext(string,
1300 mwindow->edl->session->time_format,
1301 record->default_asset->sample_rate,
1302 record->default_asset->frame_rate,
1303 mwindow->edl->session->frames_per_foot);
1306 sprintf(string, "-");
1308 title->update(string);
1313 void RecordGUI::update_cron_status(const char *status)
1315 lock_window("RecordGUI::update_cron_status");
1316 cron_status->update(status);
1320 void RecordGUI::update_power_off(int value)
1322 lock_window("RecordGUI::update_power_off");
1323 power_off->update(value);
1330 // ===================================== GUI
1331 // ================================================== modes
1333 RecordGUIModeTextBox::RecordGUIModeTextBox(RecordGUIModeMenu *mode_menu,
1334 int x, int y, int w,const char *text)
1335 : BC_TextBox(x, y, w, 1, text)
1337 this->mode_menu = mode_menu;
1340 RecordGUIModeTextBox::~RecordGUIModeTextBox()
1344 int RecordGUIModeTextBox::handle_event()
1349 RecordGUIModeListBox::RecordGUIModeListBox(RecordGUIModeMenu *mode_menu)
1350 : BC_ListBox(mode_menu->textbox->get_x() + mode_menu->textbox->get_w(),
1351 mode_menu->textbox->get_y(), xS(100), yS(50), LISTBOX_TEXT,
1352 &mode_menu->modes, 0, 0, 1, 0, 1)
1354 this->mode_menu = mode_menu;
1357 RecordGUIModeListBox::~RecordGUIModeListBox()
1361 int RecordGUIModeListBox::handle_event()
1363 return mode_menu->handle_event();
1366 RecordGUIModeMenu::RecordGUIModeMenu(RecordGUI *record_gui,
1367 int x, int y, int w,const char *text)
1369 this->record_gui = record_gui;
1370 textbox = new RecordGUIModeTextBox(this,x, y, w, "");
1371 record_gui->add_subwindow(textbox);
1372 listbox = new RecordGUIModeListBox(this);
1373 record_gui->add_subwindow(listbox);
1376 RecordGUIModeMenu::~RecordGUIModeMenu()
1378 for( int i=0; i<modes.total; ++i )
1379 delete modes.values[i];
1384 void RecordGUIModeMenu::create_objects()
1386 value = RECORD_UNTIMED;
1387 modes.append(new BC_ListBoxItem(Batch::mode_to_text(RECORD_UNTIMED)));
1388 modes.append(new BC_ListBoxItem(Batch::mode_to_text(RECORD_TIMED)));
1389 textbox->update(modes.values[value]->get_text());
1392 int RecordGUIModeMenu::handle_event()
1394 value = listbox->get_selection_number(0, 0);
1395 textbox->update(modes.values[value]->get_text());
1396 textbox->handle_event();
1397 record_gui->record->set_record_mode(value);
1398 if( value == RECORD_TIMED )
1399 record_gui->batch_duration->enable();
1401 record_gui->batch_duration->disable();
1405 void RecordGUIModeMenu::update(int value)
1407 this->value = value;
1408 textbox->update(modes.values[value]->get_text());
1411 int RecordGUIModeMenu::get_w()
1413 return textbox->get_w() + listbox->get_w();
1416 int RecordGUIModeMenu::get_h()
1418 return MAX(textbox->get_h(), listbox->get_h());
1422 RecordStatusThread::RecordStatusThread(MWindow *mwindow, RecordGUI *gui)
1425 this->mwindow = mwindow;
1427 input_lock = new Condition(0, "RecordStatusThread::input_lock");
1434 RecordStatusThread::~RecordStatusThread()
1436 if(Thread::running())
1439 input_lock->unlock();
1445 void RecordStatusThread::reset_video()
1447 new_dropped_frames = 0;
1448 displayed_dropped_frames = -1;
1449 new_frames_behind = 0;
1450 displayed_frames_behind = -1;
1452 displayed_framerate = -1.;
1456 void RecordStatusThread::reset_audio()
1458 new_clipped_samples = 0;
1459 displayed_clipped_samples = -1;
1462 void RecordStatusThread::update_frames_behind(long value)
1464 if( value != displayed_frames_behind ) {
1465 new_frames_behind = value;
1466 input_lock->unlock();
1470 void RecordStatusThread::update_dropped_frames(long value)
1472 if( value != displayed_dropped_frames ) {
1473 new_dropped_frames = value;
1474 input_lock->unlock();
1478 void RecordStatusThread::update_clipped_samples(long value)
1480 if( value != displayed_clipped_samples ) {
1481 new_clipped_samples = value;
1482 input_lock->unlock();
1486 void RecordStatusThread::update_position(double value)
1488 this->new_position = value;
1489 input_lock->unlock();
1492 void RecordStatusThread::update_framerate(double value)
1494 if( value != displayed_framerate ) {
1495 new_framerate = value;
1496 input_lock->unlock();
1500 void RecordStatusThread::get_window_lock()
1502 if( !window_locked ) {
1503 gui->lock_window("RecordStatusThread::run 1");
1509 void RecordStatusThread::
1510 update_status_string(const char *fmt, T &new_value, T &displayed_value, BC_Title *widgit)
1512 if( new_value >= 0 ) {
1513 if( displayed_value != new_value ) {
1514 displayed_value = new_value;
1517 sprintf(string, fmt, displayed_value);
1519 widgit->update(string);
1526 void RecordStatusThread::run()
1529 input_lock->lock("RecordStatusThread::run");
1531 update_status_string("%d", new_dropped_frames, displayed_dropped_frames,
1532 gui->frames_dropped);
1533 update_status_string("%d", new_frames_behind, displayed_frames_behind,
1534 gui->frames_behind);
1535 update_status_string("%d", new_clipped_samples, displayed_clipped_samples,
1536 gui->samples_clipped);
1537 update_status_string("%0.2f", new_framerate, displayed_framerate,
1539 if( new_position >= 0 ) {
1541 gui->update_title(gui->position_title, new_position);
1542 gui->update_labels(new_position);
1545 if( window_locked ) {
1546 gui->unlock_window();
1553 void RecordGUI::start_flash_batch()
1555 if( batch_flash ) return;
1556 batch_flash = new RecordGUIFlash(this);
1559 void RecordGUI::stop_flash_batch()
1561 if( !batch_flash ) return;
1566 void RecordGUI::flash_batch()
1568 lock_window("void RecordGUI::flash_batch");
1569 int cur_batch = record->current_batch();
1570 if( cur_batch >= 0 && cur_batch < batch_bay->count()) {
1571 flash_color = flash_color == GREEN ? RED : GREEN;
1572 //printf("RecordGUI::flash_batch %x\n", flash_color);
1573 batch_bay->set_row_color(cur_batch, flash_color);
1574 batch_bay->update_batch_news(cur_batch);
1580 RecordGUIFlash(RecordGUI *record_gui)
1583 this->record_gui = record_gui;
1584 flash_lock = new Condition(0,"RecordGUIFlash::flash_lock");
1592 if( Thread::running() ) {
1594 flash_lock->unlock();
1601 void RecordGUIFlash::run()
1604 record_gui->flash_batch();
1613 RecordGUIDCOffset::RecordGUIDCOffset(MWindow *mwindow, int y)
1614 : BC_Button(xS(230), y, mwindow->theme->calibrate_data)
1618 RecordGUIDCOffset::~RecordGUIDCOffset() {}
1620 int RecordGUIDCOffset::handle_event()
1625 int RecordGUIDCOffset::keypress_event() { return 0; }
1627 RecordGUIDCOffsetText::RecordGUIDCOffsetText(char *text, int y, int number)
1628 : BC_TextBox(xS(30), y+yS(1), xS(67), 1, text, 0)
1630 this->number = number;
1633 RecordGUIDCOffsetText::~RecordGUIDCOffsetText()
1637 int RecordGUIDCOffsetText::handle_event()
1642 RecordGUIReset::RecordGUIReset(MWindow *mwindow, RecordGUI *gui, int y)
1643 : BC_Button(xS(400), y, mwindow->theme->over_button)
1644 { this->gui = gui; }
1646 RecordGUIReset::~RecordGUIReset()
1650 int RecordGUIReset::handle_event()
1655 RecordGUIResetTranslation::RecordGUIResetTranslation(MWindow *mwindow, RecordGUI *gui, int y)
1656 : BC_Button(xS(250), y, mwindow->theme->reset_data)
1661 RecordGUIResetTranslation::~RecordGUIResetTranslation()
1665 int RecordGUIResetTranslation::handle_event()
1667 gui->set_translation(0, 0, 1);