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