r125: This commit was manufactured by cvs2svn to create tag 'r1_1_7-last'.
[cinelerra_cv/mob.git] / hvirtual / cinelerra / record.C
blob8224adcc6ada05855fe375cce19535a8d4301c4c
1 #include "assets.h"
2 #include "audiodevice.h"
3 #include "batch.h"
4 #include "channel.h"
5 #include "channelpicker.h"
6 #include "clip.h"
7 #include "defaults.h"
8 #include "edl.h"
9 #include "edlsession.h"
10 #include "errorbox.h"
11 #include "file.h"
12 #include "filexml.h"
13 #include "filemov.h"
14 #include "filesystem.h"
15 #include "filethread.h"
16 #include "formatcheck.h"
17 #include "indexfile.h"
18 #include "localsession.h"
19 #include "mainundo.h"
20 #include "mwindow.h"
21 #include "mwindowgui.h"
22 #include "neworappend.h"
23 #include "playbackengine.h"
24 #include "preferences.h"
25 #include "quicktime.h"
26 #include "record.h"
27 #include "recordaudio.h"
28 #include "recordconfig.h"
29 #include "recordgui.h"
30 #include "recordlabel.h"
31 #include "recordmonitor.h"
32 #include "recordthread.h"
33 #include "recordvideo.h"
34 #include "recordwindow.h"
35 #include "mainsession.h"
36 #include "sighandler.h"
37 #include "testobject.h"
38 #include "theme.h"
39 #include "timebar.h"
40 #include "tracks.h"
41 #include "videoconfig.h"
42 #include "videodevice.h"
44 #include <string.h>
46 #include <libintl.h>
47 #define _(String) gettext(String)
48 #define gettext_noop(String) String
49 #define N_(String) gettext_noop (String)
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 //printf("RecordMenuItem::handle_event 1 %d\n", thread->running());
68         if(thread->running()) 
69         {
70 //printf("RecordMenuItem::handle_event 2\n");
71                 switch(current_state)
72                 {
73                         case RECORD_INTRO:
74 //printf("RecordMenuItem::handle_event 3\n");
75                                 thread->record_window->lock_window();
76                                 thread->record_window->raise_window();
77                                 thread->record_window->unlock_window();
78 //printf("RecordMenuItem::handle_event 4\n");
79                                 break;
80                         
81                         case RECORD_CAPTURING:
82 //printf("RecordMenuItem::handle_event 5\n");
83                                 thread->record_gui->lock_window();
84                                 thread->record_gui->raise_window();
85                                 thread->record_gui->unlock_window();
86 //printf("RecordMenuItem::handle_event 6\n");
87                                 break;
88                 }
89                 return 0;
90         }
91 //printf("RecordMenuItem::handle_event 7 %d\n", thread->running());
93         thread->start();
94 //printf("RecordMenuItem::handle_event 8\n");
95         return 1;
107 Record::Record(MWindow *mwindow, RecordMenuItem *menu_item)
108  : Thread()
110         this->mwindow = mwindow;
111         this->menu_item = menu_item;
112         script = 0;
113         capture_state = IS_DONE;
114         adevice = 0;
115         vdevice = 0;
116         file = 0;
117         editing_batch = 0;
118         current_batch = 0;
120 // Initialize 601 to rgb tables
121 //      int _601_to_rgb_value;
122 //      for(int i = 0; i <= 255; i++)
123 //      {
124 //              _601_to_rgb_value = (int)(1.1644 * i - 255 * 0.0627 + 0.5);
125 //              if(_601_to_rgb_value < 0) _601_to_rgb_value = 0;
126 //              if(_601_to_rgb_value > 255) _601_to_rgb_value = 255;
127 //              _601_to_rgb_table[i] = _601_to_rgb_value;
128 //      }
131 Record::~Record()
135 int Record::set_script(FileXML *script)
137         this->script = script;
140 int Record::run_script(Asset *asset, int &do_audio, int &do_video)
142         int script_result = 0, result = 0;
143         File test_file;
145         while(!result && !script_result)
146         {
147                 result = script->read_tag();
149                 if(!result)
150                 {
151                         if(script->tag.title_is("set_path"))
152                         {
153                                 strcpy(asset->path, script->tag.get_property_text(0));
154                         }
155                         else
156                         if(script->tag.title_is("set_audio"))
157                         {
158                                 do_audio = script->tag.get_property_int(0);
159                         }
160                         else
161                         if(script->tag.title_is("set_video"))
162                         {
163                                 do_video = script->tag.get_property_int(0);
164                         }
165                         else
166                         if(script->tag.title_is("set_paste_output"))
167                         {
168                                 to_tracks = script->tag.get_property_int(0);
169                         }
170                         else
171                         if(script->tag.title_is("set_format"))
172                         {
173                                 if(!(asset->format = test_file.strtoformat(mwindow->plugindb, script->tag.get_property_text(0))))
174                                 {
175                                         printf("Invalid file format %s.  See the menu for possible file formats.\n", script->tag.get_property_text(0));
176                                 }
177                         }
178                         else
179                         if(script->tag.title_is("set_audio_compression"))
180                         {
181                                 if(!(asset->bits = test_file.strtobits(script->tag.get_property_text(0))))
182                                 {
183                                         printf("Invalid audio compressor %s.  See the menu for possible compressors.\n", script->tag.get_property_text(0));
184                                 }
185                         }
186                         else
187                         if(script->tag.title_is("set_audio_signed"))
188                         {
189                                 asset->signed_ = script->tag.get_property_int(0);
190                         }
191                         else
192                         if(script->tag.title_is("set_audio_channels"))
193                         {
194                                 asset->channels = script->tag.get_property_int(0);
195                                 if(!asset->channels || asset->channels > MAXCHANNELS)
196                                 {
197                                         printf("Invalid number of channels %d.\n", asset->channels);
198                                 }
199                         }
200                         else
201 //                      if(script->tag.title_is("set_channel"))
202 //                      {
203 //                              char string[1024];
204 //                              strcpy(string, script->tag.get_property_text(0));
205 //                              for(int i = 0; i < mwindow->channeldb.total; i++)
206 //                              {
207 //                                      if(!strcasecmp(mwindow->channeldb.values[i]->title, string))
208 //                                      {
209 //                                              current_channel = i;
210 //                                              break;
211 //                                      }
212 //                              }
213 //                      }
214 //                      else
215                         if(script->tag.title_is("set_video_compression"))
216                         {
217                                 strcpy(asset->vcodec, FileMOV::strtocompression(script->tag.get_property_text(0)));
218                         }
219                         else
220                         if(script->tag.title_is("set_video_quality"))
221                         {
222 //                              asset->quality = script->tag.get_property_int(0);
223                         }
224                         else
225                         if(script->tag.title_is("ok"))
226                         {
227                                 script_result = 1;
228                         }
229                         else
230                         {
231                                 printf(_("Record::run_script: Unrecognized command: %s\n"), script->tag.get_title());
232                         }
233                 }
234         }
236         return script_result;
239 int Record::load_defaults()
241 //printf("Record::load_defaults 1\n");
242         char string[BCTEXTLEN];
243 //printf("Record::load_defaults 1\n");
244 //printf("Record::load_defaults 1\n");
245         Defaults *defaults = mwindow->defaults;
247 //printf("Record::load_defaults 1\n");
248 // Load default asset
249         defaults->get("RECORD_PATH_0", default_asset->path);
250         sprintf(string, "WAV");
251         defaults->get("RECORD_FORMAT", string);
252         default_asset->format = File::strtoformat(mwindow->plugindb, string);
253 // Record compression can't be the same as render compression
254 // because DV can't be synthesized.
255         sprintf(default_asset->vcodec, QUICKTIME_RAW);
256         defaults->get("RECORD_COMPRESSION", default_asset->vcodec);
257 // These are locked by a specific driver.
258         if(mwindow->edl->session->vconfig_in->driver == CAPTURE_LML ||
259                 mwindow->edl->session->vconfig_in->driver == CAPTURE_BUZ)
260                 strncpy(default_asset->vcodec, QUICKTIME_MJPA, 4);
261         else
262         if(mwindow->edl->session->vconfig_in->driver == CAPTURE_FIREWIRE)
263                 strncpy(default_asset->vcodec, QUICKTIME_DV, 4);
265         default_asset->sample_rate = mwindow->edl->session->aconfig_in->in_samplerate;
266         default_asset->frame_rate = mwindow->edl->session->vconfig_in->in_framerate;
267         default_asset->width = mwindow->edl->session->vconfig_in->w;
268         default_asset->height = mwindow->edl->session->vconfig_in->h;
269         default_asset->audio_data = defaults->get("RECORD_AUDIO", 1);
270         default_asset->video_data = defaults->get("RECORD_VIDEO", 1);
274         default_asset->bits = defaults->get("RECORD_BITS", 16);
275         default_asset->dither = defaults->get("RECORD_DITHER", 0);
276         default_asset->signed_ = defaults->get("RECORD_SIGNED", 1);
277         default_asset->byte_order = defaults->get("RECORD_BYTEORDER", 1);
278         default_asset->channels = defaults->get("RECORD_CHANNELS", 2);
279         default_asset->layers = 1;
282         default_asset->load_defaults(defaults);
283         defaults->get("RECORD_AUDIO_CODEC", default_asset->acodec);
284         defaults->get("RECORD_VIDEO_CODEC", default_asset->vcodec);
287 //printf("Record::load_defaults 1\n");
289 // Load batches
290         int total_batches = defaults->get("TOTAL_BATCHES", 1);
291         if(total_batches < 1) total_batches = 1;
292         for(int i = 0; i < total_batches; i++)
293         {
294                 Batch *batch = new_batch();
295                 Asset *asset = batch->assets.values[0];
297                 sprintf(string, "RECORD_PATH_%d", i);
298                 defaults->get(string, asset->path);
299                 sprintf(string, "RECORD_CHANNEL_%d", i);
300                 batch->channel = defaults->get(string, batch->channel);
301                 sprintf(string, "RECORD_STARTTYPE_%d", i);
302                 batch->start_type = defaults->get(string, batch->start_type);
303                 sprintf(string, "RECORD_STARTDAY_%d", i);
304                 batch->start_day = defaults->get(string, batch->start_day);
305                 sprintf(string, "RECORD_STARTTIME_%d", i);
306                 batch->start_time = defaults->get(string, batch->start_time);
307                 sprintf(string, "RECORD_DURATION_%d", i);
308                 batch->duration = defaults->get(string, batch->duration);
309                 sprintf(string, "RECORD_MODE_%d", i);
310                 batch->record_mode = defaults->get(string, batch->record_mode);
311                 sprintf(string, "BATCH_ENABLED_%d", i);
312                 batch->enabled = defaults->get(string, batch->enabled);
313         }
314 //printf("Record::load_defaults 1\n");
316         load_mode = defaults->get("RECORD_LOADMODE", LOAD_PASTE);
317 //printf("Record::load_defaults 1\n");
319         monitor_audio = defaults->get("RECORD_MONITOR_AUDIO", 1);
320         monitor_video = defaults->get("RECORD_MONITOR_VIDEO", 1);
321         video_window_open = defaults->get("RECORD_MONITOR_OPEN", 1);
322         video_x = defaults->get("RECORD_VIDEO_X", 0);
323         video_y = defaults->get("RECORD_VIDEO_Y", 0);
324         video_zoom = defaults->get("RECORD_VIDEO_Z", (float)1);
325         video_brightness = defaults->get("VIDEO_BRIGHTNESS", 0);
326         video_hue = defaults->get("VIDEO_HUE", 0);
327         video_color = defaults->get("VIDEO_COLOR", 0);
328         video_contrast = defaults->get("VIDEO_CONTRAST", 0);
329         video_whiteness = defaults->get("VIDEO_WHITENESS", 0);
330         reverse_interlace = defaults->get("REVERSE_INTERLACE", 0);
331 //printf("Record::load_defaults 1\n");
332         for(int i = 0; i < MAXCHANNELS; i++) 
333         {
334                 sprintf(string, "RECORD_DCOFFSET_%d", i);
335                 dc_offset[i] = defaults->get(string, 0);
336         }
337 //printf("Record::load_defaults 1\n");
338         fill_frames = defaults->get("FILL_DROPPED_FRAMES", 0);
339 //printf("Record::load_defaults 2\n");
340         return 0;
343 int Record::save_defaults()
345         char string[BCTEXTLEN];
346         Defaults *defaults = mwindow->defaults;
347         editing_batch = 0;
349 // Save default asset
350         defaults->update("RECORD_FORMAT", File::formattostr(mwindow->plugindb, default_asset->format));
351 // These are locked by a specific driver.
352         if(!fixed_compression)
353                 defaults->update("RECORD_COMPRESSION", default_asset->vcodec);
354         defaults->update("RECORD_BITS", default_asset->bits);
355         defaults->update("RECORD_DITHER", default_asset->dither);
356         defaults->update("RECORD_SIGNED", default_asset->signed_);
357         defaults->update("RECORD_BYTEORDER", default_asset->byte_order);
358         defaults->update("RECORD_CHANNELS", default_asset->channels);
359         defaults->update("RECORD_AUDIO", default_asset->audio_data);
360         defaults->update("RECORD_VIDEO", default_asset->video_data);
366         default_asset->save_defaults(defaults);
367         defaults->update("RECORD_AUDIO_CODEC", default_asset->acodec);
368         defaults->update("RECORD_VIDEO_CODEC", default_asset->vcodec);
371         defaults->update("TOTAL_BATCHES", batches.total);
372         for(int i = 0; i < batches.total; i++)
373         {
374                 Batch *batch = batches.values[i];
375                 Asset *asset = batch->assets.values[0];
377                 sprintf(string, "RECORD_PATH_%d", i);
378                 defaults->update(string, asset->path);
379                 sprintf(string, "RECORD_CHANNEL_%d", i);
380                 defaults->update(string, batch->channel);
381                 sprintf(string, "RECORD_STARTTYPE_%d", i);
382                 defaults->update(string, batch->start_type);
383                 sprintf(string, "RECORD_STARTDAY_%d", i);
384                 defaults->update(string, batch->start_day);
385                 sprintf(string, "RECORD_STARTTIME_%d", i);
386                 defaults->update(string, batch->start_time);
387                 sprintf(string, "RECORD_DURATION_%d", i);
388                 defaults->update(string, batch->duration);
389                 sprintf(string, "RECORD_MODE_%d", i);
390                 defaults->update(string, batch->record_mode);
391                 sprintf(string, "BATCH_ENABLED_%d", i);
392                 defaults->update(string, batch->enabled);
393         }
396         defaults->update("RECORD_LOADMODE", load_mode);
397         defaults->update("RECORD_MONITOR_AUDIO", monitor_audio);
398         defaults->update("RECORD_MONITOR_VIDEO", monitor_video);
399         defaults->update("RECORD_MONITOR_OPEN", video_window_open);
400         defaults->update("RECORD_VIDEO_X", video_x);
401         defaults->update("RECORD_VIDEO_Y", video_y);
402         defaults->update("RECORD_VIDEO_Z", video_zoom);
403         defaults->update("VIDEO_BRIGHTNESS", video_brightness);
404         defaults->update("VIDEO_HUE", video_hue);
405         defaults->update("VIDEO_COLOR", video_color);
406         defaults->update("VIDEO_CONTRAST", video_contrast);
407         defaults->update("VIDEO_WHITENESS", video_whiteness);
408         defaults->update("REVERSE_INTERLACE", reverse_interlace);
409         for(int i = 0; i < MAXCHANNELS; i++) 
410         {
411                 sprintf(string, "RECORD_DCOFFSET_%d", i);
412                 defaults->update(string, dc_offset[i]);
413         }
414         defaults->update("FILL_DROPPED_FRAMES", fill_frames);
416         return 0;
419 void Record::configure_batches()
421         strcpy(batches.values[0]->assets.values[0]->path, default_asset->path);
422         for(int i = 0; i < batches.total; i++)
423         {
424                 Batch *batch = batches.values[i];
425 // Update format
426                 batch->get_current_asset()->copy_format(default_asset);
428 // Update news
429                 batch->calculate_news();
430         }
433 void Record::source_to_text(char *string, Batch *batch)
435 // Update source
436         switch(mwindow->edl->session->vconfig_in->driver)
437         {
438                 case VIDEO4LINUX:
439                 case CAPTURE_BUZ:
440                         if(batch->channel < 0 || batch->channel >= current_channeldb()->total)
441                                 sprintf(string, _("None"));
442                         else
443                                 sprintf(string, current_channeldb()->values[batch->channel]->title);
444                         break;
445         }
448 ArrayList<Channel*>* Record::current_channeldb()
450         switch(mwindow->edl->session->vconfig_in->driver)
451         {
452                 case VIDEO4LINUX:
453                         return &mwindow->channeldb_v4l;
454                         break;
455                 case CAPTURE_BUZ:
456                         return &mwindow->channeldb_buz;
457                         break;
458         }
459         return 0;
462 void Record::run()
464 //printf("Record::run 1\n");
465         int result = 0, format_error = 0;
466 //printf("Record::run 1\n");
467         int64_t start, end;
468         record_gui = 0;
469 //printf("Record::run 1\n");
471 // Default asset forms the first path in the batch capture
472 // and the file format for all operations.
473         default_asset = new Asset;
474 //printf("Record::run 1\n");
475         prompt_cancel = 0;
476 //printf("Record::run 1\n");
477         fixed_compression = VideoDevice::is_compressed(mwindow->edl->session->vconfig_in->driver);
478 //printf("Record::run 1\n");
479         load_defaults();
480 //printf("Record::run 1\n");
482         if(fixed_compression)
483         {
484                 strcpy(default_asset->vcodec, 
485                         VideoDevice::get_vcodec(mwindow->edl->session->vconfig_in->driver));
486         }
489         menu_item->current_state = RECORD_INTRO;
490 //printf("Record::run 1\n");
492 // Get information about the file format
493         do
494         {
495 // Script did not contain "ok" so pop up a window.
496 //printf("Record::run 2\n");
497                 record_window = new RecordWindow(mwindow, this);
498 //printf("Record::run 2\n");
499                 record_window->create_objects();
500 //printf("Record::run 2\n");
501                 result = record_window->run_window();
502 //printf("Record::run 3\n");
503                 delete record_window;
504                 record_window = 0;
506                 if(!result)
507                 {
508                         FormatCheck check_format(default_asset);
509                         format_error = check_format.check_format();
510                 }
511         }while(format_error && !result);
512 //printf("Record::run 4\n");
514         save_defaults();
515         mwindow->save_defaults();
516 //printf("Record::run 5\n");
518         configure_batches();
519         current_batch = 0;
520         editing_batch = 0;
521 //printf("Record::run 6\n");
523 // Run recordgui
524         if(!result)
525         {
526 //printf("Record::run 7\n");
527                 edl = new EDL;
528                 edl->create_objects();
529 //              edl->session->track_w = default_asset->width;
530 //              edl->session->track_h = default_asset->height;
531                 edl->session->output_w = default_asset->width;
532                 edl->session->output_h = default_asset->height;
533                 edl->session->aspect_w = mwindow->edl->session->aspect_w;
534                 edl->session->aspect_h = mwindow->edl->session->aspect_h;
535                 record_gui = new RecordGUI(mwindow, this);
536 //printf("Record::run 8\n");
537                 record_gui->load_defaults();
538                 record_gui->create_objects();
540 //printf("Record::run 1\n");
541                 record_monitor = new RecordMonitor(mwindow, this);
542 //printf("Record::run 1\n");
543                 record_monitor->create_objects();
544 //printf("Record::run 9\n");
545                 record_gui->update_batch_sources();
547 //printf("Record::run 1\n");
548                 menu_item->current_state = RECORD_CAPTURING;
549 //printf("Record::run 1\n");
550                 record_engine = new RecordThread(mwindow, this);
551 //printf("Record::run 1\n");
552                 record_engine->create_objects();
553 //printf("Record::run 1\n");
554                 monitor_engine = new RecordThread(mwindow, this);
555 //printf("Record::run 1\n");
556                 monitor_engine->create_objects();
557 //printf("Record::run 10\n");
559 //              duplex_engine = new PlaybackEngine(mwindow, record_monitor->window->canvas, 1);
560 //              duplex_engine->create_objects();
562 //printf("Record::run 11\n");
563                 record_gui->show_window();
564 //printf("Record::run 11\n");
565                 record_gui->flush();
566 //printf("Record::run 11\n");
567                 if(video_window_open)
568                 {
569                         record_monitor->window->show_window();
570                         record_monitor->window->raise_window();
571                         record_monitor->window->flush();
572                 }
573 //printf("Record::run 11\n");
574                 start_monitor();
575 //printf("Record::run 12\n");
576                 result = record_gui->run_window();
577 // Force monitor to quit without resuming
578                 if(monitor_engine->record_video) 
579                         monitor_engine->record_video->batch_done = 1;
580                 else
581                         monitor_engine->record_audio->batch_done = 1;
582 //printf("Record::run 13\n");
583                 stop_operation(0);
584 //printf("Record::run 14\n");
585                 close_output_file();
586 //printf("Record::run 15\n");
587                 delete record_monitor;
588 //printf("Record::run 16\n");
589                 record_gui->save_defaults();
590                 delete record_gui;
591 //printf("Record::run17\n");
592                 delete edl;
593         }
595         menu_item->current_state = RECORD_NOTHING;
596 //printf("Record::run 1\n");
598 // Save everything again
599         save_defaults();
605 // Paste into EDL
606         if(!result && load_mode != LOAD_NOTHING)
607         {
608                 mwindow->gui->lock_window();
609                 ArrayList<EDL*> new_edls;
611 //printf("Record::run 3\n");
613 // Paste assets
614                 for(int i = 0; i < batches.total; i++)
615                 {
616 //printf("Record::run 4\n");
617                         Batch *batch = batches.values[i];
618                         Asset *asset = batch->get_current_asset();
620                         if(batch->recorded)
621                         {
622                                 for(int j = 0; j < batch->assets.total; j++)
623                                 {
624                                         EDL *new_edl = new EDL;
625                                         new_edl->create_objects();
626                                         new_edl->copy_session(mwindow->edl);
627                                         mwindow->asset_to_edl(new_edl, 
628                                                 batch->assets.values[j], 
629                                                 batch->labels);
630 //new_edl->dump();
631                                         new_edls.append(new_edl);
632                                 }
633                         }
634 //printf("Record::run 5\n");
635                 }
637                 if(new_edls.total)
638                 {
639                         mwindow->undo->update_undo_before(_("render"), LOAD_ALL);
640 //printf("Record::run 6\n");
642 // For pasting, clear the active region
643                         if(load_mode == LOAD_PASTE)
644                         {
645                                 mwindow->clear(0);
646                         }
648                         mwindow->paste_edls(&new_edls, 
649                                 load_mode,
650                                 0,
651                                 -1,
652                                 mwindow->edl->session->labels_follow_edits,
653                                 mwindow->edl->session->plugins_follow_edits);
654 //printf("Record::run 7\n");
656                         new_edls.remove_all_objects();
657 //printf("Record::run 8\n");
659                         mwindow->save_backup();
660                         mwindow->undo->update_undo_after();
661                         mwindow->restart_brender();
662                         mwindow->update_plugin_guis();
663                         mwindow->gui->update(1, 
664                                 2,
665                                 1,
666                                 1,
667                                 1,
668                                 1,
669                                 0);
670                         mwindow->sync_parameters(CHANGE_ALL);
671                 }
672                 mwindow->gui->unlock_window();
673 //printf("Record::run 9\n");
674         }
676 //printf("Record::run 10\n");
677 // Delete everything
678         script = 0;
679 //printf("Record 1\n");
680         batches.remove_all_objects();
681 //printf("Record 1\n");
682         delete default_asset;
683 //printf("Record 2\n");
686 void Record::activate_batch(int number, int stop_operation)
688         if(number != current_batch)
689         {
690                 if(stop_operation) this->stop_operation(1);
691                 close_output_file();
692                 get_current_batch()->calculate_news();
694                 current_batch = number;
695                 record_gui->update_batches();
696                 record_gui->update_position(current_display_position(), current_display_length());
697                 record_gui->update_total_length(0);
698                 record_gui->update_batch_tools();
699         }
702 void Record::delete_batch()
704 // Abort if one batch left
705         if(batches.total > 1)
706         {
707 // Stop operation if active batch
708                 if(current_batch == editing_batch)
709                 {
710                         if(current_batch < batches.total - 1)
711                                 activate_batch(current_batch + 1, 1);
712                         else
713                                 activate_batch(current_batch - 1, 1);
715                         delete batches.values[editing_batch];
716                         batches.remove_number(editing_batch);
717                         editing_batch = current_batch;
718                 }
719                 else
720                 {
721                         if(current_batch > editing_batch) current_batch--;
722                         delete batches.values[editing_batch];
723                         batches.remove_number(editing_batch);
724                         if(editing_batch >= batches.total) editing_batch--;
725                 }
726                 record_gui->update_batch_tools();
727         }
730 void Record::change_editing_batch(int number)
732         this->editing_batch = number;
733         record_gui->update_batch_tools();
736 Batch* Record::new_batch()
738         Batch *result = new Batch(mwindow, this);
739 //printf("Record::new_batch 1\n");
740         result->create_objects();
741         batches.append(result);
742         result->get_current_asset()->copy_format(default_asset);
743         
744 //printf("Record::new_batch 1\n");
746         result->create_default_path();
747         result->calculate_news();
748         if(get_editing_batch()) result->copy_from(get_editing_batch());
749         editing_batch = batches.total - 1;
750 //printf("Record::new_batch 1\n");
751 // Update GUI if created yet
752         if(record_gui) record_gui->update_batch_tools();
753 //printf("Record::new_batch 2\n");
754         return result;
757 int Record::delete_output_file()
759         FILE *test;
763 // Delete old file
764         if(!file)
765         {
766                 Batch *batch = get_current_batch();
767                 if(batch && (test = fopen(batch->get_current_asset()->path, "r")))
768                 {
769                         fclose(test);
771                         record_gui->lock_window();
773 // Update GUI
774                         sprintf(batch->news, _("Deleting"));
775                         record_gui->update_batches();
777 // Remove it
778                         remove(batch->get_current_asset()->path);
780 // Update GUI
781                         sprintf(batch->news, _("OK"));
782                         record_gui->update_batches();
784                         record_gui->unlock_window();
785                 }
786         }
787         return 0;
790 int Record::open_output_file()
792         int result = 0;
793 // Create initial file for the batch
794         if(!file)
795         {
796                 Batch *batch = get_current_batch();
797                 delete_output_file();
799                 file = new File;
800                 result = file->open_file(mwindow->plugindb, 
801                         batch->get_current_asset(), 
802                         0, 
803                         1, 
804                         default_asset->sample_rate, 
805                         default_asset->frame_rate);
806 //printf("Record::open_output_file 1\n");
808                 if(result)
809                 {
810                         delete file;
811                         file = 0;
812                 }
813                 else
814                 {
815                         mwindow->sighandler->push_file(file);
816                         IndexFile::delete_index(mwindow->preferences, batch->get_current_asset());
817                         file->set_processors(mwindow->edl->session->smp + 1);
818                         batch->calculate_news();
819                         record_gui->lock_window();
820                         record_gui->update_batches();
821                         record_gui->unlock_window();
822                 }
823 //printf("Record::open_output_file 1\n");
824         }
825 //printf("Record::open_output_file 2\n");
826         return result;
829 int Record::init_next_file()
831         Batch *batch = get_current_batch();
832         Asset *asset;
834         if(file)
835         {
836                 mwindow->sighandler->pull_file(file);
837                 file->close_file();
838                 delete file;
839                 file = 0;
840         }
842         batch->current_asset++;
843         batch->assets.append(asset = new Asset);
844         *asset = *default_asset;
845         sprintf(asset->path, "%s%03d", asset->path, batch->current_asset);
846         int result = open_output_file();
847         return result;
850 // Rewind file at the end of a loop.
851 // This is called by RecordThread.
852 void Record::rewind_file()
854         if(file)
855         {
856                 if(default_asset->audio_data) 
857                         file->set_audio_position(0, default_asset->frame_rate);
858                 if(default_asset->video_data)
859                         file->set_video_position(0, default_asset->frame_rate);
860         }
862         get_current_batch()->current_sample = 0;
863         get_current_batch()->current_frame = 0;
864         record_gui->lock_window();
865         record_gui->update_position(0, current_display_length());
866         record_gui->unlock_window();
869 void Record::start_over()
871         stop_operation(1);
873         Batch *batch = get_current_batch();
874         if(file)
875         {
876                 mwindow->sighandler->pull_file(file);
877                 file->close_file();
878                 delete file;
879                 file = 0;
880         }
882         get_current_batch()->start_over();
884         record_gui->lock_window();
885         record_gui->update_position(0, 0);
886         record_gui->update_batches();
887         record_gui->unlock_window();
890 void Record::close_output_file()
892 // Can't close until recordmonitor is done
893 //printf("Record::close_output_file 1\n");
894         if(file)
895         {
896                 mwindow->sighandler->pull_file(file);
897                 file->close_file();
898                 delete file;
899                 file = 0;
900         }
901 //printf("Record::close_output_file 2\n");
904 void Record::toggle_label()
906         get_current_batch()->toggle_label(current_display_position());
907         record_gui->update_labels(current_display_position());
910 void Record::get_audio_write_length(int64_t &buffer_size, int64_t &fragment_size)
912         fragment_size = 1;
913         while(fragment_size < default_asset->sample_rate / mwindow->edl->session->record_speed) 
914                 fragment_size *= 2;
915         fragment_size /= 2;
917         for(buffer_size = fragment_size; 
918                 buffer_size < mwindow->edl->session->record_write_length; 
919                 buffer_size += fragment_size)
920                 ;
923 Batch* Record::get_current_batch()
925         if(batches.total)
926                 return batches.values[current_batch];
927         else
928                 return 0;
931 int Record::get_next_batch()
933         int i = current_batch;
934         while(i < batches.total - 1)
935         {
936                 i++;
937                 if(batches.values[i]->enabled) return i;
938         }
939         return -1;
943 Batch* Record::get_editing_batch()
945 //printf("Record::get_editing_batch %d %d\n", batches.total, editing_batch);
947         if(batches.total)
948                 return batches.values[editing_batch];
949         else
950                 return 0;
953 char* Record::current_mode()
955         return Batch::mode_to_text(get_current_batch()->record_mode);
958 int64_t Record::batch_video_offset()
960         return (int64_t)((double)get_current_batch()->file_offset * 
961                 default_asset->frame_rate + 0.5);
964 int64_t Record::current_audio_position()
966         if(file)
967         {
968                 return (int64_t)(file->get_audio_position(default_asset->sample_rate) + 
969                         get_current_batch()->file_offset + 0.5);
970         }
971         return 0;
974 int64_t Record::current_video_position()
976         if(file)
977         {
978                 return file->get_video_position(default_asset->frame_rate) + 
979                         (int64_t)((double)get_current_batch()->file_offset / 
980                                 default_asset->sample_rate * 
981                                 default_asset->frame_rate + 
982                                 0.5);
983         }
984         return 0;
987 double Record::current_display_position()
989 //printf("Record::current_display_position %d %d\n", get_current_batch()->current_sample, get_current_batch()->file_offset);
992         if(default_asset->video_data)
993                 return (double)get_current_batch()->current_frame / 
994                         default_asset->frame_rate + 
995                         get_current_batch()->file_offset;
996         else
997                 return (double)get_current_batch()->current_sample / 
998                         default_asset->sample_rate + 
999                         get_current_batch()->file_offset;
1000         return 0;
1003 double Record::current_display_length()
1005         if(default_asset->video_data)
1006                 return (double)get_current_batch()->total_frames / 
1007                         default_asset->frame_rate;
1008         else
1009                 return (double)get_current_batch()->total_samples / 
1010                         default_asset->sample_rate;
1011         return 0;
1014 char* Record::current_source()
1016         return get_current_batch()->get_source_text();
1019 char* Record::current_news()
1021         return batches.values[current_batch]->news;
1024 Asset* Record::current_asset()
1026         return batches.values[current_batch]->get_current_asset();
1029 double* Record::current_start()
1031         return &batches.values[current_batch]->start_time;
1034 int Record::get_current_channel()
1036         return get_current_batch()->channel;
1039 int Record::get_editing_channel()
1041         return get_editing_batch()->channel;
1044 Channel* Record::get_current_channel_struct()
1046         if(current_channeldb())
1047         {
1048                 int channel = get_current_channel();
1049                 if(channel >= 0 && channel < current_channeldb()->total)
1050                 {
1051                         return current_channeldb()->values[channel];
1052                 }
1053         }
1054         return 0;
1057 double* Record::current_duration()
1059         return &batches.values[current_batch]->duration;
1062 int64_t Record::current_duration_samples()
1064         return (int64_t)((float)batches.values[current_batch]->duration * default_asset->sample_rate + 0.5);
1067 int64_t Record::current_duration_frames()
1069         return (int64_t)((float)batches.values[current_batch]->duration * default_asset->frame_rate + 0.5);
1072 int* Record::current_offset_type()
1074         return &batches.values[current_batch]->start_type;
1077 ArrayList<char*>* Record::get_video_inputs() 
1079         if(default_asset->video_data && vdevice) 
1080                 return vdevice->get_inputs();
1081         else
1082                 return 0;
1085 int64_t Record::sync_position()
1087         switch(capture_state)
1088         {
1089                 case IS_DONE:
1090                         return -1;
1091                         break;    
1092                 case IS_MONITORING:
1093                         return monitor_engine->sync_position();
1094                         break;    
1095                 case IS_DUPLEXING: 
1096                 case IS_RECORDING: 
1097                         return record_engine->sync_position();
1098                         break;    
1099         }
1100         return 0;
1104 int Record::open_input_devices(int duplex, int context)
1106         int audio_opened = 0;
1107         int video_opened = 0;
1108         AudioInConfig *aconfig_in = mwindow->edl->session->aconfig_in;
1110 // Create devices
1111         if(default_asset->audio_data && context != CONTEXT_SINGLEFRAME)
1112                 adevice = new AudioDevice;
1113         else
1114                 adevice = 0;
1116         if(default_asset->video_data)
1117                 vdevice = new VideoDevice;
1118         else
1119                 vdevice = 0;
1121 // Initialize sharing
1122         if(adevice && vdevice)
1123         {
1124                 vdevice->set_adevice(adevice);
1125                 adevice->set_vdevice(vdevice);
1126         }
1128 //printf("Record::open_input_devices 1\n");
1129 // Configure audio
1130         if(adevice)
1131         {
1132                 adevice->set_software_positioning(mwindow->edl->session->record_software_position);
1133                 adevice->set_record_dither(default_asset->dither);
1135                 for(int i = 0; i < default_asset->channels; i++)
1136                 {
1137                         adevice->set_dc_offset(dc_offset[i], i);
1138                 }
1140 // Initialize full duplex
1141 // Duplex is only needed if the timeline and the recording have audio
1142                 if(duplex && mwindow->edl->tracks->playable_audio_tracks())
1143                 {
1144 // Case 1: duplex device is identical to input device
1145                         if(AudioInConfig::is_duplex(aconfig_in, mwindow->edl->session->aconfig_duplex))
1146                         {
1147                                 adevice->open_duplex(mwindow->edl->session->aconfig_duplex,
1148                                                         default_asset->sample_rate,
1149                                                         get_in_length(),
1150                                                         mwindow->edl->session->real_time_playback);
1151                                 audio_opened = 1;
1152                         }
1153                         else
1154 // Case 2: two separate devices
1155                         {
1156                                 adevice->open_output(mwindow->edl->session->aconfig_duplex,
1157                                                 default_asset->sample_rate,
1158                                                 mwindow->edl->session->playback_buffer,
1159                                                 mwindow->edl->session->real_time_playback);
1160                         }
1161                 }
1163                 if(!audio_opened)
1164                 {
1165                         adevice->open_input(mwindow->edl->session->aconfig_in, 
1166                                         default_asset->sample_rate, 
1167                                         get_in_length());
1168                 }
1169         }
1172 // Initialize video
1173         if(vdevice)
1174         {
1175                 vdevice->set_quality(default_asset->jpeg_quality);
1176                 vdevice->open_input(mwindow->edl->session->vconfig_in, 
1177                         video_x, 
1178                         video_y, 
1179                         video_zoom,
1180                         default_asset->frame_rate);
1181                 color_model = vdevice->get_best_colormodel(default_asset);
1182                 vdevice->set_field_order(reverse_interlace);
1183                 set_channel(get_current_channel());
1184                 set_video_picture();
1185         }
1186 //printf("Record::open_input_devices 2\n");
1188         return 0;
1191 int Record::close_input_devices()
1193         if(vdevice)
1194         {
1195 //printf("Record::close_input_devices 1\n");
1196                 vdevice->close_all();
1197                 delete vdevice;
1198                 vdevice = 0;
1199 //printf("Record::close_input_devices 2\n");
1200         }
1202         if(adevice)
1203         {
1204 //printf("Record::close_input_devices 3\n");
1205                 adevice->close_all();
1206                 delete adevice;
1207                 adevice = 0;
1208 //printf("Record::close_input_devices 4\n");
1209         }
1211         return 0;
1214 int Record::start_recording(int duplex, int context)
1216         if(capture_state != IS_RECORDING)
1217         {
1218                 pause_monitor();
1220 // Want the devices closed during file deletion to avoid buffer overflow
1221                 delete_output_file();
1223 // These two contexts need to open the device here to allow full duplex.  
1224 // Batch context opens them in RecordThread::run
1225                 if(context == CONTEXT_INTERACTIVE ||
1226                         context == CONTEXT_SINGLEFRAME)
1227                         open_input_devices(duplex, context);
1229                 prompt_cancel = 1;
1231 // start the duplex engine if necessary
1232 // OSS < 3.9 crashes if recording starts before playback
1233 // OSS >= 3.9 crashes if playback starts before recording
1234                 if(duplex)
1235                 {
1236                         capture_state = IS_DUPLEXING;
1237                 }
1238                 else
1239                         capture_state = IS_RECORDING;
1241 // Toggle once to cue the user that we're not dead.
1242                 if(context == CONTEXT_BATCH)
1243                 {
1244                         record_gui->lock_window();
1245                         record_gui->flash_batch();
1246                         record_gui->unlock_window();
1247                 }
1248                 record_engine->start_recording(0, context);
1249         }
1250         return 0;
1253 int Record::start_monitor()
1255         monitor_timer.update();
1256         open_input_devices(0, CONTEXT_INTERACTIVE);
1257         monitor_engine->start_recording(1, CONTEXT_INTERACTIVE);
1258         capture_state = IS_MONITORING;
1259         return 0;
1262 int Record::stop_monitor()
1264         monitor_engine->stop_recording(0);
1265         return 0;
1268 int Record::pause_monitor()
1270         if(capture_state == IS_MONITORING)
1271         {
1272                 monitor_engine->pause_recording();
1273         }
1274         return 0;
1277 int Record::resume_monitor()
1279         if(capture_state != IS_MONITORING)
1280         {
1281                 capture_state = IS_MONITORING;
1282                 monitor_timer.update();
1283                 open_input_devices(0, CONTEXT_INTERACTIVE);
1284                 monitor_engine->resume_recording();
1285         }
1286         return 0;
1289 int Record::stop_duplex()
1291         return 0;
1294 int Record::stop_operation(int resume_monitor)
1296         switch(capture_state)
1297         {
1298                 case IS_MONITORING:
1299                         if(!resume_monitor) monitor_engine->stop_recording(0);
1300                         break;
1301                 case IS_RECORDING:
1302                         record_engine->stop_recording(resume_monitor);
1303                         break;
1304                 case IS_DUPLEXING:
1305                         break;
1306                 case IS_PREVIEWING:
1307                         break;
1308         }
1309         return 0;
1313 // Remember to change meters if you change this.
1314 // Return the size of the fragments to read from the audio device.
1315 int Record::get_in_length() 
1317         int64_t fragment_size = 1;
1318         while(fragment_size < default_asset->sample_rate / mwindow->edl->session->record_speed) fragment_size *= 2;
1319         fragment_size /= 2;
1320         return fragment_size;
1323 int Record::set_video_picture()
1325 //printf("Record::set_video_picture 1 %d\n", video_color);
1326         if(default_asset->video_data && vdevice)
1327                 vdevice->set_picture(video_brightness,
1328                         video_hue,
1329                         video_color,
1330                         video_contrast,
1331                         video_whiteness);
1332         return 0;
1335 void Record::set_translation(int x, int y)
1337         video_x = x;
1338         video_y = y;
1339         if(default_asset->video_data && vdevice)
1340                 vdevice->set_translation(video_x, video_y);
1344 int Record::set_channel(int channel)
1346         if(current_channeldb())
1347         {
1348                 if(channel >= 0 && channel < current_channeldb()->total)
1349                 {
1350                         char string[BCTEXTLEN];
1351                         get_editing_batch()->channel = channel;
1352                         source_to_text(string, get_editing_batch());
1353                         record_gui->lock_window();
1354                         record_gui->batch_source->update(string);
1355                         record_monitor->window->channel_picker->channel_text->update(string);
1356                         record_gui->update_batches();
1357                         record_gui->unlock_window();
1359                         if(vdevice)
1360                         {
1361                                 vdevice->set_channel(current_channeldb()->values[channel]);
1362 //printf("Record::set_channel 1\n");
1363                                 set_video_picture();
1364                         }
1365                 }
1366         }
1367         return 0;
1370 // Change to a channel not in the db for editing
1371 void Record::set_channel(Channel *channel)
1373         if(vdevice) vdevice->set_channel(channel);
1376 void Record::get_current_time(double &seconds, int &day)
1378         time_t result = time(0) + 1;
1379         struct tm *struct_tm = localtime(&result);
1380         day = struct_tm->tm_wday;
1381         seconds = struct_tm->tm_hour * 3600 + struct_tm->tm_min * 60 + struct_tm->tm_sec;
1395 int Record::get_time_format()
1397         return mwindow->edl->session->time_format;
1400 float Record::get_frame_rate()
1402         return 0.0;
1403 //      return mwindow->session->frame_rate;
1406 int Record::set_loop_duration(int64_t value)
1408         loop_duration = value; 
1409         return 0;
1412 int Record::get_vu_format() { return mwindow->edl->session->meter_format; }
1413 float Record::get_min_db() { return mwindow->edl->session->min_meter_db; }
1415 int Record::get_rec_mode() { return record_mode; }
1416 int Record::set_rec_mode(int value) { record_mode = value; }
1418 int Record::get_video_buffersize() { return mwindow->edl->session->video_write_length; }
1419 int Record::get_everyframe() { return mwindow->edl->session->video_every_frame; }
1421 int Record::get_out_length() { return mwindow->edl->session->playback_buffer; }
1422 int Record::get_software_positioning() { return mwindow->edl->session->record_software_position; }
1423 int64_t Record::get_out_buffersize() { return mwindow->edl->session->playback_buffer; }
1424 int64_t Record::get_in_buffersize() { return mwindow->edl->session->record_write_length; }
1425 int Record::get_realtime() { return realtime; }
1426 int Record::get_meter_speed() { return mwindow->edl->session->record_speed; }
1428 int Record::enable_duplex() { return mwindow->edl->session->enable_duplex; }
1429 int64_t Record::get_playback_buffer() { return mwindow->edl->session->playback_buffer; }