00001 #include "asset.h"
00002 #include "audiodevice.h"
00003 #include "batch.h"
00004 #include "bcsignals.h"
00005 #include "condition.h"
00006 #include "drivesync.h"
00007 #include "edl.h"
00008 #include "edlsession.h"
00009 #include "file.h"
00010 #include "mutex.h"
00011 #include "mwindow.h"
00012 #include "record.h"
00013 #include "recordaudio.h"
00014 #include "recordgui.h"
00015 #include "recordthread.h"
00016 #include "recordvideo.h"
00017 #include "bctimer.h"
00018 #include "videodevice.h"
00019
00020
00021
00022 #define RING_BUFFERS 2
00023
00024
00025 RecordThread::RecordThread(MWindow *mwindow, Record *record)
00026 : Thread(1, 0, 0)
00027 {
00028 this->mwindow = mwindow;
00029 this->record = record;
00030 quit_when_completed = 0;
00031 record_timer = new Timer;
00032 record_audio = 0;
00033 record_video = 0;
00034 pause_lock = new Condition(1, "RecordThread::pause_lock");
00035 startup_lock = new Condition(1, "RecordThread::startup_lock");
00036 loop_lock = new Condition(1, "RecordThread::loop_lock");
00037 state_lock = new Mutex("RecordThread::state_lock");
00038 }
00039
00040 RecordThread::~RecordThread()
00041 {
00042 TRACE("RecordThread::~RecordThread 1");
00043 delete record_timer;
00044 delete pause_lock;
00045 delete startup_lock;
00046 delete loop_lock;
00047 delete state_lock;
00048 TRACE("RecordThread::~RecordThread 10");
00049 }
00050
00051 int RecordThread::create_objects()
00052 {
00053 if(record->default_asset->audio_data)
00054 record_audio = new RecordAudio(mwindow,
00055 record,
00056 this);
00057
00058 if(record->default_asset->video_data)
00059 record_video = new RecordVideo(mwindow,
00060 record,
00061 this);
00062 engine_done = 0;
00063 return 0;
00064 }
00065
00066 int RecordThread::start_recording(int monitor, int context)
00067 {
00068 engine_done = 0;
00069 this->monitor = monitor;
00070 this->context = context;
00071 resume_monitor = !monitor;
00072 loop_lock->lock("RecordThread::start_recording");
00073
00074 startup_lock->lock("RecordThread::start_recording");
00075
00076
00077 Thread::start();
00078 startup_lock->lock("RecordThread::start_recording");
00079 startup_lock->unlock();
00080 return 0;
00081 }
00082
00083 int RecordThread::stop_recording(int resume_monitor)
00084 {
00085
00086 state_lock->lock("RecordThread::stop_recording");
00087 engine_done = 1;
00088
00089 this->resume_monitor = resume_monitor;
00090
00091
00092
00093
00094 if(record_video)
00095 {
00096 record_video->batch_done = 1;
00097 state_lock->unlock();
00098 record_video->stop_recording();
00099 }
00100 else
00101 if(record_audio && context != CONTEXT_SINGLEFRAME)
00102 {
00103 record_audio->batch_done = 1;
00104 state_lock->unlock();
00105 record_audio->stop_recording();
00106 }
00107
00108 Thread::join();
00109 return 0;
00110 }
00111
00112 int RecordThread::pause_recording()
00113 {
00114
00115 pause_lock->lock("RecordThread::pause_recording");
00116
00117 state_lock->lock("RecordThread::pause_recording");
00118 if(record->default_asset->video_data)
00119 {
00120 record_video->batch_done = 1;
00121 }
00122 else
00123 {
00124 record_audio->batch_done = 1;
00125 }
00126 state_lock->unlock();
00127
00128 if(record->default_asset->audio_data && context != CONTEXT_SINGLEFRAME)
00129 record_audio->stop_recording();
00130 if(record->default_asset->video_data)
00131 record_video->stop_recording();
00132
00133
00134 loop_lock->lock("RecordThread::pause_recording");
00135 loop_lock->unlock();
00136
00137
00138
00139 record->close_input_devices();
00140
00141 record->capture_state = IS_DONE;
00142 return 0;
00143 }
00144
00145 int RecordThread::resume_recording()
00146 {
00147
00148 if(record_video)
00149 {
00150 record_video->batch_done = 0;
00151 }
00152 else
00153 {
00154 record_audio->batch_done = 0;
00155 }
00156 loop_lock->lock("RecordThread::resume_recording");
00157 pause_lock->unlock();
00158
00159 return 0;
00160 }
00161
00162 int64_t RecordThread::sync_position()
00163 {
00164 if(record->default_asset->audio_data)
00165 return record_audio->sync_position();
00166 else
00167 return (int64_t)((float)record_timer->get_difference() /
00168 1000 *
00169 record->default_asset->sample_rate + 0.5);
00170 }
00171
00172 void RecordThread::do_cron()
00173 {
00174 do{
00175 double position = record->current_display_position();
00176 int day;
00177 double seconds;
00178
00179
00180
00181 if(position > 0)
00182 {
00183 break;
00184 }
00185 else
00186
00187 {
00188 record->get_current_time(seconds, day);
00189
00190
00191 if(record->get_current_batch()->start_day == 7)
00192 day = record->get_current_batch()->start_day;
00193
00194 if(record->get_current_batch()->start_day == day &&
00195 record->get_current_batch()->start_time >= last_seconds &&
00196 record->get_current_batch()->start_time <= seconds)
00197 {
00198 break;
00199 }
00200
00201
00202
00203
00204 }
00205
00206 last_seconds = seconds;
00207 last_day = day;
00208 if(!engine_done) usleep(BATCH_DELAY);
00209 if(!engine_done)
00210 {
00211 record->record_gui->lock_window("RecordThread::do_cron");
00212 record->record_gui->flash_batch();
00213 record->record_gui->unlock_window();
00214 }
00215 }while(!engine_done);
00216 }
00217
00218
00219
00220 void RecordThread::run()
00221 {
00222 int rewinding_loop = 0;
00223 startup_lock->unlock();
00224 record->get_current_time(last_seconds, last_day);
00225
00226
00227 do
00228 {
00229
00230 if(context == CONTEXT_BATCH &&
00231 !rewinding_loop)
00232 {
00233 do_cron();
00234 }
00235
00236 state_lock->lock("RecordThread::run");
00237
00238 if(!engine_done)
00239 {
00240
00241 rewinding_loop = 0;
00242
00243
00244
00245 if(context == CONTEXT_BATCH)
00246 {
00247
00248 TRACE("RecordThread::run 1");
00249 record->delete_output_file();
00250 TRACE("RecordThread::run 2");
00251 record->open_input_devices(0, context);
00252 TRACE("RecordThread::run 3");
00253 }
00254
00255
00256
00257 if(!monitor && context == CONTEXT_INTERACTIVE)
00258 context = CONTEXT_BATCH;
00259
00260 if(!monitor)
00261 {
00262
00263 TRACE("RecordThread::run 4");
00264 record->open_output_file();
00265 TRACE("RecordThread::run 5");
00266 if(mwindow->edl->session->record_sync_drives)
00267 {
00268 drivesync = new DriveSync;
00269 drivesync->start();
00270 }
00271 else
00272 drivesync = 0;
00273
00274 record->get_current_batch()->recorded = 1;
00275 TRACE("RecordThread::run 6");
00276
00277
00278 if(record->default_asset->audio_data &&
00279 context != CONTEXT_SINGLEFRAME)
00280 {
00281 int buffer_size, fragment_size;
00282 record->get_audio_write_length(buffer_size,
00283 fragment_size);
00284 record->file->start_audio_thread(buffer_size, RING_BUFFERS);
00285 }
00286 TRACE("RecordThread::run 7");
00287
00288 if(record->default_asset->video_data)
00289 record->file->start_video_thread(mwindow->edl->session->video_write_length,
00290 record->vdevice->get_best_colormodel(record->default_asset),
00291 RING_BUFFERS,
00292 record->vdevice->is_compressed(1, 0));
00293 TRACE("RecordThread::run 8");
00294 }
00295
00296
00297 record->get_current_batch()->session_samples = 0;
00298 record->get_current_batch()->session_frames = 0;
00299 record_timer->update();
00300
00301
00302 TRACE("RecordThread::run 9");
00303 if(record->default_asset->audio_data && context != CONTEXT_SINGLEFRAME)
00304 record_audio->arm_recording();
00305 TRACE("RecordThread::run 10");
00306 if(record->default_asset->video_data)
00307 record_video->arm_recording();
00308 TRACE("RecordThread::run 11");
00309 state_lock->unlock();
00310
00311
00312
00313 if(record->default_asset->audio_data && context != CONTEXT_SINGLEFRAME)
00314 record_audio->start_recording();
00315 TRACE("RecordThread::run 12");
00316 if(record->default_asset->video_data)
00317 record_video->start_recording();
00318 TRACE("RecordThread::run 13");
00319
00320
00321 if(record->default_asset->audio_data && context != CONTEXT_SINGLEFRAME)
00322 record_audio->Thread::join();
00323 TRACE("RecordThread::run 14");
00324 if(record->default_asset->video_data)
00325 record_video->Thread::join();
00326 TRACE("RecordThread::run 15");
00327
00328
00329 if(!monitor)
00330 {
00331 if(drivesync) drivesync->done = 1;
00332 TRACE("RecordThread::run 16");
00333 if(record->default_asset->audio_data && context != CONTEXT_SINGLEFRAME)
00334 record->file->stop_audio_thread();
00335 TRACE("RecordThread::run 17");
00336 if(record->default_asset->video_data)
00337 record->file->stop_video_thread();
00338 TRACE("RecordThread::run 18");
00339
00340
00341 record->get_current_batch()->get_current_asset()->audio_length =
00342 record->get_current_batch()->total_samples;
00343 record->get_current_batch()->get_current_asset()->video_length =
00344 record->get_current_batch()->total_frames;
00345
00346
00347 if(!engine_done)
00348 {
00349
00350 if(record->get_current_batch()->record_mode == RECORD_LOOP)
00351 {
00352
00353 record->rewind_file();
00354 record->get_current_batch()->session_samples = 0;
00355 record->get_current_batch()->session_frames = 0;
00356 rewinding_loop = 1;
00357 }
00358 else
00359
00360 if(record->get_next_batch() >= 0 && context != CONTEXT_SINGLEFRAME)
00361 {
00362 record->activate_batch(record->get_next_batch(), 0);
00363 record->close_input_devices();
00364 }
00365 else
00366
00367 {
00368 engine_done = 1;
00369 }
00370 }
00371 TRACE("RecordThread::run 20");
00372
00373 if(drivesync) delete drivesync;
00374 }
00375 }
00376 else
00377 {
00378 state_lock->unlock();
00379 }
00380
00381
00382 loop_lock->unlock();
00383 if(monitor)
00384 {
00385
00386 pause_lock->lock("RecordThread::run");
00387 pause_lock->unlock();
00388 }
00389 }while(!engine_done);
00390
00391 record->close_input_devices();
00392
00393
00394 if(!monitor)
00395 {
00396 record->stop_duplex();
00397 if(resume_monitor) record->resume_monitor();
00398 }
00399 else
00400 {
00401 record->capture_state = IS_DONE;
00402 }
00403 }
00404