00001 #include "assets.h"
00002 #include "audioconfig.h"
00003 #include "audiodevice.h"
00004 #include "file.h"
00005 #include "filexml.h"
00006 #include "mwindow.h"
00007 #include "patchbay.h"
00008 #include "playbackengine.h"
00009 #include "preferences.h"
00010 #include "recconfirmdelete.h"
00011 #include "record.h"
00012 #include "recordengine.h"
00013 #include "recordgui.h"
00014 #include "recordlabel.h"
00015 #include "recordpreview.h"
00016 #include "recordthread.h"
00017 #include "recordmonitor.h"
00018 #include "units.h"
00019 #include "videodevice.h"
00020
00021 #include <ctype.h>
00022
00023 #include <libintl.h>
00024 #define _(String) gettext(String)
00025 #define gettext_noop(String) String
00026 #define N_(String) gettext_noop (String)
00027
00028 RecordEngine::RecordEngine(MWindow *mwindow, Record *record)
00029 {
00030 this->mwindow = mwindow;
00031 this->record = record;
00032 }
00033
00034
00035
00036
00037
00038 RecordEngine::RecordEngine(MWindow *mwindow,
00039 Record *record,
00040 File *file,
00041 Asset *asset,
00042 RecordLabels *labels)
00043 {
00044 this->mwindow = mwindow;
00045 this->record = record;
00046 this->file = file;
00047 this->labels = labels;
00048 this->asset = asset;
00049 is_saving = 0;
00050 is_previewing = 0;
00051 is_duplexing = 0;
00052 is_monitoring = 0;
00053 prev_label = -1;
00054 next_label = -1;
00055
00056 if(record->do_audio)
00057 adevice = new AudioDevice;
00058 else
00059 adevice = 0;
00060
00061 if(record->do_video)
00062 vdevice = new VideoDevice(mwindow);
00063 else
00064 vdevice = 0;
00065 }
00066
00067 RecordEngine::~RecordEngine()
00068 {
00069 delete monitor_thread;
00070 delete record_thread;
00071 delete preview_thread;
00072 if(adevice) delete adevice;
00073 if(vdevice) delete vdevice;
00074 }
00075
00076 int RecordEngine::initialize()
00077 {
00078
00079 monitor_thread->create_objects();
00080
00081
00082 record_thread->create_objects();
00083
00084 preview_thread = new RecordPreview(record, this);
00085 preview_thread->initialize();
00086
00087
00088 total_length = -1;
00089 if(record->do_audio) current_position = file->get_audio_length();
00090 else
00091 if(record->do_video) current_position = Units::tosamples((float)(file->get_video_length(record->get_framerate())), record->get_samplerate(), record->get_framerate());
00092
00093 file->seek_end();
00094
00095 duplex_thread = mwindow->playback_engine;
00096
00097
00098 jump_delay[0] = 100;
00099 jump_delay[1] = 50;
00100 jump_delay[2] = 25;
00101 jump_delay[3] = 10;
00102 jump_delay[4] = 5;
00103
00104 current_jump_jumps[0] = 20;
00105 current_jump_jumps[1] = 40;
00106 current_jump_jumps[2] = 60;
00107 current_jump_jumps[3] = 80;
00108 current_jump_jumps[4] = 100;
00109 }
00110
00111 int RecordEngine::run_script(FileXML *script)
00112 {
00113 int result = 0, script_result = 0;
00114 char string[1024];
00115
00116 while(!result && !script_result)
00117 {
00118 result = script->read_tag();
00119
00120 if(!result)
00121 {
00122 if(script->tag.title_is("set_mode"))
00123 {
00124 set_record_mode(script->tag.get_property_text(0));
00125 mode_to_text(string, get_record_mode());
00126 gui->rec_mode_menu->set_text(string);
00127 }
00128 else
00129 if(script->tag.title_is("set_duration"))
00130 {
00131 record->set_loop_duration((long)record->get_samplerate() * script->tag.get_property_int(0));
00132 gui->update_duration_boxes();
00133 }
00134 else
00135 if(script->tag.title_is("start_recording"))
00136 {
00137 gui->unlock_window();
00138 start_saving();
00139 gui->lock_window();
00140 }
00141 else
00142 if(script->tag.title_is("set_monitor_video"))
00143 {
00144 set_monitor_video(script->tag.get_property_int(0));
00145 if(!script->tag.get_property_int(0) && record->video_window_open)
00146 {
00147 record->video_window_open = 0;
00148 gui->monitor_video_window->window->hide_window();
00149 }
00150 }
00151 else
00152 if(script->tag.title_is("set_monitor_audio"))
00153 {
00154 set_monitor_audio(script->tag.get_property_int(0));
00155 }
00156 else
00157 if(script->tag.title_is("quit_when_completed"))
00158 {
00159 record_thread->quit_when_completed = 1;
00160 }
00161 else
00162 if(script->tag.title_is("ok"))
00163 {
00164 script_result = 1;
00165 }
00166 }
00167 }
00168 return script_result;
00169 }
00170
00171
00172
00173 long RecordEngine::get_dc_offset(int offset)
00174 {
00175 return record->dc_offset[offset];
00176 }
00177
00178 int RecordEngine::set_dc_offset(long new_offset, int number)
00179 {
00180 adevice->set_dc_offset(new_offset, number);
00181 }
00182
00183 long int RecordEngine::get_dc_offset(long *dc_offset, RecordGUIDCOffsetText **dc_offset_text)
00184 {
00185 return adevice->get_dc_offset(dc_offset, dc_offset_text);
00186 }
00187
00188 int RecordEngine::set_gui(RecordGUI *gui)
00189 {
00190 this->gui = gui;
00191 update_position(current_position);
00192 }
00193
00194 int RecordEngine::get_duplex_enable()
00195 {
00196 return record->enable_duplex();
00197 }
00198
00199
00200
00201
00202
00203 int RecordEngine::open_input_devices(int duplex)
00204 {
00205 int audio_opened = 0;
00206 int video_opened = 0;
00207 AudioConfig *aconfig ;
00208
00209
00210 if(record->do_audio && record->do_video)
00211 {
00212 vdevice->set_adevice(adevice);
00213 adevice->set_vdevice(vdevice);
00214 }
00215
00216
00217 if(record->do_audio)
00218 {
00219 if(record->get_software_positioning())
00220 adevice->set_software_positioning();
00221
00222 for(int i = 0; i < asset->channels; i++)
00223 {
00224 adevice->set_dc_offset(record->dc_offset[i], i);
00225 }
00226 }
00227
00228
00229
00230 if(duplex &&
00231 record->do_audio &&
00232 mwindow->patches->total_playable_atracks())
00233 {
00234
00235 if(aconfig->audio_in_driver == aconfig->audio_duplex_driver &&
00236 !strcmp(aconfig->oss_in_device, aconfig->oss_duplex_device) &&
00237 aconfig->oss_in_bits == aconfig->oss_duplex_bits &&
00238 aconfig->oss_in_channels == aconfig->oss_duplex_channels)
00239 {
00240
00241
00242
00243 audio_opened = 1;
00244 }
00245 else
00246
00247 {
00248
00249
00250
00251 }
00252 }
00253
00254 if(record->do_audio && !audio_opened)
00255 {
00256
00257
00258
00259 }
00260
00261
00262 if(record->do_video)
00263 {
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275 }
00276
00277 return 0;
00278 }
00279
00280
00281 int RecordEngine::close_input_devices()
00282 {
00283 if(record->do_audio)
00284 adevice->close_all();
00285 if(record->do_video)
00286 vdevice->close_all();
00287
00288 return 0;
00289 }
00290
00291 int RecordEngine::start_monitor()
00292 {
00293 monitor_timer.update();
00294 open_input_devices(0);
00295 monitor_thread->start_recording(0, 0);
00296 is_monitoring = 1;
00297 return 0;
00298 }
00299
00300 int RecordEngine::stop_monitor()
00301 {
00302
00303
00304
00305
00306
00307 return 0;
00308 }
00309
00310 int RecordEngine::pause_monitor()
00311 {
00312 if(is_monitoring)
00313 {
00314 is_monitoring = 0;
00315 monitor_thread->pause_recording();
00316 }
00317 return 0;
00318 }
00319
00320 int RecordEngine::resume_monitor()
00321 {
00322 if(!is_monitoring)
00323 {
00324 is_monitoring = 1;
00325 monitor_timer.update();
00326 open_input_devices(0);
00327 monitor_thread->resume_recording();
00328 }
00329 return 0;
00330 }
00331
00332 int RecordEngine::start_saving(int duplex)
00333 {
00334 if(!is_saving)
00335 {
00336 pause_monitor();
00337 record_timer.update();
00338 open_input_devices(duplex);
00339
00340 duplex = record->enable_duplex() && duplex;
00341
00342
00343
00344
00345 if(duplex)
00346 {
00347 long start, end;
00348 record->get_duplex_range(&start, &end);
00349 duplex_thread->reset_parameters();
00350 duplex_thread->arm_playback(0, 0, 1, adevice);
00351 duplex_thread->start_playback();
00352 is_duplexing = 1;
00353 }
00354
00355
00356
00357 is_saving = 1;
00358 }
00359 return 0;
00360 }
00361
00362 int RecordEngine::save_frame()
00363 {
00364 if(!is_saving)
00365 {
00366 pause_monitor();
00367 record_timer.update();
00368 record->do_audio = 0;
00369 open_input_devices(0);
00370
00371
00372 record_thread->start_recording(0, 0);
00373 is_saving = 1;
00374 }
00375 return 0;
00376 }
00377
00378 int RecordEngine::stop_saving(int no_monitor)
00379 {
00380 if(is_saving)
00381 {
00382
00383 record_thread->stop_recording(no_monitor);
00384 }
00385 return 0;
00386 }
00387
00388 int RecordEngine::stop_duplex()
00389 {
00390 if(is_duplexing)
00391 {
00392 is_duplexing = 0;
00393 duplex_thread->stop_playback(0);
00394
00395
00396 }
00397 return 0;
00398 }
00399
00400 int RecordEngine::start_preview()
00401 {
00402 if(!is_previewing)
00403 {
00404 stop_operation();
00405 pause_monitor();
00406
00407 preview_timer.update();
00408 open_output_devices();
00409 preview_thread->start_preview(current_position, file);
00410
00411 is_previewing = 1;
00412 }
00413 return 0;
00414 }
00415
00416 int RecordEngine::stop_preview(int no_monitor)
00417 {
00418 if(is_previewing)
00419 {
00420 preview_thread->stop_preview(no_monitor);
00421
00422 }
00423 return 0;
00424 }
00425
00426 int RecordEngine::stop_operation(int no_monitor)
00427 {
00428
00429 if(is_saving) stop_saving(no_monitor);
00430 else
00431 if(is_previewing) stop_preview(no_monitor);
00432 return 0;
00433 }
00434
00435 int RecordEngine::set_video_picture()
00436 {
00437 if(record->do_video && vdevice)
00438 vdevice->set_picture(record->video_brightness,
00439 record->video_hue,
00440 record->video_color,
00441 record->video_contrast,
00442 record->video_whiteness);
00443 return 0;
00444 }
00445
00446 int RecordEngine::open_output_devices()
00447 {
00448 if(record->do_audio)
00449 {
00450
00451
00452
00453 if(record->get_software_positioning()) adevice->set_software_positioning();
00454 }
00455
00456
00457 return 0;
00458 }
00459
00460 int RecordEngine::close_output_devices()
00461 {
00462 if(record->do_audio)
00463 adevice->close_all();
00464
00465 return 0;
00466 }
00467
00468
00469
00470 int RecordEngine::lock_window()
00471 {
00472 gui->lock_window();
00473 }
00474
00475 int RecordEngine::unlock_window()
00476 {
00477 gui->unlock_window();
00478 }
00479
00480 int RecordEngine::update_position(long new_position)
00481 {
00482 if(new_position < 0) new_position = 0;
00483 current_position = new_position;
00484
00485 gui->update_position(new_position);
00486
00487 if(new_position > total_length)
00488 {
00489 total_length = new_position;
00490
00491 }
00492
00493 if(prev_label != labels->get_prev_label(new_position))
00494 {
00495 prev_label = labels->get_prev_label(new_position);
00496 gui->update_prev_label(prev_label);
00497 }
00498
00499 if(next_label != labels->get_next_label(new_position))
00500 {
00501 next_label = labels->get_next_label(new_position);
00502
00503 gui->update_next_label(next_label);
00504 }
00505 }
00506
00507 int RecordEngine::goto_prev_label()
00508 {
00509 if(!is_saving)
00510 {
00511 stop_operation();
00512 long new_position;
00513
00514 new_position = labels->goto_prev_label(current_position);
00515 if(new_position != -1)
00516 {
00517
00518 if(record->do_video) file->set_video_position(Units::toframes(new_position, record->get_samplerate(), record->get_framerate()), record->get_framerate());
00519 update_position(new_position);
00520 }
00521 }
00522 }
00523
00524 int RecordEngine::goto_next_label()
00525 {
00526 if(!is_saving)
00527 {
00528 stop_operation();
00529 long new_position;
00530
00531 new_position = labels->goto_next_label(current_position);
00532 if(new_position != -1 && new_position <= total_length)
00533 {
00534
00535 if(record->do_video) file->set_video_position(Units::toframes(new_position, record->get_samplerate(), record->get_framerate()), record->get_framerate());
00536 update_position(new_position);
00537 }
00538 }
00539 return 0;
00540 }
00541
00542 int RecordEngine::toggle_label()
00543 {
00544 labels->toggle_label(current_position);
00545 update_position(current_position);
00546 return 0;
00547 }
00548
00549 int RecordEngine::calibrate_dc_offset()
00550 {
00551 if(record->do_audio)
00552 {
00553 get_dc_offset(record->dc_offset, gui->dc_offset_text);
00554 }
00555 return 0;
00556 }
00557
00558 int RecordEngine::calibrate_dc_offset(long new_value, int channel)
00559 {
00560 if(record->do_audio)
00561 {
00562 set_dc_offset(new_value, channel);
00563 record->dc_offset[channel] = new_value;
00564 }
00565 return 0;
00566 }
00567
00568 int RecordEngine::reset_over()
00569 {
00570 }
00571
00572 int RecordEngine::set_done(int value)
00573 {
00574 stop_operation(1);
00575 stop_monitor();
00576 gui->set_done(value);
00577 }
00578
00579 int RecordEngine::start_over()
00580 {
00581 if((record->do_audio && file->get_audio_length() > 0) ||
00582 (record->do_video && file->get_video_length(record->get_framerate()) > 0))
00583 {
00584 RecConfirmDelete dialog(mwindow);
00585 dialog.create_objects("start over");
00586 int result = dialog.run_window();
00587 if(!result)
00588 {
00589 stop_operation();
00590
00591 file->close_file();
00592 remove(asset->path);
00593
00594
00595
00596
00597
00598
00599
00600 labels->delete_new_labels();
00601 update_position(0);
00602 total_length = 0;
00603
00604
00605 record->startsource_sample = 0;
00606 record->startsource_frame = 0;
00607 }
00608 }
00609 }
00610
00611 int RecordEngine::change_channel(Channel *channel)
00612 {
00613 if(record->do_video && vdevice)
00614 return vdevice->set_channel(channel);
00615 else
00616 return 0;
00617 }
00618
00619 ArrayList<char*>* RecordEngine::get_video_inputs()
00620 {
00621 if(record->do_video && vdevice)
00622 return vdevice->get_inputs();
00623 else
00624 return 0;
00625 }
00626
00627 int RecordEngine::get_vu_format() { return record->get_vu_format(); }
00628 int RecordEngine::get_dither() { return record->default_asset->dither * record->default_asset->bits; }
00629 int RecordEngine::get_input_channels() { return asset->channels; }
00630 int RecordEngine::get_format(char *string)
00631 {
00632 File file;
00633 strcpy(string, file.formattostr(mwindow->plugindb, asset->format));
00634 }
00635 int RecordEngine::get_samplerate() { return asset->rate; }
00636 int RecordEngine::get_bits() { return asset->bits; }
00637 int RecordEngine::get_time_format() { return record->get_time_format(); }
00638 float RecordEngine::get_frame_rate() { return record->get_frame_rate(); }
00639 int RecordEngine::get_loop_hr() { return record->loop_duration / asset->rate / 3600; }
00640 int RecordEngine::get_loop_min() { return record->loop_duration / asset->rate / 60 - (long)get_loop_hr() * 60; }
00641 int RecordEngine::get_loop_sec() { return record->loop_duration / asset->rate - (long)get_loop_hr() * 3600 - (long)get_loop_min() * 60; }
00642 long RecordEngine::get_loop_duration() { return record->loop_duration; }
00643 float RecordEngine::get_min_db() { return record->get_min_db(); }
00644 int RecordEngine::get_meter_over_hold(int divisions) { return divisions * 15; }
00645 int RecordEngine::get_meter_peak_hold(int divisions) { return divisions * 2; }
00646 int RecordEngine::get_meter_speed() { return record->get_meter_speed(); }
00647 float RecordEngine::get_frames_per_foot() { }
00648
00649 int RecordEngine::set_monitor_video(int value)
00650 {
00651 }
00652
00653 int RecordEngine::set_monitor_audio(int value)
00654 {
00655 }
00656
00657 int RecordEngine::set_record_mode(char *text)
00658 {
00659 record->record_mode = text_to_mode(text);
00660 }
00661
00662 int RecordEngine::get_record_mode(char *text)
00663 {
00664 mode_to_text(text, record->record_mode);
00665 }
00666
00667 int RecordEngine::get_record_mode()
00668 {
00669 return record->record_mode;
00670 }
00671
00672 int RecordEngine::mode_to_text(char *string, int mode)
00673 {
00674 switch(mode)
00675 {
00676 case 0: sprintf(string, _("Untimed")); break;
00677 case 1: sprintf(string, _("Timed")); break;
00678 case 2: sprintf(string, _("Loop")); break;
00679 }
00680 }
00681
00682 int RecordEngine::text_to_mode(char *string)
00683 {
00684 if(!strcasecmp(string, _("Untimed"))) return 0;
00685 if(!strcasecmp(string, _("Timed"))) return 1;
00686 if(!strcasecmp(string, _("Loop"))) return 2;
00687 }
00688
00689 long RecordEngine::get_current_delay()
00690 {
00691 if(current_jump_jump > 0) current_jump_jump--;
00692 if(current_jump_jump == 0 && current_jump_delay < 1)
00693 {
00694 current_jump_delay++;
00695 current_jump_jump = current_jump_jumps[current_jump_delay];
00696 }
00697 return jump_delay[current_jump_delay];
00698 }
00699
00700 int RecordEngine::reset_current_delay()
00701 {
00702 current_jump_delay = 0;
00703 current_jump_jump = current_jump_jumps[current_jump_delay];
00704 }
00705
00706 int RecordEngine::set_loop_duration()
00707 {
00708 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));
00709 }
00710
00711
00712
00713
00714 int RecordEngine::get_in_length()
00715 {
00716 long fragment_size = 1;
00717 while(fragment_size < asset->rate / record->get_meter_speed()) fragment_size *= 2;
00718 fragment_size /= 2;
00719 return fragment_size;
00720 }
00721
00722
00723
00724 long RecordEngine::absolute_monitor_position()
00725 {
00726 if(is_monitoring)
00727 {
00728 if(record->do_audio)
00729 {
00730
00731 }
00732 else
00733 {
00734 return (long)((float)monitor_timer.get_difference() / 1000 * record->get_samplerate());
00735 }
00736 }
00737 else
00738 return -1;
00739 }
00740
00741 long RecordEngine::absolute_preview_position()
00742 {
00743 if(is_previewing)
00744 {
00745 if(record->do_audio)
00746 {
00747 return preview_thread->absolute_position();
00748 }
00749 else
00750 {
00751 return (long)((float)preview_timer.get_difference() / 1000 * record->get_samplerate());
00752 }
00753 }
00754 else
00755 return -1;
00756 }
00757
00758 long RecordEngine::absolute_record_position()
00759 {
00760 if(is_saving)
00761 {
00762 if(record->do_audio)
00763 {
00764
00765 }
00766 else
00767 {
00768 return (long)((float)record_timer.get_difference() / 1000 * record->get_samplerate());
00769 }
00770 }
00771 else
00772 return -1;
00773 }
00774