2 #include "audioconfig.h"
3 #include "audiodevice.h"
8 #include "playbackengine.h"
9 #include "preferences.h"
10 #include "recconfirmdelete.h"
12 #include "recordengine.h"
13 #include "recordgui.h"
14 #include "recordlabel.h"
15 #include "recordpreview.h"
16 #include "recordthread.h"
17 #include "recordmonitor.h"
19 #include "videodevice.h"
24 #define _(String) gettext(String)
25 #define gettext_noop(String) String
26 #define N_(String) gettext_noop (String)
28 RecordEngine::RecordEngine(MWindow *mwindow, Record *record)
30 this->mwindow = mwindow;
31 this->record = record;
38 RecordEngine::RecordEngine(MWindow *mwindow,
44 this->mwindow = mwindow;
45 this->record = record;
47 this->labels = labels;
57 adevice = new AudioDevice;
62 vdevice = new VideoDevice(mwindow);
67 RecordEngine::~RecordEngine()
69 delete monitor_thread;
71 delete preview_thread;
72 if(adevice) delete adevice;
73 if(vdevice) delete vdevice;
76 int RecordEngine::initialize()
78 // monitor_thread = new RecordThread(mwindow, record, this);
79 monitor_thread->create_objects();
81 // record_thread = new RecordThread(mwindow, record, this);
82 record_thread->create_objects();
84 preview_thread = new RecordPreview(record, this);
85 preview_thread->initialize();
89 if(record->do_audio) current_position = file->get_audio_length();
91 if(record->do_video) current_position = Units::tosamples((float)(file->get_video_length(record->get_framerate())), record->get_samplerate(), record->get_framerate());
95 duplex_thread = mwindow->playback_engine;
97 // initialize seek buttons
104 current_jump_jumps[0] = 20;
105 current_jump_jumps[1] = 40;
106 current_jump_jumps[2] = 60;
107 current_jump_jumps[3] = 80;
108 current_jump_jumps[4] = 100;
111 int RecordEngine::run_script(FileXML *script)
113 int result = 0, script_result = 0;
116 while(!result && !script_result)
118 result = script->read_tag();
122 if(script->tag.title_is("set_mode"))
124 set_record_mode(script->tag.get_property_text(0));
125 mode_to_text(string, get_record_mode());
126 gui->rec_mode_menu->set_text(string);
129 if(script->tag.title_is("set_duration"))
131 record->set_loop_duration((long)record->get_samplerate() * script->tag.get_property_int(0));
132 gui->update_duration_boxes();
135 if(script->tag.title_is("start_recording"))
137 gui->unlock_window();
142 if(script->tag.title_is("set_monitor_video"))
144 set_monitor_video(script->tag.get_property_int(0));
145 if(!script->tag.get_property_int(0) && record->video_window_open)
147 record->video_window_open = 0;
148 gui->monitor_video_window->window->hide_window();
152 if(script->tag.title_is("set_monitor_audio"))
154 set_monitor_audio(script->tag.get_property_int(0));
157 if(script->tag.title_is("quit_when_completed"))
159 record_thread->quit_when_completed = 1;
162 if(script->tag.title_is("ok"))
168 return script_result;
171 // ============================================= accounting
173 long RecordEngine::get_dc_offset(int offset)
175 return record->dc_offset[offset];
178 int RecordEngine::set_dc_offset(long new_offset, int number)
180 adevice->set_dc_offset(new_offset, number);
183 long int RecordEngine::get_dc_offset(long *dc_offset, RecordGUIDCOffsetText **dc_offset_text)
185 return adevice->get_dc_offset(dc_offset, dc_offset_text);
188 int RecordEngine::set_gui(RecordGUI *gui)
191 update_position(current_position);
194 int RecordEngine::get_duplex_enable()
196 return record->enable_duplex();
201 // ================================================ operations
203 int RecordEngine::open_input_devices(int duplex)
205 int audio_opened = 0;
206 int video_opened = 0;
207 AudioConfig *aconfig /* = mwindow->preferences->aconfig */;
209 // Initialize sharing
210 if(record->do_audio && record->do_video)
212 vdevice->set_adevice(adevice);
213 adevice->set_vdevice(vdevice);
219 if(record->get_software_positioning())
220 adevice->set_software_positioning();
222 for(int i = 0; i < asset->channels; i++)
224 adevice->set_dc_offset(record->dc_offset[i], i);
229 // Duplex is only needed if the timeline and the recording have audio
232 mwindow->patches->total_playable_atracks())
234 // duplex device is identical to input device
235 if(aconfig->audio_in_driver == aconfig->audio_duplex_driver &&
236 !strcmp(aconfig->oss_in_device, aconfig->oss_duplex_device) &&
237 aconfig->oss_in_bits == aconfig->oss_duplex_bits &&
238 aconfig->oss_in_channels == aconfig->oss_duplex_channels)
240 // adevice->open_duplex(mwindow->preferences->aconfig,
241 // record->get_samplerate(),
246 // two separate devices
248 // adevice->open_output(mwindow->preferences->aconfig,
249 // record->get_samplerate(),
250 // record->get_out_length());
254 if(record->do_audio && !audio_opened)
256 // adevice->open_input(mwindow->preferences->aconfig,
257 // record->get_samplerate(),
264 // vdevice->open_input(mwindow->preferences->vconfig,
269 // record->video_zoom,
270 // get_frame_rate());
271 // vdevice->set_field_order(record->reverse_interlace);
272 // if(record->get_current_channel())
273 // vdevice->set_channel(record->get_current_channel());
274 // set_video_picture();
281 int RecordEngine::close_input_devices()
284 adevice->close_all();
286 vdevice->close_all();
291 int RecordEngine::start_monitor()
293 monitor_timer.update();
294 open_input_devices(0);
295 monitor_thread->start_recording(0, 0);
300 int RecordEngine::stop_monitor()
304 // is_monitoring = 0;
305 // monitor_thread->stop_recording();
310 int RecordEngine::pause_monitor()
315 monitor_thread->pause_recording();
320 int RecordEngine::resume_monitor()
325 monitor_timer.update();
326 open_input_devices(0);
327 monitor_thread->resume_recording();
332 int RecordEngine::start_saving(int duplex)
337 record_timer.update();
338 open_input_devices(duplex);
340 duplex = record->enable_duplex() && duplex;
342 // start the duplex engine if necessary
343 // OSS < 3.9 crashes if recording starts before playback
344 // OSS >= 3.9 crashes if playback starts before recording
348 record->get_duplex_range(&start, &end);
349 duplex_thread->reset_parameters();
350 duplex_thread->arm_playback(0, 0, 1, adevice);
351 duplex_thread->start_playback();
355 // record_thread->start_recording();
362 int RecordEngine::save_frame()
367 record_timer.update();
368 record->do_audio = 0;
369 open_input_devices(0);
371 // start the duplex engine if necessary
372 record_thread->start_recording(0, 0);
378 int RecordEngine::stop_saving(int no_monitor)
382 // automatically stops duplex here and resumes monitor
383 record_thread->stop_recording(no_monitor);
388 int RecordEngine::stop_duplex()
393 duplex_thread->stop_playback(0);
394 // OSS can't resume recording if buffers underrun
395 // so stop playback first
400 int RecordEngine::start_preview()
407 preview_timer.update();
408 open_output_devices();
409 preview_thread->start_preview(current_position, file);
416 int RecordEngine::stop_preview(int no_monitor)
420 preview_thread->stop_preview(no_monitor);
421 // preview engine automatically triggers monitor when finished
426 int RecordEngine::stop_operation(int no_monitor)
428 // Resumes monitoring after stopping
429 if(is_saving) stop_saving(no_monitor);
431 if(is_previewing) stop_preview(no_monitor);
435 int RecordEngine::set_video_picture()
437 if(record->do_video && vdevice)
438 vdevice->set_picture(record->video_brightness,
441 record->video_contrast,
442 record->video_whiteness);
446 int RecordEngine::open_output_devices()
450 // adevice->open_output(mwindow->preferences->aconfig,
451 // record->get_samplerate(),
452 // record->get_out_length());
453 if(record->get_software_positioning()) adevice->set_software_positioning();
456 // Video is already open for monitoring
460 int RecordEngine::close_output_devices()
463 adevice->close_all();
464 // Video is already open for monitoring
470 int RecordEngine::lock_window()
475 int RecordEngine::unlock_window()
477 gui->unlock_window();
480 int RecordEngine::update_position(long new_position)
482 if(new_position < 0) new_position = 0; // fread error in filepcm
483 current_position = new_position;
485 gui->update_position(new_position);
487 if(new_position > total_length)
489 total_length = new_position;
490 // gui->update_total_length(new_position);
493 if(prev_label != labels->get_prev_label(new_position))
495 prev_label = labels->get_prev_label(new_position);
496 gui->update_prev_label(prev_label);
499 if(next_label != labels->get_next_label(new_position))
501 next_label = labels->get_next_label(new_position);
503 gui->update_next_label(next_label);
507 int RecordEngine::goto_prev_label()
514 new_position = labels->goto_prev_label(current_position);
515 if(new_position != -1)
517 // if(record->do_audio) file->set_audio_position(new_position);
518 if(record->do_video) file->set_video_position(Units::toframes(new_position, record->get_samplerate(), record->get_framerate()), record->get_framerate());
519 update_position(new_position);
524 int RecordEngine::goto_next_label()
531 new_position = labels->goto_next_label(current_position);
532 if(new_position != -1 && new_position <= total_length)
534 // if(record->do_audio) file->set_audio_position(new_position);
535 if(record->do_video) file->set_video_position(Units::toframes(new_position, record->get_samplerate(), record->get_framerate()), record->get_framerate());
536 update_position(new_position);
542 int RecordEngine::toggle_label()
544 labels->toggle_label(current_position);
545 update_position(current_position);
549 int RecordEngine::calibrate_dc_offset()
553 get_dc_offset(record->dc_offset, gui->dc_offset_text);
558 int RecordEngine::calibrate_dc_offset(long new_value, int channel)
562 set_dc_offset(new_value, channel);
563 record->dc_offset[channel] = new_value;
568 int RecordEngine::reset_over()
572 int RecordEngine::set_done(int value)
576 gui->set_done(value);
579 int RecordEngine::start_over()
581 if((record->do_audio && file->get_audio_length() > 0) ||
582 (record->do_video && file->get_video_length(record->get_framerate()) > 0))
584 RecConfirmDelete dialog(mwindow);
585 dialog.create_objects("start over");
586 int result = dialog.run_window();
595 // file->set_processors(mwindow->preferences->smp ? 2: 1);
596 // file->set_preload(mwindow->preferences->playback_preload);
597 // file->try_to_open_file(mwindow->plugindb, asset, 1, 1);
599 // start the engine over
600 labels->delete_new_labels();
603 // gui->update_total_length(0);
605 record->startsource_sample = 0;
606 record->startsource_frame = 0;
611 int RecordEngine::change_channel(Channel *channel)
613 if(record->do_video && vdevice)
614 return vdevice->set_channel(channel);
619 ArrayList<char*>* RecordEngine::get_video_inputs()
621 if(record->do_video && vdevice)
622 return vdevice->get_inputs();
627 int RecordEngine::get_vu_format() { return record->get_vu_format(); }
628 int RecordEngine::get_dither() { return record->default_asset->dither * record->default_asset->bits; }
629 int RecordEngine::get_input_channels() { return asset->channels; }
630 int RecordEngine::get_format(char *string)
633 strcpy(string, file.formattostr(mwindow->plugindb, asset->format));
635 int RecordEngine::get_samplerate() { return asset->rate; }
636 int RecordEngine::get_bits() { return asset->bits; }
637 int RecordEngine::get_time_format() { return record->get_time_format(); }
638 float RecordEngine::get_frame_rate() { return record->get_frame_rate(); }
639 int RecordEngine::get_loop_hr() { return record->loop_duration / asset->rate / 3600; }
640 int RecordEngine::get_loop_min() { return record->loop_duration / asset->rate / 60 - (long)get_loop_hr() * 60; }
641 int RecordEngine::get_loop_sec() { return record->loop_duration / asset->rate - (long)get_loop_hr() * 3600 - (long)get_loop_min() * 60; }
642 long RecordEngine::get_loop_duration() { return record->loop_duration; }
643 float RecordEngine::get_min_db() { return record->get_min_db(); }
644 int RecordEngine::get_meter_over_hold(int divisions) { return divisions * 15; }
645 int RecordEngine::get_meter_peak_hold(int divisions) { return divisions * 2; }
646 int RecordEngine::get_meter_speed() { return record->get_meter_speed(); }
647 float RecordEngine::get_frames_per_foot() { /* return mwindow->preferences->frames_per_foot; */ }
649 int RecordEngine::set_monitor_video(int value)
653 int RecordEngine::set_monitor_audio(int value)
657 int RecordEngine::set_record_mode(char *text)
659 record->record_mode = text_to_mode(text);
662 int RecordEngine::get_record_mode(char *text)
664 mode_to_text(text, record->record_mode);
667 int RecordEngine::get_record_mode()
669 return record->record_mode;
672 int RecordEngine::mode_to_text(char *string, int mode)
676 case 0: sprintf(string, _("Untimed")); break;
677 case 1: sprintf(string, _("Timed")); break;
678 case 2: sprintf(string, _("Loop")); break;
682 int RecordEngine::text_to_mode(char *string)
684 if(!strcasecmp(string, _("Untimed"))) return 0;
685 if(!strcasecmp(string, _("Timed"))) return 1;
686 if(!strcasecmp(string, _("Loop"))) return 2;
689 long RecordEngine::get_current_delay()
691 if(current_jump_jump > 0) current_jump_jump--;
692 if(current_jump_jump == 0 && current_jump_delay < /*JUMP_DELAYS*/ 1)
694 current_jump_delay++;
695 current_jump_jump = current_jump_jumps[current_jump_delay];
697 return jump_delay[current_jump_delay];
700 int RecordEngine::reset_current_delay()
702 current_jump_delay = 0;
703 current_jump_jump = current_jump_jumps[current_jump_delay];
706 int RecordEngine::set_loop_duration()
708 record->set_loop_duration((long)record->get_samplerate() * (atol(gui->loop_sec->get_text()) + atol(gui->loop_min->get_text()) * 60 + atol(gui->loop_hr->get_text()) * 3600));
712 // Remember to change meters if you change this.
713 // Return the size of the fragments to read from the audio device.
714 int RecordEngine::get_in_length()
716 long fragment_size = 1;
717 while(fragment_size < asset->rate / record->get_meter_speed()) fragment_size *= 2;
719 return fragment_size;
722 // Different absolute positions are defined for each operation so threads
723 // can end at different times without screwing up the frame synchronization.
724 long RecordEngine::absolute_monitor_position()
730 // return monitor_thread->absolute_position();
734 return (long)((float)monitor_timer.get_difference() / 1000 * record->get_samplerate());
741 long RecordEngine::absolute_preview_position()
747 return preview_thread->absolute_position();
751 return (long)((float)preview_timer.get_difference() / 1000 * record->get_samplerate());
758 long RecordEngine::absolute_record_position()
764 // return record_thread->absolute_position();
768 return (long)((float)record_timer.get_difference() / 1000 * record->get_samplerate());