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