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