00001 #include "cache.h"
00002 #include "condition.h"
00003 #include "bchash.h"
00004 #include "edl.h"
00005 #include "edlsession.h"
00006 #include "localsession.h"
00007 #include "mbuttons.h"
00008 #include "mutex.h"
00009 #include "mwindow.h"
00010 #include "mwindowgui.h"
00011 #include "patchbay.h"
00012 #include "tracking.h"
00013 #include "playbackengine.h"
00014 #include "playtransport.h"
00015 #include "preferences.h"
00016 #include "renderengine.h"
00017 #include "mainsession.h"
00018 #include "trackcanvas.h"
00019 #include "transportque.h"
00020 #include "vrender.h"
00021
00022
00023 PlaybackEngine::PlaybackEngine(MWindow *mwindow, Canvas *output)
00024 : Thread(1, 0, 0)
00025 {
00026 this->mwindow = mwindow;
00027 this->output = output;
00028 is_playing_back = 0;
00029 tracking_position = 0;
00030 tracking_active = 0;
00031 audio_cache = 0;
00032 video_cache = 0;
00033 last_command = STOP;
00034 tracking_lock = new Mutex("PlaybackEngine::tracking_lock");
00035 tracking_done = new Condition(1, "PlaybackEngine::tracking_done");
00036 pause_lock = new Condition(0, "PlaybackEngine::pause_lock");
00037 start_lock = new Condition(0, "PlaybackEngine::start_lock");
00038 render_engine = 0;
00039 debug = 0;
00040 }
00041
00042 PlaybackEngine::~PlaybackEngine()
00043 {
00044 done = 1;
00045 que->send_command(STOP,
00046 CHANGE_NONE,
00047 0,
00048 0);
00049 interrupt_playback();
00050
00051 Thread::join();
00052 delete preferences;
00053 delete command;
00054 delete que;
00055 delete_render_engine();
00056 delete audio_cache;
00057 delete video_cache;
00058 delete tracking_lock;
00059 delete tracking_done;
00060 delete pause_lock;
00061 delete start_lock;
00062 }
00063
00064 int PlaybackEngine::create_objects()
00065 {
00066 int result = 0;
00067 preferences = new Preferences;
00068 command = new TransportCommand;
00069 que = new TransportQue;
00070
00071 que->command.change_type = CHANGE_ALL;
00072
00073 preferences->copy_from(mwindow->preferences);
00074
00075 done = 0;
00076 Thread::start();
00077 start_lock->lock("PlaybackEngine::create_objects");
00078 return result;
00079 }
00080
00081 ChannelDB* PlaybackEngine::get_channeldb()
00082 {
00083 PlaybackConfig *config = command->get_edl()->session->playback_config;
00084 switch(config->vconfig->driver)
00085 {
00086 case VIDEO4LINUX2JPEG:
00087 return mwindow->channeldb_v4l2jpeg;
00088 break;
00089 case PLAYBACK_BUZ:
00090 return mwindow->channeldb_buz;
00091 break;
00092 }
00093 return 0;
00094 }
00095
00096 int PlaybackEngine::create_render_engine()
00097 {
00098
00099 int current_vchannel = 0;
00100 int current_achannel = 0;
00101
00102 delete_render_engine();
00103
00104
00105 render_engine = new RenderEngine(this,
00106 preferences,
00107 command,
00108 output,
00109 mwindow->plugindb,
00110 get_channeldb());
00111 return 0;
00112 }
00113
00114 void PlaybackEngine::delete_render_engine()
00115 {
00116 delete render_engine;
00117 render_engine = 0;
00118 }
00119
00120 void PlaybackEngine::arm_render_engine()
00121 {
00122 int current_achannel = 0, current_vchannel = 0;
00123 if(render_engine)
00124 render_engine->arm_command(command,
00125 current_achannel,
00126 current_vchannel);
00127 }
00128
00129 void PlaybackEngine::start_render_engine()
00130 {
00131 if(render_engine) render_engine->start_command();
00132 }
00133
00134 void PlaybackEngine::wait_render_engine()
00135 {
00136 if(command->realtime && render_engine)
00137 {
00138 render_engine->join();
00139 }
00140 }
00141
00142 void PlaybackEngine::create_cache()
00143 {
00144 if(audio_cache) delete audio_cache;
00145 audio_cache = 0;
00146 if(video_cache) delete video_cache;
00147 video_cache = 0;
00148 if(!audio_cache)
00149 audio_cache = new CICache(preferences, mwindow->plugindb);
00150 if(!video_cache)
00151 video_cache = new CICache(preferences, mwindow->plugindb);
00152 }
00153
00154
00155 void PlaybackEngine::perform_change()
00156 {
00157 switch(command->change_type)
00158 {
00159 case CHANGE_ALL:
00160 create_cache();
00161 case CHANGE_EDL:
00162 create_render_engine();
00163 case CHANGE_PARAMS:
00164 if(command->change_type != CHANGE_EDL &&
00165 command->change_type != CHANGE_ALL)
00166 render_engine->edl->synchronize_params(command->get_edl());
00167 case CHANGE_NONE:
00168 break;
00169 }
00170 }
00171
00172 void PlaybackEngine::sync_parameters(EDL *edl)
00173 {
00174
00175 command->get_edl()->synchronize_params(edl);
00176 if(render_engine) render_engine->edl->synchronize_params(edl);
00177 }
00178
00179
00180 void PlaybackEngine::interrupt_playback(int wait_tracking)
00181 {
00182 if(render_engine)
00183 render_engine->interrupt_playback();
00184
00185
00186 pause_lock->unlock();
00187
00188
00189 if(wait_tracking)
00190 {
00191 tracking_done->lock("PlaybackEngine::interrupt_playback");
00192 tracking_done->unlock();
00193 }
00194 }
00195
00196
00197
00198 int PlaybackEngine::get_output_levels(double *levels, long position)
00199 {
00200 int result = 0;
00201 if(render_engine && render_engine->do_audio)
00202 {
00203 result = 1;
00204 render_engine->get_output_levels(levels, position);
00205 }
00206 return result;
00207 }
00208
00209
00210 int PlaybackEngine::get_module_levels(ArrayList<double> *module_levels, long position)
00211 {
00212 int result = 0;
00213 if(render_engine && render_engine->do_audio)
00214 {
00215 result = 1;
00216 render_engine->get_module_levels(module_levels, position);
00217 }
00218 return result;
00219 }
00220
00221 int PlaybackEngine::brender_available(long position)
00222 {
00223 return 0;
00224 }
00225
00226 void PlaybackEngine::init_cursor()
00227 {
00228 }
00229
00230 void PlaybackEngine::stop_cursor()
00231 {
00232 }
00233
00234
00235 void PlaybackEngine::init_tracking()
00236 {
00237 if(!command->single_frame())
00238 tracking_active = 1;
00239 else
00240 tracking_active = 0;
00241
00242 tracking_position = command->playbackstart;
00243 tracking_done->lock("PlaybackEngine::init_tracking");
00244 init_cursor();
00245 }
00246
00247 void PlaybackEngine::stop_tracking()
00248 {
00249 tracking_active = 0;
00250 stop_cursor();
00251 tracking_done->unlock();
00252 }
00253
00254 void PlaybackEngine::update_tracking(double position)
00255 {
00256 tracking_lock->lock("PlaybackEngine::update_tracking");
00257
00258 tracking_position = position;
00259
00260
00261 if(tracking_active) tracking_active = 2;
00262 tracking_timer.update();
00263 tracking_lock->unlock();
00264 }
00265
00266 double PlaybackEngine::get_tracking_position()
00267 {
00268 double result = 0;
00269
00270 tracking_lock->lock("PlaybackEngine::get_tracking_position");
00271
00272
00273
00274
00275
00276 if(tracking_active == 2)
00277 {
00278
00279
00280
00281
00282 if(command->get_edl()->session->video_every_frame &&
00283 render_engine &&
00284 render_engine->do_video)
00285 {
00286 result = tracking_position;
00287 }
00288 else
00289
00290 {
00291 double loop_start = command->get_edl()->local_session->loop_start;
00292 double loop_end = command->get_edl()->local_session->loop_end;
00293 double loop_size = loop_end - loop_start;
00294
00295 if(command->get_direction() == PLAY_FORWARD)
00296 {
00297
00298 result = tracking_position +
00299 command->get_speed() *
00300 tracking_timer.get_difference() /
00301 1000.0;
00302
00303
00304
00305 if(command->get_edl()->local_session->loop_playback)
00306 {
00307 while(result > loop_end) result -= loop_size;
00308 }
00309 }
00310 else
00311 {
00312
00313 result = tracking_position -
00314 command->get_speed() *
00315 tracking_timer.get_difference() /
00316 1000.0;
00317
00318
00319 if(command->get_edl()->local_session->loop_playback)
00320 {
00321 while(result < loop_start) result += loop_size;
00322 }
00323 }
00324
00325 }
00326 }
00327 else
00328 result = tracking_position;
00329
00330 tracking_lock->unlock();
00331
00332
00333
00334
00335 return result;
00336 }
00337
00338 void PlaybackEngine::update_transport(int command, int paused)
00339 {
00340
00341
00342
00343 }
00344
00345 void PlaybackEngine::run()
00346 {
00347 start_lock->unlock();
00348
00349 do
00350 {
00351
00352 que->output_lock->lock("PlaybackEngine::run");
00353
00354 wait_render_engine();
00355
00356
00357
00358 que->input_lock->lock("PlaybackEngine::run");
00359 if(done) return;
00360
00361 command->copy_from(&que->command);
00362 que->command.reset();
00363 que->input_lock->unlock();
00364
00365
00366
00367
00368 switch(command->command)
00369 {
00370
00371 case COMMAND_NONE:
00372
00373 perform_change();
00374 break;
00375
00376 case PAUSE:
00377 init_cursor();
00378 pause_lock->lock("PlaybackEngine::run");
00379 stop_cursor();
00380 break;
00381
00382 case STOP:
00383
00384 break;
00385
00386 case CURRENT_FRAME:
00387 last_command = command->command;
00388 perform_change();
00389 arm_render_engine();
00390
00391 start_render_engine();
00392 break;
00393
00394 default:
00395 last_command = command->command;
00396 is_playing_back = 1;
00397 if(command->command == SINGLE_FRAME_FWD ||
00398 command->command == SINGLE_FRAME_REWIND)
00399 {
00400 command->playbackstart = get_tracking_position();
00401 }
00402
00403 perform_change();
00404 arm_render_engine();
00405
00406
00407
00408 init_tracking();
00409
00410
00411 start_render_engine();
00412 break;
00413 }
00414
00415
00416
00417 }while(!done);
00418 }
00419
00420
00421