Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members

recordengine.C

Go to the documentation of this file.
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 //      monitor_thread = new RecordThread(mwindow, record, this);
00079         monitor_thread->create_objects();
00080         
00081 //      record_thread = new RecordThread(mwindow, record, this);
00082         record_thread->create_objects();
00083 
00084         preview_thread = new RecordPreview(record, this);
00085         preview_thread->initialize();
00086 
00087 // put at end of file
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 // initialize seek buttons
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 // ============================================= accounting
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 // ================================================ operations
00202 
00203 int RecordEngine::open_input_devices(int duplex)
00204 {
00205         int audio_opened = 0;
00206         int video_opened = 0;
00207         AudioConfig *aconfig /* = mwindow->preferences->aconfig */;
00208 
00209 // Initialize sharing
00210         if(record->do_audio && record->do_video)
00211         {
00212                 vdevice->set_adevice(adevice);
00213                 adevice->set_vdevice(vdevice);
00214         }
00215 
00216 // Initialize audio
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 // Duplex is only needed if the timeline and the recording have audio
00230         if(duplex &&
00231                 record->do_audio && 
00232                 mwindow->patches->total_playable_atracks())
00233         {
00234 // duplex device is identical to input device
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 //                      adevice->open_duplex(mwindow->preferences->aconfig, 
00241 //                                              record->get_samplerate(), 
00242 //                                              get_in_length());
00243                         audio_opened = 1;
00244                 }
00245                 else
00246 // two separate devices
00247                 {
00248 //                      adevice->open_output(mwindow->preferences->aconfig, 
00249 //                                      record->get_samplerate(), 
00250 //                                      record->get_out_length());
00251                 }
00252         }
00253 
00254         if(record->do_audio && !audio_opened)
00255         {
00256 //              adevice->open_input(mwindow->preferences->aconfig, 
00257 //                              record->get_samplerate(), 
00258 //                              get_in_length());
00259         }
00260 
00261 // Initialize video
00262         if(record->do_video)
00263         {
00264 //              vdevice->open_input(mwindow->preferences->vconfig, 
00265 //                      record->frame_w, 
00266 //                      record->frame_h,
00267 //                      record->video_x, 
00268 //                      record->video_y, 
00269 //                      record->video_zoom,
00270 //                      get_frame_rate());
00271 //              vdevice->set_field_order(record->reverse_interlace);
00272 //              if(record->get_current_channel())
00273 //                      vdevice->set_channel(record->get_current_channel());
00274 //              set_video_picture();
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 //      if(is_monitoring)
00303 //      {
00304 //              is_monitoring = 0;
00305 //              monitor_thread->stop_recording();
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 // start the duplex engine if necessary
00343 // OSS < 3.9 crashes if recording starts before playback
00344 // OSS >= 3.9 crashes if playback starts before recording
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 //              record_thread->start_recording();
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 // start the duplex engine if necessary
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 // automatically stops duplex here and resumes monitor
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 // OSS can't resume recording if buffers underrun
00395 // so stop playback first
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 // preview engine automatically triggers monitor when finished
00422         }
00423         return 0;
00424 }
00425 
00426 int RecordEngine::stop_operation(int no_monitor)
00427 {
00428 // Resumes monitoring after stopping
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 //              adevice->open_output(mwindow->preferences->aconfig, 
00451 //                              record->get_samplerate(), 
00452 //                              record->get_out_length());
00453                 if(record->get_software_positioning()) adevice->set_software_positioning();
00454         }
00455 
00456 // Video is already open for monitoring
00457         return 0;
00458 }
00459 
00460 int RecordEngine::close_output_devices()
00461 {
00462         if(record->do_audio)
00463                 adevice->close_all();
00464 // Video is already open for monitoring
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;      // fread error in filepcm
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 //              gui->update_total_length(new_position);
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 //                      if(record->do_audio) file->set_audio_position(new_position);
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 //                      if(record->do_audio) file->set_audio_position(new_position);
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 // remove file
00591                         file->close_file();
00592                         remove(asset->path);
00593 
00594 // reopen file
00595 //                      file->set_processors(mwindow->preferences->smp ? 2: 1);
00596 //                      file->set_preload(mwindow->preferences->playback_preload);
00597 //                      file->try_to_open_file(mwindow->plugindb, asset, 1, 1);
00598 
00599 // start the engine over
00600                         labels->delete_new_labels();
00601                         update_position(0);
00602                         total_length = 0;
00603 //                      gui->update_total_length(0);
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() { /* return mwindow->preferences->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 < /*JUMP_DELAYS*/ 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 // Remember to change meters if you change this.
00713 // Return the size of the fragments to read from the audio device.
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 // Different absolute positions are defined for each operation so threads
00723 // can end at different times without screwing up the frame synchronization.
00724 long RecordEngine::absolute_monitor_position()
00725 {
00726         if(is_monitoring)
00727         {
00728                 if(record->do_audio)
00729                 {
00730 //                      return monitor_thread->absolute_position();
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 //                      return record_thread->absolute_position();
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 

Generated on Sun Jan 8 13:38:59 2006 for Cinelerra-svn by  doxygen 1.4.4