2 #include "audiodevice.h"
8 #include "edlsession.h"
13 #include "recordaudio.h"
14 #include "recordgui.h"
15 #include "recordthread.h"
16 #include "recordvideo.h"
18 #include "videodevice.h"
22 #define RING_BUFFERS 2
25 RecordThread::RecordThread(MWindow *mwindow, Record *record)
28 this->mwindow = mwindow;
29 this->record = record;
30 quit_when_completed = 0;
31 record_timer = new Timer;
34 pause_lock = new Condition(1, "RecordThread::pause_lock");
35 startup_lock = new Condition(1, "RecordThread::startup_lock");
36 loop_lock = new Condition(1, "RecordThread::loop_lock");
37 state_lock = new Mutex("RecordThread::state_lock");
40 RecordThread::~RecordThread()
42 TRACE("RecordThread::~RecordThread 1");
48 TRACE("RecordThread::~RecordThread 10");
51 int RecordThread::create_objects()
53 if(record->default_asset->audio_data)
54 record_audio = new RecordAudio(mwindow,
58 if(record->default_asset->video_data)
59 record_video = new RecordVideo(mwindow,
66 int RecordThread::start_recording(int monitor, int context)
69 this->monitor = monitor;
70 this->context = context;
71 resume_monitor = !monitor;
72 loop_lock->lock("RecordThread::start_recording");
74 startup_lock->lock("RecordThread::start_recording");
78 startup_lock->lock("RecordThread::start_recording");
79 startup_lock->unlock();
83 int RecordThread::stop_recording(int resume_monitor)
85 // Stop RecordThread while waiting for batch
86 state_lock->lock("RecordThread::stop_recording");
89 this->resume_monitor = resume_monitor;
90 // In the monitor engine, stops the engine.
91 // In the recording engine, causes the monitor engine not to be restarted.
92 // Video thread stops the audio thread itself
93 // printf("RecordThread::stop_recording 1\n");
96 record_video->batch_done = 1;
98 record_video->stop_recording();
101 if(record_audio && context != CONTEXT_SINGLEFRAME)
103 record_audio->batch_done = 1;
104 state_lock->unlock();
105 record_audio->stop_recording();
112 int RecordThread::pause_recording()
114 // Stop the thread before finishing the loop
115 pause_lock->lock("RecordThread::pause_recording");
117 state_lock->lock("RecordThread::pause_recording");
118 if(record->default_asset->video_data)
120 record_video->batch_done = 1;
124 record_audio->batch_done = 1;
126 state_lock->unlock();
127 // Stop the recordings
128 if(record->default_asset->audio_data && context != CONTEXT_SINGLEFRAME)
129 record_audio->stop_recording();
130 if(record->default_asset->video_data)
131 record_video->stop_recording();
133 // Wait for thread to stop before closing devices
134 loop_lock->lock("RecordThread::pause_recording");
139 record->close_input_devices();
140 //printf("RecordThread::pause_recording 2\n");
141 record->capture_state = IS_DONE;
145 int RecordThread::resume_recording()
147 //printf("RecordThread::resume_recording 1\n");
150 record_video->batch_done = 0;
154 record_audio->batch_done = 0;
156 loop_lock->lock("RecordThread::resume_recording");
157 pause_lock->unlock();
158 //printf("RecordThread::resume_recording 2\n");
162 int64_t RecordThread::sync_position()
164 if(record->default_asset->audio_data)
165 return record_audio->sync_position();
167 return (int64_t)((float)record_timer->get_difference() /
169 record->default_asset->sample_rate + 0.5);
172 void RecordThread::do_cron()
175 double position = record->current_display_position();
180 // Batch already started
186 // Delay until start of batch
188 record->get_current_time(seconds, day);
191 if(record->get_current_batch()->start_day == 7)
192 day = record->get_current_batch()->start_day;
194 if(record->get_current_batch()->start_day == day &&
195 record->get_current_batch()->start_time >= last_seconds &&
196 record->get_current_batch()->start_time <= seconds)
201 // record->record_gui->lock_window();
202 // record->record_gui->flash_batch();
203 // record->record_gui->unlock_window();
206 last_seconds = seconds;
208 if(!engine_done) usleep(BATCH_DELAY);
211 record->record_gui->lock_window("RecordThread::do_cron");
212 record->record_gui->flash_batch();
213 record->record_gui->unlock_window();
215 }while(!engine_done);
220 void RecordThread::run()
222 int rewinding_loop = 0;
223 startup_lock->unlock();
224 record->get_current_time(last_seconds, last_day);
229 // Prepare next batch
230 if(context == CONTEXT_BATCH &&
236 state_lock->lock("RecordThread::run");
237 // Test for stopped while waiting
243 // Batch context needs to open the device here. Interactive and singleframe
244 // contexts need to open in Record::start_recording to allow full duplex.
245 if(context == CONTEXT_BATCH)
247 // Delete output file before opening the devices to avoid buffer overflow.
248 TRACE("RecordThread::run 1");
249 record->delete_output_file();
250 TRACE("RecordThread::run 2");
251 record->open_input_devices(0, context);
252 TRACE("RecordThread::run 3");
255 // Switch interactive recording to batch recording
256 // to get delay before next batch
257 if(!monitor && context == CONTEXT_INTERACTIVE)
258 context = CONTEXT_BATCH;
262 // This draws to RecordGUI, incidentally
263 TRACE("RecordThread::run 4");
264 record->open_output_file();
265 TRACE("RecordThread::run 5");
266 if(mwindow->edl->session->record_sync_drives)
268 drivesync = new DriveSync;
274 record->get_current_batch()->recorded = 1;
275 TRACE("RecordThread::run 6");
277 // Open file threads here to keep loop synchronized
278 if(record->default_asset->audio_data &&
279 context != CONTEXT_SINGLEFRAME)
281 int buffer_size, fragment_size;
282 record->get_audio_write_length(buffer_size,
284 record->file->start_audio_thread(buffer_size, RING_BUFFERS);
286 TRACE("RecordThread::run 7");
288 if(record->default_asset->video_data)
289 record->file->start_video_thread(mwindow->edl->session->video_write_length,
290 record->vdevice->get_best_colormodel(record->default_asset),
292 record->vdevice->is_compressed(1, 0));
293 TRACE("RecordThread::run 8");
296 // Reset synchronization counters
297 record->get_current_batch()->session_samples = 0;
298 record->get_current_batch()->session_frames = 0;
299 record_timer->update();
302 TRACE("RecordThread::run 9");
303 if(record->default_asset->audio_data && context != CONTEXT_SINGLEFRAME)
304 record_audio->arm_recording();
305 TRACE("RecordThread::run 10");
306 if(record->default_asset->video_data)
307 record_video->arm_recording();
308 TRACE("RecordThread::run 11");
309 state_lock->unlock();
313 if(record->default_asset->audio_data && context != CONTEXT_SINGLEFRAME)
314 record_audio->start_recording();
315 TRACE("RecordThread::run 12");
316 if(record->default_asset->video_data)
317 record_video->start_recording();
318 TRACE("RecordThread::run 13");
321 if(record->default_asset->audio_data && context != CONTEXT_SINGLEFRAME)
322 record_audio->Thread::join();
323 TRACE("RecordThread::run 14");
324 if(record->default_asset->video_data)
325 record_video->Thread::join();
326 TRACE("RecordThread::run 15");
328 // Stop file threads here to keep loop synchronized
331 if(drivesync) drivesync->done = 1;
332 TRACE("RecordThread::run 16");
333 if(record->default_asset->audio_data && context != CONTEXT_SINGLEFRAME)
334 record->file->stop_audio_thread();
335 TRACE("RecordThread::run 17");
336 if(record->default_asset->video_data)
337 record->file->stop_video_thread();
338 TRACE("RecordThread::run 18");
341 record->get_current_batch()->get_current_asset()->audio_length =
342 record->get_current_batch()->total_samples;
343 record->get_current_batch()->get_current_asset()->video_length =
344 record->get_current_batch()->total_frames;
346 // Reset the loop flag and rewind files for the next loop
349 // Rewind loop if in loop mode
350 if(record->get_current_batch()->record_mode == RECORD_LOOP)
352 // Don't close devices when rewinding a loop
353 record->rewind_file();
354 record->get_current_batch()->session_samples = 0;
355 record->get_current_batch()->session_frames = 0;
359 // Advance batch if not terminated by user and not single frame and continue loop
360 if(record->get_next_batch() >= 0 && context != CONTEXT_SINGLEFRAME)
362 record->activate_batch(record->get_next_batch(), 0);
363 record->close_input_devices();
371 TRACE("RecordThread::run 20");
373 if(drivesync) delete drivesync;
378 state_lock->unlock();
381 // Wait for thread to stop before closing devices
385 // Pause until monitor is resumed
386 pause_lock->lock("RecordThread::run");
387 pause_lock->unlock();
389 }while(!engine_done);
391 record->close_input_devices();
393 // Resume monitoring only if not a monitor ourselves
396 record->stop_duplex();
397 if(resume_monitor) record->resume_monitor();
401 record->capture_state = IS_DONE;