4 #include "edlsession.h"
5 #include "localsession.h"
8 #include "mwindowgui.h"
11 #include "playbackengine.h"
12 #include "playtransport.h"
13 #include "preferences.h"
14 #include "renderengine.h"
15 #include "mainsession.h"
16 #include "trackcanvas.h"
17 #include "transportque.h"
18 #include "videodevice.h"
22 PlaybackEngine::PlaybackEngine(MWindow *mwindow, Canvas *output)
25 this->mwindow = mwindow;
26 this->output = output;
28 tracking_position = 0;
33 Thread::set_synchronous(1);
36 PlaybackEngine::~PlaybackEngine()
38 //printf("PlaybackEngine::~PlaybackEngine 1\n");
40 que->send_command(STOP,
45 //printf("PlaybackEngine::~PlaybackEngine 1\n");
47 //printf("PlaybackEngine::~PlaybackEngine 1\n");
49 //printf("PlaybackEngine::~PlaybackEngine 1\n");
51 //printf("PlaybackEngine::~PlaybackEngine 1\n");
53 //printf("PlaybackEngine::~PlaybackEngine 1\n");
54 delete_render_engines();
55 //printf("PlaybackEngine::~PlaybackEngine 1\n");
56 if(audio_cache) delete audio_cache;
57 //printf("PlaybackEngine::~PlaybackEngine 1\n");
58 if(video_cache) delete video_cache;
59 //printf("PlaybackEngine::~PlaybackEngine 2\n");
62 int PlaybackEngine::create_objects()
65 preferences = new Preferences;
66 command = new TransportCommand;
67 que = new TransportQue;
68 // Set the first change to maximum
69 que->command.change_type = CHANGE_ALL;
71 *preferences = *mwindow->preferences;
75 //printf("PlaybackEngine::create_objects 1\n");
77 //printf("PlaybackEngine::create_objects 1\n");
79 //printf("PlaybackEngine::create_objects 1\n");
81 //printf("PlaybackEngine::create_objects 1\n");
86 int PlaybackEngine::create_render_engines()
88 //printf("PlaybackEngine::create_render_engines 1 %d\n", command->edl->session->playback_strategy);
89 // Fix playback configurations
90 int playback_strategy = command->get_edl()->session->playback_strategy;
91 int current_vchannel = 0;
92 int current_achannel = 0;
94 delete_render_engines();
97 //printf("PlaybackEngine::create_render_engines %d\n", command->get_edl()->session->playback_config[playback_strategy].total);
99 i < command->get_edl()->session->playback_config[playback_strategy].total;
102 RenderEngine *engine = new RenderEngine(this,
107 &mwindow->channeldb_buz,
109 render_engines.append(engine);
114 void PlaybackEngine::delete_render_engines()
116 render_engines.remove_all_objects();
119 void PlaybackEngine::arm_render_engines()
121 int current_achannel = 0, current_vchannel = 0;
122 for(int i = 0; i < render_engines.total; i++)
124 //printf("PlaybackEngine::arm_render_engines %ld\n", command->playbackstart);
125 render_engines.values[i]->arm_command(command,
131 void PlaybackEngine::start_render_engines()
133 //printf("PlaybackEngine::start_render_engines 1 %d\n", render_engines.total);
134 for(int i = 0; i < render_engines.total; i++)
136 render_engines.values[i]->start_command();
140 void PlaybackEngine::wait_render_engines()
142 //printf("PlaybackEngine::wait_render_engines 1 %d %d\n", command->command, command->realtime);
143 if(command->realtime)
145 for(int i = 0; i < render_engines.total; i++)
147 //printf("PlaybackEngine::wait_render_engines 2 %p %d\n", render_engines.values[i], render_engines.values[i]->get_tid());
148 render_engines.values[i]->join();
150 //printf("PlaybackEngine::wait_render_engines 3 %d\n", render_engines.total);
154 void PlaybackEngine::create_cache()
156 if(audio_cache) delete audio_cache;
158 if(video_cache) delete video_cache;
161 audio_cache = new CICache(command->get_edl(), preferences, mwindow->plugindb);
163 audio_cache->set_edl(command->get_edl());
166 video_cache = new CICache(command->get_edl(), preferences, mwindow->plugindb);
168 video_cache->set_edl(command->get_edl());
172 void PlaybackEngine::perform_change()
174 //printf("PlaybackEngine::perform_change 1 %x\n", command->change_type);
175 switch(command->change_type)
180 audio_cache->set_edl(command->get_edl());
181 video_cache->set_edl(command->get_edl());
182 //printf("PlaybackEngine::perform_change 1\n");
183 create_render_engines();
185 //printf("PlaybackEngine::perform_change 1\n");
186 if(command->change_type != CHANGE_EDL &&
187 command->change_type != CHANGE_ALL)
188 for(int i = 0; i < render_engines.total; i++)
189 render_engines.values[i]->edl->synchronize_params(command->get_edl());
191 //printf("PlaybackEngine::perform_change 2\n");
196 void PlaybackEngine::sync_parameters(EDL *edl)
198 // TODO: lock out render engine from keyframe deletions
199 for(int i = 0; i < render_engines.total; i++)
200 render_engines.values[i]->edl->synchronize_params(edl);
204 void PlaybackEngine::interrupt_playback(int wait_tracking)
206 //printf("PlaybackEngine::interrupt_playback 1\n");
207 for(int i = 0; i < render_engines.total; i++)
208 render_engines.values[i]->interrupt_playback();
213 // Wait for tracking to finish if it is running
214 //printf("PlaybackEngine::interrupt_playback 2\n");
217 tracking_done.lock();
218 tracking_done.unlock();
220 //printf("PlaybackEngine::interrupt_playback 3\n");
224 // Return 1 if levels exist
225 int PlaybackEngine::get_output_levels(double *levels, long position)
228 for(int j = 0; j < render_engines.total; j++)
230 if(render_engines.values[j]->do_audio)
233 render_engines.values[j]->get_output_levels(levels, position);
240 int PlaybackEngine::get_module_levels(ArrayList<double> *module_levels, long position)
243 for(int j = 0; j < render_engines.total; j++)
245 if(render_engines.values[j]->do_audio)
248 render_engines.values[j]->get_module_levels(module_levels, position);
255 int PlaybackEngine::brender_available(long position)
260 void PlaybackEngine::init_cursor()
264 void PlaybackEngine::stop_cursor()
269 void PlaybackEngine::init_tracking()
271 if(!command->single_frame())
276 tracking_position = command->playbackstart;
277 tracking_done.lock();
279 //printf("PlaybackEngine::init_tracking %ld\n", tracking_position);
282 void PlaybackEngine::stop_tracking()
284 // Set the tracking position to right now before stopping it.
285 // tracking_position = get_tracking_position();
286 //printf("PlaybackEngine::stop_tracking %ld\n", tracking_position);
289 //printf("PlaybackEngine::stop_tracking 1\n");
290 tracking_done.unlock();
293 void PlaybackEngine::update_tracking(double position)
295 tracking_lock.lock();
297 tracking_position = position;
299 // Signal that the timer is accurate.
300 if(tracking_active) tracking_active = 2;
301 tracking_timer.update();
302 tracking_lock.unlock();
305 double PlaybackEngine::get_tracking_position()
309 tracking_lock.lock();
312 // Adjust for elapsed time since last update_tracking.
313 // But tracking timer isn't accurate until the first update_tracking
315 if(tracking_active == 2)
317 //printf("PlaybackEngine::get_tracking_position %d %d %d\n", command->get_direction(), tracking_position, tracking_timer.get_scaled_difference(command->get_edl()->session->sample_rate));
320 // Don't interpolate when every frame is played.
321 if(command->get_edl()->session->video_every_frame &&
322 render_engines.total &&
323 render_engines.values[0]->do_video)
325 result = tracking_position;
330 double loop_start = command->get_edl()->local_session->loop_start;
331 double loop_end = command->get_edl()->local_session->loop_end;
332 double loop_size = loop_end - loop_start;
334 if(command->get_direction() == PLAY_FORWARD)
337 result = tracking_position +
338 command->get_speed() *
339 tracking_timer.get_difference() /
342 // Compensate for loop
343 //printf("PlaybackEngine::get_tracking_position 1 %d\n", command->get_edl()->local_session->loop_playback);
344 if(command->get_edl()->local_session->loop_playback)
346 while(result > loop_end) result -= loop_size;
352 result = tracking_position -
353 command->get_speed() *
354 tracking_timer.get_difference() /
357 // Compensate for loop
358 if(command->get_edl()->local_session->loop_playback)
360 while(result < loop_start) result += loop_size;
367 result = tracking_position;
369 tracking_lock.unlock();
370 //printf("PlaybackEngine::get_tracking_position %f %f %d\n", result, tracking_position, tracking_active);
377 void PlaybackEngine::update_transport(int command, int paused)
379 // mwindow->gui->lock_window();
380 // mwindow->gui->mbuttons->transport->update_gui_state(command, paused);
381 // mwindow->gui->unlock_window();
384 void PlaybackEngine::run()
389 // Wait for current command to finish
390 //printf("PlaybackEngine::run 1\n");
391 que->output_lock.lock();
392 //printf("PlaybackEngine::run 2\n");
394 wait_render_engines();
396 //printf("PlaybackEngine::run 3 %d\n", que->command.command);
398 // Read the new command
399 que->input_lock.lock();
402 //printf("PlaybackEngine::run 3\n");
403 *command = que->command;
404 //printf("PlaybackEngine::run 3 %f %f\n", command->playbackstart, que->command.playbackstart);
405 que->command.reset();
406 //printf("PlaybackEngine::run 3 %p\n", this);
407 que->input_lock.unlock();
409 // printf("PlaybackEngine::run 4 %d %x %x\n",
410 // this->command->command,
411 // this->command->change_type,
412 // que->command.change_type);
415 switch(command->command)
417 // Parameter change only
419 // command->command = last_command;
436 //printf("PlaybackEngine::run 5\n");
437 last_command = command->command;
438 //printf("PlaybackEngine::run 5.1\n");
440 //printf("PlaybackEngine::run 7\n");
441 arm_render_engines();
442 // Dispatch the command
443 start_render_engines();
444 //printf("PlaybackEngine::run 8\n");
448 //printf("PlaybackEngine::run 5\n");
449 last_command = command->command;
451 //printf("PlaybackEngine::run 6 %f %f\n", command->playbackstart, get_tracking_position());
452 if(command->command == SINGLE_FRAME_FWD ||
453 command->command == SINGLE_FRAME_REWIND)
455 command->playbackstart = get_tracking_position();
459 //printf("PlaybackEngine::run 9 %f\n", command->playbackstart);
460 arm_render_engines();
462 // Start tracking after arming so the tracking position doesn't change.
463 // The tracking for a single frame command occurs during PAUSE
464 //printf("PlaybackEngine::run 9 %d\n", command->playbackstart);
467 // Dispatch the command
468 //printf("PlaybackEngine::run 10\n");
469 start_render_engines();
470 //printf("PlaybackEngine::run 11\n");
474 //printf("PlaybackEngine::run 12\n");
499 int PlaybackEngine::reset_parameters()
501 // called before every playback
508 playback_start = playback_end = 0;
517 int PlaybackEngine::init_parameters()
519 // is_playing_back = 1;
521 correction_factor = 0;
523 // correct playback buffer sizes
527 audio_module_fragment =
528 command->get_edl()->session->audio_module_fragment;
530 // get maximum actual buffer size written to device plus padding
531 if(speed != 1) output_length = (long)(output_length / speed) + 16;
532 if(output_length < playback_buffer) output_length = playback_buffer;
534 // samples to read at a time is a multiple of the playback buffer greater than read_length
535 while(input_length < command->get_edl()->session->audio_read_length)
536 input_length += playback_buffer;
540 int PlaybackEngine::init_audio_device()
545 int PlaybackEngine::init_video_device()
552 int PlaybackEngine::start_reconfigure()
554 reconfigure_status = is_playing_back;
555 // if(is_playing_back) stop_playback(0);
559 int PlaybackEngine::stop_reconfigure()
564 int PlaybackEngine::reset_buttons()
570 long PlaybackEngine::absolute_position(int sync_time)
575 long PlaybackEngine::get_position(int sync_time)
579 switch(is_playing_back)
583 result = absolute_position(sync_time);
585 result = (long)(result * speed);
587 // adjust direction and initial position
590 result = playback_end - result;
591 result += loop_adjustment;
593 // adjust for looping
594 // while(mwindow->session->loop_playback && follow_loop &&
595 // result < mwindow->session->loop_start)
597 // result += mwindow->session->loop_end - mwindow->session->loop_start;
598 // loop_adjustment += mwindow->session->loop_end - mwindow->session->loop_start;
603 result += playback_start;
604 result -= loop_adjustment;
606 // while(mwindow->session->loop_playback && follow_loop &&
607 // result > mwindow->session->loop_end)
609 // result -= mwindow->session->loop_end - mwindow->session->loop_start;
610 // loop_adjustment += mwindow->session->loop_end - mwindow->session->loop_start;
617 result = last_position;
630 int PlaybackEngine::move_right(long distance)
632 mwindow->move_right(distance);
637 int PlaybackEngine::cleanup()
642 int PlaybackEngine::wait_for_startup()
647 int PlaybackEngine::wait_for_completion()
649 // must use mutex not join since playback engine also terminates itself