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()
59 int RecordThread::create_objects()
61 if(record->default_asset->audio_data)
62 record_audio = new RecordAudio(mwindow,
66 if(record->default_asset->video_data)
67 record_video = new RecordVideo(mwindow,
74 int RecordThread::start_recording(int monitor, int context)
77 this->monitor = monitor;
78 this->context = context;
79 resume_monitor = !monitor;
80 loop_lock->lock("RecordThread::start_recording");
82 startup_lock->lock("RecordThread::start_recording");
86 startup_lock->lock("RecordThread::start_recording");
87 startup_lock->unlock();
91 int RecordThread::stop_recording(int resume_monitor)
94 // Stop RecordThread while waiting for batch
95 state_lock->lock("RecordThread::stop_recording");
100 pause_lock->unlock();
104 this->resume_monitor = resume_monitor;
105 // In the monitor engine, stops the engine.
106 // In the recording engine, causes the monitor engine not to be restarted.
107 // Video thread stops the audio thread itself
108 // printf("RecordThread::stop_recording 1\n");
112 record_video->batch_done = 1;
113 state_lock->unlock();
114 record_video->stop_recording();
117 if(record_audio && context != CONTEXT_SINGLEFRAME)
119 record_audio->batch_done = 1;
120 state_lock->unlock();
121 record_audio->stop_recording();
130 int RecordThread::pause_recording()
132 // Stop the thread before finishing the loop
133 pause_lock->lock("RecordThread::pause_recording");
135 state_lock->lock("RecordThread::pause_recording");
136 if(record->default_asset->video_data)
138 record_video->batch_done = 1;
140 else if (record->default_asset->audio_data)
142 record_audio->batch_done = 1;
144 state_lock->unlock();
145 // Stop the recordings
146 if(record->default_asset->audio_data && context != CONTEXT_SINGLEFRAME)
147 record_audio->stop_recording();
148 if(record->default_asset->video_data)
149 record_video->stop_recording();
151 // Wait for thread to stop before closing devices
152 loop_lock->lock("RecordThread::pause_recording");
157 record->close_input_devices(monitor);
158 //printf("RecordThread::pause_recording 2\n");
159 record->capture_state = IS_DONE;
163 int RecordThread::resume_recording()
165 //printf("RecordThread::resume_recording 1\n");
168 record_video->batch_done = 0;
170 else if (record_audio)
172 record_audio->batch_done = 0;
174 loop_lock->lock("RecordThread::resume_recording");
175 pause_lock->unlock();
176 //printf("RecordThread::resume_recording 2\n");
180 int64_t RecordThread::sync_position()
182 if(record->default_asset->audio_data)
183 return record_audio->sync_position();
185 return (int64_t)((float)record_timer->get_difference() /
187 record->default_asset->sample_rate + 0.5);
190 void RecordThread::do_cron()
193 double position = record->current_display_position();
198 // Batch already started
204 // Delay until start of batch
206 record->get_current_time(seconds, day);
209 if(record->get_current_batch()->start_day == 7)
210 day = record->get_current_batch()->start_day;
212 if(record->get_current_batch()->start_day == day &&
213 record->get_current_batch()->start_time >= last_seconds &&
214 record->get_current_batch()->start_time <= seconds)
219 // record->record_gui->lock_window();
220 // record->record_gui->flash_batch();
221 // record->record_gui->unlock_window();
224 last_seconds = seconds;
226 if(!engine_done) usleep(BATCH_DELAY);
229 record->record_gui->lock_window("RecordThread::do_cron");
230 record->record_gui->flash_batch();
231 record->record_gui->unlock_window();
233 }while(!engine_done);
238 void RecordThread::run()
240 int rewinding_loop = 0;
241 startup_lock->unlock();
242 record->get_current_time(last_seconds, last_day);
247 // Prepare next batch
248 if(context == CONTEXT_BATCH &&
254 state_lock->lock("RecordThread::run");
255 // Test for stopped while waiting
261 // Batch context needs to open the device here. Interactive and singleframe
262 // contexts need to open in Record::start_recording to allow full duplex.
263 if(context == CONTEXT_BATCH)
265 // Delete output file before opening the devices to avoid buffer overflow.
266 TRACE("RecordThread::run 1");
267 record->delete_output_file();
268 TRACE("RecordThread::run 2");
269 record->open_input_devices(0, context);
270 TRACE("RecordThread::run 3");
273 // Switch interactive recording to batch recording
274 // to get delay before next batch
275 if(!monitor && context == CONTEXT_INTERACTIVE)
276 context = CONTEXT_BATCH;
280 // This draws to RecordGUI, incidentally
281 TRACE("RecordThread::run 4");
282 record->open_output_file();
283 TRACE("RecordThread::run 5");
284 if(mwindow->edl->session->record_sync_drives)
286 drivesync = new DriveSync;
292 record->get_current_batch()->recorded = 1;
293 TRACE("RecordThread::run 6");
295 // Open file threads here to keep loop synchronized
296 if(record->default_asset->audio_data &&
297 context != CONTEXT_SINGLEFRAME)
299 int buffer_size, fragment_size;
300 record->get_audio_write_length(buffer_size,
302 record->file->start_audio_thread(buffer_size, RING_BUFFERS);
304 TRACE("RecordThread::run 7");
306 if(record->default_asset->video_data)
307 record->file->start_video_thread(mwindow->edl->session->video_write_length,
308 record->vdevice->get_best_colormodel(record->default_asset),
310 record->vdevice->is_compressed(1, 0));
311 TRACE("RecordThread::run 8");
314 // Reset synchronization counters
315 record->get_current_batch()->session_samples = 0;
316 record->get_current_batch()->session_frames = 0;
317 record_timer->update();
320 TRACE("RecordThread::run 9");
321 if(record->default_asset->audio_data && context != CONTEXT_SINGLEFRAME)
322 record_audio->arm_recording();
323 TRACE("RecordThread::run 10");
324 if(record->default_asset->video_data)
325 record_video->arm_recording();
326 TRACE("RecordThread::run 11");
327 state_lock->unlock();
331 if(record->default_asset->audio_data && context != CONTEXT_SINGLEFRAME)
332 record_audio->start_recording();
333 TRACE("RecordThread::run 12");
334 if(record->default_asset->video_data)
335 record_video->start_recording();
336 TRACE("RecordThread::run 13");
339 if(record->default_asset->audio_data && context != CONTEXT_SINGLEFRAME)
340 record_audio->Thread::join();
341 TRACE("RecordThread::run 14");
342 if(record->default_asset->video_data)
343 record_video->Thread::join();
344 TRACE("RecordThread::run 15");
346 // Stop file threads here to keep loop synchronized
349 if(drivesync) drivesync->done = 1;
350 TRACE("RecordThread::run 16");
351 if(record->default_asset->audio_data && context != CONTEXT_SINGLEFRAME)
352 record->file->stop_audio_thread();
353 TRACE("RecordThread::run 17");
354 if(record->default_asset->video_data)
355 record->file->stop_video_thread();
356 TRACE("RecordThread::run 18");
359 record->get_current_batch()->get_current_asset()->audio_length =
360 record->get_current_batch()->total_samples;
361 record->get_current_batch()->get_current_asset()->video_length =
362 record->get_current_batch()->total_frames;
364 // Reset the loop flag and rewind files for the next loop
367 // Rewind loop if in loop mode
368 if(record->get_current_batch()->record_mode == RECORD_LOOP)
370 // Don't close devices when rewinding a loop
371 record->rewind_file();
372 record->get_current_batch()->session_samples = 0;
373 record->get_current_batch()->session_frames = 0;
377 // Advance batch if not terminated by user and not single frame and continue loop
378 if(record->get_next_batch() >= 0 && context != CONTEXT_SINGLEFRAME)
380 record->activate_batch(record->get_next_batch(), 0);
381 record->close_input_devices(monitor);
389 TRACE("RecordThread::run 20");
391 if(drivesync) delete drivesync;
397 state_lock->unlock();
401 // Wait for thread to stop before closing devices
405 // Pause until monitor is resumed
406 pause_lock->lock("RecordThread::run");
407 pause_lock->unlock();
410 }while(!engine_done);
413 record->close_input_devices(monitor);
416 // Resume monitoring only if not a monitor ourselves
419 record->stop_duplex();
420 if(resume_monitor) record->resume_monitor();
424 record->capture_state = IS_DONE;
432 // c-file-style: "linux"