r860: Merge 2.1:
[cinelerra_cv.git] / cinelerra / record.C
blob262d7bef056aef18a726cd130286f7e674dcf29c
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 "bchash.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 "mutex.h"
24 #include "mwindow.h"
25 #include "mwindowgui.h"
26 #include "picture.h"
27 #include "playbackengine.h"
28 #include "preferences.h"
29 #include "quicktime.h"
30 #include "record.h"
31 #include "recordaudio.h"
32 #include "recordconfig.h"
33 #include "recordgui.h"
34 #include "recordlabel.h"
35 #include "recordmonitor.h"
36 #include "recordthread.h"
37 #include "recordvideo.h"
38 #include "recordwindow.h"
39 #include "mainsession.h"
40 #include "sighandler.h"
41 #include "testobject.h"
42 #include "theme.h"
43 #include "timebar.h"
44 #include "tracks.h"
45 #include "videoconfig.h"
46 #include "videodevice.h"
48 #include <string.h>
52 RecordMenuItem::RecordMenuItem(MWindow *mwindow)
53  : BC_MenuItem(_("Record..."), "r", 'r')
55         this->mwindow = mwindow;
56         thread = new Record(mwindow, this);
57         current_state = RECORD_NOTHING;
60 RecordMenuItem::~RecordMenuItem()
62         delete thread;
65 int RecordMenuItem::handle_event()
67         if(thread->running()) 
68         {
69                 switch(current_state)
70                 {
71                         case RECORD_INTRO:
72                                 thread->window_lock->lock("RecordMenuItem::handle_event 1");
73                                 if(thread->record_window)
74                                 {
75                                         thread->record_window->lock_window("RecordMenuItem::handle_event 1");
76                                         thread->record_window->raise_window();
77                                         thread->record_window->unlock_window();
78                                 }
79                                 thread->window_lock->unlock();
80                                 break;
81                         
82                         case RECORD_CAPTURING:
83                                 thread->window_lock->lock("RecordMenuItem::handle_event 2");
84                                 if(thread->record_gui)
85                                 {
86                                         thread->record_gui->lock_window("RecordMenuItem::handle_event 2");
87                                         thread->record_gui->raise_window();
88                                         thread->record_gui->unlock_window();
89                                 }
90                                 thread->window_lock->unlock();
91                                 break;
92                 }
93                 return 0;
94         }
96         thread->start();
97         return 1;
109 Record::Record(MWindow *mwindow, RecordMenuItem *menu_item)
110  : Thread()
112         this->mwindow = mwindow;
113         this->menu_item = menu_item;
114         script = 0;
115         capture_state = IS_DONE;
116         adevice = 0;
117         vdevice = 0;
118         file = 0;
119         editing_batch = 0;
120         current_batch = 0;
121 SET_TRACE
122         picture = new PictureConfig(mwindow->defaults);
123 SET_TRACE
124         channeldb = new ChannelDB;
125         master_channel = new Channel;
126         window_lock = new Mutex("Record::window_lock");
129 Record::~Record()
131         delete picture;
132         delete channeldb;
133         delete master_channel;
134         delete window_lock;
138 int Record::load_defaults()
140         char string[BCTEXTLEN];
141         BC_Hash *defaults = mwindow->defaults;
143 // Load file format
144 //      default_asset->load_defaults(defaults, 
145 //              "RECORD_", 
146 //              1,
147 //              1,
148 //              1,
149 //              1,
150 //              1);
151 // This reads back everything that was saved in save_defaults.
152         default_asset->copy_from(mwindow->edl->session->recording_format, 0);
153         default_asset->channels = mwindow->edl->session->aconfig_in->channels;
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->layers = 1;
162 // Fix encoding parameters depending on driver.
163 // These are locked by a specific driver.
164         if(mwindow->edl->session->vconfig_in->driver == CAPTURE_LML ||
165                 mwindow->edl->session->vconfig_in->driver == CAPTURE_BUZ ||
166                 mwindow->edl->session->vconfig_in->driver == VIDEO4LINUX2JPEG)
167                 strncpy(default_asset->vcodec, QUICKTIME_MJPA, 4);
168         else
169         if(mwindow->edl->session->vconfig_in->driver == CAPTURE_FIREWIRE ||
170                 mwindow->edl->session->vconfig_in->driver == CAPTURE_IEC61883)
171         {
172                 strncpy(default_asset->vcodec, QUICKTIME_DVSD, 4);
173         }
178 // Load batches
179         int total_batches = defaults->get("TOTAL_BATCHES", 1);
180         if(total_batches < 1) total_batches = 1;
181         for(int i = 0; i < total_batches; i++)
182         {
183                 Batch *batch = new_batch();
184                 Asset *asset = batch->assets.values[0];
186                 sprintf(string, "RECORD_PATH_%d", i);
187                 defaults->get(string, asset->path);
188                 sprintf(string, "RECORD_CHANNEL_%d", i);
189                 batch->channel = defaults->get(string, batch->channel);
190                 sprintf(string, "RECORD_STARTTYPE_%d", i);
191                 batch->start_type = defaults->get(string, batch->start_type);
192                 sprintf(string, "RECORD_STARTDAY_%d", i);
193                 batch->start_day = defaults->get(string, batch->start_day);
194                 sprintf(string, "RECORD_STARTTIME_%d", i);
195                 batch->start_time = defaults->get(string, batch->start_time);
196                 sprintf(string, "RECORD_DURATION_%d", i);
197                 batch->duration = defaults->get(string, batch->duration);
198                 sprintf(string, "RECORD_MODE_%d", i);
199                 batch->record_mode = defaults->get(string, batch->record_mode);
200                 sprintf(string, "BATCH_ENABLED_%d", i);
201                 batch->enabled = defaults->get(string, batch->enabled);
202         }
205         load_mode = defaults->get("RECORD_LOADMODE", LOAD_PASTE);
207         monitor_audio = defaults->get("RECORD_MONITOR_AUDIO", 1);
208         monitor_video = defaults->get("RECORD_MONITOR_VIDEO", 1);
209         video_window_open = defaults->get("RECORD_MONITOR_OPEN", 1);
210         video_x = defaults->get("RECORD_VIDEO_X", 0);
211         video_y = defaults->get("RECORD_VIDEO_Y", 0);
212         video_zoom = defaults->get("RECORD_VIDEO_Z", (float)1);
214 SET_TRACE
215         picture->load_defaults();
216 SET_TRACE
218         reverse_interlace = defaults->get("REVERSE_INTERLACE", 0);
219         for(int i = 0; i < MAXCHANNELS; i++) 
220         {
221                 sprintf(string, "RECORD_DCOFFSET_%d", i);
222                 dc_offset[i] = defaults->get(string, 0);
223         }
224         fill_frames = defaults->get("FILL_DROPPED_FRAMES", 0);
225         return 0;
228 int Record::save_defaults()
230         char string[BCTEXTLEN];
231         BC_Hash *defaults = mwindow->defaults;
232         editing_batch = 0;
234 // Save default asset path but not the format because that's
235 // overridden by the driver.
236 // The format is saved in preferences.
237         if(batches.total)
238                 strcpy(default_asset->path, batches.values[0]->assets.values[0]->path);
239         default_asset->save_defaults(defaults,
240                 "RECORD_",
241                 0,
242                 0,
243                 0,
244                 0,
245                 0);
247 //      default_asset->save_defaults(defaults,
248 //              "RECORD_",
249 //              1,
250 //              !fixed_compression,
251 //              1,
252 //              1,
253 //              1);
255 //      defaults->update("RECORD_CHANNELS", default_asset->channels);
262         defaults->update("TOTAL_BATCHES", batches.total);
263         for(int i = 0; i < batches.total; i++)
264         {
265                 Batch *batch = batches.values[i];
266                 Asset *asset = batch->assets.values[0];
268                 sprintf(string, "RECORD_PATH_%d", i);
269                 defaults->update(string, asset->path);
270                 sprintf(string, "RECORD_CHANNEL_%d", i);
271                 defaults->update(string, batch->channel);
272                 sprintf(string, "RECORD_STARTTYPE_%d", i);
273                 defaults->update(string, batch->start_type);
274                 sprintf(string, "RECORD_STARTDAY_%d", i);
275                 defaults->update(string, batch->start_day);
276                 sprintf(string, "RECORD_STARTTIME_%d", i);
277                 defaults->update(string, batch->start_time);
278                 sprintf(string, "RECORD_DURATION_%d", i);
279                 defaults->update(string, batch->duration);
280                 sprintf(string, "RECORD_MODE_%d", i);
281                 defaults->update(string, batch->record_mode);
282                 sprintf(string, "BATCH_ENABLED_%d", i);
283                 defaults->update(string, batch->enabled);
284         }
287         defaults->update("RECORD_LOADMODE", load_mode);
288         defaults->update("RECORD_MONITOR_AUDIO", monitor_audio);
289         defaults->update("RECORD_MONITOR_VIDEO", monitor_video);
290         defaults->update("RECORD_MONITOR_OPEN", video_window_open);
291         defaults->update("RECORD_VIDEO_X", video_x);
292         defaults->update("RECORD_VIDEO_Y", video_y);
293         defaults->update("RECORD_VIDEO_Z", video_zoom);
294         
295 SET_TRACE
296         picture->save_defaults();
297 SET_TRACE
298         defaults->update("REVERSE_INTERLACE", reverse_interlace);
299         for(int i = 0; i < MAXCHANNELS; i++)
300         {
301                 sprintf(string, "RECORD_DCOFFSET_%d", i);
302                 defaults->update(string, dc_offset[i]);
303         }
304         defaults->update("FILL_DROPPED_FRAMES", fill_frames);
306         return 0;
309 void Record::configure_batches()
311         strcpy(batches.values[0]->assets.values[0]->path, default_asset->path);
312         for(int i = 0; i < batches.total; i++)
313         {
314                 Batch *batch = batches.values[i];
315 // Update format
316                 batch->get_current_asset()->copy_format(default_asset);
318 // Update news
319                 batch->calculate_news();
320         }
323 void Record::source_to_text(char *string, Batch *batch)
325 // Update source
326         strcpy(string, "Record::source_to_text: not implemented");
327         switch(mwindow->edl->session->vconfig_in->driver)
328         {
329                 case VIDEO4LINUX:
330                 case VIDEO4LINUX2:
331                 case CAPTURE_BUZ:
332                 case VIDEO4LINUX2JPEG:
333                         if(batch->channel < 0 || batch->channel >= channeldb->size())
334                                 sprintf(string, _("None"));
335                         else
336                                 sprintf(string, channeldb->get(batch->channel)->title);
337                         break;
338         }
342 char* Record::get_channeldb_prefix()
344         char *path = "";
345         switch(mwindow->edl->session->vconfig_in->driver)
346         {
347                 case VIDEO4LINUX:
348                         path = "channels_v4l";
349                         break;
350                 case VIDEO4LINUX2:
351                         path = "channels_v4l2";
352                         break;
353                 case VIDEO4LINUX2JPEG:
354                         path = "channels_v4l2jpeg";
355                         break;
356                 case CAPTURE_BUZ:
357                         path = "channels_buz";
358                         break;
359         }
361         return path;
364 void Record::run()
366         int result = 0, format_error = 0;
367         int64_t start, end;
368         record_gui = 0;
370 // Default asset forms the first path in the batch capture
371 // and the file format for all operations.
372         default_asset = new Asset;
373         prompt_cancel = 0;
375 // Determine information about the device.
376         channeldb->load(get_channeldb_prefix());
377         fixed_compression = VideoDevice::is_compressed(
378                 mwindow->edl->session->vconfig_in->driver,
379                 0,
380                 1);
381         load_defaults();
383         if(fixed_compression)
384         {
385                 VideoDevice device;
386                 device.fix_asset(default_asset, 
387                         mwindow->edl->session->vconfig_in->driver);
388         }
391         menu_item->current_state = RECORD_INTRO;
393 // // Get information about the file format
394 //      do
395 //      {
396 //              int x = mwindow->gui->get_root_w(0, 1) / 2 - RECORD_WINDOW_WIDTH / 2;
397 //              int y = mwindow->gui->get_root_h(1) / 2 - RECORD_WINDOW_HEIGHT / 2;
399 //              window_lock->lock("Record::run 1");
400 //              record_window = new RecordWindow(mwindow, this, x, y);
401 //              record_window->create_objects();
402 //              window_lock->unlock();
403 // 
404 // 
405 //              result = record_window->run_window();
406 //              window_lock->lock("Record::run 2");
407 //              delete record_window;
408 //              record_window = 0;
409 //              window_lock->unlock();
410 // 
411 // 
412 // 
413 //              if(!result)
414 //              {
415 //                      FormatCheck check_format(default_asset);
416 //                      format_error = check_format.check_format();
417 //              }
418 //      }while(format_error && !result);
420         channeldb->save(get_channeldb_prefix());
421         save_defaults();
422         mwindow->save_defaults();
424         configure_batches();
425         current_batch = 0;
426         editing_batch = 0;
428 // Run recordgui
429         if(!result)
430         {
431                 edl = new EDL;
432                 edl->create_objects();
433                 edl->session->output_w = default_asset->width;
434                 edl->session->output_h = default_asset->height;
435                 edl->session->aspect_w = mwindow->edl->session->aspect_w;
436                 edl->session->aspect_h = mwindow->edl->session->aspect_h;
438 SET_TRACE
439                 window_lock->lock("Record::run 3");
440 SET_TRACE
441                 record_gui = new RecordGUI(mwindow, this);
442                 record_gui->load_defaults();
443                 record_gui->create_objects();
445 SET_TRACE
446                 record_monitor = new RecordMonitor(mwindow, this);
447 SET_TRACE
448                 record_monitor->create_objects();
449 SET_TRACE
450                 record_gui->update_batch_sources();
452 SET_TRACE
453                 menu_item->current_state = RECORD_CAPTURING;
454                 record_engine = new RecordThread(mwindow, this);
455                 record_engine->create_objects();
456                 monitor_engine = new RecordThread(mwindow, this);
457                 monitor_engine->create_objects();
459 SET_TRACE
461                 record_gui->show_window();
462                 record_gui->flush();
463                 if(video_window_open)
464                 {
465                         record_monitor->window->show_window();
466                         record_monitor->window->raise_window();
467                         record_monitor->window->flush();
468                 }
470 SET_TRACE
471                 start_monitor();
473 SET_TRACE
474                 window_lock->unlock();
476                 result = record_gui->run_window();
477 // Must unlock to stop operation
478                 record_gui->unlock_window();
480 // Force monitor to quit without resuming
481                 if(monitor_engine->record_video) 
482                         monitor_engine->record_video->batch_done = 1;
483                 else
484                         monitor_engine->record_audio->batch_done = 1;
486 SET_TRACE
487 //              stop_operation(0);
488 // Need to stop everything this time
489                 monitor_engine->stop_recording(0);
490 SET_TRACE
491                 record_engine->stop_recording(0);
492 SET_TRACE
494                 close_output_file();
495 SET_TRACE
497                 window_lock->lock("Record::run 4");
499 SET_TRACE
500                 delete record_monitor;
501                 record_monitor = 0;
502 SET_TRACE
505                 delete record_engine;
506                 record_engine = 0;
507 SET_TRACE
509                 delete monitor_engine;
510                 monitor_engine = 0;
512 SET_TRACE
513                 record_gui->save_defaults();
515 SET_TRACE
516                 delete record_gui;
517                 record_gui = 0;
518                 window_lock->unlock();
520 SET_TRACE
521                 delete edl;
523 SET_TRACE
524         }
526         menu_item->current_state = RECORD_NOTHING;
528 // Save everything again
529         save_defaults();
535 // Paste into EDL
536         if(!result && load_mode != LOAD_NOTHING)
537         {
538                 mwindow->gui->lock_window("Record::run");
539                 ArrayList<EDL*> new_edls;
542 // Paste assets
543                 for(int i = 0; i < batches.total; i++)
544                 {
545                         Batch *batch = batches.values[i];
546                         Asset *asset = batch->get_current_asset();
548                         if(batch->recorded)
549                         {
550                                 for(int j = 0; j < batch->assets.total; j++)
551                                 {
552                                         EDL *new_edl = new EDL;
553                                         new_edl->create_objects();
554                                         new_edl->copy_session(mwindow->edl);
555                                         mwindow->asset_to_edl(new_edl, 
556                                                 batch->assets.values[j], 
557                                                 batch->labels);
558                                         new_edls.append(new_edl);
559                                 }
560                         }
561                 }
563                 if(new_edls.total)
564                 {
566 // For pasting, clear the active region
567                         if(load_mode == LOAD_PASTE)
568                         {
569                                 mwindow->clear(0);
570                         }
572                         mwindow->paste_edls(&new_edls, 
573                                 load_mode,
574                                 0,
575                                 -1,
576                                 mwindow->edl->session->labels_follow_edits,
577                                 mwindow->edl->session->plugins_follow_edits);
578 //printf("Record::run 7\n");
580                         new_edls.remove_all_objects();
581 //printf("Record::run 8\n");
583                         mwindow->save_backup();
584                         mwindow->undo->update_undo(_("record"), LOAD_ALL);
585                         mwindow->restart_brender();
586                         mwindow->update_plugin_guis();
587                         mwindow->gui->update(1, 
588                                 2,
589                                 1,
590                                 1,
591                                 1,
592                                 1,
593                                 0);
594                         mwindow->sync_parameters(CHANGE_ALL);
595                 }
596                 mwindow->gui->unlock_window();
597         }
599 // Delete everything
600         script = 0;
601         batches.remove_all_objects();
602         Garbage::delete_object(default_asset);
605 void Record::activate_batch(int number, int stop_operation)
607         if(number != current_batch)
608         {
609                 if(stop_operation) this->stop_operation(1);
610                 close_output_file();
611                 get_current_batch()->calculate_news();
613                 current_batch = number;
614                 record_gui->update_batches();
615                 record_gui->update_position(current_display_position());
616                 record_gui->update_batch_tools();
617         }
620 void Record::delete_batch()
622 // Abort if one batch left
623         if(batches.total > 1)
624         {
625 // Stop operation if active batch
626                 if(current_batch == editing_batch)
627                 {
628                         if(current_batch < batches.total - 1)
629                                 activate_batch(current_batch + 1, 1);
630                         else
631                                 activate_batch(current_batch - 1, 1);
633                         delete batches.values[editing_batch];
634                         batches.remove_number(editing_batch);
635                         editing_batch = current_batch;
636                 }
637                 else
638                 {
639                         if(current_batch > editing_batch) current_batch--;
640                         delete batches.values[editing_batch];
641                         batches.remove_number(editing_batch);
642                         if(editing_batch >= batches.total) editing_batch--;
643                 }
644                 record_gui->update_batch_tools();
645         }
648 void Record::change_editing_batch(int number)
650         this->editing_batch = number;
651         record_gui->update_batch_tools();
654 Batch* Record::new_batch()
656         Batch *result = new Batch(mwindow, this);
657 //printf("Record::new_batch 1\n");
658         result->create_objects();
659         batches.append(result);
660         result->get_current_asset()->copy_format(default_asset);
661         
662 //printf("Record::new_batch 1\n");
664         result->create_default_path();
665         result->calculate_news();
666         if(get_editing_batch()) result->copy_from(get_editing_batch());
667         editing_batch = batches.total - 1;
668 //printf("Record::new_batch 1\n");
669 // Update GUI if created yet
670         if(record_gui) record_gui->update_batch_tools();
671 //printf("Record::new_batch 2\n");
672         return result;
675 int Record::delete_output_file()
677         FILE *test;
681 // Delete old file
682         if(!file)
683         {
684                 Batch *batch = get_current_batch();
685                 if(batch && (test = fopen(batch->get_current_asset()->path, "r")))
686                 {
687                         fclose(test);
689                         record_gui->lock_window("Record::delete_output_file");
691 // Update GUI
692                         sprintf(batch->news, _("Deleting"));
693                         record_gui->update_batches();
695 // Remove it
696                         remove(batch->get_current_asset()->path);
698 // Update GUI
699                         sprintf(batch->news, _("OK"));
700                         record_gui->update_batches();
702                         record_gui->unlock_window();
703                 }
704         }
705         return 0;
708 int Record::open_output_file()
710         int result = 0;
711 // Create initial file for the batch
712         if(!file)
713         {
714                 Batch *batch = get_current_batch();
715                 delete_output_file();
717                 file = new File;
718                 result = file->open_file(mwindow->preferences, 
719                         batch->get_current_asset(), 
720                         0, 
721                         1, 
722                         default_asset->sample_rate, 
723                         default_asset->frame_rate);
725                 if(result)
726                 {
727                         delete file;
728                         file = 0;
729                 }
730                 else
731                 {
732                         mwindow->sighandler->push_file(file);
733                         IndexFile::delete_index(mwindow->preferences, 
734                                 batch->get_current_asset());
735                         file->set_processors(mwindow->preferences->real_processors);
736                         batch->calculate_news();
737                         record_gui->lock_window("Record::open_output_file");
738                         record_gui->update_batches();
739                         record_gui->unlock_window();
740                 }
741         }
742         return result;
745 int Record::init_next_file()
747         Batch *batch = get_current_batch();
748         Asset *asset;
750         if(file)
751         {
752                 mwindow->sighandler->pull_file(file);
753                 file->close_file();
754                 delete file;
755                 file = 0;
756         }
758         batch->current_asset++;
759         batch->assets.append(asset = new Asset);
760         *asset = *default_asset;
761         sprintf(asset->path, "%s%03d", asset->path, batch->current_asset);
762         int result = open_output_file();
763         return result;
766 // Rewind file at the end of a loop.
767 // This is called by RecordThread.
768 void Record::rewind_file()
770         if(file)
771         {
772                 if(default_asset->audio_data) 
773                         file->set_audio_position(0, default_asset->frame_rate);
774                 if(default_asset->video_data)
775                         file->set_video_position(0, default_asset->frame_rate);
776         }
778         get_current_batch()->current_sample = 0;
779         get_current_batch()->current_frame = 0;
780         record_gui->lock_window("Record::rewind_file");
781         record_gui->update_position(0);
782         record_gui->unlock_window();
785 void Record::start_over()
787         stop_operation(1);
789         Batch *batch = get_current_batch();
790         if(file)
791         {
792                 mwindow->sighandler->pull_file(file);
793                 file->close_file();
794                 delete file;
795                 file = 0;
796         }
798         get_current_batch()->start_over();
800         record_gui->lock_window("Record::start_over");
801         record_gui->update_position(0);
802         record_gui->update_batches();
803         record_gui->unlock_window();
806 void Record::close_output_file()
808 // Can't close until recordmonitor is done
809 //printf("Record::close_output_file 1\n");
810         if(file)
811         {
812                 mwindow->sighandler->pull_file(file);
813                 file->close_file();
814                 delete file;
815                 file = 0;
816         }
817 //printf("Record::close_output_file 2\n");
820 void Record::toggle_label()
822         get_current_batch()->toggle_label(current_display_position());
823         record_gui->update_labels(current_display_position());
826 void Record::get_audio_write_length(int &buffer_size, 
827         int &fragment_size)
829         fragment_size = 1;
830         while(fragment_size < default_asset->sample_rate / mwindow->edl->session->record_speed) 
831                 fragment_size *= 2;
832         fragment_size /= 2;
833         CLAMP(fragment_size, 1024, 32768);
835         for(buffer_size = fragment_size; 
836                 buffer_size < mwindow->edl->session->record_write_length; 
837                 buffer_size += fragment_size)
838                 ;
841 Batch* Record::get_current_batch()
843         if(batches.total)
844                 return batches.values[current_batch];
845         else
846                 return 0;
849 int Record::get_next_batch()
851         int i = current_batch;
852         while(i < batches.total - 1)
853         {
854                 i++;
855                 if(batches.values[i]->enabled) return i;
856         }
857         return -1;
861 Batch* Record::get_editing_batch()
863 //printf("Record::get_editing_batch %d %d\n", batches.total, editing_batch);
865         if(batches.total)
866                 return batches.values[editing_batch];
867         else
868                 return 0;
871 char* Record::current_mode()
873         return Batch::mode_to_text(get_current_batch()->record_mode);
876 int64_t Record::batch_video_offset()
878         return (int64_t)((double)get_current_batch()->file_offset * 
879                 default_asset->frame_rate + 0.5);
882 int64_t Record::current_audio_position()
884         if(file)
885         {
886                 return (int64_t)(file->get_audio_position(default_asset->sample_rate) + 
887                         get_current_batch()->file_offset + 0.5);
888         }
889         return 0;
892 int64_t Record::current_video_position()
894         if(file)
895         {
896                 return file->get_video_position(default_asset->frame_rate) + 
897                         (int64_t)((double)get_current_batch()->file_offset / 
898                                 default_asset->sample_rate * 
899                                 default_asset->frame_rate + 
900                                 0.5);
901         }
902         return 0;
905 double Record::current_display_position()
907 //printf("Record::current_display_position %d %d\n", get_current_batch()->current_sample, get_current_batch()->file_offset);
910         if(default_asset->video_data)
911                 return (double)get_current_batch()->current_frame / 
912                         default_asset->frame_rate + 
913                         get_current_batch()->file_offset;
914         else
915                 return (double)get_current_batch()->current_sample / 
916                         default_asset->sample_rate + 
917                         get_current_batch()->file_offset;
918         return 0;
921 char* Record::current_source()
923         return get_current_batch()->get_source_text();
926 char* Record::current_news()
928         return batches.values[current_batch]->news;
931 Asset* Record::current_asset()
933         return batches.values[current_batch]->get_current_asset();
936 double* Record::current_start()
938         return &batches.values[current_batch]->start_time;
941 int Record::get_current_channel()
943         return get_current_batch()->channel;
946 int Record::get_editing_channel()
948         return get_editing_batch()->channel;
951 Channel* Record::get_current_channel_struct()
953         int channel = get_current_channel();
954         if(channel >= 0 && channel < channeldb->size())
955         {
956                 return channeldb->get(channel);
957         }
958         return 0;
961 double* Record::current_duration()
963         return &batches.values[current_batch]->duration;
966 int64_t Record::current_duration_samples()
968         return (int64_t)((float)batches.values[current_batch]->duration * default_asset->sample_rate + 0.5);
971 int64_t Record::current_duration_frames()
973         return (int64_t)((float)batches.values[current_batch]->duration * default_asset->frame_rate + 0.5);
976 int* Record::current_offset_type()
978         return &batches.values[current_batch]->start_type;
981 ArrayList<Channel*>* Record::get_video_inputs() 
983         if(default_asset->video_data && vdevice) 
984                 return vdevice->get_inputs();
985         else
986                 return 0;
989 int64_t Record::sync_position()
991         switch(capture_state)
992         {
993                 case IS_DONE:
994                         return -1;
995                         break;    
996                 case IS_MONITORING:
997                         return monitor_engine->sync_position();
998                         break;    
999                 case IS_DUPLEXING: 
1000                 case IS_RECORDING: 
1001                         return record_engine->sync_position();
1002                         break;    
1003         }
1004         return 0;
1008 int Record::open_input_devices(int duplex, int context)
1010         int audio_opened = 0;
1011         int video_opened = 0;
1012         AudioInConfig *aconfig_in = mwindow->edl->session->aconfig_in;
1015 // Create devices
1016         if(default_asset->audio_data && context != CONTEXT_SINGLEFRAME)
1017                 adevice = new AudioDevice(mwindow);
1018         else
1019                 adevice = 0;
1021         if(default_asset->video_data)
1022                 vdevice = new VideoDevice(mwindow);
1023         else
1024                 vdevice = 0;
1026 // Initialize sharing
1027         if(adevice && vdevice)
1028         {
1029                 vdevice->set_adevice(adevice);
1030                 adevice->set_vdevice(vdevice);
1031         }
1033 // Configure audio
1034         if(adevice)
1035         {
1036                 adevice->set_software_positioning(mwindow->edl->session->record_software_position);
1038 // Initialize full duplex
1039 // Duplex is only needed if the timeline and the recording have audio
1040                 if(duplex && mwindow->edl->tracks->playable_audio_tracks())
1041                 {
1042 // Case 1: duplex device is identical to input device
1043 //                      if(AudioInConfig::is_duplex(aconfig_in, mwindow->edl->session->aconfig_duplex))
1044 //                      {
1045 //                              adevice->open_duplex(mwindow->edl->session->aconfig_duplex,
1046 //                                                      default_asset->sample_rate,
1047 //                                                      get_in_length(),
1048 //                                                      mwindow->edl->session->real_time_playback);
1049 //                              audio_opened = 1;
1050 //                      }
1051 //                      else
1052 // Case 2: two separate devices
1053                         {
1054                                 adevice->open_output(mwindow->edl->session->aconfig_duplex,
1055                                                 default_asset->sample_rate,
1056                                                 mwindow->edl->session->playback_buffer,
1057                                                 mwindow->edl->session->audio_channels,
1058                                                 mwindow->edl->session->real_time_playback);
1059                         }
1060                 }
1062                 if(!audio_opened)
1063                 {
1064                         adevice->open_input(mwindow->edl->session->aconfig_in, 
1065                                 mwindow->edl->session->vconfig_in, 
1066                                 default_asset->sample_rate, 
1067                                 get_in_length(),
1068                                 default_asset->channels,
1069                                 mwindow->edl->session->real_time_record);
1070                         adevice->start_recording();
1071                 }
1072         }
1075 // Initialize video
1076         if(vdevice)
1077         {
1078                 vdevice->set_quality(default_asset->jpeg_quality);
1079                 vdevice->open_input(mwindow->edl->session->vconfig_in, 
1080                         video_x, 
1081                         video_y, 
1082                         video_zoom,
1083                         default_asset->frame_rate);
1085 // Get configuration parameters from device probe
1086                 color_model = vdevice->get_best_colormodel(default_asset);
1087                 master_channel->copy_usage(vdevice->channel);
1088                 picture->copy_usage(vdevice->picture);
1089                 vdevice->set_field_order(reverse_interlace);
1091 // Set the device configuration
1092                 set_channel(get_current_channel());
1093         }
1095         return 0;
1098 int Record::close_input_devices(int is_monitor)
1100         if(is_monitor && capture_state != IS_MONITORING) return 0;
1102         if(vdevice)
1103         {
1104                 vdevice->close_all();
1105                 delete vdevice;
1106                 vdevice = 0;
1107         }
1109         if(adevice)
1110         {
1111                 adevice->close_all();
1112                 delete adevice;
1113                 adevice = 0;
1114         }
1116         return 0;
1119 int Record::start_recording(int duplex, int context)
1121         if(capture_state != IS_RECORDING)
1122         {
1123                 pause_monitor();
1125 // Want the devices closed during file deletion to avoid buffer overflow
1126                 delete_output_file();
1128 // These two contexts need to open the device here to allow full duplex.  
1129 // Batch context opens them in RecordThread::run
1130                 if(context == CONTEXT_INTERACTIVE ||
1131                         context == CONTEXT_SINGLEFRAME)
1132                         open_input_devices(duplex, context);
1134                 prompt_cancel = 1;
1136 // start the duplex engine if necessary
1137 // OSS < 3.9 crashes if recording starts before playback
1138 // OSS >= 3.9 crashes if playback starts before recording
1139                 if(duplex)
1140                 {
1141                         capture_state = IS_DUPLEXING;
1142                 }
1143                 else
1144                         capture_state = IS_RECORDING;
1146 // Toggle once to cue the user that we're not dead.
1147                 if(context == CONTEXT_BATCH)
1148                 {
1149                         record_gui->lock_window("Record::start_recording");
1150                         record_gui->flash_batch();
1151                         record_gui->unlock_window();
1152                 }
1153                 record_engine->start_recording(0, context);
1154         }
1155         return 0;
1158 int Record::start_monitor()
1160         monitor_timer.update();
1161         open_input_devices(0, CONTEXT_INTERACTIVE);
1162         monitor_engine->start_recording(1, CONTEXT_INTERACTIVE);
1163         capture_state = IS_MONITORING;
1164         return 0;
1167 int Record::stop_monitor()
1169         monitor_engine->stop_recording(0);
1170         return 0;
1173 int Record::pause_monitor()
1175         if(capture_state == IS_MONITORING)
1176         {
1177                 monitor_engine->pause_recording();
1178         }
1179         return 0;
1182 int Record::resume_monitor()
1184         if(capture_state != IS_MONITORING)
1185         {
1186                 capture_state = IS_MONITORING;
1187                 monitor_timer.update();
1188                 open_input_devices(0, CONTEXT_INTERACTIVE);
1189                 monitor_engine->resume_recording();
1190         }
1191         return 0;
1194 int Record::stop_duplex()
1196         return 0;
1199 int Record::stop_operation(int resume_monitor)
1201         switch(capture_state)
1202         {
1203                 case IS_MONITORING:
1204                         if(!resume_monitor) monitor_engine->stop_recording(0);
1205                         break;
1206                 case IS_RECORDING:
1207                         record_engine->stop_recording(resume_monitor);
1208                         break;
1209                 case IS_DUPLEXING:
1210                         break;
1211                 case IS_PREVIEWING:
1212                         break;
1213         }
1214         return 0;
1218 // Remember to change meters if you change this.
1219 // Return the size of the fragments to read from the audio device.
1220 int Record::get_in_length()
1222         int64_t fragment_size = 1;
1223         while(fragment_size < default_asset->sample_rate / 
1224                 mwindow->edl->session->record_speed)
1225                 fragment_size *= 2;
1226         fragment_size /= 2;
1227         fragment_size = MAX(fragment_size, 512);
1228         return fragment_size;
1231 int Record::set_video_picture()
1233         if(default_asset->video_data && vdevice)
1234                 vdevice->set_picture(picture);
1235         return 0;
1238 void Record::set_translation(int x, int y)
1240         video_x = x;
1241         video_y = y;
1242         if(default_asset->video_data && vdevice)
1243                 vdevice->set_translation(video_x, video_y);
1247 int Record::set_channel(int channel)
1249         if(channel >= 0 && channel < channeldb->size())
1250         {
1251                 char string[BCTEXTLEN];
1252                 get_editing_batch()->channel = channel;
1253                 source_to_text(string, get_editing_batch());
1256                 record_gui->lock_window("Record::set_channel");
1257                 record_gui->batch_source->update(string);
1258                 record_monitor->window->channel_picker->channel_text->update(string);
1259                 record_gui->update_batches();
1260                 record_gui->unlock_window();
1263                 if(vdevice)
1264                 {
1265                         vdevice->set_channel(channeldb->get(channel));
1266                         set_video_picture();
1267                 }
1268         }
1269         return 0;
1272 // Change to a channel not in the db for editing
1273 void Record::set_channel(Channel *channel)
1275         if(vdevice) vdevice->set_channel(channel);
1278 int Record::has_signal()
1280         if(vdevice) return vdevice->has_signal();
1281         return 0;
1284 void Record::get_current_time(double &seconds, int &day)
1286         time_t result = time(0) + 1;
1287         struct tm *struct_tm = localtime(&result);
1288         day = struct_tm->tm_wday;
1289         seconds = struct_tm->tm_hour * 3600 + struct_tm->tm_min * 60 + struct_tm->tm_sec;
1303 int Record::get_time_format()
1305         return mwindow->edl->session->time_format;
1308 float Record::get_frame_rate()
1310         return 0.0;
1311 //      return mwindow->session->frame_rate;
1314 int Record::set_loop_duration(int64_t value)
1316         loop_duration = value; 
1317         return 0;
1320 int Record::get_vu_format() { return mwindow->edl->session->meter_format; }
1321 float Record::get_min_db() { return mwindow->edl->session->min_meter_db; }
1323 int Record::get_rec_mode() { return record_mode; }
1324 int Record::set_rec_mode(int value) { record_mode = value; }
1326 int Record::get_video_buffersize() { return mwindow->edl->session->video_write_length; }
1327 int Record::get_everyframe() { return mwindow->edl->session->video_every_frame; }
1329 int Record::get_out_length() { return mwindow->edl->session->playback_buffer; }
1330 int Record::get_software_positioning() { return mwindow->edl->session->record_software_position; }
1331 int64_t Record::get_out_buffersize() { return mwindow->edl->session->playback_buffer; }
1332 int64_t Record::get_in_buffersize() { return mwindow->edl->session->record_write_length; }
1333 int Record::get_realtime() { return realtime; }
1334 int Record::get_meter_speed() { return mwindow->edl->session->record_speed; }
1336 int Record::enable_duplex() { return mwindow->edl->session->enable_duplex; }
1337 int64_t Record::get_playback_buffer() { return mwindow->edl->session->playback_buffer; }