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