remove old quicktime, replaced with current ffmpeg
[goodguy/history.git] / cinelerra-5.0 / 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, 1, 0);
408         load_mode = new LoadMode(mwindow, this, 
409                 get_w() / 2 - loadmode_w / 2, y, 
410                 &record->load_mode, 1, 0);
411         load_mode->create_objects();
412         y += load_mode->get_h() + 5;
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 // Recompute batch list based on previous extents
469         int bottom_margin = mwindow->session->rwindow_h - 
470                 batch_bay->get_y() - 
471                 batch_bay->get_h();
472         int mode_margin = mwindow->session->rwindow_h - load_mode->get_y();
473         mwindow->session->rwindow_x = get_x();
474         mwindow->session->rwindow_y = get_y();
475         mwindow->session->rwindow_w = w;
476         mwindow->session->rwindow_h = h;
477         mwindow->theme->get_recordgui_sizes(this, w, h);
478         mwindow->theme->draw_rwindow_bg(this);
479
480         int new_h = mwindow->session->rwindow_h - bottom_margin - batch_bay->get_y();
481         if(new_h < 10) new_h = 10;
482         batch_bay->reposition_window(batch_bay->get_x(), 
483                 batch_bay->get_y(),
484                 mwindow->session->rwindow_w - 20,
485                 mwindow->session->rwindow_h - bottom_margin - batch_bay->get_y());
486
487         load_mode->reposition_window(mwindow->session->rwindow_w / 2 - 
488                         mwindow->theme->loadmode_w / 2,
489                 mwindow->session->rwindow_h - mode_margin);
490
491         flash();
492         return 1;
493 }
494
495 void RecordGUI::update_batch_tools()
496 {
497         lock_window("RecordGUI::update_batch_tools");
498 //printf("RecordGUI::update_batch_tools 1\n");
499         Batch *batch = get_editing_batch();
500         batch_path->update(batch->asset->path);
501
502 // File is open in editing batch
503 //      if(current_batch() == editing_batch() && record->file)
504 //              batch_path->disable();
505 //      else
506 //              batch_path->enable();
507
508         batch_start->update(&batch->start_day, &batch->start_time);
509         batch_duration->update(0, &batch->duration);
510         batch_source->update(batch->get_source_text());
511         batch_mode->update(batch->record_mode);
512         if( batch_mode->value == RECORD_TIMED )
513                 batch_duration->enable();
514         else
515                 batch_duration->disable();
516         flush();
517         unlock_window();
518 }
519
520 void RecordGUI::enable_batch_buttons()
521 {
522         lock_window("RecordGUI::enable_batch_buttons");
523         new_batch->enable();
524         delete_batch->enable();
525         start_batches->enable();
526         stop_batches->disable();
527         activate_batch->enable();
528         unlock_window();
529 }
530
531 void RecordGUI::disable_batch_buttons()
532 {
533         lock_window("RecordGUI::disable_batch_buttons");
534         new_batch->disable();
535         delete_batch->disable();
536         start_batches->disable();
537         stop_batches->enable();
538         activate_batch->disable();
539         unlock_window();
540 }
541
542 RecordGUIBatches::RecordGUIBatches(RecordGUI *gui, int x, int y, int w, int h)
543  : RecordBatchesGUI(gui->record->record_batches, x, y, w, h)
544 {
545         this->gui = gui;
546 }
547
548 // Do nothing for double clicks to protect active batch
549 int RecordGUIBatches::handle_event()
550 {
551         return 1;
552 }
553
554 int RecordGUIBatches::selection_changed()
555 {
556         RecordBatchesGUI::selection_changed();
557         gui->update_batch_tools();
558         return 1;
559 }
560
561
562 RecordGUISave::RecordGUISave(RecordGUI *gui)
563  : BC_Button(10, 
564         gui->get_h() - BC_WindowBase::get_resources()->ok_images[0]->get_h() - 10, 
565         BC_WindowBase::get_resources()->ok_images)
566 {
567         set_tooltip(_("Save the recording and quit."));
568         this->gui = gui;
569 }
570
571 int RecordGUISave::handle_event()
572 {
573         gui->set_done(0);
574         return 1;
575 }
576
577 int RecordGUISave::keypress_event()
578 {
579 //      if(get_keypress() == RETURN)
580 //      {
581 //              handle_event();
582 //              return 1;
583 //      }
584         return 0;
585 }
586
587 RecordGUICancel::RecordGUICancel(RecordGUI *gui)
588  : BC_CancelButton(gui)
589 {
590         set_tooltip(_("Quit without pasting into project."));
591         this->gui = gui;
592 }
593
594 int RecordGUICancel::handle_event()
595 {
596         gui->interrupt_thread->start(0);
597         return 1;
598 }
599
600 int RecordGUICancel::keypress_event()
601 {
602         if(get_keypress() == ESC)
603         {
604                 handle_event();
605                 return 1;
606         }
607
608         return 0;
609 }
610
611
612 RecordGUIOK::RecordGUIOK(RecordGUI *gui)
613  : BC_OKButton(gui)
614 {
615         set_tooltip(_("Quit and paste into project."));
616         this->gui = gui;
617 }
618
619 int RecordGUIOK::handle_event()
620 {
621         gui->interrupt_thread->start(1);
622         return 1;
623 }
624
625
626 RecordGUIStartOver::RecordGUIStartOver(RecordGUI *gui, int x, int y)
627  : BC_GenericButton(x, y, _("Start Over"))
628 {
629         set_tooltip(_("Rewind the current file and erase."));
630         this->gui = gui;
631 }
632 RecordGUIStartOver::~RecordGUIStartOver()
633 {
634 }
635
636 int RecordGUIStartOver::handle_event()
637 {
638         if(!gui->startover_thread->running())
639                 gui->startover_thread->start();
640         return 1;
641 }
642
643
644 RecordGUIDropFrames::RecordGUIDropFrames(RecordGUI *gui, int x, int y)
645  : BC_CheckBox(x, y, gui->record->drop_overrun_frames, _("drop overrun frames"))
646 {
647         this->set_underline(0);
648         this->gui = gui;
649         set_tooltip(_("Drop input frames when behind."));
650 }
651
652 int RecordGUIDropFrames::handle_event()
653 {
654         gui->record->drop_overrun_frames = get_value();
655         return 1;
656 }
657
658 int RecordGUIDropFrames::keypress_event()
659 {
660         if(get_keypress() == 'd') {
661                 set_value(get_value() ? 0 : 1);
662                 handle_event();
663                 return 1;
664         }
665         return 0;
666 }
667
668 RecordGUIFillFrames::RecordGUIFillFrames(RecordGUI *gui, int x, int y)
669  : BC_CheckBox(x, y, gui->record->fill_underrun_frames, _("fill underrun frames"))
670 {
671         this->set_underline(0);
672         this->gui = gui;
673         set_tooltip(_("Write extra frames when behind."));
674 }
675
676 int RecordGUIFillFrames::handle_event()
677 {
678         gui->record->fill_underrun_frames = get_value();
679         return 1;
680 }
681
682 int RecordGUIFillFrames::keypress_event()
683 {
684         if(get_keypress() == 'f') {
685                 set_value(get_value() ? 0 : 1);
686                 handle_event();
687                 return 1;
688         }
689         return 0;
690 }
691
692 RecordGUIPowerOff::RecordGUIPowerOff(RecordGUI *gui, int x, int y)
693  : BC_CheckBox(x, y, gui->record->power_off, _("poweroff when done"))
694 {
695         this->set_underline(0);
696         this->gui = gui;
697         set_tooltip(_("poweroff system when batch record done."));
698 }
699
700 int RecordGUIPowerOff::handle_event()
701 {
702         gui->record->power_off = get_value();
703         return 1;
704 }
705
706 int RecordGUIPowerOff::keypress_event()
707 {
708         if(get_keypress() == 'p') {
709                 set_value(get_value() ? 0 : 1);
710                 handle_event();
711                 return 1;
712         }
713         return 0;
714 }
715
716
717 RecordGUICommCheck::RecordGUICommCheck(RecordGUI *gui, int x, int y)
718  : BC_CheckBox(x, y, gui->record->commercial_check, _("check for ads"))
719 {
720         this->set_underline(0);
721         this->gui = gui;
722         set_tooltip(_("check for commercials."));
723 }
724
725 int RecordGUICommCheck::handle_event()
726 {
727         gui->record->update_skimming(get_value());
728         return 1;
729 }
730
731
732 int RecordGUICommCheck::keypress_event()
733 {
734         if(get_keypress() == 'c') {
735                 set_value(get_value() ? 0 : 1);
736                 gui->record->update_skimming(get_value());
737                 handle_event();
738                 return 1;
739         }
740         return 0;
741 }
742
743
744 RecordGUIMonitorVideo::RecordGUIMonitorVideo(RecordGUI *gui, int x, int y)
745  : BC_CheckBox(x, y, gui->record->monitor_video, _("Monitor video"))
746 {
747         this->set_underline(8);
748         this->gui = gui;
749 }
750
751 int RecordGUIMonitorVideo::handle_event()
752 {
753 // Video capture constitutively, just like audio, but only flash on screen if 1
754         int mode = get_value();
755         Record *record = gui->record;
756         record->set_video_monitoring(mode);
757         if(record->monitor_video) {
758                 unlock_window();
759                 BC_Window *window = record->record_monitor->window;
760                 window->lock_window("RecordGUIMonitorVideo::handle_event");
761                 window->show_window();
762                 window->raise_window();
763                 window->flush();
764                 window->unlock_window();
765                 lock_window("RecordGUIMonitorVideo::handle_event");
766                 record->video_window_open = 1;
767         }
768         return 1;
769 }
770
771
772 int RecordGUIMonitorVideo::keypress_event()
773 {
774         if(get_keypress() == 'v') {
775                 set_value(get_value() ? 0 : 1);
776                 handle_event();
777                 return 1;
778         }
779         return 0;
780 }
781
782
783
784 RecordGUIMonitorAudio::RecordGUIMonitorAudio(RecordGUI *gui, int x, int y)
785  : BC_CheckBox(x, y, gui->record->monitor_audio, _("Monitor audio"))
786 {
787         this->set_underline(8);
788         this->gui = gui;
789 }
790
791 int RecordGUIMonitorAudio::handle_event()
792 {
793         int mode = get_value();
794         Record *record = gui->record;
795         record->set_audio_monitoring(mode);
796         if(record->monitor_audio) {
797                 unlock_window();
798                 BC_Window *window = record->record_monitor->window;
799                 window->lock_window("RecordGUIMonitorAudio::handle_event");
800                 window->show_window();
801                 window->raise_window();
802                 window->flush();
803                 window->unlock_window();
804                 lock_window("RecordGUIMonitorAudio::handle_event");
805                 record->video_window_open = 1;
806         }
807         return 1;
808 }
809
810 int RecordGUIMonitorAudio::keypress_event()
811 {
812         if(get_keypress() == 'a') {
813                 set_value(get_value() ? 0 : 1);
814                 handle_event();
815                 return 1;
816         }
817         return 0;
818 }
819
820
821 RecordGUIAudioMeters::RecordGUIAudioMeters(RecordGUI *gui, int x, int y)
822  : BC_CheckBox(x, y, gui->record->metering_audio, _("Audio meters"))
823 {
824         this->set_underline(6);
825         this->gui = gui;
826 }
827
828 int RecordGUIAudioMeters::handle_event()
829 {
830         int mode = get_value();
831         Record *record = gui->record;
832         record->set_audio_metering(mode);
833         if(record->metering_audio) {
834                 unlock_window();
835                 BC_Window *window = record->record_monitor->window;
836                 window->lock_window("RecordGUIAudioMeters::handle_event");
837                 window->show_window();
838                 window->raise_window();
839                 window->flush();
840                 window->unlock_window();
841                 lock_window("RecordGUIAudioMeters::handle_event");
842                 record->video_window_open = 1;
843         }
844         return 1;
845 }
846
847 int RecordGUIAudioMeters::keypress_event()
848 {
849         if(get_keypress() == 'm') {
850                 set_value(get_value() ? 0 : 1);
851                 handle_event();
852                 return 1;
853         }
854         return 0;
855 }
856
857 RecordPath::RecordPath(RecordGUI *gui, int x, int y)
858  : RecordBatchesGUI::Path(gui->record->record_batches, x, y)
859 {
860         this->gui = gui;
861 }
862
863 int RecordPath::handle_event()
864 {
865         return RecordBatchesGUI::Path::handle_event();
866 }
867
868
869 RecordStart::RecordStart(RecordGUI *gui, int x, int y)
870  : RecordBatchesGUI::StartTime(gui, gui->record->record_batches, x, y)
871 {
872         this->gui = gui;
873 }
874
875 int RecordStart::handle_event()
876 {
877         return RecordBatchesGUI::StartTime::handle_event();
878 }
879
880 RecordDuration::RecordDuration(RecordGUI *gui, int x, int y)
881  : RecordBatchesGUI::Duration(gui, gui->record->record_batches, x, y)
882 {
883         this->gui = gui;
884 }
885
886 int RecordDuration::handle_event()
887 {
888         return RecordBatchesGUI::Duration::handle_event();
889 }
890
891
892 RecordSource::RecordSource(RecordGUI *gui, int x, int y)
893  : RecordBatchesGUI::Source(gui, gui->record->record_batches, x, y)
894 {
895         this->gui = gui;
896 }
897
898 int RecordSource::handle_event()
899 {
900         gui->record->set_batch_channel_no(get_number());
901         return RecordBatchesGUI::Source::handle_event();
902 }
903
904
905 RecordNews::RecordNews(RecordGUI *gui, int x, int y)
906  : RecordBatchesGUI::News(gui->record->record_batches, x, y)
907 {
908         this->gui = gui;
909 }
910
911 int RecordNews::handle_event()
912 {
913         return RecordBatchesGUI::News::handle_event();
914 }
915
916
917 RecordGUINewBatch::RecordGUINewBatch(RecordGUI *gui, int x, int y)
918  : RecordBatchesGUI::NewBatch(gui->record->record_batches, x, y)
919 {
920         this->gui = gui;
921         set_tooltip(_("Create new clip."));
922 }
923 int RecordGUINewBatch::handle_event()
924 {
925         gui->record->new_batch();
926         return RecordBatchesGUI::NewBatch::handle_event();
927 }
928
929
930 RecordGUIDeleteBatch::RecordGUIDeleteBatch(RecordGUI *gui, int x, int y)
931  : RecordBatchesGUI::DeleteBatch(gui->record->record_batches, x, y)
932 {
933         this->gui = gui;
934         set_tooltip(_("Delete clip."));
935 }
936
937 int RecordGUIDeleteBatch::handle_event()
938 {
939         gui->record->delete_batch();
940         return RecordBatchesGUI::DeleteBatch::handle_event();
941 }
942
943
944 RecordGUIStartBatches::RecordGUIStartBatches(RecordGUI *gui, int x, int y)
945  : RecordBatchesGUI::StartBatches(gui->record->record_batches, x, y)
946 {
947         this->gui = gui;
948         set_tooltip(_("Start batch recording\nfrom the current position."));
949 }
950
951 int RecordGUIStartBatches::handle_event()
952 {
953         Record *record = gui->record;
954         record->start_cron_thread();
955         return RecordBatchesGUI::StartBatches::handle_event();
956 }
957
958
959 RecordGUIStopBatches::RecordGUIStopBatches(RecordGUI *gui, int x, int y)
960  : RecordBatchesGUI::StopBatches(gui->record->record_batches, x, y)
961 {
962         this->gui = gui;
963 }
964
965 int RecordGUIStopBatches::handle_event()
966 {
967         Record *record = gui->record;
968         unlock_window();
969         record->stop_cron_thread(_("Stopped"));
970         lock_window();
971         return RecordBatchesGUI::StopBatches::handle_event();
972 }
973
974
975 RecordGUIActivateBatch::RecordGUIActivateBatch(RecordGUI *gui, int x, int y)
976  : RecordBatchesGUI::ActivateBatch(gui->record->record_batches, x, y)
977 {
978         this->gui = gui;
979         set_tooltip(_("Make the highlighted\nclip active."));
980 }
981 int RecordGUIActivateBatch::handle_event()
982 {
983         gui->record->activate_batch(gui->record->editing_batch());
984         gui->update_cron_status(_("Idle"));
985         return RecordBatchesGUI::ActivateBatch::handle_event();
986 }
987
988
989 RecordGUILabel::RecordGUILabel(RecordGUI *gui, int x, int y)
990  : BC_GenericButton(x, y, _("Label"))
991
992         this->gui = gui;
993         set_underline(0);
994 }
995
996
997 RecordGUILabel::~RecordGUILabel()
998 {
999 }
1000
1001 int RecordGUILabel::handle_event()
1002 {
1003         gui->record->toggle_label();
1004         return 1;
1005 }
1006
1007 int RecordGUILabel::keypress_event()
1008 {
1009         if(get_keypress() == 'l') {
1010                 handle_event();
1011                 return 1;
1012         }
1013         return 0;
1014 }
1015
1016
1017 RecordGUIClearLabels::RecordGUIClearLabels(RecordGUI *gui, int x, int y)
1018  : BC_GenericButton(x, y, _("ClrLbls"))
1019
1020         this->gui = gui;
1021 }
1022
1023
1024 RecordGUIClearLabels::~RecordGUIClearLabels()
1025 {
1026 }
1027
1028 int RecordGUIClearLabels::handle_event()
1029 {
1030         gui->record->clear_labels();
1031         return 1;
1032 }
1033
1034
1035 EndRecordThread::EndRecordThread(RecordGUI *gui)
1036  : Thread(1, 0, 0)
1037 {
1038         this->gui = gui;
1039         is_ok = 0;
1040 }
1041
1042 EndRecordThread::~EndRecordThread()
1043 {
1044         if(Thread::running()) {
1045                 window->lock_window("EndRecordThread::~EndRecordThread");
1046                 window->set_done(1);
1047                 window->unlock_window();
1048                 Thread::join();
1049         }
1050 }
1051
1052 void EndRecordThread::start(int is_ok)
1053 {
1054         this->is_ok = is_ok;
1055         if( gui->record->writing_file ) {
1056                 if(!running())          
1057                         Thread::start();
1058         }
1059         else {
1060                 gui->set_done(!is_ok);
1061         }
1062 }
1063
1064 void EndRecordThread::run()
1065 {
1066         window = new QuestionWindow(gui->record->mwindow);
1067         window->create_objects(_("Interrupt recording in progress?"), 0);
1068         int result = window->run_window();
1069         delete window;
1070         if(result == 2) gui->set_done(!is_ok);
1071 }
1072
1073
1074 RecordStartoverThread::RecordStartoverThread(RecordGUI *gui)
1075  : Thread(1, 0, 0)
1076 {
1077         this->gui = gui;
1078 }
1079 RecordStartoverThread::~RecordStartoverThread()
1080 {
1081         if(Thread::running()) {
1082                 window->lock_window("RecordStartoverThread::~RecordStartoverThread");
1083                 window->set_done(1);
1084                 window->unlock_window();
1085                 Thread::join();
1086         }
1087 }
1088
1089 void RecordStartoverThread::run()
1090 {
1091         Record *record = gui->record;
1092         window = new QuestionWindow(record->mwindow);
1093         window->create_objects(_("Rewind batch and overwrite?"), 0);
1094         int result = window->run_window();
1095         if(result == 2) record->start_over();
1096         delete window;
1097 }
1098
1099
1100 int RecordGUI::set_translation(int x, int y, float z)
1101 {
1102         record->video_x = x;
1103         record->video_y = y;
1104         record->video_zoom = z;
1105         return 0;
1106 }
1107
1108 void RecordGUI::reset_video()
1109 {
1110         total_dropped_frames = 0;
1111         status_thread->reset_video();
1112         update_framerate(record->default_asset->frame_rate);
1113 }
1114
1115 void RecordGUI::update_dropped_frames(long value)
1116 {
1117         status_thread->update_dropped_frames(value);
1118 }
1119
1120 void RecordGUI::update_frames_behind(long value)
1121 {
1122         status_thread->update_frames_behind(value);
1123 }
1124
1125 void RecordGUI::update_position(double value) 
1126
1127         status_thread->update_position(value);
1128 }
1129
1130 void RecordGUI::update_framerate(double value)
1131 {
1132         status_thread->update_framerate(value);
1133 }
1134
1135 void RecordGUI::update_video(int dropped, int behind)
1136 {
1137         total_dropped_frames += dropped;
1138         update_dropped_frames(total_dropped_frames);
1139         update_frames_behind(behind);
1140         status_thread->update_position(record->current_display_position());
1141 }
1142
1143 void RecordGUI::reset_audio()
1144 {
1145 //      gui->lock_window("RecordAudio::run 2");
1146 // reset meter
1147         total_clipped_samples = 0;
1148         status_thread->reset_audio();
1149         AudioDevice *adevice = record->adevice;
1150         RecordMonitorGUI *window = record->record_monitor->window;
1151         window->lock_window("RecordAudio::run 2");
1152         MeterPanel *meters = window->meters;
1153         if( meters ) {
1154                 int dmix = adevice && (adevice->get_idmix() || adevice->get_odmix());
1155                 meters->init_meters(dmix);
1156         }
1157         window->unlock_window();
1158 //      gui->unlock_window();
1159 }
1160
1161 void RecordGUI::update_clipped_samples(long value)
1162 {
1163         status_thread->update_clipped_samples(value);
1164 }
1165
1166 void RecordGUI::update_audio(int channels, double *max, int *over)
1167 {
1168 // Get clipping status
1169         int clipped = 0;
1170         for( int ch=0; ch<channels && !clipped; ++ch )
1171                 if( over[ch] ) clipped = 1;
1172         if( clipped ) {
1173                 update_clipped_samples(++total_clipped_samples);
1174         }
1175 // Update meters if monitoring
1176         if( record->metering_audio ) {
1177                 RecordMonitorGUI *window = record->record_monitor->window;
1178                 window->lock_window("RecordAudio::run 1");
1179                 MeterPanel *meters = window->meters;
1180                 int nmeters = meters->meters.total;
1181                 for( int ch=0; ch<nmeters; ++ch ) {
1182                         double vmax = ch < channels ? max[ch] : 0.;
1183                         int   vover = ch < channels ? over[ch] : 0;
1184                         meters->meters.values[ch]->update(vmax, vover);
1185                 }
1186                 window->unlock_window();
1187         }
1188 // update position, if no video
1189         if( !record->default_asset->video_data )
1190                 update_position(record->current_display_position());
1191 }
1192
1193
1194 int RecordGUI::keypress_event()
1195 {
1196         return record_transport->keypress_event();
1197 }
1198
1199 void RecordGUI::update_labels(double new_position)
1200 {
1201         RecordLabel *prev, *next;
1202
1203         for(prev = record->get_current_batch()->labels->last; 
1204                 prev; 
1205                 prev = prev->previous) {
1206                 if(prev->position <= new_position) break;
1207         }
1208
1209         for(next = record->get_current_batch()->labels->first; 
1210                 next; 
1211                 next = next->next)
1212         {
1213                 if(next->position > new_position) break;
1214         }
1215
1216         if(prev)
1217                 update_title(prev_label_title, prev->position);
1218         else
1219                 update_title(prev_label_title, -1);
1220
1221 //      if(next)
1222 //              update_title(next_label_title, (double)next->position / record->default_asset->sample_rate);
1223 //      else
1224 //              update_title(next_label_title, -1);
1225 }
1226
1227
1228 int RecordGUI::update_prev_label(long new_position) 
1229
1230         update_title(prev_label_title, new_position);
1231         return 0;
1232 }
1233
1234 // int RecordGUI::update_next_label(long new_position) 
1235 // { 
1236 //      update_title(next_label_title, new_position); 
1237 // }
1238 // 
1239 int RecordGUI::update_title(BC_Title *title, double position)
1240 {
1241         static char string[256];
1242
1243         if(position >= 0) {
1244                 Units::totext(string, 
1245                                 position, 
1246                                 mwindow->edl->session->time_format, 
1247                                 record->default_asset->sample_rate, 
1248                                 record->default_asset->frame_rate, 
1249                                 mwindow->edl->session->frames_per_foot);
1250         }
1251         else {
1252                 sprintf(string, "-");
1253         }
1254         lock_window("RecordGUI::update_title");
1255         title->update(string);
1256         unlock_window();
1257         return 0;
1258 }
1259
1260
1261 void RecordGUI::update_cron_status(const char *status)
1262 {
1263         lock_window("RecordGUI::update_cron_status");
1264         cron_status->update(status);
1265         unlock_window();
1266 }
1267
1268 void RecordGUI::update_power_off(int value)
1269 {
1270         lock_window("RecordGUI::update_power_off");
1271         power_off->update(value);
1272         unlock_window();
1273 }
1274
1275
1276
1277
1278 // ===================================== GUI
1279 // ================================================== modes
1280
1281 RecordGUIModeTextBox::RecordGUIModeTextBox(RecordGUIModeMenu *mode_menu,
1282                 int x, int y, int w,const char *text)
1283  : BC_TextBox(x, y, w, 1, text)
1284 {
1285         this->mode_menu = mode_menu;
1286 }
1287
1288 RecordGUIModeTextBox::~RecordGUIModeTextBox()
1289 {
1290 }
1291
1292 int RecordGUIModeTextBox::handle_event()
1293 {
1294         return 0;
1295 }
1296
1297 RecordGUIModeListBox::RecordGUIModeListBox(RecordGUIModeMenu *mode_menu)
1298  : BC_ListBox(mode_menu->textbox->get_x() + mode_menu->textbox->get_w(),
1299                 mode_menu->textbox->get_y(), 100, 50, LISTBOX_TEXT,
1300                 &mode_menu->modes, 0, 0, 1, 0, 1)
1301 {
1302         this->mode_menu = mode_menu;
1303 }
1304
1305 RecordGUIModeListBox::~RecordGUIModeListBox()
1306 {
1307 }
1308
1309 int RecordGUIModeListBox::handle_event()
1310 {
1311         return mode_menu->handle_event();
1312 }
1313
1314 RecordGUIModeMenu::RecordGUIModeMenu(RecordGUI *record_gui,
1315                 int x, int y, int w,const char *text)
1316 {
1317         this->record_gui = record_gui;
1318         textbox = new RecordGUIModeTextBox(this,x, y, w, "");
1319         record_gui->add_subwindow(textbox);
1320         listbox = new RecordGUIModeListBox(this);
1321         record_gui->add_subwindow(listbox);
1322 }
1323
1324 RecordGUIModeMenu::~RecordGUIModeMenu()
1325 {
1326         for( int i=0; i<modes.total; ++i )
1327                 delete modes.values[i];
1328         delete listbox;
1329         delete textbox;
1330 }
1331
1332 void RecordGUIModeMenu::create_objects()
1333 {
1334         value = RECORD_UNTIMED;
1335         modes.append(new BC_ListBoxItem(Batch::mode_to_text(RECORD_UNTIMED)));
1336         modes.append(new BC_ListBoxItem(Batch::mode_to_text(RECORD_TIMED)));
1337         textbox->update(modes.values[value]->get_text());
1338 }
1339
1340 int RecordGUIModeMenu::handle_event()
1341 {
1342         value = listbox->get_selection_number(0, 0);
1343         textbox->update(modes.values[value]->get_text());
1344         textbox->handle_event();
1345         record_gui->record->set_record_mode(value);
1346         if( value == RECORD_TIMED )
1347                 record_gui->batch_duration->enable();
1348         else
1349                 record_gui->batch_duration->disable();
1350         return 0;
1351 }
1352
1353 void RecordGUIModeMenu::update(int value)
1354 {
1355         this->value = value;
1356         textbox->update(modes.values[value]->get_text());
1357 }
1358
1359 int RecordGUIModeMenu::get_w()
1360 {
1361         return textbox->get_w() + listbox->get_w();
1362 }
1363
1364 int RecordGUIModeMenu::get_h()
1365 {
1366         return MAX(textbox->get_h(), listbox->get_h());
1367 }
1368
1369
1370 RecordStatusThread::RecordStatusThread(MWindow *mwindow, RecordGUI *gui)
1371  : Thread(1, 0, 0)
1372 {
1373         this->mwindow = mwindow;
1374         this->gui = gui;
1375         input_lock = new Condition(0, "RecordStatusThread::input_lock");
1376         reset_video();
1377         reset_audio();
1378         done = 0;
1379 }
1380
1381 RecordStatusThread::~RecordStatusThread()
1382 {
1383         if(Thread::running())
1384         {
1385                 done = 1;
1386                 input_lock->unlock();
1387                 Thread::join();
1388         }
1389 }
1390
1391 void RecordStatusThread::reset_video()
1392 {
1393         new_dropped_frames = 0;
1394         displayed_dropped_frames = -1;
1395         new_frames_behind = 0;
1396         displayed_frames_behind = -1;
1397         new_position = 0;
1398         displayed_framerate = -1.;
1399         new_framerate = 0.;
1400 }
1401
1402 void RecordStatusThread::reset_audio()
1403 {
1404         new_clipped_samples = 0;
1405         displayed_clipped_samples = -1;
1406 }
1407
1408 void RecordStatusThread::update_frames_behind(long value)
1409 {
1410         if( value != displayed_frames_behind ) {
1411                 new_frames_behind = value;
1412                 input_lock->unlock();
1413         }
1414 }
1415
1416 void RecordStatusThread::update_dropped_frames(long value)
1417 {
1418         if( value != displayed_dropped_frames ) {
1419                 new_dropped_frames = value;
1420                 input_lock->unlock();
1421         }
1422 }
1423
1424 void RecordStatusThread::update_clipped_samples(long value)
1425 {
1426         if( value != displayed_clipped_samples ) {
1427                 new_clipped_samples = value;
1428                 input_lock->unlock();
1429         }
1430 }
1431
1432 void RecordStatusThread::update_position(double value)
1433 {
1434         this->new_position = value;
1435         input_lock->unlock();
1436 }
1437
1438 void RecordStatusThread::update_framerate(double value)
1439 {
1440         if( value != displayed_framerate ) {
1441                 new_framerate = value;
1442                 input_lock->unlock();
1443         }
1444 }
1445
1446
1447 template<class T>
1448 void RecordStatusThread::
1449 update_status_string(const char *fmt, T &new_value, T &displayed_value, BC_Title *widgit)
1450 {
1451         if( new_value >= 0 ) {
1452                 if( displayed_value != new_value ) {
1453                         displayed_value = new_value;
1454                         if( widgit ) {
1455                                 char string[64];
1456                                 sprintf(string, fmt, displayed_value);
1457                                 gui->lock_window("RecordStatusThread::run 1");
1458                                 widgit->update(string);
1459                                 gui->unlock_window();
1460                         }
1461                 }
1462                 new_value = -1;
1463         }
1464 }
1465
1466 void RecordStatusThread::run()
1467 {
1468         while(!done) {
1469                 input_lock->lock("RecordStatusThread::run");
1470                 if(done) break;
1471                 gui->record->window_lock->lock("RecordStatusThread::run");
1472                 update_status_string("%d", new_dropped_frames, displayed_dropped_frames,
1473                                         gui->frames_dropped);
1474                 update_status_string("%d", new_frames_behind, displayed_frames_behind,
1475                                         gui->frames_behind);
1476                 update_status_string("%d", new_clipped_samples, displayed_clipped_samples,
1477                                         gui->samples_clipped);
1478                 update_status_string("%0.2f", new_framerate, displayed_framerate,
1479                                         gui->framerate);
1480                 if( new_position >= 0 ) {
1481                         gui->update_title(gui->position_title, new_position);
1482                         gui->update_labels(new_position);
1483                         new_position = -1;
1484                 }
1485                 gui->record->window_lock->unlock();
1486         }
1487 }
1488
1489
1490 void RecordGUI::start_flash_batch()
1491 {
1492         if( batch_flash ) return;
1493         batch_flash = new RecordGUIFlash(this);
1494 }
1495
1496 void RecordGUI::stop_flash_batch()
1497 {
1498         if( !batch_flash ) return;
1499         delete batch_flash;
1500         batch_flash = 0;
1501 }
1502
1503 void RecordGUI::flash_batch()
1504 {
1505         lock_window("void RecordGUI::flash_batch");
1506         int cur_batch = record->current_batch();
1507         if( cur_batch >= 0 && cur_batch < batch_bay->count()) {
1508                 flash_color = flash_color == GREEN ? RED : GREEN;
1509 //printf("RecordGUI::flash_batch %x\n", flash_color);
1510                 batch_bay->set_row_color(cur_batch, flash_color);
1511                 batch_bay->update_batch_news(cur_batch);
1512         }
1513         unlock_window();
1514 }
1515
1516 RecordGUIFlash::
1517 RecordGUIFlash(RecordGUI *record_gui)
1518  : Thread(1, 0, 0)
1519 {
1520         this->record_gui = record_gui;
1521         flash_lock = new Condition(0,"RecordGUIFlash::flash_lock");
1522         done = 0;
1523         Thread::start();
1524 }
1525
1526 RecordGUIFlash::
1527 ~RecordGUIFlash()
1528 {
1529         if( Thread::running() ) {
1530                 done = 1;
1531                 flash_lock->unlock();
1532                 Thread::cancel();
1533                 Thread::join();
1534         }
1535         delete flash_lock;
1536 }
1537
1538 void RecordGUIFlash::run()
1539 {
1540         while( !done ) {
1541                 record_gui->flash_batch();
1542                 enable_cancel();
1543                 Timer::delay(500);
1544                 disable_cancel();
1545         }
1546 }
1547
1548
1549
1550 RecordGUIDCOffset::RecordGUIDCOffset(MWindow *mwindow, int y)
1551  : BC_Button(230, y, mwindow->theme->calibrate_data)
1552 {
1553 }
1554
1555 RecordGUIDCOffset::~RecordGUIDCOffset() {}
1556
1557 int RecordGUIDCOffset::handle_event()
1558 {
1559         return 1;
1560 }
1561
1562 int RecordGUIDCOffset::keypress_event() { return 0; }
1563
1564 RecordGUIDCOffsetText::RecordGUIDCOffsetText(char *text, int y, int number)
1565  : BC_TextBox(30, y+1, 67, 1, text, 0)
1566
1567         this->number = number; 
1568 }
1569
1570 RecordGUIDCOffsetText::~RecordGUIDCOffsetText()
1571 {
1572 }
1573         
1574 int RecordGUIDCOffsetText::handle_event()
1575 {
1576         return 1;
1577 }
1578
1579 RecordGUIReset::RecordGUIReset(MWindow *mwindow, RecordGUI *gui, int y)
1580  : BC_Button(400, y, mwindow->theme->over_button)
1581 { this->gui = gui; }
1582
1583 RecordGUIReset::~RecordGUIReset() 
1584 {
1585 }
1586
1587 int RecordGUIReset::handle_event()
1588 {
1589         return 1;
1590 }
1591
1592 RecordGUIResetTranslation::RecordGUIResetTranslation(MWindow *mwindow, RecordGUI *gui, int y)
1593  : BC_Button(250, y, mwindow->theme->reset_data)
1594 {
1595         this->gui = gui;
1596 }
1597
1598 RecordGUIResetTranslation::~RecordGUIResetTranslation() 
1599 {
1600 }
1601
1602 int RecordGUIResetTranslation::handle_event()
1603 {
1604         gui->set_translation(0, 0, 1);
1605         return 1;
1606 }
1607
1608
1609