r370: Heroine Virutal's official release 1.2.1
[cinelerra_cv/mob.git] / hvirtual / cinelerra / record.C
blob800d95b45dec08a5422acc337da2befb4979502e
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 Picture;
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                 strncpy(default_asset->vcodec, QUICKTIME_DV, 4);
174 // Load batches
175         int total_batches = defaults->get("TOTAL_BATCHES", 1);
176         if(total_batches < 1) total_batches = 1;
177         for(int i = 0; i < total_batches; i++)
178         {
179                 Batch *batch = new_batch();
180                 Asset *asset = batch->assets.values[0];
182                 sprintf(string, "RECORD_PATH_%d", i);
183                 defaults->get(string, asset->path);
184                 sprintf(string, "RECORD_CHANNEL_%d", i);
185                 batch->channel = defaults->get(string, batch->channel);
186                 sprintf(string, "RECORD_STARTTYPE_%d", i);
187                 batch->start_type = defaults->get(string, batch->start_type);
188                 sprintf(string, "RECORD_STARTDAY_%d", i);
189                 batch->start_day = defaults->get(string, batch->start_day);
190                 sprintf(string, "RECORD_STARTTIME_%d", i);
191                 batch->start_time = defaults->get(string, batch->start_time);
192                 sprintf(string, "RECORD_DURATION_%d", i);
193                 batch->duration = defaults->get(string, batch->duration);
194                 sprintf(string, "RECORD_MODE_%d", i);
195                 batch->record_mode = defaults->get(string, batch->record_mode);
196                 sprintf(string, "BATCH_ENABLED_%d", i);
197                 batch->enabled = defaults->get(string, batch->enabled);
198         }
201         load_mode = defaults->get("RECORD_LOADMODE", LOAD_PASTE);
203         monitor_audio = defaults->get("RECORD_MONITOR_AUDIO", 1);
204         monitor_video = defaults->get("RECORD_MONITOR_VIDEO", 1);
205         video_window_open = defaults->get("RECORD_MONITOR_OPEN", 1);
206         video_x = defaults->get("RECORD_VIDEO_X", 0);
207         video_y = defaults->get("RECORD_VIDEO_Y", 0);
208         video_zoom = defaults->get("RECORD_VIDEO_Z", (float)1);
210         picture->load_defaults(defaults);
212         reverse_interlace = defaults->get("REVERSE_INTERLACE", 0);
213         for(int i = 0; i < MAXCHANNELS; i++) 
214         {
215                 sprintf(string, "RECORD_DCOFFSET_%d", i);
216                 dc_offset[i] = defaults->get(string, 0);
217         }
218         fill_frames = defaults->get("FILL_DROPPED_FRAMES", 0);
219         return 0;
222 int Record::save_defaults()
224         char string[BCTEXTLEN];
225         Defaults *defaults = mwindow->defaults;
226         editing_batch = 0;
228 // Save default asset
229         default_asset->save_defaults(defaults,
230                 "RECORD_",
231                 1,
232                 !fixed_compression,
233                 1,
234                 1,
235                 1);
237         defaults->update("RECORD_CHANNELS", default_asset->channels);
244         defaults->update("TOTAL_BATCHES", batches.total);
245         for(int i = 0; i < batches.total; i++)
246         {
247                 Batch *batch = batches.values[i];
248                 Asset *asset = batch->assets.values[0];
250                 sprintf(string, "RECORD_PATH_%d", i);
251                 defaults->update(string, asset->path);
252                 sprintf(string, "RECORD_CHANNEL_%d", i);
253                 defaults->update(string, batch->channel);
254                 sprintf(string, "RECORD_STARTTYPE_%d", i);
255                 defaults->update(string, batch->start_type);
256                 sprintf(string, "RECORD_STARTDAY_%d", i);
257                 defaults->update(string, batch->start_day);
258                 sprintf(string, "RECORD_STARTTIME_%d", i);
259                 defaults->update(string, batch->start_time);
260                 sprintf(string, "RECORD_DURATION_%d", i);
261                 defaults->update(string, batch->duration);
262                 sprintf(string, "RECORD_MODE_%d", i);
263                 defaults->update(string, batch->record_mode);
264                 sprintf(string, "BATCH_ENABLED_%d", i);
265                 defaults->update(string, batch->enabled);
266         }
269         defaults->update("RECORD_LOADMODE", load_mode);
270         defaults->update("RECORD_MONITOR_AUDIO", monitor_audio);
271         defaults->update("RECORD_MONITOR_VIDEO", monitor_video);
272         defaults->update("RECORD_MONITOR_OPEN", video_window_open);
273         defaults->update("RECORD_VIDEO_X", video_x);
274         defaults->update("RECORD_VIDEO_Y", video_y);
275         defaults->update("RECORD_VIDEO_Z", video_zoom);
276         
277         picture->save_defaults(defaults);
278         defaults->update("REVERSE_INTERLACE", reverse_interlace);
279         for(int i = 0; i < MAXCHANNELS; i++)
280         {
281                 sprintf(string, "RECORD_DCOFFSET_%d", i);
282                 defaults->update(string, dc_offset[i]);
283         }
284         defaults->update("FILL_DROPPED_FRAMES", fill_frames);
286         return 0;
289 void Record::configure_batches()
291         strcpy(batches.values[0]->assets.values[0]->path, default_asset->path);
292         for(int i = 0; i < batches.total; i++)
293         {
294                 Batch *batch = batches.values[i];
295 // Update format
296                 batch->get_current_asset()->copy_format(default_asset);
298 // Update news
299                 batch->calculate_news();
300         }
303 void Record::source_to_text(char *string, Batch *batch)
305 // Update source
306         strcpy(string, "Record::source_to_text: not implemented");
307         switch(mwindow->edl->session->vconfig_in->driver)
308         {
309                 case VIDEO4LINUX:
310                 case VIDEO4LINUX2:
311                 case CAPTURE_BUZ:
312                 case VIDEO4LINUX2JPEG:
313                         if(batch->channel < 0 || batch->channel >= channeldb->size())
314                                 sprintf(string, _("None"));
315                         else
316                                 sprintf(string, channeldb->get(batch->channel)->title);
317                         break;
318         }
322 char* Record::get_channeldb_prefix()
324         char *path = "";
325         switch(mwindow->edl->session->vconfig_in->driver)
326         {
327                 case VIDEO4LINUX:
328                         path = "channels_v4l";
329                         break;
330                 case VIDEO4LINUX2:
331                         path = "channels_v4l2";
332                         break;
333                 case VIDEO4LINUX2JPEG:
334                         path = "channels_v4l2jpeg";
335                         break;
336                 case CAPTURE_BUZ:
337                         path = "channels_buz";
338                         break;
339         }
341         return path;
344 void Record::run()
346         int result = 0, format_error = 0;
347         int64_t start, end;
348         record_gui = 0;
350 // Default asset forms the first path in the batch capture
351 // and the file format for all operations.
352         default_asset = new Asset;
353         prompt_cancel = 0;
355 // Determine information about the device.
356         channeldb->load(get_channeldb_prefix());
357         fixed_compression = VideoDevice::is_compressed(
358                 mwindow->edl->session->vconfig_in->driver,
359                 0,
360                 1);
361         load_defaults();
363         if(fixed_compression)
364         {
365                 strcpy(default_asset->vcodec, 
366                         VideoDevice::get_vcodec(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;
377                 
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();
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();
392                 if(!result)
393                 {
394                         FormatCheck check_format(default_asset);
395                         format_error = check_format.check_format();
396                 }
397         }while(format_error && !result);
399         channeldb->save(get_channeldb_prefix());
400         save_defaults();
401         mwindow->save_defaults();
403         configure_batches();
404         current_batch = 0;
405         editing_batch = 0;
407 // Run recordgui
408         if(!result)
409         {
410                 edl = new EDL;
411                 edl->create_objects();
412                 edl->session->output_w = default_asset->width;
413                 edl->session->output_h = default_asset->height;
414                 edl->session->aspect_w = mwindow->edl->session->aspect_w;
415                 edl->session->aspect_h = mwindow->edl->session->aspect_h;
417                 window_lock->lock("Record::run 3");
418                 record_gui = new RecordGUI(mwindow, this);
419                 record_gui->load_defaults();
420                 record_gui->create_objects();
422                 record_monitor = new RecordMonitor(mwindow, this);
423                 record_monitor->create_objects();
424                 record_gui->update_batch_sources();
426                 menu_item->current_state = RECORD_CAPTURING;
427                 record_engine = new RecordThread(mwindow, this);
428                 record_engine->create_objects();
429                 monitor_engine = new RecordThread(mwindow, this);
430                 monitor_engine->create_objects();
433                 record_gui->show_window();
434                 record_gui->flush();
435                 if(video_window_open)
436                 {
437                         record_monitor->window->show_window();
438                         record_monitor->window->raise_window();
439                         record_monitor->window->flush();
440                 }
442                 start_monitor();
444                 window_lock->unlock();
446                 result = record_gui->run_window();
448 // Force monitor to quit without resuming
449                 if(monitor_engine->record_video) 
450                         monitor_engine->record_video->batch_done = 1;
451                 else
452                         monitor_engine->record_audio->batch_done = 1;
454                 stop_operation(0);;
456                 close_output_file();
458                 window_lock->lock("Record::run 4");
459                 delete record_monitor;
460                 record_monitor = 0;
462                 record_gui->save_defaults();
464 TRACE("Record::run 1");
465                 delete record_gui;
466                 record_gui = 0;
467                 window_lock->unlock();
469 TRACE("Record::run 2");
470                 delete edl;
472 TRACE("Record::run 3");
473         }
475         menu_item->current_state = RECORD_NOTHING;
477 // Save everything again
478         save_defaults();
484 // Paste into EDL
485         if(!result && load_mode != LOAD_NOTHING)
486         {
487                 mwindow->gui->lock_window("Record::run");
488                 ArrayList<EDL*> new_edls;
491 // Paste assets
492                 for(int i = 0; i < batches.total; i++)
493                 {
494                         Batch *batch = batches.values[i];
495                         Asset *asset = batch->get_current_asset();
497                         if(batch->recorded)
498                         {
499                                 for(int j = 0; j < batch->assets.total; j++)
500                                 {
501                                         EDL *new_edl = new EDL;
502                                         new_edl->create_objects();
503                                         new_edl->copy_session(mwindow->edl);
504                                         mwindow->asset_to_edl(new_edl, 
505                                                 batch->assets.values[j], 
506                                                 batch->labels);
507                                         new_edls.append(new_edl);
508                                 }
509                         }
510                 }
512                 if(new_edls.total)
513                 {
514                         mwindow->undo->update_undo_before(_("render"), LOAD_ALL);
516 // For pasting, clear the active region
517                         if(load_mode == LOAD_PASTE)
518                         {
519                                 mwindow->clear(0);
520                         }
522                         mwindow->paste_edls(&new_edls, 
523                                 load_mode,
524                                 0,
525                                 -1,
526                                 mwindow->edl->session->labels_follow_edits,
527                                 mwindow->edl->session->plugins_follow_edits);
528 //printf("Record::run 7\n");
530                         new_edls.remove_all_objects();
531 //printf("Record::run 8\n");
533                         mwindow->save_backup();
534                         mwindow->undo->update_undo_after();
535                         mwindow->restart_brender();
536                         mwindow->update_plugin_guis();
537                         mwindow->gui->update(1, 
538                                 2,
539                                 1,
540                                 1,
541                                 1,
542                                 1,
543                                 0);
544                         mwindow->sync_parameters(CHANGE_ALL);
545                 }
546                 mwindow->gui->unlock_window();
547         }
549 // Delete everything
550         script = 0;
551         batches.remove_all_objects();
552         delete default_asset;
555 void Record::activate_batch(int number, int stop_operation)
557         if(number != current_batch)
558         {
559                 if(stop_operation) this->stop_operation(1);
560                 close_output_file();
561                 get_current_batch()->calculate_news();
563                 current_batch = number;
564                 record_gui->update_batches();
565                 record_gui->update_position(current_display_position());
566                 record_gui->update_batch_tools();
567         }
570 void Record::delete_batch()
572 // Abort if one batch left
573         if(batches.total > 1)
574         {
575 // Stop operation if active batch
576                 if(current_batch == editing_batch)
577                 {
578                         if(current_batch < batches.total - 1)
579                                 activate_batch(current_batch + 1, 1);
580                         else
581                                 activate_batch(current_batch - 1, 1);
583                         delete batches.values[editing_batch];
584                         batches.remove_number(editing_batch);
585                         editing_batch = current_batch;
586                 }
587                 else
588                 {
589                         if(current_batch > editing_batch) current_batch--;
590                         delete batches.values[editing_batch];
591                         batches.remove_number(editing_batch);
592                         if(editing_batch >= batches.total) editing_batch--;
593                 }
594                 record_gui->update_batch_tools();
595         }
598 void Record::change_editing_batch(int number)
600         this->editing_batch = number;
601         record_gui->update_batch_tools();
604 Batch* Record::new_batch()
606         Batch *result = new Batch(mwindow, this);
607 //printf("Record::new_batch 1\n");
608         result->create_objects();
609         batches.append(result);
610         result->get_current_asset()->copy_format(default_asset);
611         
612 //printf("Record::new_batch 1\n");
614         result->create_default_path();
615         result->calculate_news();
616         if(get_editing_batch()) result->copy_from(get_editing_batch());
617         editing_batch = batches.total - 1;
618 //printf("Record::new_batch 1\n");
619 // Update GUI if created yet
620         if(record_gui) record_gui->update_batch_tools();
621 //printf("Record::new_batch 2\n");
622         return result;
625 int Record::delete_output_file()
627         FILE *test;
631 // Delete old file
632         if(!file)
633         {
634                 Batch *batch = get_current_batch();
635                 if(batch && (test = fopen(batch->get_current_asset()->path, "r")))
636                 {
637                         fclose(test);
639                         record_gui->lock_window("Record::delete_output_file");
641 // Update GUI
642                         sprintf(batch->news, _("Deleting"));
643                         record_gui->update_batches();
645 // Remove it
646                         remove(batch->get_current_asset()->path);
648 // Update GUI
649                         sprintf(batch->news, _("OK"));
650                         record_gui->update_batches();
652                         record_gui->unlock_window();
653                 }
654         }
655         return 0;
658 int Record::open_output_file()
660         int result = 0;
661 // Create initial file for the batch
662         if(!file)
663         {
664                 Batch *batch = get_current_batch();
665                 delete_output_file();
667                 file = new File;
668                 result = file->open_file(mwindow->plugindb, 
669                         batch->get_current_asset(), 
670                         0, 
671                         1, 
672                         default_asset->sample_rate, 
673                         default_asset->frame_rate);
674 //printf("Record::open_output_file 1\n");
676                 if(result)
677                 {
678                         delete file;
679                         file = 0;
680                 }
681                 else
682                 {
683                         mwindow->sighandler->push_file(file);
684                         IndexFile::delete_index(mwindow->preferences, 
685                                 batch->get_current_asset());
686                         file->set_processors(mwindow->preferences->processors);
687                         batch->calculate_news();
688                         record_gui->lock_window("Record::open_output_file");
689                         record_gui->update_batches();
690                         record_gui->unlock_window();
691                 }
692 //printf("Record::open_output_file 1\n");
693         }
694 //printf("Record::open_output_file 2\n");
695         return result;
698 int Record::init_next_file()
700         Batch *batch = get_current_batch();
701         Asset *asset;
703         if(file)
704         {
705                 mwindow->sighandler->pull_file(file);
706                 file->close_file();
707                 delete file;
708                 file = 0;
709         }
711         batch->current_asset++;
712         batch->assets.append(asset = new Asset);
713         *asset = *default_asset;
714         sprintf(asset->path, "%s%03d", asset->path, batch->current_asset);
715         int result = open_output_file();
716         return result;
719 // Rewind file at the end of a loop.
720 // This is called by RecordThread.
721 void Record::rewind_file()
723         if(file)
724         {
725                 if(default_asset->audio_data) 
726                         file->set_audio_position(0, default_asset->frame_rate);
727                 if(default_asset->video_data)
728                         file->set_video_position(0, default_asset->frame_rate);
729         }
731         get_current_batch()->current_sample = 0;
732         get_current_batch()->current_frame = 0;
733         record_gui->lock_window("Record::rewind_file");
734         record_gui->update_position(0);
735         record_gui->unlock_window();
738 void Record::start_over()
740         stop_operation(1);
742         Batch *batch = get_current_batch();
743         if(file)
744         {
745                 mwindow->sighandler->pull_file(file);
746                 file->close_file();
747                 delete file;
748                 file = 0;
749         }
751         get_current_batch()->start_over();
753         record_gui->lock_window("Record::start_over");
754         record_gui->update_position(0);
755         record_gui->update_batches();
756         record_gui->unlock_window();
759 void Record::close_output_file()
761 // Can't close until recordmonitor is done
762 //printf("Record::close_output_file 1\n");
763         if(file)
764         {
765                 mwindow->sighandler->pull_file(file);
766                 file->close_file();
767                 delete file;
768                 file = 0;
769         }
770 //printf("Record::close_output_file 2\n");
773 void Record::toggle_label()
775         get_current_batch()->toggle_label(current_display_position());
776         record_gui->update_labels(current_display_position());
779 void Record::get_audio_write_length(int &buffer_size, 
780         int &fragment_size)
782         fragment_size = 1;
783         while(fragment_size < default_asset->sample_rate / mwindow->edl->session->record_speed) 
784                 fragment_size *= 2;
785         fragment_size /= 2;
786         CLAMP(fragment_size, 1024, 32768);
788         for(buffer_size = fragment_size; 
789                 buffer_size < mwindow->edl->session->record_write_length; 
790                 buffer_size += fragment_size)
791                 ;
794 Batch* Record::get_current_batch()
796         if(batches.total)
797                 return batches.values[current_batch];
798         else
799                 return 0;
802 int Record::get_next_batch()
804         int i = current_batch;
805         while(i < batches.total - 1)
806         {
807                 i++;
808                 if(batches.values[i]->enabled) return i;
809         }
810         return -1;
814 Batch* Record::get_editing_batch()
816 //printf("Record::get_editing_batch %d %d\n", batches.total, editing_batch);
818         if(batches.total)
819                 return batches.values[editing_batch];
820         else
821                 return 0;
824 char* Record::current_mode()
826         return Batch::mode_to_text(get_current_batch()->record_mode);
829 int64_t Record::batch_video_offset()
831         return (int64_t)((double)get_current_batch()->file_offset * 
832                 default_asset->frame_rate + 0.5);
835 int64_t Record::current_audio_position()
837         if(file)
838         {
839                 return (int64_t)(file->get_audio_position(default_asset->sample_rate) + 
840                         get_current_batch()->file_offset + 0.5);
841         }
842         return 0;
845 int64_t Record::current_video_position()
847         if(file)
848         {
849                 return file->get_video_position(default_asset->frame_rate) + 
850                         (int64_t)((double)get_current_batch()->file_offset / 
851                                 default_asset->sample_rate * 
852                                 default_asset->frame_rate + 
853                                 0.5);
854         }
855         return 0;
858 double Record::current_display_position()
860 //printf("Record::current_display_position %d %d\n", get_current_batch()->current_sample, get_current_batch()->file_offset);
863         if(default_asset->video_data)
864                 return (double)get_current_batch()->current_frame / 
865                         default_asset->frame_rate + 
866                         get_current_batch()->file_offset;
867         else
868                 return (double)get_current_batch()->current_sample / 
869                         default_asset->sample_rate + 
870                         get_current_batch()->file_offset;
871         return 0;
874 char* Record::current_source()
876         return get_current_batch()->get_source_text();
879 char* Record::current_news()
881         return batches.values[current_batch]->news;
884 Asset* Record::current_asset()
886         return batches.values[current_batch]->get_current_asset();
889 double* Record::current_start()
891         return &batches.values[current_batch]->start_time;
894 int Record::get_current_channel()
896         return get_current_batch()->channel;
899 int Record::get_editing_channel()
901         return get_editing_batch()->channel;
904 Channel* Record::get_current_channel_struct()
906         int channel = get_current_channel();
907         if(channel >= 0 && channel < channeldb->size())
908         {
909                 return channeldb->get(channel);
910         }
911         return 0;
914 double* Record::current_duration()
916         return &batches.values[current_batch]->duration;
919 int64_t Record::current_duration_samples()
921         return (int64_t)((float)batches.values[current_batch]->duration * default_asset->sample_rate + 0.5);
924 int64_t Record::current_duration_frames()
926         return (int64_t)((float)batches.values[current_batch]->duration * default_asset->frame_rate + 0.5);
929 int* Record::current_offset_type()
931         return &batches.values[current_batch]->start_type;
934 ArrayList<Channel*>* Record::get_video_inputs() 
936         if(default_asset->video_data && vdevice) 
937                 return vdevice->get_inputs();
938         else
939                 return 0;
942 int64_t Record::sync_position()
944         switch(capture_state)
945         {
946                 case IS_DONE:
947                         return -1;
948                         break;    
949                 case IS_MONITORING:
950                         return monitor_engine->sync_position();
951                         break;    
952                 case IS_DUPLEXING: 
953                 case IS_RECORDING: 
954                         return record_engine->sync_position();
955                         break;    
956         }
957         return 0;
961 int Record::open_input_devices(int duplex, int context)
963         int audio_opened = 0;
964         int video_opened = 0;
965         AudioInConfig *aconfig_in = mwindow->edl->session->aconfig_in;
967 // Create devices
968         if(default_asset->audio_data && context != CONTEXT_SINGLEFRAME)
969                 adevice = new AudioDevice;
970         else
971                 adevice = 0;
973         if(default_asset->video_data)
974                 vdevice = new VideoDevice;
975         else
976                 vdevice = 0;
978 // Initialize sharing
979         if(adevice && vdevice)
980         {
981                 vdevice->set_adevice(adevice);
982                 adevice->set_vdevice(vdevice);
983         }
985 // Configure audio
986         if(adevice)
987         {
988                 adevice->set_software_positioning(mwindow->edl->session->record_software_position);
989                 adevice->set_record_dither(default_asset->dither);
991                 for(int i = 0; i < default_asset->channels; i++)
992                 {
993                         adevice->set_dc_offset(dc_offset[i], i);
994                 }
996 // Initialize full duplex
997 // Duplex is only needed if the timeline and the recording have audio
998                 if(duplex && mwindow->edl->tracks->playable_audio_tracks())
999                 {
1000 // Case 1: duplex device is identical to input device
1001                         if(AudioInConfig::is_duplex(aconfig_in, mwindow->edl->session->aconfig_duplex))
1002                         {
1003                                 adevice->open_duplex(mwindow->edl->session->aconfig_duplex,
1004                                                         default_asset->sample_rate,
1005                                                         get_in_length(),
1006                                                         mwindow->edl->session->real_time_playback);
1007                                 audio_opened = 1;
1008                         }
1009                         else
1010 // Case 2: two separate devices
1011                         {
1012                                 adevice->open_output(mwindow->edl->session->aconfig_duplex,
1013                                                 default_asset->sample_rate,
1014                                                 mwindow->edl->session->playback_buffer,
1015                                                 mwindow->edl->session->real_time_playback);
1016                         }
1017                 }
1019                 if(!audio_opened)
1020                 {
1021                         adevice->open_input(mwindow->edl->session->aconfig_in, 
1022                                 mwindow->edl->session->vconfig_in, 
1023                                 default_asset->sample_rate, 
1024                                 get_in_length());
1025                 }
1026         }
1029 // Initialize video
1030         if(vdevice)
1031         {
1032                 vdevice->set_quality(default_asset->jpeg_quality);
1033                 vdevice->open_input(mwindow->edl->session->vconfig_in, 
1034                         video_x, 
1035                         video_y, 
1036                         video_zoom,
1037                         default_asset->frame_rate);
1039 // Get configuration parameters from device probe
1040                 color_model = vdevice->get_best_colormodel(default_asset);
1041                 master_channel->copy_usage(vdevice->channel);
1042                 picture->copy_usage(vdevice->picture);
1043                 vdevice->set_field_order(reverse_interlace);
1045 // Set the device configuration
1046                 set_channel(get_current_channel());
1047         }
1049         return 0;
1052 int Record::close_input_devices()
1054         if(vdevice)
1055         {
1056                 vdevice->close_all();
1057                 delete vdevice;
1058                 vdevice = 0;
1059         }
1061         if(adevice)
1062         {
1063                 adevice->close_all();
1064                 delete adevice;
1065                 adevice = 0;
1066         }
1068         return 0;
1071 int Record::start_recording(int duplex, int context)
1073         if(capture_state != IS_RECORDING)
1074         {
1075                 pause_monitor();
1077 // Want the devices closed during file deletion to avoid buffer overflow
1078                 delete_output_file();
1080 // These two contexts need to open the device here to allow full duplex.  
1081 // Batch context opens them in RecordThread::run
1082                 if(context == CONTEXT_INTERACTIVE ||
1083                         context == CONTEXT_SINGLEFRAME)
1084                         open_input_devices(duplex, context);
1086                 prompt_cancel = 1;
1088 // start the duplex engine if necessary
1089 // OSS < 3.9 crashes if recording starts before playback
1090 // OSS >= 3.9 crashes if playback starts before recording
1091                 if(duplex)
1092                 {
1093                         capture_state = IS_DUPLEXING;
1094                 }
1095                 else
1096                         capture_state = IS_RECORDING;
1098 // Toggle once to cue the user that we're not dead.
1099                 if(context == CONTEXT_BATCH)
1100                 {
1101                         record_gui->lock_window("Record::start_recording");
1102                         record_gui->flash_batch();
1103                         record_gui->unlock_window();
1104                 }
1105                 record_engine->start_recording(0, context);
1106         }
1107         return 0;
1110 int Record::start_monitor()
1112         monitor_timer.update();
1113         open_input_devices(0, CONTEXT_INTERACTIVE);
1114         monitor_engine->start_recording(1, CONTEXT_INTERACTIVE);
1115         capture_state = IS_MONITORING;
1116         return 0;
1119 int Record::stop_monitor()
1121         monitor_engine->stop_recording(0);
1122         return 0;
1125 int Record::pause_monitor()
1127         if(capture_state == IS_MONITORING)
1128         {
1129                 monitor_engine->pause_recording();
1130         }
1131         return 0;
1134 int Record::resume_monitor()
1136         if(capture_state != IS_MONITORING)
1137         {
1138                 capture_state = IS_MONITORING;
1139                 monitor_timer.update();
1140                 open_input_devices(0, CONTEXT_INTERACTIVE);
1141                 monitor_engine->resume_recording();
1142         }
1143         return 0;
1146 int Record::stop_duplex()
1148         return 0;
1151 int Record::stop_operation(int resume_monitor)
1153         switch(capture_state)
1154         {
1155                 case IS_MONITORING:
1156                         if(!resume_monitor) monitor_engine->stop_recording(0);
1157                         break;
1158                 case IS_RECORDING:
1159                         record_engine->stop_recording(resume_monitor);
1160                         break;
1161                 case IS_DUPLEXING:
1162                         break;
1163                 case IS_PREVIEWING:
1164                         break;
1165         }
1166         return 0;
1170 // Remember to change meters if you change this.
1171 // Return the size of the fragments to read from the audio device.
1172 int Record::get_in_length() 
1174         int64_t fragment_size = 1;
1175         while(fragment_size < default_asset->sample_rate / mwindow->edl->session->record_speed) fragment_size *= 2;
1176         fragment_size /= 2;
1177         return fragment_size;
1180 int Record::set_video_picture()
1182         if(default_asset->video_data && vdevice)
1183                 vdevice->set_picture(picture);
1184         return 0;
1187 void Record::set_translation(int x, int y)
1189         video_x = x;
1190         video_y = y;
1191         if(default_asset->video_data && vdevice)
1192                 vdevice->set_translation(video_x, video_y);
1196 int Record::set_channel(int channel)
1198         if(channel >= 0 && channel < channeldb->size())
1199         {
1200                 char string[BCTEXTLEN];
1201                 get_editing_batch()->channel = channel;
1202                 source_to_text(string, get_editing_batch());
1205                 record_gui->lock_window("Record::set_channel");
1206                 record_gui->batch_source->update(string);
1207                 record_monitor->window->channel_picker->channel_text->update(string);
1208                 record_gui->update_batches();
1209                 record_gui->unlock_window();
1212                 if(vdevice)
1213                 {
1214                         vdevice->set_channel(channeldb->get(channel));
1215                         set_video_picture();
1216                 }
1217         }
1218         return 0;
1221 // Change to a channel not in the db for editing
1222 void Record::set_channel(Channel *channel)
1224         if(vdevice) vdevice->set_channel(channel);
1227 void Record::get_current_time(double &seconds, int &day)
1229         time_t result = time(0) + 1;
1230         struct tm *struct_tm = localtime(&result);
1231         day = struct_tm->tm_wday;
1232         seconds = struct_tm->tm_hour * 3600 + struct_tm->tm_min * 60 + struct_tm->tm_sec;
1246 int Record::get_time_format()
1248         return mwindow->edl->session->time_format;
1251 float Record::get_frame_rate()
1253         return 0.0;
1254 //      return mwindow->session->frame_rate;
1257 int Record::set_loop_duration(int64_t value)
1259         loop_duration = value; 
1260         return 0;
1263 int Record::get_vu_format() { return mwindow->edl->session->meter_format; }
1264 float Record::get_min_db() { return mwindow->edl->session->min_meter_db; }
1266 int Record::get_rec_mode() { return record_mode; }
1267 int Record::set_rec_mode(int value) { record_mode = value; }
1269 int Record::get_video_buffersize() { return mwindow->edl->session->video_write_length; }
1270 int Record::get_everyframe() { return mwindow->edl->session->video_every_frame; }
1272 int Record::get_out_length() { return mwindow->edl->session->playback_buffer; }
1273 int Record::get_software_positioning() { return mwindow->edl->session->record_software_position; }
1274 int64_t Record::get_out_buffersize() { return mwindow->edl->session->playback_buffer; }
1275 int64_t Record::get_in_buffersize() { return mwindow->edl->session->record_write_length; }
1276 int Record::get_realtime() { return realtime; }
1277 int Record::get_meter_speed() { return mwindow->edl->session->record_speed; }
1279 int Record::enable_duplex() { return mwindow->edl->session->enable_duplex; }
1280 int64_t Record::get_playback_buffer() { return mwindow->edl->session->playback_buffer; }