r1014: Enable horizontal scrolling with the mouse wheel by pressing Ctrl.
[cinelerra_cv/ct.git] / cinelerra / record.C
bloba01a9b129aa436ed6c834ecf800ac5f2dfcfb44a
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 "removethread.h"
40 #include "mainsession.h"
41 #include "sighandler.h"
42 #include "testobject.h"
43 #include "theme.h"
44 #include "timebar.h"
45 #include "tracks.h"
46 #include "videoconfig.h"
47 #include "videodevice.h"
49 #include <string.h>
53 RecordMenuItem::RecordMenuItem(MWindow *mwindow)
54  : BC_MenuItem(_("Record..."), "r", 'r')
56         this->mwindow = mwindow;
57         thread = new Record(mwindow, this);
58         current_state = RECORD_NOTHING;
61 RecordMenuItem::~RecordMenuItem()
63         delete thread;
66 int RecordMenuItem::handle_event()
68         if(thread->running()) 
69         {
70                 switch(current_state)
71                 {
72                         case RECORD_INTRO:
73                                 thread->window_lock->lock("RecordMenuItem::handle_event 1");
74                                 if(thread->record_window)
75                                 {
76                                         thread->record_window->lock_window("RecordMenuItem::handle_event 1");
77                                         thread->record_window->raise_window();
78                                         thread->record_window->unlock_window();
79                                 }
80                                 thread->window_lock->unlock();
81                                 break;
82                         
83                         case RECORD_CAPTURING:
84                                 thread->window_lock->lock("RecordMenuItem::handle_event 2");
85                                 if(thread->record_gui)
86                                 {
87                                         thread->record_gui->lock_window("RecordMenuItem::handle_event 2");
88                                         thread->record_gui->raise_window();
89                                         thread->record_gui->unlock_window();
90                                 }
91                                 thread->window_lock->unlock();
92                                 break;
93                 }
94                 return 0;
95         }
97         thread->start();
98         return 1;
110 Record::Record(MWindow *mwindow, RecordMenuItem *menu_item)
111  : Thread()
113         this->mwindow = mwindow;
114         this->menu_item = menu_item;
115         script = 0;
116         capture_state = IS_DONE;
117         adevice = 0;
118         vdevice = 0;
119         file = 0;
120         editing_batch = 0;
121         current_batch = 0;
122 SET_TRACE
123         picture = new PictureConfig(mwindow->defaults);
124 SET_TRACE
125         channeldb = new ChannelDB;
126         master_channel = new Channel;
127         window_lock = new Mutex("Record::window_lock");
130 Record::~Record()
132         delete picture;
133         delete channeldb;
134         delete master_channel;
135         delete window_lock;
139 int Record::load_defaults()
141         char string[BCTEXTLEN];
142         BC_Hash *defaults = mwindow->defaults;
144 // Load file format
145 //      default_asset->load_defaults(defaults, 
146 //              "RECORD_", 
147 //              1,
148 //              1,
149 //              1,
150 //              1,
151 //              1);
152 // This reads back everything that was saved in save_defaults.
153         default_asset->copy_from(mwindow->edl->session->recording_format, 0);
154         default_asset->channels = mwindow->edl->session->aconfig_in->channels;
155         default_asset->sample_rate = mwindow->edl->session->aconfig_in->in_samplerate;
156         default_asset->frame_rate = mwindow->edl->session->vconfig_in->in_framerate;
157         default_asset->width = mwindow->edl->session->vconfig_in->w;
158         default_asset->height = mwindow->edl->session->vconfig_in->h;
159         default_asset->layers = 1;
163 // Fix encoding parameters depending on driver.
164 // These are locked by a specific driver.
165         if(mwindow->edl->session->vconfig_in->driver == CAPTURE_LML ||
166                 mwindow->edl->session->vconfig_in->driver == CAPTURE_BUZ ||
167                 mwindow->edl->session->vconfig_in->driver == VIDEO4LINUX2JPEG)
168                 strncpy(default_asset->vcodec, QUICKTIME_MJPA, 4);
169         else
170         if(mwindow->edl->session->vconfig_in->driver == CAPTURE_FIREWIRE ||
171                 mwindow->edl->session->vconfig_in->driver == CAPTURE_IEC61883)
172         {
173                 strncpy(default_asset->vcodec, QUICKTIME_DVSD, 4);
174         }
179 // Load batches
180         int total_batches = defaults->get("TOTAL_BATCHES", 1);
181         if(total_batches < 1) total_batches = 1;
182         for(int i = 0; i < total_batches; i++)
183         {
184                 Batch *batch = new_batch();
185                 Asset *asset = batch->assets.values[0];
187                 sprintf(string, "RECORD_PATH_%d", i);
188                 defaults->get(string, asset->path);
189                 sprintf(string, "RECORD_CHANNEL_%d", i);
190                 batch->channel = defaults->get(string, batch->channel);
191                 sprintf(string, "RECORD_STARTTYPE_%d", i);
192                 batch->start_type = defaults->get(string, batch->start_type);
193                 sprintf(string, "RECORD_STARTDAY_%d", i);
194                 batch->start_day = defaults->get(string, batch->start_day);
195                 sprintf(string, "RECORD_STARTTIME_%d", i);
196                 batch->start_time = defaults->get(string, batch->start_time);
197                 sprintf(string, "RECORD_DURATION_%d", i);
198                 batch->duration = defaults->get(string, batch->duration);
199                 sprintf(string, "RECORD_MODE_%d", i);
200                 batch->record_mode = defaults->get(string, batch->record_mode);
201                 sprintf(string, "BATCH_ENABLED_%d", i);
202                 batch->enabled = defaults->get(string, batch->enabled);
203         }
206         load_mode = defaults->get("RECORD_LOADMODE", LOAD_PASTE);
208         monitor_audio = defaults->get("RECORD_MONITOR_AUDIO", 1);
209         monitor_video = defaults->get("RECORD_MONITOR_VIDEO", 1);
210         video_window_open = defaults->get("RECORD_MONITOR_OPEN", 1);
211         video_x = defaults->get("RECORD_VIDEO_X", 0);
212         video_y = defaults->get("RECORD_VIDEO_Y", 0);
213         video_zoom = defaults->get("RECORD_VIDEO_Z", (float)1);
215 SET_TRACE
216         picture->load_defaults();
217 SET_TRACE
219         reverse_interlace = defaults->get("REVERSE_INTERLACE", 0);
220         for(int i = 0; i < MAXCHANNELS; i++) 
221         {
222                 sprintf(string, "RECORD_DCOFFSET_%d", i);
223                 dc_offset[i] = defaults->get(string, 0);
224         }
225         fill_frames = defaults->get("FILL_DROPPED_FRAMES", 0);
226         return 0;
229 int Record::save_defaults()
231         char string[BCTEXTLEN];
232         BC_Hash *defaults = mwindow->defaults;
233         editing_batch = 0;
235 // Save default asset path but not the format because that's
236 // overridden by the driver.
237 // The format is saved in preferences.
238         if(batches.total)
239                 strcpy(default_asset->path, batches.values[0]->assets.values[0]->path);
240         default_asset->save_defaults(defaults,
241                 "RECORD_",
242                 0,
243                 0,
244                 0,
245                 0,
246                 0);
248 //      default_asset->save_defaults(defaults,
249 //              "RECORD_",
250 //              1,
251 //              !fixed_compression,
252 //              1,
253 //              1,
254 //              1);
256 //      defaults->update("RECORD_CHANNELS", default_asset->channels);
263         defaults->update("TOTAL_BATCHES", batches.total);
264         for(int i = 0; i < batches.total; i++)
265         {
266                 Batch *batch = batches.values[i];
267                 Asset *asset = batch->assets.values[0];
269                 sprintf(string, "RECORD_PATH_%d", i);
270                 defaults->update(string, asset->path);
271                 sprintf(string, "RECORD_CHANNEL_%d", i);
272                 defaults->update(string, batch->channel);
273                 sprintf(string, "RECORD_STARTTYPE_%d", i);
274                 defaults->update(string, batch->start_type);
275                 sprintf(string, "RECORD_STARTDAY_%d", i);
276                 defaults->update(string, batch->start_day);
277                 sprintf(string, "RECORD_STARTTIME_%d", i);
278                 defaults->update(string, batch->start_time);
279                 sprintf(string, "RECORD_DURATION_%d", i);
280                 defaults->update(string, batch->duration);
281                 sprintf(string, "RECORD_MODE_%d", i);
282                 defaults->update(string, batch->record_mode);
283                 sprintf(string, "BATCH_ENABLED_%d", i);
284                 defaults->update(string, batch->enabled);
285         }
288         defaults->update("RECORD_LOADMODE", load_mode);
289         defaults->update("RECORD_MONITOR_AUDIO", monitor_audio);
290         defaults->update("RECORD_MONITOR_VIDEO", monitor_video);
291         defaults->update("RECORD_MONITOR_OPEN", video_window_open);
292         defaults->update("RECORD_VIDEO_X", video_x);
293         defaults->update("RECORD_VIDEO_Y", video_y);
294         defaults->update("RECORD_VIDEO_Z", video_zoom);
295         
296 SET_TRACE
297         picture->save_defaults();
298 SET_TRACE
299         defaults->update("REVERSE_INTERLACE", reverse_interlace);
300         for(int i = 0; i < MAXCHANNELS; i++)
301         {
302                 sprintf(string, "RECORD_DCOFFSET_%d", i);
303                 defaults->update(string, dc_offset[i]);
304         }
305         defaults->update("FILL_DROPPED_FRAMES", fill_frames);
307         return 0;
310 void Record::configure_batches()
312         strcpy(batches.values[0]->assets.values[0]->path, default_asset->path);
313         for(int i = 0; i < batches.total; i++)
314         {
315                 Batch *batch = batches.values[i];
316 // Update format
317                 batch->get_current_asset()->copy_format(default_asset);
319 // Update news
320                 batch->calculate_news();
321         }
324 void Record::source_to_text(char *string, Batch *batch)
326 // Update source
327         strcpy(string, "Record::source_to_text: not implemented");
328         switch(mwindow->edl->session->vconfig_in->driver)
329         {
330                 case VIDEO4LINUX:
331                 case VIDEO4LINUX2:
332                 case CAPTURE_BUZ:
333                 case VIDEO4LINUX2JPEG:
334                         if(batch->channel < 0 || batch->channel >= channeldb->size())
335                                 sprintf(string, _("None"));
336                         else
337                                 sprintf(string, channeldb->get(batch->channel)->title);
338                         break;
339         }
343 void Record::run()
345         int result = 0, format_error = 0;
346         int64_t start, end;
347         record_gui = 0;
349 // Default asset forms the first path in the batch capture
350 // and the file format for all operations.
351         default_asset = new Asset;
352         prompt_cancel = 0;
354 // Determine information about the device.
355         VideoDevice::load_channeldb(channeldb, mwindow->edl->session->vconfig_in);
356         fixed_compression = VideoDevice::is_compressed(
357                 mwindow->edl->session->vconfig_in->driver,
358                 0,
359                 1);
360         load_defaults();
362         if(fixed_compression)
363         {
364                 VideoDevice device;
365                 device.fix_asset(default_asset, 
366                         mwindow->edl->session->vconfig_in->driver);
367         }
370         menu_item->current_state = RECORD_INTRO;
372 // // Get information about the file format
373 //      do
374 //      {
375 //              int x = mwindow->gui->get_root_w(0, 1) / 2 - RECORD_WINDOW_WIDTH / 2;
376 //              int y = mwindow->gui->get_root_h(1) / 2 - RECORD_WINDOW_HEIGHT / 2;
378 //              window_lock->lock("Record::run 1");
379 //              record_window = new RecordWindow(mwindow, this, x, y);
380 //              record_window->create_objects();
381 //              window_lock->unlock();
382 // 
383 // 
384 //              result = record_window->run_window();
385 //              window_lock->lock("Record::run 2");
386 //              delete record_window;
387 //              record_window = 0;
388 //              window_lock->unlock();
389 // 
390 // 
391 // 
392 //              if(!result)
393 //              {
394 //                      FormatCheck check_format(default_asset);
395 //                      format_error = check_format.check_format();
396 //              }
397 //      }while(format_error && !result);
399         default_asset->channels = mwindow->edl->session->aconfig_in->channels;
400         VideoDevice::save_channeldb(channeldb, mwindow->edl->session->vconfig_in);
401         save_defaults();
402         mwindow->save_defaults();
404         configure_batches();
405         current_batch = 0;
406         editing_batch = 0;
408 // Run recordgui
409         if(!result)
410         {
411                 edl = new EDL;
412                 edl->create_objects();
413                 edl->session->output_w = default_asset->width;
414                 edl->session->output_h = default_asset->height;
415                 edl->session->aspect_w = mwindow->edl->session->aspect_w;
416                 edl->session->aspect_h = mwindow->edl->session->aspect_h;
418 SET_TRACE
419                 window_lock->lock("Record::run 3");
420 SET_TRACE
421                 record_gui = new RecordGUI(mwindow, this);
422                 record_gui->load_defaults();
423                 record_gui->create_objects();
425 SET_TRACE
426                 record_monitor = new RecordMonitor(mwindow, this);
427 SET_TRACE
428                 record_monitor->create_objects();
429 SET_TRACE
430                 record_gui->update_batch_sources();
432 SET_TRACE
433                 menu_item->current_state = RECORD_CAPTURING;
434                 record_engine = new RecordThread(mwindow, this);
435                 record_engine->create_objects();
436                 monitor_engine = new RecordThread(mwindow, this);
437                 monitor_engine->create_objects();
439 SET_TRACE
441                 record_gui->show_window();
442                 record_gui->flush();
443                 if(video_window_open)
444                 {
445                         record_monitor->window->show_window();
446                         record_monitor->window->raise_window();
447                         record_monitor->window->flush();
448                 }
450 SET_TRACE
451                 start_monitor();
453 SET_TRACE
454                 window_lock->unlock();
456                 result = record_gui->run_window();
457 // Must unlock to stop operation
458                 record_gui->unlock_window();
460 // Force monitor to quit without resuming
461                 if(monitor_engine->record_video) 
462                         monitor_engine->record_video->batch_done = 1;
463                 else if (monitor_engine->record_audio)
464                         monitor_engine->record_audio->batch_done = 1;
466 SET_TRACE
467 //              stop_operation(0);
468 // Need to stop everything this time
469                 monitor_engine->stop_recording(0);
470 SET_TRACE
471                 record_engine->stop_recording(0);
472 SET_TRACE
474                 close_output_file();
475 SET_TRACE
477                 window_lock->lock("Record::run 4");
479 SET_TRACE
480                 delete record_monitor;
481                 record_monitor = 0;
482 SET_TRACE
485                 delete record_engine;
486                 record_engine = 0;
487 SET_TRACE
489                 delete monitor_engine;
490                 monitor_engine = 0;
492 SET_TRACE
493                 record_gui->save_defaults();
495 SET_TRACE
496                 delete record_gui;
497                 record_gui = 0;
498                 window_lock->unlock();
500 SET_TRACE
501                 delete edl;
503 SET_TRACE
504         }
506         menu_item->current_state = RECORD_NOTHING;
508 // Save everything again
509         save_defaults();
515 // Paste into EDL
516         if(!result && load_mode != LOAD_NOTHING)
517         {
518                 mwindow->gui->lock_window("Record::run");
519                 ArrayList<EDL*> new_edls;
522 // Paste assets
523                 for(int i = 0; i < batches.total; i++)
524                 {
525                         Batch *batch = batches.values[i];
526                         Asset *asset = batch->get_current_asset();
528                         if(batch->recorded)
529                         {
530                                 for(int j = 0; j < batch->assets.total; j++)
531                                 {
532                                         Asset *new_asset = batch->assets.values[j];
533                                         EDL *new_edl = new EDL;
534                                         mwindow->remove_asset_from_caches(new_asset);
535                                         new_edl->create_objects();
536                                         new_edl->copy_session(mwindow->edl);
537                                         mwindow->asset_to_edl(new_edl, 
538                                                 new_asset, 
539                                                 batch->labels);
540                                         new_edls.append(new_edl);
541                                 }
542                         }
543                 }
545                 if(new_edls.total)
546                 {
548 // For pasting, clear the active region
549                         if(load_mode == LOAD_PASTE)
550                         {
551                                 mwindow->clear(0);
552                         }
554                         mwindow->paste_edls(&new_edls, 
555                                 load_mode,
556                                 0,
557                                 -1,
558                                 mwindow->edl->session->labels_follow_edits,
559                                 mwindow->edl->session->plugins_follow_edits,
560                                 0); // overwrite
561 //printf("Record::run 7\n");
563                         new_edls.remove_all_objects();
564 //printf("Record::run 8\n");
566                         mwindow->save_backup();
567                         mwindow->undo->update_undo(_("record"), LOAD_ALL);
568                         mwindow->restart_brender();
569                         mwindow->update_plugin_guis();
570                         mwindow->gui->update(1, 
571                                 2,
572                                 1,
573                                 1,
574                                 1,
575                                 1,
576                                 0);
577                         mwindow->sync_parameters(CHANGE_ALL);
578                 }
579                 mwindow->gui->unlock_window();
580         }
582 // Delete everything
583         script = 0;
584         batches.remove_all_objects();
585         Garbage::delete_object(default_asset);
588 void Record::activate_batch(int number, int stop_operation)
590         if(number != current_batch)
591         {
592                 if(stop_operation) this->stop_operation(1);
593                 close_output_file();
594                 get_current_batch()->calculate_news();
596                 current_batch = number;
597                 record_gui->update_batches();
598                 record_gui->update_position(current_display_position());
599                 record_gui->update_batch_tools();
600         }
603 void Record::delete_batch()
605 // Abort if one batch left
606         if(batches.total > 1)
607         {
608 // Stop operation if active batch
609                 if(current_batch == editing_batch)
610                 {
611                         if(current_batch < batches.total - 1)
612                                 activate_batch(current_batch + 1, 1);
613                         else
614                                 activate_batch(current_batch - 1, 1);
616                         delete batches.values[editing_batch];
617                         batches.remove_number(editing_batch);
618                         editing_batch = current_batch;
619                 }
620                 else
621                 {
622                         if(current_batch > editing_batch) current_batch--;
623                         delete batches.values[editing_batch];
624                         batches.remove_number(editing_batch);
625                         if(editing_batch >= batches.total) editing_batch--;
626                 }
627                 record_gui->update_batch_tools();
628         }
631 void Record::change_editing_batch(int number)
633         this->editing_batch = number;
634         record_gui->update_batch_tools();
637 Batch* Record::new_batch()
639         Batch *result = new Batch(mwindow, this);
640 //printf("Record::new_batch 1\n");
641         result->create_objects();
642         batches.append(result);
643         result->get_current_asset()->copy_format(default_asset);
644         
645 //printf("Record::new_batch 1\n");
647         result->create_default_path();
648         result->calculate_news();
649         if(get_editing_batch()) result->copy_from(get_editing_batch());
650         editing_batch = batches.total - 1;
651 //printf("Record::new_batch 1\n");
652 // Update GUI if created yet
653         if(record_gui) record_gui->update_batch_tools();
654 //printf("Record::new_batch 2\n");
655         return result;
658 int Record::delete_output_file()
660         FILE *test;
664 // Delete old file
665         if(!file)
666         {
667                 Batch *batch = get_current_batch();
668                 if(batch && (test = fopen(batch->get_current_asset()->path, "r")))
669                 {
670                         fclose(test);
672                         record_gui->lock_window("Record::delete_output_file");
674 // Update GUI
675                         sprintf(batch->news, _("Deleting"));
676                         record_gui->update_batches();
678 // Remove it from disk
679                         mwindow->remove_asset_from_caches(batch->get_current_asset());
680                         mwindow->remove_thread->remove_file(batch->get_current_asset()->path);
681 //                      remove(batch->get_current_asset()->path);
683 // Update GUI
684                         sprintf(batch->news, _("OK"));
685                         record_gui->update_batches();
687                         record_gui->unlock_window();
688                 }
689         }
690         return 0;
693 int Record::open_output_file()
695         int result = 0;
696 // Create initial file for the batch
697         if(!file)
698         {
699                 Batch *batch = get_current_batch();
700                 delete_output_file();
702                 file = new File;
703                 result = file->open_file(mwindow->preferences, 
704                         batch->get_current_asset(), 
705                         0, 
706                         1, 
707                         default_asset->sample_rate, 
708                         default_asset->frame_rate);
710                 if(result)
711                 {
712                         delete file;
713                         file = 0;
714                 }
715                 else
716                 {
717                         mwindow->sighandler->push_file(file);
718                         IndexFile::delete_index(mwindow->preferences, 
719                                 batch->get_current_asset());
720                         file->set_processors(mwindow->preferences->real_processors);
721                         batch->calculate_news();
722                         record_gui->lock_window("Record::open_output_file");
723                         record_gui->update_batches();
724                         record_gui->unlock_window();
725                 }
726         }
727         return result;
730 int Record::init_next_file()
732         Batch *batch = get_current_batch();
733         Asset *asset;
735         if(file)
736         {
737                 mwindow->sighandler->pull_file(file);
738                 file->close_file();
739                 delete file;
740                 file = 0;
741         }
743         batch->current_asset++;
744         batch->assets.append(asset = new Asset);
745         *asset = *default_asset;
746         sprintf(asset->path, "%s%03d", asset->path, batch->current_asset);
747         int result = open_output_file();
748         return result;
751 // Rewind file at the end of a loop.
752 // This is called by RecordThread.
753 void Record::rewind_file()
755         if(file)
756         {
757                 if(default_asset->audio_data) 
758                         file->set_audio_position(0, default_asset->frame_rate);
759                 if(default_asset->video_data)
760                         file->set_video_position(0, default_asset->frame_rate);
761         }
763         get_current_batch()->current_sample = 0;
764         get_current_batch()->current_frame = 0;
765         record_gui->lock_window("Record::rewind_file");
766         record_gui->update_position(0);
767         record_gui->unlock_window();
770 void Record::start_over()
772         stop_operation(1);
774         Batch *batch = get_current_batch();
775         if(file)
776         {
777                 mwindow->sighandler->pull_file(file);
778                 file->close_file();
779                 delete file;
780                 file = 0;
781         }
783         get_current_batch()->start_over();
785         record_gui->lock_window("Record::start_over");
786         record_gui->update_position(0);
787         record_gui->update_batches();
788         record_gui->unlock_window();
791 void Record::close_output_file()
793 // Can't close until recordmonitor is done
794 //printf("Record::close_output_file 1\n");
795         if(file)
796         {
797                 mwindow->sighandler->pull_file(file);
798                 file->close_file();
799                 delete file;
800                 file = 0;
801         }
802 //printf("Record::close_output_file 2\n");
805 void Record::toggle_label()
807         get_current_batch()->toggle_label(current_display_position());
808         record_gui->update_labels(current_display_position());
811 void Record::get_audio_write_length(int &buffer_size, 
812         int &fragment_size)
814         fragment_size = 1;
815         while(fragment_size < default_asset->sample_rate / mwindow->edl->session->record_speed) 
816                 fragment_size *= 2;
817         fragment_size /= 2;
818         CLAMP(fragment_size, 1024, 32768);
820         for(buffer_size = fragment_size; 
821                 buffer_size < mwindow->edl->session->record_write_length; 
822                 buffer_size += fragment_size)
823                 ;
826 Batch* Record::get_current_batch()
828         if(batches.total)
829                 return batches.values[current_batch];
830         else
831                 return 0;
834 int Record::get_next_batch()
836         int i = current_batch;
837         while(i < batches.total - 1)
838         {
839                 i++;
840                 if(batches.values[i]->enabled) return i;
841         }
842         return -1;
846 Batch* Record::get_editing_batch()
848 //printf("Record::get_editing_batch %d %d\n", batches.total, editing_batch);
850         if(batches.total)
851                 return batches.values[editing_batch];
852         else
853                 return 0;
856 char* Record::current_mode()
858         return Batch::mode_to_text(get_current_batch()->record_mode);
861 int64_t Record::batch_video_offset()
863         return (int64_t)((double)get_current_batch()->file_offset * 
864                 default_asset->frame_rate + 0.5);
867 int64_t Record::current_audio_position()
869         if(file)
870         {
871                 return (int64_t)(file->get_audio_position(default_asset->sample_rate) + 
872                         get_current_batch()->file_offset + 0.5);
873         }
874         return 0;
877 int64_t Record::current_video_position()
879         if(file)
880         {
881                 return file->get_video_position(default_asset->frame_rate) + 
882                         (int64_t)((double)get_current_batch()->file_offset / 
883                                 default_asset->sample_rate * 
884                                 default_asset->frame_rate + 
885                                 0.5);
886         }
887         return 0;
890 double Record::current_display_position()
892 //printf("Record::current_display_position %d %d\n", get_current_batch()->current_sample, get_current_batch()->file_offset);
895         if(default_asset->video_data)
896                 return (double)get_current_batch()->current_frame / 
897                         default_asset->frame_rate + 
898                         get_current_batch()->file_offset;
899         else
900                 return (double)get_current_batch()->current_sample / 
901                         default_asset->sample_rate + 
902                         get_current_batch()->file_offset;
903         return 0;
906 char* Record::current_source()
908         return get_current_batch()->get_source_text();
911 char* Record::current_news()
913         return batches.values[current_batch]->news;
916 Asset* Record::current_asset()
918         return batches.values[current_batch]->get_current_asset();
921 double* Record::current_start()
923         return &batches.values[current_batch]->start_time;
926 int Record::get_current_channel()
928         return get_current_batch()->channel;
931 int Record::get_editing_channel()
933         return get_editing_batch()->channel;
936 Channel* Record::get_current_channel_struct()
938         int channel = get_current_channel();
939         if(channel >= 0 && channel < channeldb->size())
940         {
941                 return channeldb->get(channel);
942         }
943         return 0;
946 double* Record::current_duration()
948         return &batches.values[current_batch]->duration;
951 int64_t Record::current_duration_samples()
953         return (int64_t)((float)batches.values[current_batch]->duration * default_asset->sample_rate + 0.5);
956 int64_t Record::current_duration_frames()
958         return (int64_t)((float)batches.values[current_batch]->duration * default_asset->frame_rate + 0.5);
961 int* Record::current_offset_type()
963         return &batches.values[current_batch]->start_type;
966 ArrayList<Channel*>* Record::get_video_inputs() 
968         if(default_asset->video_data && vdevice) 
969                 return vdevice->get_inputs();
970         else
971                 return 0;
974 int64_t Record::sync_position()
976         switch(capture_state)
977         {
978                 case IS_DONE:
979                         return -1;
980                         break;    
981                 case IS_MONITORING:
982                         return monitor_engine->sync_position();
983                         break;    
984                 case IS_DUPLEXING: 
985                 case IS_RECORDING: 
986                         return record_engine->sync_position();
987                         break;    
988         }
989         return 0;
993 int Record::open_input_devices(int duplex, int context)
995         int audio_opened = 0;
996         int video_opened = 0;
997         AudioInConfig *aconfig_in = mwindow->edl->session->aconfig_in;
1000 // Create devices
1001         if(default_asset->audio_data && context != CONTEXT_SINGLEFRAME)
1002                 adevice = new AudioDevice(mwindow);
1003         else
1004                 adevice = 0;
1006         if(default_asset->video_data)
1007                 vdevice = new VideoDevice(mwindow);
1008         else
1009                 vdevice = 0;
1011 // Initialize sharing
1012         if(adevice && vdevice)
1013         {
1014                 vdevice->set_adevice(adevice);
1015                 adevice->set_vdevice(vdevice);
1016         }
1018 // Configure audio
1019         if(adevice)
1020         {
1021                 adevice->set_software_positioning(mwindow->edl->session->record_software_position);
1023 // Initialize full duplex
1024 // Duplex is only needed if the timeline and the recording have audio
1025                 if(duplex && mwindow->edl->tracks->playable_audio_tracks())
1026                 {
1027 // Case 1: duplex device is identical to input device
1028 //                      if(AudioInConfig::is_duplex(aconfig_in, mwindow->edl->session->aconfig_duplex))
1029 //                      {
1030 //                              adevice->open_duplex(mwindow->edl->session->aconfig_duplex,
1031 //                                                      default_asset->sample_rate,
1032 //                                                      get_in_length(),
1033 //                                                      mwindow->edl->session->real_time_playback);
1034 //                              audio_opened = 1;
1035 //                      }
1036 //                      else
1037 // Case 2: two separate devices
1038                         {
1039                                 adevice->open_output(mwindow->edl->session->aconfig_duplex,
1040                                                 default_asset->sample_rate,
1041                                                 mwindow->edl->session->playback_buffer,
1042                                                 mwindow->edl->session->audio_channels,
1043                                                 mwindow->edl->session->real_time_playback);
1044                         }
1045                 }
1047                 if(!audio_opened)
1048                 {
1049                         adevice->open_input(mwindow->edl->session->aconfig_in, 
1050                                 mwindow->edl->session->vconfig_in, 
1051                                 default_asset->sample_rate, 
1052                                 get_in_length(),
1053                                 default_asset->channels,
1054                                 mwindow->edl->session->real_time_record);
1055                         adevice->start_recording();
1056                 }
1057         }
1060 // Initialize video
1061         if(vdevice)
1062         {
1063                 vdevice->set_quality(default_asset->jpeg_quality);
1064                 vdevice->open_input(mwindow->edl->session->vconfig_in, 
1065                         video_x, 
1066                         video_y, 
1067                         video_zoom,
1068                         default_asset->frame_rate);
1070 // Get configuration parameters from device probe
1071                 color_model = vdevice->get_best_colormodel(default_asset);
1072                 master_channel->copy_usage(vdevice->channel);
1073                 picture->copy_usage(vdevice->picture);
1074                 vdevice->set_field_order(reverse_interlace);
1076 // Set the device configuration
1077                 set_channel(get_current_channel());
1078         }
1080         return 0;
1083 int Record::close_input_devices(int is_monitor)
1085         if(is_monitor && capture_state != IS_MONITORING) return 0;
1087         if(vdevice)
1088         {
1089                 vdevice->close_all();
1090                 delete vdevice;
1091                 vdevice = 0;
1092         }
1094         if(adevice)
1095         {
1096                 adevice->close_all();
1097                 delete adevice;
1098                 adevice = 0;
1099         }
1101         return 0;
1104 int Record::start_recording(int duplex, int context)
1106         if(capture_state != IS_RECORDING)
1107         {
1108                 pause_monitor();
1110 // Want the devices closed during file deletion to avoid buffer overflow
1111                 delete_output_file();
1113 // These two contexts need to open the device here to allow full duplex.  
1114 // Batch context opens them in RecordThread::run
1115                 if(context == CONTEXT_INTERACTIVE ||
1116                         context == CONTEXT_SINGLEFRAME)
1117                         open_input_devices(duplex, context);
1119                 prompt_cancel = 1;
1121 // start the duplex engine if necessary
1122 // OSS < 3.9 crashes if recording starts before playback
1123 // OSS >= 3.9 crashes if playback starts before recording
1124                 if(duplex)
1125                 {
1126                         capture_state = IS_DUPLEXING;
1127                 }
1128                 else
1129                         capture_state = IS_RECORDING;
1131 // Toggle once to cue the user that we're not dead.
1132                 if(context == CONTEXT_BATCH)
1133                 {
1134                         record_gui->lock_window("Record::start_recording");
1135                         record_gui->flash_batch();
1136                         record_gui->unlock_window();
1137                 }
1138                 record_engine->start_recording(0, context);
1139         }
1140         return 0;
1143 int Record::start_monitor()
1145         monitor_timer.update();
1146         open_input_devices(0, CONTEXT_INTERACTIVE);
1147         monitor_engine->start_recording(1, CONTEXT_INTERACTIVE);
1148         capture_state = IS_MONITORING;
1149         return 0;
1152 int Record::stop_monitor()
1154         monitor_engine->stop_recording(0);
1155         return 0;
1158 int Record::pause_monitor()
1160         if(capture_state == IS_MONITORING)
1161         {
1162                 monitor_engine->pause_recording();
1163         }
1164         return 0;
1167 int Record::resume_monitor()
1169         if(capture_state != IS_MONITORING)
1170         {
1171                 capture_state = IS_MONITORING;
1172                 monitor_timer.update();
1173                 open_input_devices(0, CONTEXT_INTERACTIVE);
1174                 monitor_engine->resume_recording();
1175         }
1176         return 0;
1179 int Record::stop_duplex()
1181         return 0;
1184 int Record::stop_operation(int resume_monitor)
1186         switch(capture_state)
1187         {
1188                 case IS_MONITORING:
1189                         if(!resume_monitor) monitor_engine->stop_recording(0);
1190                         break;
1191                 case IS_RECORDING:
1192                         record_engine->stop_recording(resume_monitor);
1193                         break;
1194                 case IS_DUPLEXING:
1195                         break;
1196                 case IS_PREVIEWING:
1197                         break;
1198         }
1199         return 0;
1203 // Remember to change meters if you change this.
1204 // Return the size of the fragments to read from the audio device.
1205 int Record::get_in_length()
1207         int64_t fragment_size = 1;
1208         while(fragment_size < default_asset->sample_rate / 
1209                 mwindow->edl->session->record_speed)
1210                 fragment_size *= 2;
1211         fragment_size /= 2;
1212         fragment_size = MAX(fragment_size, 512);
1213         return fragment_size;
1216 int Record::set_video_picture()
1218         if(default_asset->video_data && vdevice)
1219                 vdevice->set_picture(picture);
1220         return 0;
1223 void Record::set_translation(int x, int y)
1225         video_x = x;
1226         video_y = y;
1227         if(default_asset->video_data && vdevice)
1228                 vdevice->set_translation(video_x, video_y);
1232 int Record::set_channel(int channel)
1234         if(channel >= 0 && channel < channeldb->size())
1235         {
1236                 char string[BCTEXTLEN];
1237                 get_editing_batch()->channel = channel;
1238                 source_to_text(string, get_editing_batch());
1241                 record_gui->lock_window("Record::set_channel");
1242                 record_gui->batch_source->update(string);
1243                 record_monitor->window->channel_picker->channel_text->update(string);
1244                 record_gui->update_batches();
1245                 record_gui->unlock_window();
1248                 if(vdevice)
1249                 {
1250                         vdevice->set_channel(channeldb->get(channel));
1251                         set_video_picture();
1252                 }
1253         }
1254         return 0;
1257 // Change to a channel not in the db for editing
1258 void Record::set_channel(Channel *channel)
1260         if(vdevice) vdevice->set_channel(channel);
1263 int Record::has_signal()
1265         if(vdevice) return vdevice->has_signal();
1266         return 0;
1269 void Record::get_current_time(double &seconds, int &day)
1271         time_t result = time(0) + 1;
1272         struct tm *struct_tm = localtime(&result);
1273         day = struct_tm->tm_wday;
1274         seconds = struct_tm->tm_hour * 3600 + struct_tm->tm_min * 60 + struct_tm->tm_sec;
1288 int Record::get_time_format()
1290         return mwindow->edl->session->time_format;
1293 float Record::get_frame_rate()
1295         return 0.0;
1296 //      return mwindow->session->frame_rate;
1299 int Record::set_loop_duration(int64_t value)
1301         loop_duration = value; 
1302         return 0;
1305 int Record::get_vu_format() { return mwindow->edl->session->meter_format; }
1306 float Record::get_min_db() { return mwindow->edl->session->min_meter_db; }
1308 int Record::get_rec_mode() { return record_mode; }
1309 int Record::set_rec_mode(int value) { record_mode = value; }
1311 int Record::get_video_buffersize() { return mwindow->edl->session->video_write_length; }
1312 int Record::get_everyframe() { return mwindow->edl->session->video_every_frame; }
1314 int Record::get_out_length() { return mwindow->edl->session->playback_buffer; }
1315 int Record::get_software_positioning() { return mwindow->edl->session->record_software_position; }
1316 int64_t Record::get_out_buffersize() { return mwindow->edl->session->playback_buffer; }
1317 int64_t Record::get_in_buffersize() { return mwindow->edl->session->record_write_length; }
1318 int Record::get_realtime() { return realtime; }
1319 int Record::get_meter_speed() { return mwindow->edl->session->record_speed; }
1321 int Record::enable_duplex() { return mwindow->edl->session->enable_duplex; }
1322 int64_t Record::get_playback_buffer() { return mwindow->edl->session->playback_buffer; }