1f5b392153591117e63353d3d4bf7d82a8680768
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / recordgui.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008-2017 Adam Williams <broadcast at earthling dot net>
5  *
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.
10  *
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.
15  *
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
19  *
20  */
21
22 #include "asset.h"
23 #include "batch.h"
24 #include "bcsignals.h"
25 #include "browsebutton.h"
26 #include "channel.h"
27 #include "channelpicker.h"
28 #include "clip.h"
29 #include "condition.h"
30 #include "bchash.h"
31 #include "edl.h"
32 #include "edlsession.h"
33 #include "file.h"
34 #include "filesystem.h"
35 #include "keys.h"
36 #include "language.h"
37 #include "loadmode.h"
38 #include "meterpanel.h"
39 #include "mutex.h"
40 #include "mwindow.h"
41 #include "mwindowgui.h"
42 #include "preferences.h"
43 #include "question.h"
44 #include "recconfirmdelete.h"
45 #include "recordgui.h"
46 #include "record.h"
47 #include "recordlabel.h"
48 #include "recordmonitor.h"
49 #include "recordtransport.h"
50 #include "recordvideo.h"
51 #include "mainsession.h"
52 #include "theme.h"
53 #include "units.h"
54 #include "videodevice.h"
55
56 #include <time.h>
57
58
59
60
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)
66 {
67         this->mwindow = mwindow;
68         this->record = record;
69
70         current_operation = 0;
71         position_title = 0;
72         prev_label_title = 0;
73         frames_behind = 0;
74         frames_dropped = 0;
75         framerate = 0;
76         samples_clipped = 0;
77         cron_status = 0;
78         batch_bay = 0;
79         batch_path = 0;
80         status_thread = 0;
81         batch_start = 0;
82         batch_duration = 0;
83         record_transport = 0;
84         batch_browse = 0;
85         batch_source = 0;
86         batch_mode = 0;
87         new_batch = 0;
88         delete_batch = 0;
89         start_batches = 0;
90         stop_batches = 0;
91         activate_batch = 0;
92         label_button = 0;
93         drop_frames = 0;
94         fill_frames = 0;
95         monitor_video = 0;
96         monitor_audio = 0;
97         meter_audio = 0;
98         batch_flash = 0;
99         startover_thread = 0;
100         interrupt_thread = 0;
101         load_mode = 0;
102         flash_color = 0;
103         loop_hr = 0;
104         loop_min = 0;
105         loop_sec = 0;
106         reset = 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;
111                 meter[i] = 0;
112         }
113         total_dropped_frames = 0;
114         total_clipped_samples = 0;
115 }
116
117 RecordGUI::~RecordGUI()
118 {
119         delete status_thread;
120         delete record_transport;
121         delete batch_source;
122         delete batch_mode;
123         delete batch_flash;
124         delete startover_thread;
125         delete interrupt_thread;
126         delete batch_start;
127         delete batch_duration;
128         delete load_mode;
129 }
130
131
132 void RecordGUI::create_objects()
133 {
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];
137         flash_color = RED;
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"));
143
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);
147
148         int x = xs10;
149         int y = ys10;
150         int x1 = 0;
151         BC_Title *title;
152         int pad = max(BC_TextBox::calculate_h(this, MEDIUMFONT, 1, 1),
153                 BC_Title::calculate_h(this, "X")) + ys5;
154         int button_y = 0;
155
156 // Current batch
157         add_subwindow(title = new BC_Title(x, y, _("Path:")));
158         x1 = max(title->get_w(), x1);
159         y += pad;
160         add_subwindow(title = new BC_Title(x, y, _("Start time:")));
161         x1 = max(title->get_w(), x1);
162         y += pad;
163         add_subwindow(title = new BC_Title(x, y, _("Duration time:")));
164         x1 = max(title->get_w(), x1);
165         y += pad;
166         add_subwindow(title = new BC_Title(x, y, _("Source:")));
167         x1 = max(title->get_w(), x1);
168         y += pad;
169         add_subwindow(title = new BC_Title(x, y, _("Mode:")));
170         x1 = max(title->get_w(), x1);
171         y += pad;
172         add_subwindow(title = new BC_Title(x, y, _("Transport:")));
173         x1 = max(title->get_w(), x1);
174         y += pad;
175
176         button_y = max(y, button_y);
177
178
179
180         int x2 = 0;
181         y = ys10;
182         x = x1 + xs20;
183         add_subwindow(batch_path = new RecordPath(this, x, y));
184         add_subwindow(batch_browse = new BrowseButton(mwindow->theme,
185                 this,
186                 batch_path,
187                 batch_path->get_x() + batch_path->get_w(),
188                 y,
189                 asset->path,
190                 _(PROGRAM_NAME ": Record path"),
191                 _("Select a file to record to:"),
192                 0));
193         x2 = max(x2, batch_path->get_w() + batch_browse->get_w());
194         y += pad;
195         batch_start = new RecordStart(this, x, y);
196         batch_start->create_objects();
197         x2 = max(x2, batch_start->get_w());
198         y += pad;
199         batch_duration = new RecordDuration(this, x, y);
200         batch_duration->create_objects();
201         x2 = max(x2, batch_duration->get_w());
202         y += pad;
203         batch_source = new RecordSource(this, x, y);
204         batch_source->create_objects();
205         x2 = max(x2, batch_source->get_w());
206         y += pad;
207         batch_mode = new RecordGUIModeMenu(this, x, y, xS(200), "");
208         batch_mode->create_objects();
209         x2 = max(x2, batch_mode->get_w());
210         y += pad;
211         record_transport = new RecordTransport(mwindow,
212                 record, this, x, y);
213         record_transport->create_objects();
214         x2 = max(x2, record_transport->get_w());
215
216
217
218
219 // Compression settings
220         x = x2 + x1 + xs30;
221         y = ys10;
222         int x3 = 0;
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);
226         y += pad;
227
228         if(asset->audio_data)
229         {
230                 add_subwindow(title = new BC_Title(x, y, _("Audio compression:")));
231                 x3 = max(title->get_w(), x3);
232                 y += pad;
233                 add_subwindow(title = new BC_Title(x, y, _("Samplerate:")));
234                 x3 = max(title->get_w(), x3);
235                 y += pad;
236                 add_subwindow(title = new BC_Title(x, y, _("Clipped samples:")));
237                 x3 = max(title->get_w(), x3);
238                 y += pad;
239         }
240
241         if(asset->video_data)
242         {
243                 add_subwindow(title = new BC_Title(x, y, _("Video compression:")));
244                 x3 = max(title->get_w(), x3);
245                 y += pad;
246                 add_subwindow(title = new BC_Title(x, y, _("Framerate:")));
247                 x3 = max(title->get_w(), x3);
248                 y += pad;
249                 add_subwindow(title = new BC_Title(x, y, _("Frames dropped:")));
250                 x3 = max(title->get_w(), x3);
251                 y += pad;
252                 add_subwindow(title = new BC_Title(x, y, _("Frames behind:")));
253                 x3 = max(title->get_w(), x3);
254                 y += pad;
255         }
256
257         add_subwindow(title = new BC_Title(x, y, _("Position:")));
258         x3 = max(title->get_w(), x3);
259         y += pad;
260         add_subwindow(title = new BC_Title(x, y, _("Prev label:")));
261         x3 = max(title->get_w(), x3);
262         y += pad;
263
264         button_y = max(y, button_y);
265         y = ys10;
266         x = x3 + x2 + x1 + xS(40);
267
268         add_subwindow(new BC_Title(x, y,
269                 File::formattostr(asset->format),
270                 MEDIUMFONT,
271                 mwindow->theme->recordgui_fixed_color));
272         y += pad;
273
274         if(asset->audio_data) {
275                 add_subwindow(new BC_Title(x, y,
276                         File::bitstostr(asset->bits),
277                         MEDIUMFONT,
278                         mwindow->theme->recordgui_fixed_color));
279
280                 y += pad;
281                 sprintf(string, "%d", asset->sample_rate);
282                 add_subwindow(new BC_Title(x, y,
283                         string, MEDIUMFONT,
284                         mwindow->theme->recordgui_fixed_color));
285
286                 y += pad;
287                 add_subwindow(samples_clipped = new BC_Title(x, y,
288                         "0", MEDIUMFONT,
289                         mwindow->theme->recordgui_variable_color));
290                 y += pad;
291         }
292
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),
297                         MEDIUMFONT,
298                         mwindow->theme->recordgui_fixed_color));
299
300                 y += pad;
301                 sprintf(string, "%0.2f", asset->frame_rate);
302                 add_subwindow(framerate = new BC_Title(x, y,
303                         string, MEDIUMFONT,
304                         mwindow->theme->recordgui_fixed_color));
305
306                 y += pad;
307                 add_subwindow(frames_dropped = new BC_Title(x, y,
308                         "0", MEDIUMFONT,
309                         mwindow->theme->recordgui_variable_color));
310                 y += pad;
311                 add_subwindow(frames_behind = new BC_Title(x, y,
312                         "0", MEDIUMFONT,
313                         mwindow->theme->recordgui_variable_color));
314                 y += pad;
315         }
316
317         add_subwindow(position_title = new BC_Title(x, y,
318                 "", MEDIUMFONT,
319                 mwindow->theme->recordgui_variable_color));
320
321         y += pad;
322         add_subwindow(prev_label_title = new BC_Title(x, y,
323                 _("None"), MEDIUMFONT,
324                 mwindow->theme->recordgui_variable_color));
325
326         y += pad + ys10;
327         button_y = max(y, button_y);
328
329 // Buttons
330         x = xs10;
331         y = button_y;
332
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());
347
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());
361
362         x = x1 = xs10;
363         y = y_max + pad;
364         y1 = y + pad + ys5;
365
366         fill_frames = 0;
367         monitor_video = 0;
368         monitor_audio = 0;
369         meter_audio = 0;
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;
376         }
377
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;
383         }
384
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
389 // Batches
390         x = xs10;
391         y += ys5;
392         if( fill_frames )
393                 y = y1 + fill_frames->get_h();
394         else if( monitor_audio )
395                 y += monitor_audio->get_h();
396
397         int bottom_margin = max(BC_OKButton::calculate_h(),
398                 LoadMode::calculate_h(this, mwindow->theme)) + ys5;
399
400
401         add_subwindow(batch_bay = new RecordGUIBatches(this, x, y,
402                 get_w() - xs20, get_h() - y - bottom_margin - ys10));
403         y += batch_bay->get_h() + ys5;
404         record->record_batches.gui = batch_bay;
405         batch_bay->update_batches(-1);
406
407 // Controls
408         int loadmode_w = LoadMode::calculate_w(this, mwindow->theme);
409         load_mode = new LoadMode(mwindow, this,
410                 get_w() / 2 - loadmode_w / 2, y, &record->load_mode);
411         load_mode->create_objects();
412         y += load_mode->get_h() + ys5;
413
414         add_subwindow(new RecordGUIOK(this));
415
416         interrupt_thread = new EndRecordThread(this);
417 //      add_subwindow(new RecordGUISave(record, this));
418         add_subwindow(new RecordGUICancel(this));
419
420         startover_thread = new RecordStartoverThread(this);
421
422         enable_batch_buttons();
423         if( batch_mode->value == RECORD_TIMED )
424                 batch_duration->enable();
425         else
426                 batch_duration->disable();
427         unlock_window();
428 }
429
430 void RecordGUI::update_batches()
431 {
432         lock_window("void RecordGUI::Update_batches");
433         batch_bay->update_batches();
434         unlock_window();
435 }
436
437
438 Batch *RecordGUI::get_current_batch()
439 {
440         return record->get_editing_batch();
441 }
442
443 Batch *RecordGUI::get_editing_batch()
444 {
445         return record->get_editing_batch();
446 }
447
448 void RecordGUI::update_batch_sources()
449 {
450 //printf("RecordGUI::update_batch_sources 1\n");
451         ChannelPicker *channel_picker =
452                 record->record_monitor->window->channel_picker;
453         if(channel_picker)
454                 batch_source->update_list(&channel_picker->channel_listitems);
455 //printf("RecordGUI::update_batch_sources 2\n");
456 }
457
458 int RecordGUI::translation_event()
459 {
460         mwindow->session->rwindow_x = get_x();
461         mwindow->session->rwindow_y = get_y();
462         return 0;
463 }
464
465
466 int RecordGUI::resize_event(int w, int h)
467 {
468         int xs20 = xS(20), ys10 = yS(10);
469 // Recompute batch list based on previous extents
470         int bottom_margin = mwindow->session->rwindow_h -
471                 batch_bay->get_y() -
472                 batch_bay->get_h();
473         int mode_margin = mwindow->session->rwindow_h - load_mode->get_y();
474         mwindow->session->rwindow_x = get_x();
475         mwindow->session->rwindow_y = get_y();
476         mwindow->session->rwindow_w = w;
477         mwindow->session->rwindow_h = h;
478         mwindow->theme->get_recordgui_sizes(this, w, h);
479         mwindow->theme->draw_rwindow_bg(this);
480
481         int new_h = mwindow->session->rwindow_h - bottom_margin - batch_bay->get_y();
482         if(new_h < ys10) new_h = ys10;
483         batch_bay->reposition_window(batch_bay->get_x(),
484                 batch_bay->get_y(),
485                 mwindow->session->rwindow_w - xs20,
486                 mwindow->session->rwindow_h - bottom_margin - batch_bay->get_y());
487
488         load_mode->reposition_window(mwindow->session->rwindow_w / 2 -
489                         mwindow->theme->loadmode_w / 2,
490                 mwindow->session->rwindow_h - mode_margin);
491
492         flash();
493         return 1;
494 }
495
496 void RecordGUI::update_batch_tools()
497 {
498         lock_window("RecordGUI::update_batch_tools");
499 //printf("RecordGUI::update_batch_tools 1\n");
500         Batch *batch = get_editing_batch();
501         batch_path->update(batch->asset->path);
502
503 // File is open in editing batch
504 //      if(current_batch() == editing_batch() && record->file)
505 //              batch_path->disable();
506 //      else
507 //              batch_path->enable();
508
509         batch_start->update(&batch->start_day, &batch->start_time);
510         batch_duration->update(0, &batch->duration);
511         batch_source->update(batch->get_source_text());
512         batch_mode->update(batch->record_mode);
513         if( batch_mode->value == RECORD_TIMED )
514                 batch_duration->enable();
515         else
516                 batch_duration->disable();
517         flush();
518         unlock_window();
519 }
520
521 void RecordGUI::enable_batch_buttons()
522 {
523         lock_window("RecordGUI::enable_batch_buttons");
524         new_batch->enable();
525         delete_batch->enable();
526         start_batches->enable();
527         stop_batches->disable();
528         activate_batch->enable();
529         unlock_window();
530 }
531
532 void RecordGUI::disable_batch_buttons()
533 {
534         lock_window("RecordGUI::disable_batch_buttons");
535         new_batch->disable();
536         delete_batch->disable();
537         start_batches->disable();
538         stop_batches->enable();
539         activate_batch->disable();
540         unlock_window();
541 }
542
543 RecordGUIBatches::RecordGUIBatches(RecordGUI *gui, int x, int y, int w, int h)
544  : RecordBatchesGUI(gui->record->record_batches, x, y, w, h)
545 {
546         this->gui = gui;
547 }
548
549 // Do nothing for double clicks to protect active batch
550 int RecordGUIBatches::handle_event()
551 {
552         return 1;
553 }
554
555 int RecordGUIBatches::selection_changed()
556 {
557         RecordBatchesGUI::selection_changed();
558         gui->update_batch_tools();
559         return 1;
560 }
561
562
563 RecordGUISave::RecordGUISave(RecordGUI *gui)
564  : BC_Button(xS(10),
565         gui->get_h() - BC_WindowBase::get_resources()->ok_images[0]->get_h() - yS(10),
566         BC_WindowBase::get_resources()->ok_images)
567 {
568         set_tooltip(_("Save the recording and quit."));
569         this->gui = gui;
570 }
571
572 int RecordGUISave::handle_event()
573 {
574         gui->set_done(0);
575         return 1;
576 }
577
578 int RecordGUISave::keypress_event()
579 {
580 //      if(get_keypress() == RETURN)
581 //      {
582 //              handle_event();
583 //              return 1;
584 //      }
585         return 0;
586 }
587
588 RecordGUICancel::RecordGUICancel(RecordGUI *gui)
589  : BC_CancelButton(gui)
590 {
591         set_tooltip(_("Quit without pasting into project."));
592         this->gui = gui;
593 }
594
595 int RecordGUICancel::handle_event()
596 {
597         gui->interrupt_thread->start(0);
598         return 1;
599 }
600
601 int RecordGUICancel::keypress_event()
602 {
603         if(get_keypress() == ESC)
604         {
605                 handle_event();
606                 return 1;
607         }
608
609         return 0;
610 }
611
612
613 RecordGUIOK::RecordGUIOK(RecordGUI *gui)
614  : BC_OKButton(gui)
615 {
616         set_tooltip(_("Quit and paste into project."));
617         this->gui = gui;
618 }
619
620 int RecordGUIOK::handle_event()
621 {
622         gui->interrupt_thread->start(1);
623         return 1;
624 }
625
626
627 RecordGUIStartOver::RecordGUIStartOver(RecordGUI *gui, int x, int y)
628  : BC_GenericButton(x, y, _("Start Over"))
629 {
630         set_tooltip(_("Rewind the current file and erase."));
631         this->gui = gui;
632 }
633 RecordGUIStartOver::~RecordGUIStartOver()
634 {
635 }
636
637 int RecordGUIStartOver::handle_event()
638 {
639         if(!gui->startover_thread->running())
640                 gui->startover_thread->start();
641         return 1;
642 }
643
644
645 RecordGUIDropFrames::RecordGUIDropFrames(RecordGUI *gui, int x, int y)
646  : BC_CheckBox(x, y, gui->record->drop_overrun_frames, _("drop overrun frames"))
647 {
648         this->set_underline(0);
649         this->gui = gui;
650         set_tooltip(_("Drop input frames when behind."));
651 }
652
653 int RecordGUIDropFrames::handle_event()
654 {
655         gui->record->drop_overrun_frames = get_value();
656         return 1;
657 }
658
659 int RecordGUIDropFrames::keypress_event()
660 {
661         if( get_keypress() == caption[0] ) {
662                 set_value(get_value() ? 0 : 1);
663                 handle_event();
664                 return 1;
665         }
666         return 0;
667 }
668
669 RecordGUIFillFrames::RecordGUIFillFrames(RecordGUI *gui, int x, int y)
670  : BC_CheckBox(x, y, gui->record->fill_underrun_frames, _("fill underrun frames"))
671 {
672         this->set_underline(0);
673         this->gui = gui;
674         set_tooltip(_("Write extra frames when behind."));
675 }
676
677 int RecordGUIFillFrames::handle_event()
678 {
679         gui->record->fill_underrun_frames = get_value();
680         return 1;
681 }
682
683 int RecordGUIFillFrames::keypress_event()
684 {
685         if( get_keypress() == caption[0] ) {
686                 set_value(get_value() ? 0 : 1);
687                 handle_event();
688                 return 1;
689         }
690         return 0;
691 }
692
693 RecordGUIPowerOff::RecordGUIPowerOff(RecordGUI *gui, int x, int y)
694  : BC_CheckBox(x, y, gui->record->power_off, _("poweroff when done"))
695 {
696         this->set_underline(0);
697         this->gui = gui;
698         set_tooltip(_("poweroff system when batch record done."));
699 }
700
701 int RecordGUIPowerOff::handle_event()
702 {
703         gui->record->power_off = get_value();
704         return 1;
705 }
706
707 int RecordGUIPowerOff::keypress_event()
708 {
709         if( get_keypress() == caption[0] ) {
710                 set_value(get_value() ? 0 : 1);
711                 handle_event();
712                 return 1;
713         }
714         return 0;
715 }
716
717
718 RecordGUICommCheck::RecordGUICommCheck(RecordGUI *gui, int x, int y)
719  : BC_CheckBox(x, y, gui->record->commercial_check, _("check for ads"))
720 {
721         this->set_underline(0);
722         this->gui = gui;
723         set_tooltip(_("check for commercials."));
724 }
725
726 int RecordGUICommCheck::handle_event()
727 {
728         gui->record->update_skimming(get_value());
729         return 1;
730 }
731
732
733 int RecordGUICommCheck::keypress_event()
734 {
735         if( get_keypress() == caption[0] ) {
736                 set_value(get_value() ? 0 : 1);
737                 gui->record->update_skimming(get_value());
738                 handle_event();
739                 return 1;
740         }
741         return 0;
742 }
743
744
745 RecordGUIMonitorVideo::RecordGUIMonitorVideo(RecordGUI *gui, int x, int y)
746  : BC_CheckBox(x, y, gui->record->monitor_video, _("Monitor video"))
747 {
748         this->set_underline(8);
749         this->gui = gui;
750 }
751
752 int RecordGUIMonitorVideo::handle_event()
753 {
754 // Video capture constitutively, just like audio, but only flash on screen if 1
755         int mode = get_value();
756         Record *record = gui->record;
757         record->set_video_monitoring(mode);
758         if(record->monitor_video) {
759                 unlock_window();
760                 BC_Window *window = record->record_monitor->window;
761                 window->lock_window("RecordGUIMonitorVideo::handle_event");
762                 window->show_window();
763                 window->raise_window();
764                 window->flush();
765                 window->unlock_window();
766                 lock_window("RecordGUIMonitorVideo::handle_event");
767                 record->video_window_open = 1;
768         }
769         return 1;
770 }
771
772
773 int RecordGUIMonitorVideo::keypress_event()
774 {
775         if(get_keypress() == 'v') {
776                 set_value(get_value() ? 0 : 1);
777                 handle_event();
778                 return 1;
779         }
780         return 0;
781 }
782
783
784
785 RecordGUIMonitorAudio::RecordGUIMonitorAudio(RecordGUI *gui, int x, int y)
786  : BC_CheckBox(x, y, gui->record->monitor_audio, _("Monitor audio"))
787 {
788         this->set_underline(8);
789         this->gui = gui;
790 }
791
792 int RecordGUIMonitorAudio::handle_event()
793 {
794         int mode = get_value();
795         Record *record = gui->record;
796         record->set_audio_monitoring(mode);
797         if(record->monitor_audio) {
798                 unlock_window();
799                 BC_Window *window = record->record_monitor->window;
800                 window->lock_window("RecordGUIMonitorAudio::handle_event");
801                 window->show_window();
802                 window->raise_window();
803                 window->flush();
804                 window->unlock_window();
805                 lock_window("RecordGUIMonitorAudio::handle_event");
806                 record->video_window_open = 1;
807         }
808         return 1;
809 }
810
811 int RecordGUIMonitorAudio::keypress_event()
812 {
813         if(get_keypress() == 'a') {
814                 set_value(get_value() ? 0 : 1);
815                 handle_event();
816                 return 1;
817         }
818         return 0;
819 }
820
821
822 RecordGUIAudioMeters::RecordGUIAudioMeters(RecordGUI *gui, int x, int y)
823  : BC_CheckBox(x, y, gui->record->metering_audio, _("Audio meters"))
824 {
825         this->set_underline(6);
826         this->gui = gui;
827 }
828
829 int RecordGUIAudioMeters::handle_event()
830 {
831         int mode = get_value();
832         Record *record = gui->record;
833         record->set_audio_metering(mode);
834         if(record->metering_audio) {
835                 unlock_window();
836                 BC_Window *window = record->record_monitor->window;
837                 window->lock_window("RecordGUIAudioMeters::handle_event");
838                 window->show_window();
839                 window->raise_window();
840                 window->flush();
841                 window->unlock_window();
842                 lock_window("RecordGUIAudioMeters::handle_event");
843                 record->video_window_open = 1;
844         }
845         return 1;
846 }
847
848 int RecordGUIAudioMeters::keypress_event()
849 {
850         if(get_keypress() == 'm') {
851                 set_value(get_value() ? 0 : 1);
852                 handle_event();
853                 return 1;
854         }
855         return 0;
856 }
857
858 RecordPath::RecordPath(RecordGUI *gui, int x, int y)
859  : RecordBatchesGUI::Path(gui->record->record_batches, x, y)
860 {
861         this->gui = gui;
862 }
863
864 int RecordPath::handle_event()
865 {
866         return RecordBatchesGUI::Path::handle_event();
867 }
868
869
870 RecordStart::RecordStart(RecordGUI *gui, int x, int y)
871  : RecordBatchesGUI::StartTime(gui, gui->record->record_batches, x, y)
872 {
873         this->gui = gui;
874 }
875
876 int RecordStart::handle_event()
877 {
878         return RecordBatchesGUI::StartTime::handle_event();
879 }
880
881 RecordDuration::RecordDuration(RecordGUI *gui, int x, int y)
882  : RecordBatchesGUI::Duration(gui, gui->record->record_batches, x, y)
883 {
884         this->gui = gui;
885 }
886
887 int RecordDuration::handle_event()
888 {
889         return RecordBatchesGUI::Duration::handle_event();
890 }
891
892
893 RecordSource::RecordSource(RecordGUI *gui, int x, int y)
894  : RecordBatchesGUI::Source(gui, gui->record->record_batches, x, y)
895 {
896         this->gui = gui;
897 }
898
899 int RecordSource::handle_event()
900 {
901         gui->record->set_batch_channel_no(get_number());
902         return RecordBatchesGUI::Source::handle_event();
903 }
904
905
906 RecordNews::RecordNews(RecordGUI *gui, int x, int y)
907  : RecordBatchesGUI::News(gui->record->record_batches, x, y)
908 {
909         this->gui = gui;
910 }
911
912 int RecordNews::handle_event()
913 {
914         return RecordBatchesGUI::News::handle_event();
915 }
916
917
918 RecordGUINewBatch::RecordGUINewBatch(RecordGUI *gui, int x, int y)
919  : RecordBatchesGUI::NewBatch(gui->record->record_batches, x, y)
920 {
921         this->gui = gui;
922         set_tooltip(_("Create new clip."));
923 }
924 int RecordGUINewBatch::handle_event()
925 {
926         gui->record->new_batch();
927         return RecordBatchesGUI::NewBatch::handle_event();
928 }
929
930
931 RecordGUIDeleteBatch::RecordGUIDeleteBatch(RecordGUI *gui, int x, int y)
932  : RecordBatchesGUI::DeleteBatch(gui->record->record_batches, x, y)
933 {
934         this->gui = gui;
935         set_tooltip(_("Delete clip."));
936 }
937
938 int RecordGUIDeleteBatch::handle_event()
939 {
940         gui->record->delete_batch();
941         return RecordBatchesGUI::DeleteBatch::handle_event();
942 }
943
944
945 RecordGUIStartBatches::RecordGUIStartBatches(RecordGUI *gui, int x, int y)
946  : RecordBatchesGUI::StartBatches(gui->record->record_batches, x, y)
947 {
948         this->gui = gui;
949         set_tooltip(_("Start batch recording\nfrom the current position."));
950 }
951
952 int RecordGUIStartBatches::handle_event()
953 {
954         Record *record = gui->record;
955         record->start_cron_thread();
956         return RecordBatchesGUI::StartBatches::handle_event();
957 }
958
959
960 RecordGUIStopBatches::RecordGUIStopBatches(RecordGUI *gui, int x, int y)
961  : RecordBatchesGUI::StopBatches(gui->record->record_batches, x, y)
962 {
963         this->gui = gui;
964 }
965
966 int RecordGUIStopBatches::handle_event()
967 {
968         Record *record = gui->record;
969         unlock_window();
970         record->stop_cron_thread(_("Stopped"));
971         lock_window();
972         return RecordBatchesGUI::StopBatches::handle_event();
973 }
974
975
976 RecordGUIActivateBatch::RecordGUIActivateBatch(RecordGUI *gui, int x, int y)
977  : RecordBatchesGUI::ActivateBatch(gui->record->record_batches, x, y)
978 {
979         this->gui = gui;
980         set_tooltip(_("Make the highlighted\nclip active."));
981 }
982 int RecordGUIActivateBatch::handle_event()
983 {
984         gui->record->activate_batch(gui->record->editing_batch());
985         gui->update_cron_status(_("Idle"));
986         return RecordBatchesGUI::ActivateBatch::handle_event();
987 }
988
989
990 RecordGUILabel::RecordGUILabel(RecordGUI *gui, int x, int y)
991  : BC_GenericButton(x, y, _("Label"))
992 {
993         this->gui = gui;
994         set_underline(0);
995 }
996
997
998 RecordGUILabel::~RecordGUILabel()
999 {
1000 }
1001
1002 int RecordGUILabel::handle_event()
1003 {
1004         gui->record->toggle_label();
1005         return 1;
1006 }
1007
1008 int RecordGUILabel::keypress_event()
1009 {
1010         if( get_keypress() == *get_text() ) {
1011                 handle_event();
1012                 return 1;
1013         }
1014         return 0;
1015 }
1016
1017
1018 RecordGUIClearLabels::RecordGUIClearLabels(RecordGUI *gui, int x, int y)
1019  : BC_GenericButton(x, y, _("ClrLbls"))
1020 {
1021         this->gui = gui;
1022 }
1023
1024
1025 RecordGUIClearLabels::~RecordGUIClearLabels()
1026 {
1027 }
1028
1029 int RecordGUIClearLabels::handle_event()
1030 {
1031         gui->record->clear_labels();
1032         return 1;
1033 }
1034
1035
1036 EndRecordThread::EndRecordThread(RecordGUI *gui)
1037  : Thread(1, 0, 0)
1038 {
1039         this->gui = gui;
1040         is_ok = 0;
1041 }
1042
1043 EndRecordThread::~EndRecordThread()
1044 {
1045         if(Thread::running()) {
1046                 window->lock_window("EndRecordThread::~EndRecordThread");
1047                 window->set_done(1);
1048                 window->unlock_window();
1049         }
1050         Thread::join();
1051 }
1052
1053 void EndRecordThread::start(int is_ok)
1054 {
1055         this->is_ok = is_ok;
1056         if( gui->record->writing_file ) {
1057                 if(!running())
1058                         Thread::start();
1059         }
1060         else {
1061                 gui->set_done(!is_ok);
1062         }
1063 }
1064
1065 void EndRecordThread::run()
1066 {
1067         window = new QuestionWindow(gui->record->mwindow);
1068         window->create_objects(_("Interrupt recording in progress?"), 0);
1069         int result = window->run_window();
1070         delete window;
1071         if(result == 2) gui->set_done(!is_ok);
1072 }
1073
1074
1075 RecordStartoverThread::RecordStartoverThread(RecordGUI *gui)
1076  : Thread(1, 0, 0)
1077 {
1078         this->gui = gui;
1079 }
1080 RecordStartoverThread::~RecordStartoverThread()
1081 {
1082         if(Thread::running()) {
1083                 window->lock_window("RecordStartoverThread::~RecordStartoverThread");
1084                 window->set_done(1);
1085                 window->unlock_window();
1086         }
1087         Thread::join();
1088 }
1089
1090 void RecordStartoverThread::run()
1091 {
1092         Record *record = gui->record;
1093         window = new QuestionWindow(record->mwindow);
1094         window->create_objects(_("Rewind batch and overwrite?"), 0);
1095         int result = window->run_window();
1096         if(result == 2) record->start_over();
1097         delete window;
1098 }
1099
1100
1101 int RecordGUI::set_translation(int x, int y, float z)
1102 {
1103         record->video_x = x;
1104         record->video_y = y;
1105         record->video_zoom = z;
1106         return 0;
1107 }
1108
1109 void RecordGUI::reset_video()
1110 {
1111         total_dropped_frames = 0;
1112         status_thread->reset_video();
1113         update_framerate(record->default_asset->frame_rate);
1114 }
1115
1116 void RecordGUI::update_dropped_frames(long value)
1117 {
1118         status_thread->update_dropped_frames(value);
1119 }
1120
1121 void RecordGUI::update_frames_behind(long value)
1122 {
1123         status_thread->update_frames_behind(value);
1124 }
1125
1126 void RecordGUI::update_position(double value)
1127 {
1128         status_thread->update_position(value);
1129 }
1130
1131 void RecordGUI::update_framerate(double value)
1132 {
1133         status_thread->update_framerate(value);
1134 }
1135
1136 void RecordGUI::update_video(int dropped, int behind)
1137 {
1138         total_dropped_frames += dropped;
1139         update_dropped_frames(total_dropped_frames);
1140         update_frames_behind(behind);
1141         status_thread->update_position(record->current_display_position());
1142 }
1143
1144 void RecordGUI::reset_audio()
1145 {
1146 //      gui->lock_window("RecordAudio::run 2");
1147 // reset meter
1148         total_clipped_samples = 0;
1149         status_thread->reset_audio();
1150         AudioDevice *adevice = record->adevice;
1151         RecordMonitorGUI *window = record->record_monitor->window;
1152         window->lock_window("RecordAudio::run 2");
1153         MeterPanel *meters = window->meters;
1154         if( meters ) {
1155                 int dmix = adevice && (adevice->get_idmix() || adevice->get_odmix());
1156                 meters->init_meters(dmix);
1157         }
1158         window->unlock_window();
1159 //      gui->unlock_window();
1160 }
1161
1162 void RecordGUI::update_clipped_samples(long value)
1163 {
1164         status_thread->update_clipped_samples(value);
1165 }
1166
1167 void RecordGUI::update_audio(int channels, double *max, int *over)
1168 {
1169 // Get clipping status
1170         int clipped = 0;
1171         for( int ch=0; ch<channels && !clipped; ++ch )
1172                 if( over[ch] ) clipped = 1;
1173         if( clipped ) {
1174                 update_clipped_samples(++total_clipped_samples);
1175         }
1176 // Update meters if monitoring
1177         if( record->metering_audio ) {
1178                 RecordMonitorGUI *window = record->record_monitor->window;
1179                 window->lock_window("RecordAudio::run 1");
1180                 MeterPanel *meters = window->meters;
1181                 int nmeters = meters->meters.total;
1182                 for( int ch=0; ch<nmeters; ++ch ) {
1183                         double vmax = ch < channels ? max[ch] : 0.;
1184                         int   vover = ch < channels ? over[ch] : 0;
1185                         meters->meters.values[ch]->update(vmax, vover);
1186                 }
1187                 window->unlock_window();
1188         }
1189 // update position, if no video
1190         if( !record->default_asset->video_data )
1191                 update_position(record->current_display_position());
1192 }
1193
1194
1195 int RecordGUI::keypress_event()
1196 {
1197         return record_transport->keypress_event();
1198 }
1199
1200 void RecordGUI::update_labels(double new_position)
1201 {
1202         RecordLabel *prev, *next;
1203
1204         for(prev = record->get_current_batch()->labels->last;
1205                 prev;
1206                 prev = prev->previous) {
1207                 if(prev->position <= new_position) break;
1208         }
1209
1210         for(next = record->get_current_batch()->labels->first;
1211                 next;
1212                 next = next->next)
1213         {
1214                 if(next->position > new_position) break;
1215         }
1216
1217         if(prev)
1218                 update_title(prev_label_title, prev->position);
1219         else
1220                 update_title(prev_label_title, -1);
1221
1222 //      if(next)
1223 //              update_title(next_label_title, (double)next->position / record->default_asset->sample_rate);
1224 //      else
1225 //              update_title(next_label_title, -1);
1226 }
1227
1228
1229 int RecordGUI::update_prev_label(long new_position)
1230 {
1231         update_title(prev_label_title, new_position);
1232         return 0;
1233 }
1234
1235 // int RecordGUI::update_next_label(long new_position)
1236 // {
1237 //      update_title(next_label_title, new_position);
1238 // }
1239 //
1240 int RecordGUI::update_title(BC_Title *title, double position)
1241 {
1242         static char string[256];
1243
1244         if(position >= 0) {
1245                 Units::totext(string,
1246                                 position,
1247                                 mwindow->edl->session->time_format,
1248                                 record->default_asset->sample_rate,
1249                                 record->default_asset->frame_rate,
1250                                 mwindow->edl->session->frames_per_foot);
1251         }
1252         else {
1253                 sprintf(string, "-");
1254         }
1255         title->update(string);
1256         return 0;
1257 }
1258
1259
1260 void RecordGUI::update_cron_status(const char *status)
1261 {
1262         lock_window("RecordGUI::update_cron_status");
1263         cron_status->update(status);
1264         unlock_window();
1265 }
1266
1267 void RecordGUI::update_power_off(int value)
1268 {
1269         lock_window("RecordGUI::update_power_off");
1270         power_off->update(value);
1271         unlock_window();
1272 }
1273
1274
1275
1276
1277 // ===================================== GUI
1278 // ================================================== modes
1279
1280 RecordGUIModeTextBox::RecordGUIModeTextBox(RecordGUIModeMenu *mode_menu,
1281                 int x, int y, int w,const char *text)
1282  : BC_TextBox(x, y, w, 1, text)
1283 {
1284         this->mode_menu = mode_menu;
1285 }
1286
1287 RecordGUIModeTextBox::~RecordGUIModeTextBox()
1288 {
1289 }
1290
1291 int RecordGUIModeTextBox::handle_event()
1292 {
1293         return 0;
1294 }
1295
1296 RecordGUIModeListBox::RecordGUIModeListBox(RecordGUIModeMenu *mode_menu)
1297  : BC_ListBox(mode_menu->textbox->get_x() + mode_menu->textbox->get_w(),
1298                 mode_menu->textbox->get_y(), xS(100), yS(50), LISTBOX_TEXT,
1299                 &mode_menu->modes, 0, 0, 1, 0, 1)
1300 {
1301         this->mode_menu = mode_menu;
1302 }
1303
1304 RecordGUIModeListBox::~RecordGUIModeListBox()
1305 {
1306 }
1307
1308 int RecordGUIModeListBox::handle_event()
1309 {
1310         return mode_menu->handle_event();
1311 }
1312
1313 RecordGUIModeMenu::RecordGUIModeMenu(RecordGUI *record_gui,
1314                 int x, int y, int w,const char *text)
1315 {
1316         this->record_gui = record_gui;
1317         textbox = new RecordGUIModeTextBox(this,x, y, w, "");
1318         record_gui->add_subwindow(textbox);
1319         listbox = new RecordGUIModeListBox(this);
1320         record_gui->add_subwindow(listbox);
1321 }
1322
1323 RecordGUIModeMenu::~RecordGUIModeMenu()
1324 {
1325         for( int i=0; i<modes.total; ++i )
1326                 delete modes.values[i];
1327         delete listbox;
1328         delete textbox;
1329 }
1330
1331 void RecordGUIModeMenu::create_objects()
1332 {
1333         value = RECORD_UNTIMED;
1334         modes.append(new BC_ListBoxItem(Batch::mode_to_text(RECORD_UNTIMED)));
1335         modes.append(new BC_ListBoxItem(Batch::mode_to_text(RECORD_TIMED)));
1336         textbox->update(modes.values[value]->get_text());
1337 }
1338
1339 int RecordGUIModeMenu::handle_event()
1340 {
1341         value = listbox->get_selection_number(0, 0);
1342         textbox->update(modes.values[value]->get_text());
1343         textbox->handle_event();
1344         record_gui->record->set_record_mode(value);
1345         if( value == RECORD_TIMED )
1346                 record_gui->batch_duration->enable();
1347         else
1348                 record_gui->batch_duration->disable();
1349         return 0;
1350 }
1351
1352 void RecordGUIModeMenu::update(int value)
1353 {
1354         this->value = value;
1355         textbox->update(modes.values[value]->get_text());
1356 }
1357
1358 int RecordGUIModeMenu::get_w()
1359 {
1360         return textbox->get_w() + listbox->get_w();
1361 }
1362
1363 int RecordGUIModeMenu::get_h()
1364 {
1365         return MAX(textbox->get_h(), listbox->get_h());
1366 }
1367
1368
1369 RecordStatusThread::RecordStatusThread(MWindow *mwindow, RecordGUI *gui)
1370  : Thread(1, 0, 0)
1371 {
1372         this->mwindow = mwindow;
1373         this->gui = gui;
1374         input_lock = new Condition(0, "RecordStatusThread::input_lock");
1375         reset_video();
1376         reset_audio();
1377         window_locked = 0;
1378         done = 0;
1379 }
1380
1381 RecordStatusThread::~RecordStatusThread()
1382 {
1383         if(Thread::running())
1384         {
1385                 done = 1;
1386                 input_lock->unlock();
1387         }
1388         Thread::join();
1389         delete input_lock;
1390 }
1391
1392 void RecordStatusThread::reset_video()
1393 {
1394         new_dropped_frames = 0;
1395         displayed_dropped_frames = -1;
1396         new_frames_behind = 0;
1397         displayed_frames_behind = -1;
1398         new_position = 0;
1399         displayed_framerate = -1.;
1400         new_framerate = 0.;
1401 }
1402
1403 void RecordStatusThread::reset_audio()
1404 {
1405         new_clipped_samples = 0;
1406         displayed_clipped_samples = -1;
1407 }
1408
1409 void RecordStatusThread::update_frames_behind(long value)
1410 {
1411         if( value != displayed_frames_behind ) {
1412                 new_frames_behind = value;
1413                 input_lock->unlock();
1414         }
1415 }
1416
1417 void RecordStatusThread::update_dropped_frames(long value)
1418 {
1419         if( value != displayed_dropped_frames ) {
1420                 new_dropped_frames = value;
1421                 input_lock->unlock();
1422         }
1423 }
1424
1425 void RecordStatusThread::update_clipped_samples(long value)
1426 {
1427         if( value != displayed_clipped_samples ) {
1428                 new_clipped_samples = value;
1429                 input_lock->unlock();
1430         }
1431 }
1432
1433 void RecordStatusThread::update_position(double value)
1434 {
1435         this->new_position = value;
1436         input_lock->unlock();
1437 }
1438
1439 void RecordStatusThread::update_framerate(double value)
1440 {
1441         if( value != displayed_framerate ) {
1442                 new_framerate = value;
1443                 input_lock->unlock();
1444         }
1445 }
1446
1447 void RecordStatusThread::get_window_lock()
1448 {
1449         if( !window_locked ) {
1450                 gui->lock_window("RecordStatusThread::run 1");
1451                 window_locked = 1;
1452         }
1453 }
1454
1455 template<class T>
1456 void RecordStatusThread::
1457 update_status_string(const char *fmt, T &new_value, T &displayed_value, BC_Title *widgit)
1458 {
1459         if( new_value >= 0 ) {
1460                 if( displayed_value != new_value ) {
1461                         displayed_value = new_value;
1462                         if( widgit ) {
1463                                 char string[64];
1464                                 sprintf(string, fmt, displayed_value);
1465                                 get_window_lock();
1466                                 widgit->update(string);
1467                         }
1468                 }
1469                 new_value = -1;
1470         }
1471 }
1472
1473 void RecordStatusThread::run()
1474 {
1475         while(!done) {
1476                 input_lock->lock("RecordStatusThread::run");
1477                 if(done) break;
1478                 update_status_string("%d", new_dropped_frames, displayed_dropped_frames,
1479                                         gui->frames_dropped);
1480                 update_status_string("%d", new_frames_behind, displayed_frames_behind,
1481                                         gui->frames_behind);
1482                 update_status_string("%d", new_clipped_samples, displayed_clipped_samples,
1483                                         gui->samples_clipped);
1484                 update_status_string("%0.2f", new_framerate, displayed_framerate,
1485                                         gui->framerate);
1486                 if( new_position >= 0 ) {
1487                         get_window_lock();
1488                         gui->update_title(gui->position_title, new_position);
1489                         gui->update_labels(new_position);
1490                         new_position = -1;
1491                 }
1492                 if( window_locked ) {
1493                         gui->unlock_window();
1494                         window_locked = 0;
1495                 }
1496         }
1497 }
1498
1499
1500 void RecordGUI::start_flash_batch()
1501 {
1502         if( batch_flash ) return;
1503         batch_flash = new RecordGUIFlash(this);
1504 }
1505
1506 void RecordGUI::stop_flash_batch()
1507 {
1508         if( !batch_flash ) return;
1509         delete batch_flash;
1510         batch_flash = 0;
1511 }
1512
1513 void RecordGUI::flash_batch()
1514 {
1515         lock_window("void RecordGUI::flash_batch");
1516         int cur_batch = record->current_batch();
1517         if( cur_batch >= 0 && cur_batch < batch_bay->count()) {
1518                 flash_color = flash_color == GREEN ? RED : GREEN;
1519 //printf("RecordGUI::flash_batch %x\n", flash_color);
1520                 batch_bay->set_row_color(cur_batch, flash_color);
1521                 batch_bay->update_batch_news(cur_batch);
1522         }
1523         unlock_window();
1524 }
1525
1526 RecordGUIFlash::
1527 RecordGUIFlash(RecordGUI *record_gui)
1528  : Thread(1, 0, 0)
1529 {
1530         this->record_gui = record_gui;
1531         flash_lock = new Condition(0,"RecordGUIFlash::flash_lock");
1532         done = 0;
1533         Thread::start();
1534 }
1535
1536 RecordGUIFlash::
1537 ~RecordGUIFlash()
1538 {
1539         if( Thread::running() ) {
1540                 done = 1;
1541                 flash_lock->unlock();
1542                 Thread::cancel();
1543         }
1544         Thread::join();
1545         delete flash_lock;
1546 }
1547
1548 void RecordGUIFlash::run()
1549 {
1550         while( !done ) {
1551                 record_gui->flash_batch();
1552                 enable_cancel();
1553                 Timer::delay(500);
1554                 disable_cancel();
1555         }
1556 }
1557
1558
1559
1560 RecordGUIDCOffset::RecordGUIDCOffset(MWindow *mwindow, int y)
1561  : BC_Button(xS(230), y, mwindow->theme->calibrate_data)
1562 {
1563 }
1564
1565 RecordGUIDCOffset::~RecordGUIDCOffset() {}
1566
1567 int RecordGUIDCOffset::handle_event()
1568 {
1569         return 1;
1570 }
1571
1572 int RecordGUIDCOffset::keypress_event() { return 0; }
1573
1574 RecordGUIDCOffsetText::RecordGUIDCOffsetText(char *text, int y, int number)
1575  : BC_TextBox(xS(30), y+yS(1), xS(67), 1, text, 0)
1576 {
1577         this->number = number;
1578 }
1579
1580 RecordGUIDCOffsetText::~RecordGUIDCOffsetText()
1581 {
1582 }
1583
1584 int RecordGUIDCOffsetText::handle_event()
1585 {
1586         return 1;
1587 }
1588
1589 RecordGUIReset::RecordGUIReset(MWindow *mwindow, RecordGUI *gui, int y)
1590  : BC_Button(xS(400), y, mwindow->theme->over_button)
1591 { this->gui = gui; }
1592
1593 RecordGUIReset::~RecordGUIReset()
1594 {
1595 }
1596
1597 int RecordGUIReset::handle_event()
1598 {
1599         return 1;
1600 }
1601
1602 RecordGUIResetTranslation::RecordGUIResetTranslation(MWindow *mwindow, RecordGUI *gui, int y)
1603  : BC_Button(xS(250), y, mwindow->theme->reset_data)
1604 {
1605         this->gui = gui;
1606 }
1607
1608 RecordGUIResetTranslation::~RecordGUIResetTranslation()
1609 {
1610 }
1611
1612 int RecordGUIResetTranslation::handle_event()
1613 {
1614         gui->set_translation(0, 0, 1);
1615         return 1;
1616 }
1617