r689: Fixed that changes made by dragging a control would often store each
[cinelerra_cv.git] / cinelerra / record.C
blobebb4dd5ff404571fc6f4cbc83cc0d5d992d23679
1 #include "asset.h"
2 #include "assets.h"
3 #include "audiodevice.h"
4 #include "batch.h"
5 #include "channel.h"
6 #include "channeldb.h"
7 #include "channelpicker.h"
8 #include "clip.h"
9 #include "defaults.h"
10 #include "edl.h"
11 #include "edlsession.h"
12 #include "errorbox.h"
13 #include "file.h"
14 #include "filexml.h"
15 #include "filemov.h"
16 #include "filesystem.h"
17 #include "filethread.h"
18 #include "formatcheck.h"
19 #include "indexfile.h"
20 #include "language.h"
21 #include "localsession.h"
22 #include "mainundo.h"
23 #include "mwindow.h"
24 #include "mwindowgui.h"
25 #include "picture.h"
26 #include "playbackengine.h"
27 #include "preferences.h"
28 #include "quicktime.h"
29 #include "record.h"
30 #include "recordaudio.h"
31 #include "recordconfig.h"
32 #include "recordgui.h"
33 #include "recordlabel.h"
34 #include "recordmonitor.h"
35 #include "recordthread.h"
36 #include "recordvideo.h"
37 #include "recordwindow.h"
38 #include "mainsession.h"
39 #include "sighandler.h"
40 #include "testobject.h"
41 #include "theme.h"
42 #include "timebar.h"
43 #include "tracks.h"
44 #include "videoconfig.h"
45 #include "videodevice.h"
47 #include <string.h>
51 RecordMenuItem::RecordMenuItem(MWindow *mwindow)
52  : BC_MenuItem(_("Record..."), "r", 'r')
54         this->mwindow = mwindow;
55         thread = new Record(mwindow, this);
56         current_state = RECORD_NOTHING;
59 RecordMenuItem::~RecordMenuItem()
61         delete thread;
64 int RecordMenuItem::handle_event()
66         if(thread->running()) 
67         {
68                 switch(current_state)
69                 {
70                         case RECORD_INTRO:
71                                 thread->window_lock->lock("RecordMenuItem::handle_event 1");
72                                 if(thread->record_window)
73                                 {
74                                         thread->record_window->lock_window("RecordMenuItem::handle_event 1");
75                                         thread->record_window->raise_window();
76                                         thread->record_window->unlock_window();
77                                 }
78                                 thread->window_lock->unlock();
79                                 break;
80                         
81                         case RECORD_CAPTURING:
82                                 thread->window_lock->lock("RecordMenuItem::handle_event 2");
83                                 if(thread->record_gui)
84                                 {
85                                         thread->record_gui->lock_window("RecordMenuItem::handle_event 2");
86                                         thread->record_gui->raise_window();
87                                         thread->record_gui->unlock_window();
88                                 }
89                                 thread->window_lock->unlock();
90                                 break;
91                 }
92                 return 0;
93         }
95         thread->start();
96         return 1;
108 Record::Record(MWindow *mwindow, RecordMenuItem *menu_item)
109  : Thread()
111         this->mwindow = mwindow;
112         this->menu_item = menu_item;
113         script = 0;
114         capture_state = IS_DONE;
115         adevice = 0;
116         vdevice = 0;
117         file = 0;
118         editing_batch = 0;
119         current_batch = 0;
120         picture = new PictureConfig(mwindow);
121         channeldb = new ChannelDB;
122         master_channel = new Channel;
123         window_lock = new Mutex("Record::window_lock");
126 Record::~Record()
128         delete picture;
129         delete channeldb;
130         delete master_channel;
131         delete window_lock;
135 int Record::load_defaults()
137         char string[BCTEXTLEN];
138         Defaults *defaults = mwindow->defaults;
140 // Load default asset
141         default_asset->load_defaults(defaults, 
142                 "RECORD_", 
143                 1,
144                 1,
145                 1,
146                 1,
147                 1);
154         default_asset->sample_rate = mwindow->edl->session->aconfig_in->in_samplerate;
155         default_asset->frame_rate = mwindow->edl->session->vconfig_in->in_framerate;
156         default_asset->width = mwindow->edl->session->vconfig_in->w;
157         default_asset->height = mwindow->edl->session->vconfig_in->h;
158         default_asset->channels = defaults->get("RECORD_CHANNELS", 2);
159         default_asset->layers = 1;
162 // These are locked by a specific driver.
163         if(mwindow->edl->session->vconfig_in->driver == CAPTURE_LML ||
164                 mwindow->edl->session->vconfig_in->driver == CAPTURE_BUZ ||
165                 mwindow->edl->session->vconfig_in->driver == VIDEO4LINUX2JPEG)
166                 strncpy(default_asset->vcodec, QUICKTIME_MJPA, 4);
167         else
168         if(mwindow->edl->session->vconfig_in->driver == CAPTURE_FIREWIRE ||
169                 mwindow->edl->session->vconfig_in->driver == CAPTURE_IEC61883)
170         {
171                 strncpy(default_asset->vcodec, QUICKTIME_DVSD, 4);
172         }
177 // Load batches
178         int total_batches = defaults->get("TOTAL_BATCHES", 1);
179         if(total_batches < 1) total_batches = 1;
180         for(int i = 0; i < total_batches; i++)
181         {
182                 Batch *batch = new_batch();
183                 Asset *asset = batch->assets.values[0];
185                 sprintf(string, "RECORD_PATH_%d", i);
186                 defaults->get(string, asset->path);
187                 sprintf(string, "RECORD_CHANNEL_%d", i);
188                 batch->channel = defaults->get(string, batch->channel);
189                 sprintf(string, "RECORD_STARTTYPE_%d", i);
190                 batch->start_type = defaults->get(string, batch->start_type);
191                 sprintf(string, "RECORD_STARTDAY_%d", i);
192                 batch->start_day = defaults->get(string, batch->start_day);
193                 sprintf(string, "RECORD_STARTTIME_%d", i);
194                 batch->start_time = defaults->get(string, batch->start_time);
195                 sprintf(string, "RECORD_DURATION_%d", i);
196                 batch->duration = defaults->get(string, batch->duration);
197                 sprintf(string, "RECORD_MODE_%d", i);
198                 batch->record_mode = defaults->get(string, batch->record_mode);
199                 sprintf(string, "BATCH_ENABLED_%d", i);
200                 batch->enabled = defaults->get(string, batch->enabled);
201         }
204         load_mode = defaults->get("RECORD_LOADMODE", LOAD_PASTE);
206         monitor_audio = defaults->get("RECORD_MONITOR_AUDIO", 1);
207         monitor_video = defaults->get("RECORD_MONITOR_VIDEO", 1);
208         video_window_open = defaults->get("RECORD_MONITOR_OPEN", 1);
209         video_x = defaults->get("RECORD_VIDEO_X", 0);
210         video_y = defaults->get("RECORD_VIDEO_Y", 0);
211         video_zoom = defaults->get("RECORD_VIDEO_Z", (float)1);
213         picture->load_defaults();
215         reverse_interlace = defaults->get("REVERSE_INTERLACE", 0);
216         for(int i = 0; i < MAXCHANNELS; i++) 
217         {
218                 sprintf(string, "RECORD_DCOFFSET_%d", i);
219                 dc_offset[i] = defaults->get(string, 0);
220         }
221         fill_frames = defaults->get("FILL_DROPPED_FRAMES", 0);
222         return 0;
225 int Record::save_defaults()
227         char string[BCTEXTLEN];
228         Defaults *defaults = mwindow->defaults;
229         editing_batch = 0;
231 // Save default asset
232         default_asset->save_defaults(defaults,
233                 "RECORD_",
234                 1,
235                 !fixed_compression,
236                 1,
237                 1,
238                 1);
240         defaults->update("RECORD_CHANNELS", default_asset->channels);
247         defaults->update("TOTAL_BATCHES", batches.total);
248         for(int i = 0; i < batches.total; i++)
249         {
250                 Batch *batch = batches.values[i];
251                 Asset *asset = batch->assets.values[0];
253                 sprintf(string, "RECORD_PATH_%d", i);
254                 defaults->update(string, asset->path);
255                 sprintf(string, "RECORD_CHANNEL_%d", i);
256                 defaults->update(string, batch->channel);
257                 sprintf(string, "RECORD_STARTTYPE_%d", i);
258                 defaults->update(string, batch->start_type);
259                 sprintf(string, "RECORD_STARTDAY_%d", i);
260                 defaults->update(string, batch->start_day);
261                 sprintf(string, "RECORD_STARTTIME_%d", i);
262                 defaults->update(string, batch->start_time);
263                 sprintf(string, "RECORD_DURATION_%d", i);
264                 defaults->update(string, batch->duration);
265                 sprintf(string, "RECORD_MODE_%d", i);
266                 defaults->update(string, batch->record_mode);
267                 sprintf(string, "BATCH_ENABLED_%d", i);
268                 defaults->update(string, batch->enabled);
269         }
272         defaults->update("RECORD_LOADMODE", load_mode);
273         defaults->update("RECORD_MONITOR_AUDIO", monitor_audio);
274         defaults->update("RECORD_MONITOR_VIDEO", monitor_video);
275         defaults->update("RECORD_MONITOR_OPEN", video_window_open);
276         defaults->update("RECORD_VIDEO_X", video_x);
277         defaults->update("RECORD_VIDEO_Y", video_y);
278         defaults->update("RECORD_VIDEO_Z", video_zoom);
279         
280         picture->save_defaults();
281         defaults->update("REVERSE_INTERLACE", reverse_interlace);
282         for(int i = 0; i < MAXCHANNELS; i++)
283         {
284                 sprintf(string, "RECORD_DCOFFSET_%d", i);
285                 defaults->update(string, dc_offset[i]);
286         }
287         defaults->update("FILL_DROPPED_FRAMES", fill_frames);
289         return 0;
292 void Record::configure_batches()
294         strcpy(batches.values[0]->assets.values[0]->path, default_asset->path);
295         for(int i = 0; i < batches.total; i++)
296         {
297                 Batch *batch = batches.values[i];
298 // Update format
299                 batch->get_current_asset()->copy_format(default_asset);
301 // Update news
302                 batch->calculate_news();
303         }
306 void Record::source_to_text(char *string, Batch *batch)
308 // Update source
309         strcpy(string, "Record::source_to_text: not implemented");
310         switch(mwindow->edl->session->vconfig_in->driver)
311         {
312                 case VIDEO4LINUX:
313                 case VIDEO4LINUX2:
314                 case CAPTURE_BUZ:
315                 case VIDEO4LINUX2JPEG:
316                         if(batch->channel < 0 || batch->channel >= channeldb->size())
317                                 sprintf(string, _("None"));
318                         else
319                                 sprintf(string, channeldb->get(batch->channel)->title);
320                         break;
321         }
325 char* Record::get_channeldb_prefix()
327         char *path = "";
328         switch(mwindow->edl->session->vconfig_in->driver)
329         {
330                 case VIDEO4LINUX:
331                         path = "channels_v4l";
332                         break;
333                 case VIDEO4LINUX2:
334                         path = "channels_v4l2";
335                         break;
336                 case VIDEO4LINUX2JPEG:
337                         path = "channels_v4l2jpeg";
338                         break;
339                 case CAPTURE_BUZ:
340                         path = "channels_buz";
341                         break;
342         }
344         return path;
347 void Record::run()
349         int result = 0, format_error = 0;
350         int64_t start, end;
351         record_gui = 0;
353 // Default asset forms the first path in the batch capture
354 // and the file format for all operations.
355         default_asset = new Asset;
356         prompt_cancel = 0;
358 // Determine information about the device.
359         channeldb->load(get_channeldb_prefix());
360         fixed_compression = VideoDevice::is_compressed(
361                 mwindow->edl->session->vconfig_in->driver,
362                 0,
363                 1);
364         load_defaults();
366         if(fixed_compression)
367         {
368                 strcpy(default_asset->vcodec, 
369                         VideoDevice::get_vcodec(mwindow->edl->session->vconfig_in->driver));
370         }
373         menu_item->current_state = RECORD_INTRO;
375 // Get information about the file format
376         do
377         {
378                 int x = mwindow->gui->get_root_w(0, 1) / 2 - RECORD_WINDOW_WIDTH / 2;
379                 int y = mwindow->gui->get_root_h(1) / 2 - RECORD_WINDOW_HEIGHT / 2;
380                 
381                 window_lock->lock("Record::run 1");
382                 record_window = new RecordWindow(mwindow, this, x, y);
383                 record_window->create_objects();
384                 window_lock->unlock();
387                 result = record_window->run_window();
388                 window_lock->lock("Record::run 2");
389                 delete record_window;
390                 record_window = 0;
391                 window_lock->unlock();
395                 if(!result)
396                 {
397                         FormatCheck check_format(default_asset);
398                         format_error = check_format.check_format();
399                 }
400         }while(format_error && !result);
402         channeldb->save(get_channeldb_prefix());
403         save_defaults();
404         mwindow->save_defaults();
406         configure_batches();
407         current_batch = 0;
408         editing_batch = 0;
410 // Run recordgui
411         if(!result)
412         {
413                 edl = new EDL;
414                 edl->create_objects();
415                 edl->session->output_w = default_asset->width;
416                 edl->session->output_h = default_asset->height;
417                 edl->session->aspect_w = mwindow->edl->session->aspect_w;
418                 edl->session->aspect_h = mwindow->edl->session->aspect_h;
420                 window_lock->lock("Record::run 3");
421 SET_TRACE
422                 record_gui = new RecordGUI(mwindow, this);
423 SET_TRACE
424                 record_gui->load_defaults();
425 SET_TRACE
426                 record_gui->create_objects();
427 SET_TRACE
429                 record_monitor = new RecordMonitor(mwindow, this);
430 SET_TRACE
431                 record_monitor->create_objects();
432 SET_TRACE
433                 record_gui->update_batch_sources();
434 SET_TRACE
436                 menu_item->current_state = RECORD_CAPTURING;
437 SET_TRACE
438                 record_engine = new RecordThread(mwindow, this);
439 SET_TRACE
440                 record_engine->create_objects();
441 SET_TRACE
442                 monitor_engine = new RecordThread(mwindow, this);
443 SET_TRACE
444                 monitor_engine->create_objects();
445 SET_TRACE
448                 record_gui->show_window();
449 SET_TRACE
450                 record_gui->flush();
451 SET_TRACE
452                 if(video_window_open)
453                 {
454                         record_monitor->window->show_window();
455                         record_monitor->window->raise_window();
456                         record_monitor->window->flush();
457                 }
458 SET_TRACE
460                 start_monitor();
461 SET_TRACE
463                 window_lock->unlock();
465                 result = record_gui->run_window();
467 // Force monitor to quit without resuming
468                 if(monitor_engine->record_video) 
469                         monitor_engine->record_video->batch_done = 1;
470                 else
471                         monitor_engine->record_audio->batch_done = 1;
473                 stop_operation(0);;
475                 close_output_file();
477                 window_lock->lock("Record::run 4");
478                 delete record_monitor;
479                 record_monitor = 0;
481                 record_gui->save_defaults();
483 TRACE("Record::run 1");
484                 delete record_gui;
485                 record_gui = 0;
486                 window_lock->unlock();
488 TRACE("Record::run 2");
489                 delete edl;
491 TRACE("Record::run 3");
492         }
494         menu_item->current_state = RECORD_NOTHING;
496 // Save everything again
497         save_defaults();
503 // Paste into EDL
504         if(!result && load_mode != LOAD_NOTHING)
505         {
506                 mwindow->gui->lock_window("Record::run");
507                 ArrayList<EDL*> new_edls;
510 // Paste assets
511                 for(int i = 0; i < batches.total; i++)
512                 {
513                         Batch *batch = batches.values[i];
514                         Asset *asset = batch->get_current_asset();
516                         if(batch->recorded)
517                         {
518                                 for(int j = 0; j < batch->assets.total; j++)
519                                 {
520                                         EDL *new_edl = new EDL;
521                                         new_edl->create_objects();
522                                         new_edl->copy_session(mwindow->edl);
523                                         mwindow->asset_to_edl(new_edl, 
524                                                 batch->assets.values[j], 
525                                                 batch->labels);
526                                         new_edls.append(new_edl);
527                                 }
528                         }
529                 }
531                 if(new_edls.total)
532                 {
534 // For pasting, clear the active region
535                         if(load_mode == LOAD_PASTE)
536                         {
537                                 mwindow->clear(0);
538                         }
540                         mwindow->paste_edls(&new_edls, 
541                                 load_mode,
542                                 0,
543                                 -1,
544                                 mwindow->edl->session->labels_follow_edits,
545                                 mwindow->edl->session->plugins_follow_edits);
546 //printf("Record::run 7\n");
548                         new_edls.remove_all_objects();
549 //printf("Record::run 8\n");
551                         mwindow->save_backup();
552                         mwindow->undo->update_undo(_("record"), LOAD_ALL);
553                         mwindow->restart_brender();
554                         mwindow->update_plugin_guis();
555                         mwindow->gui->update(1, 
556                                 2,
557                                 1,
558                                 1,
559                                 1,
560                                 1,
561                                 0);
562                         mwindow->sync_parameters(CHANGE_ALL);
563                 }
564                 mwindow->gui->unlock_window();
565         }
567 // Delete everything
568         script = 0;
569         batches.remove_all_objects();
570         delete default_asset;
573 void Record::activate_batch(int number, int stop_operation)
575         if(number != current_batch)
576         {
577                 if(stop_operation) this->stop_operation(1);
578                 close_output_file();
579                 get_current_batch()->calculate_news();
581                 current_batch = number;
582                 record_gui->update_batches();
583                 record_gui->update_position(current_display_position());
584                 record_gui->update_batch_tools();
585         }
588 void Record::delete_batch()
590 // Abort if one batch left
591         if(batches.total > 1)
592         {
593 // Stop operation if active batch
594                 if(current_batch == editing_batch)
595                 {
596                         if(current_batch < batches.total - 1)
597                                 activate_batch(current_batch + 1, 1);
598                         else
599                                 activate_batch(current_batch - 1, 1);
601                         delete batches.values[editing_batch];
602                         batches.remove_number(editing_batch);
603                         editing_batch = current_batch;
604                 }
605                 else
606                 {
607                         if(current_batch > editing_batch) current_batch--;
608                         delete batches.values[editing_batch];
609                         batches.remove_number(editing_batch);
610                         if(editing_batch >= batches.total) editing_batch--;
611                 }
612                 record_gui->update_batch_tools();
613         }
616 void Record::change_editing_batch(int number)
618         this->editing_batch = number;
619         record_gui->update_batch_tools();
622 Batch* Record::new_batch()
624         Batch *result = new Batch(mwindow, this);
625 //printf("Record::new_batch 1\n");
626         result->create_objects();
627         batches.append(result);
628         result->get_current_asset()->copy_format(default_asset);
629         
630 //printf("Record::new_batch 1\n");
632         result->create_default_path();
633         result->calculate_news();
634         if(get_editing_batch()) result->copy_from(get_editing_batch());
635         editing_batch = batches.total - 1;
636 //printf("Record::new_batch 1\n");
637 // Update GUI if created yet
638         if(record_gui) record_gui->update_batch_tools();
639 //printf("Record::new_batch 2\n");
640         return result;
643 int Record::delete_output_file()
645         FILE *test;
649 // Delete old file
650         if(!file)
651         {
652                 Batch *batch = get_current_batch();
653                 if(batch && (test = fopen(batch->get_current_asset()->path, "r")))
654                 {
655                         fclose(test);
657                         record_gui->lock_window("Record::delete_output_file");
659 // Update GUI
660                         sprintf(batch->news, _("Deleting"));
661                         record_gui->update_batches();
663 // Remove it
664                         remove(batch->get_current_asset()->path);
666 // Update GUI
667                         sprintf(batch->news, _("OK"));
668                         record_gui->update_batches();
670                         record_gui->unlock_window();
671                 }
672         }
673         return 0;
676 int Record::open_output_file()
678         int result = 0;
679 // Create initial file for the batch
680         if(!file)
681         {
682                 Batch *batch = get_current_batch();
683                 delete_output_file();
685                 file = new File;
686                 result = file->open_file(mwindow->preferences, 
687                         batch->get_current_asset(), 
688                         0, 
689                         1, 
690                         default_asset->sample_rate, 
691                         default_asset->frame_rate);
692 //printf("Record::open_output_file 1\n");
694                 if(result)
695                 {
696                         delete file;
697                         file = 0;
698                 }
699                 else
700                 {
701                         mwindow->sighandler->push_file(file);
702                         IndexFile::delete_index(mwindow->preferences, 
703                                 batch->get_current_asset());
704                         file->set_processors(mwindow->preferences->processors);
705                         batch->calculate_news();
706                         record_gui->lock_window("Record::open_output_file");
707                         record_gui->update_batches();
708                         record_gui->unlock_window();
709                 }
710 //printf("Record::open_output_file 1\n");
711         }
712 //printf("Record::open_output_file 2\n");
713         return result;
716 int Record::init_next_file()
718         Batch *batch = get_current_batch();
719         Asset *asset;
721         if(file)
722         {
723                 mwindow->sighandler->pull_file(file);
724                 file->close_file();
725                 delete file;
726                 file = 0;
727         }
729         batch->current_asset++;
730         batch->assets.append(asset = new Asset);
731         *asset = *default_asset;
732         sprintf(asset->path, "%s%03d", asset->path, batch->current_asset);
733         int result = open_output_file();
734         return result;
737 // Rewind file at the end of a loop.
738 // This is called by RecordThread.
739 void Record::rewind_file()
741         if(file)
742         {
743                 if(default_asset->audio_data) 
744                         file->set_audio_position(0, default_asset->frame_rate);
745                 if(default_asset->video_data)
746                         file->set_video_position(0, default_asset->frame_rate);
747         }
749         get_current_batch()->current_sample = 0;
750         get_current_batch()->current_frame = 0;
751         record_gui->lock_window("Record::rewind_file");
752         record_gui->update_position(0);
753         record_gui->unlock_window();
756 void Record::start_over()
758         stop_operation(1);
760         Batch *batch = get_current_batch();
761         if(file)
762         {
763                 mwindow->sighandler->pull_file(file);
764                 file->close_file();
765                 delete file;
766                 file = 0;
767         }
769         get_current_batch()->start_over();
771         record_gui->lock_window("Record::start_over");
772         record_gui->update_position(0);
773         record_gui->update_batches();
774         record_gui->unlock_window();
777 void Record::close_output_file()
779 // Can't close until recordmonitor is done
780 //printf("Record::close_output_file 1\n");
781         if(file)
782         {
783                 mwindow->sighandler->pull_file(file);
784                 file->close_file();
785                 delete file;
786                 file = 0;
787         }
788 //printf("Record::close_output_file 2\n");
791 void Record::toggle_label()
793         get_current_batch()->toggle_label(current_display_position());
794         record_gui->update_labels(current_display_position());
797 void Record::get_audio_write_length(int &buffer_size, 
798         int &fragment_size)
800         fragment_size = 1;
801         while(fragment_size < default_asset->sample_rate / mwindow->edl->session->record_speed) 
802                 fragment_size *= 2;
803         fragment_size /= 2;
804         CLAMP(fragment_size, 1024, 32768);
806         for(buffer_size = fragment_size; 
807                 buffer_size < mwindow->edl->session->record_write_length; 
808                 buffer_size += fragment_size)
809                 ;
812 Batch* Record::get_current_batch()
814         if(batches.total)
815                 return batches.values[current_batch];
816         else
817                 return 0;
820 int Record::get_next_batch()
822         int i = current_batch;
823         while(i < batches.total - 1)
824         {
825                 i++;
826                 if(batches.values[i]->enabled) return i;
827         }
828         return -1;
832 Batch* Record::get_editing_batch()
834 //printf("Record::get_editing_batch %d %d\n", batches.total, editing_batch);
836         if(batches.total)
837                 return batches.values[editing_batch];
838         else
839                 return 0;
842 char* Record::current_mode()
844         return Batch::mode_to_text(get_current_batch()->record_mode);
847 int64_t Record::batch_video_offset()
849         return (int64_t)((double)get_current_batch()->file_offset * 
850                 default_asset->frame_rate + 0.5);
853 int64_t Record::current_audio_position()
855         if(file)
856         {
857                 return (int64_t)(file->get_audio_position(default_asset->sample_rate) + 
858                         get_current_batch()->file_offset + 0.5);
859         }
860         return 0;
863 int64_t Record::current_video_position()
865         if(file)
866         {
867                 return file->get_video_position(default_asset->frame_rate) + 
868                         (int64_t)((double)get_current_batch()->file_offset / 
869                                 default_asset->sample_rate * 
870                                 default_asset->frame_rate + 
871                                 0.5);
872         }
873         return 0;
876 double Record::current_display_position()
878 //printf("Record::current_display_position %d %d\n", get_current_batch()->current_sample, get_current_batch()->file_offset);
881         if(default_asset->video_data)
882                 return (double)get_current_batch()->current_frame / 
883                         default_asset->frame_rate + 
884                         get_current_batch()->file_offset;
885         else
886                 return (double)get_current_batch()->current_sample / 
887                         default_asset->sample_rate + 
888                         get_current_batch()->file_offset;
889         return 0;
892 char* Record::current_source()
894         return get_current_batch()->get_source_text();
897 char* Record::current_news()
899         return batches.values[current_batch]->news;
902 Asset* Record::current_asset()
904         return batches.values[current_batch]->get_current_asset();
907 double* Record::current_start()
909         return &batches.values[current_batch]->start_time;
912 int Record::get_current_channel()
914         return get_current_batch()->channel;
917 int Record::get_editing_channel()
919         return get_editing_batch()->channel;
922 Channel* Record::get_current_channel_struct()
924         int channel = get_current_channel();
925         if(channel >= 0 && channel < channeldb->size())
926         {
927                 return channeldb->get(channel);
928         }
929         return 0;
932 double* Record::current_duration()
934         return &batches.values[current_batch]->duration;
937 int64_t Record::current_duration_samples()
939         return (int64_t)((float)batches.values[current_batch]->duration * default_asset->sample_rate + 0.5);
942 int64_t Record::current_duration_frames()
944         return (int64_t)((float)batches.values[current_batch]->duration * default_asset->frame_rate + 0.5);
947 int* Record::current_offset_type()
949         return &batches.values[current_batch]->start_type;
952 ArrayList<Channel*>* Record::get_video_inputs() 
954         if(default_asset->video_data && vdevice) 
955                 return vdevice->get_inputs();
956         else
957                 return 0;
960 int64_t Record::sync_position()
962         switch(capture_state)
963         {
964                 case IS_DONE:
965                         return -1;
966                         break;    
967                 case IS_MONITORING:
968                         return monitor_engine->sync_position();
969                         break;    
970                 case IS_DUPLEXING: 
971                 case IS_RECORDING: 
972                         return record_engine->sync_position();
973                         break;    
974         }
975         return 0;
979 int Record::open_input_devices(int duplex, int context)
981         int audio_opened = 0;
982         int video_opened = 0;
983         AudioInConfig *aconfig_in = mwindow->edl->session->aconfig_in;
985 // Create devices
986         if(default_asset->audio_data && context != CONTEXT_SINGLEFRAME)
987                 adevice = new AudioDevice;
988         else
989                 adevice = 0;
991         if(default_asset->video_data)
992                 vdevice = new VideoDevice(mwindow);
993         else
994                 vdevice = 0;
996 // Initialize sharing
997         if(adevice && vdevice)
998         {
999                 vdevice->set_adevice(adevice);
1000                 adevice->set_vdevice(vdevice);
1001         }
1003 // Configure audio
1004         if(adevice)
1005         {
1006                 adevice->set_software_positioning(mwindow->edl->session->record_software_position);
1007                 adevice->set_record_dither(default_asset->dither);
1009                 for(int i = 0; i < default_asset->channels; i++)
1010                 {
1011                         adevice->set_dc_offset(dc_offset[i], i);
1012                 }
1014 // Initialize full duplex
1015 // Duplex is only needed if the timeline and the recording have audio
1016                 if(duplex && mwindow->edl->tracks->playable_audio_tracks())
1017                 {
1018 // Case 1: duplex device is identical to input device
1019                         if(AudioInConfig::is_duplex(aconfig_in, mwindow->edl->session->aconfig_duplex))
1020                         {
1021                                 adevice->open_duplex(mwindow->edl->session->aconfig_duplex,
1022                                                         default_asset->sample_rate,
1023                                                         get_in_length(),
1024                                                         mwindow->edl->session->real_time_playback);
1025                                 audio_opened = 1;
1026                         }
1027                         else
1028 // Case 2: two separate devices
1029                         {
1030                                 adevice->open_output(mwindow->edl->session->aconfig_duplex,
1031                                                 default_asset->sample_rate,
1032                                                 mwindow->edl->session->playback_buffer,
1033                                                 mwindow->edl->session->real_time_playback);
1034                         }
1035                 }
1037                 if(!audio_opened)
1038                 {
1039                         adevice->open_input(mwindow->edl->session->aconfig_in, 
1040                                 mwindow->edl->session->vconfig_in, 
1041                                 default_asset->sample_rate, 
1042                                 get_in_length());
1043                 }
1044         }
1047 // Initialize video
1048         if(vdevice)
1049         {
1050                 vdevice->set_quality(default_asset->jpeg_quality);
1051                 vdevice->open_input(mwindow->edl->session->vconfig_in, 
1052                         video_x, 
1053                         video_y, 
1054                         video_zoom,
1055                         default_asset->frame_rate);
1057 // Get configuration parameters from device probe
1058                 color_model = vdevice->get_best_colormodel(default_asset);
1059                 master_channel->copy_usage(vdevice->channel);
1060                 picture->copy_usage(vdevice->picture);
1061                 vdevice->set_field_order(reverse_interlace);
1063 // Set the device configuration
1064                 set_channel(get_current_channel());
1065         }
1067         return 0;
1070 int Record::close_input_devices()
1072         if(vdevice)
1073         {
1074                 vdevice->close_all();
1075                 delete vdevice;
1076                 vdevice = 0;
1077         }
1079         if(adevice)
1080         {
1081                 adevice->close_all();
1082                 delete adevice;
1083                 adevice = 0;
1084         }
1086         return 0;
1089 int Record::start_recording(int duplex, int context)
1091         if(capture_state != IS_RECORDING)
1092         {
1093                 pause_monitor();
1095 // Want the devices closed during file deletion to avoid buffer overflow
1096                 delete_output_file();
1098 // These two contexts need to open the device here to allow full duplex.  
1099 // Batch context opens them in RecordThread::run
1100                 if(context == CONTEXT_INTERACTIVE ||
1101                         context == CONTEXT_SINGLEFRAME)
1102                         open_input_devices(duplex, context);
1104                 prompt_cancel = 1;
1106 // start the duplex engine if necessary
1107 // OSS < 3.9 crashes if recording starts before playback
1108 // OSS >= 3.9 crashes if playback starts before recording
1109                 if(duplex)
1110                 {
1111                         capture_state = IS_DUPLEXING;
1112                 }
1113                 else
1114                         capture_state = IS_RECORDING;
1116 // Toggle once to cue the user that we're not dead.
1117                 if(context == CONTEXT_BATCH)
1118                 {
1119                         record_gui->lock_window("Record::start_recording");
1120                         record_gui->flash_batch();
1121                         record_gui->unlock_window();
1122                 }
1123                 record_engine->start_recording(0, context);
1124         }
1125         return 0;
1128 int Record::start_monitor()
1130         monitor_timer.update();
1131         open_input_devices(0, CONTEXT_INTERACTIVE);
1132         monitor_engine->start_recording(1, CONTEXT_INTERACTIVE);
1133         capture_state = IS_MONITORING;
1134         return 0;
1137 int Record::stop_monitor()
1139         monitor_engine->stop_recording(0);
1140         return 0;
1143 int Record::pause_monitor()
1145         if(capture_state == IS_MONITORING)
1146         {
1147                 monitor_engine->pause_recording();
1148         }
1149         return 0;
1152 int Record::resume_monitor()
1154         if(capture_state != IS_MONITORING)
1155         {
1156                 capture_state = IS_MONITORING;
1157                 monitor_timer.update();
1158                 open_input_devices(0, CONTEXT_INTERACTIVE);
1159                 monitor_engine->resume_recording();
1160         }
1161         return 0;
1164 int Record::stop_duplex()
1166         return 0;
1169 int Record::stop_operation(int resume_monitor)
1171         switch(capture_state)
1172         {
1173                 case IS_MONITORING:
1174                         if(!resume_monitor) monitor_engine->stop_recording(0);
1175                         break;
1176                 case IS_RECORDING:
1177                         record_engine->stop_recording(resume_monitor);
1178                         break;
1179                 case IS_DUPLEXING:
1180                         break;
1181                 case IS_PREVIEWING:
1182                         break;
1183         }
1184         return 0;
1188 // Remember to change meters if you change this.
1189 // Return the size of the fragments to read from the audio device.
1190 int Record::get_in_length() 
1192         int64_t fragment_size = 1;
1193         while(fragment_size < default_asset->sample_rate / mwindow->edl->session->record_speed) fragment_size *= 2;
1194         fragment_size /= 2;
1195         return fragment_size;
1198 int Record::set_video_picture()
1200         if(default_asset->video_data && vdevice)
1201                 vdevice->set_picture(picture);
1202         return 0;
1205 void Record::set_translation(int x, int y)
1207         video_x = x;
1208         video_y = y;
1209         if(default_asset->video_data && vdevice)
1210                 vdevice->set_translation(video_x, video_y);
1214 int Record::set_channel(int channel)
1216         if(channel >= 0 && channel < channeldb->size())
1217         {
1218                 char string[BCTEXTLEN];
1219                 get_editing_batch()->channel = channel;
1220                 source_to_text(string, get_editing_batch());
1223                 record_gui->lock_window("Record::set_channel");
1224                 record_gui->batch_source->update(string);
1225                 record_monitor->window->channel_picker->channel_text->update(string);
1226                 record_gui->update_batches();
1227                 record_gui->unlock_window();
1230                 if(vdevice)
1231                 {
1232                         vdevice->set_channel(channeldb->get(channel));
1233                         set_video_picture();
1234                 }
1235         }
1236         return 0;
1239 // Change to a channel not in the db for editing
1240 void Record::set_channel(Channel *channel)
1242         if(vdevice) vdevice->set_channel(channel);
1245 int Record::has_signal()
1247         if(vdevice) return vdevice->has_signal();
1248         return 0;
1251 void Record::get_current_time(double &seconds, int &day)
1253         time_t result = time(0) + 1;
1254         struct tm *struct_tm = localtime(&result);
1255         day = struct_tm->tm_wday;
1256         seconds = struct_tm->tm_hour * 3600 + struct_tm->tm_min * 60 + struct_tm->tm_sec;
1270 int Record::get_time_format()
1272         return mwindow->edl->session->time_format;
1275 float Record::get_frame_rate()
1277         return 0.0;
1278 //      return mwindow->session->frame_rate;
1281 int Record::set_loop_duration(int64_t value)
1283         loop_duration = value; 
1284         return 0;
1287 int Record::get_vu_format() { return mwindow->edl->session->meter_format; }
1288 float Record::get_min_db() { return mwindow->edl->session->min_meter_db; }
1290 int Record::get_rec_mode() { return record_mode; }
1291 int Record::set_rec_mode(int value) { record_mode = value; }
1293 int Record::get_video_buffersize() { return mwindow->edl->session->video_write_length; }
1294 int Record::get_everyframe() { return mwindow->edl->session->video_every_frame; }
1296 int Record::get_out_length() { return mwindow->edl->session->playback_buffer; }
1297 int Record::get_software_positioning() { return mwindow->edl->session->record_software_position; }
1298 int64_t Record::get_out_buffersize() { return mwindow->edl->session->playback_buffer; }
1299 int64_t Record::get_in_buffersize() { return mwindow->edl->session->record_write_length; }
1300 int Record::get_realtime() { return realtime; }
1301 int Record::get_meter_speed() { return mwindow->edl->session->record_speed; }
1303 int Record::enable_duplex() { return mwindow->edl->session->enable_duplex; }
1304 int64_t Record::get_playback_buffer() { return mwindow->edl->session->playback_buffer; }