X-Git-Url: https://main.carlh.net/gitweb/?p=dcpomatic.git;a=blobdiff_plain;f=src%2Ftools%2Fdcpomatic_player.cc;h=bbbbe3a1d20574fa2eab24591c2a9c1e9c745cba;hp=6bd5b36ffd1f0f61974c6b94d9de177f7a632aa3;hb=3e3e8433842820ce6380e8f5c1917ae1a28e2e57;hpb=5eb8b5c3a1566aef638e9d9df03b88d320735092 diff --git a/src/tools/dcpomatic_player.cc b/src/tools/dcpomatic_player.cc index 6bd5b36ff..bbbbe3a1d 100644 --- a/src/tools/dcpomatic_player.cc +++ b/src/tools/dcpomatic_player.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2017-2019 Carl Hetherington + Copyright (C) 2017-2020 Carl Hetherington This file is part of DCP-o-matic. @@ -28,7 +28,10 @@ #include "wx/player_config_dialog.h" #include "wx/verify_dcp_dialog.h" #include "wx/standard_controls.h" +#include "wx/playlist_controls.h" +#ifdef DCPOMATIC_VARIANT_SWAROOP #include "wx/swaroop_controls.h" +#endif #include "wx/timer_display.h" #include "wx/system_information_dialog.h" #include "lib/cross.h" @@ -73,6 +76,7 @@ #include #endif #include +#include #include #ifdef check @@ -93,8 +97,62 @@ using boost::optional; using boost::dynamic_pointer_cast; using boost::thread; using boost::bind; +using dcp::raw_convert; using namespace dcpomatic; +#ifdef DCPOMATIC_PLAYER_STRESS_TEST +/* Interval to check what to do next with the stress checker, in milliseconds */ +#define STRESS_TEST_CHECK_INTERVAL 20 + +class Command +{ +public: + enum Type { + NONE, + OPEN, + PLAY, + WAIT, + STOP, + SEEK, + }; + + Command(string line) + : type (NONE) + , int_param (0) + { + vector bits; + boost::split (bits, line, boost::is_any_of(" ")); + if (bits[0] == "O") { + if (bits.size() != 2) { + return; + } + type = OPEN; + string_param = bits[1]; + } else if (bits[0] == "P") { + type = PLAY; + } else if (bits[0] == "W") { + if (bits.size() != 2) { + return; + } + type = WAIT; + int_param = raw_convert(bits[1]); + } else if (bits[0] == "S") { + type = STOP; + } else if (bits[0] == "K") { + if (bits.size() != 2) { + return; + } + type = SEEK; + int_param = raw_convert(bits[1]); + } + } + + Type type; + string string_param; + int int_param; +}; +#endif + enum { ID_file_open = 1, ID_file_add_ov, @@ -139,7 +197,11 @@ public: , _system_information_dialog (0) , _view_full_screen (0) , _view_dual_screen (0) - { +#ifdef DCPOMATIC_PLAYER_STRESS_TEST + , _timer (this) + , _stress_suspended (false) +#endif +{ dcpomatic_log.reset (new NullLog()); #if defined(DCPOMATIC_WINDOWS) @@ -191,7 +253,13 @@ public: _controls = sc; sc->ResetFilm.connect (bind(&DOMFrame::reset_film_weak, this, _1)); #else - _controls = new StandardControls (_overall_panel, _viewer, false); + if (Config::instance()->player_mode() == Config::PLAYER_MODE_DUAL) { + PlaylistControls* pc = new PlaylistControls (_overall_panel, _viewer); + _controls = pc; + pc->ResetFilm.connect (bind(&DOMFrame::reset_film_weak, this, _1)); + } else { + _controls = new StandardControls (_overall_panel, _viewer, false); + } #endif _viewer->set_dcp_decode_reduction (Config::instance()->decode_reduction ()); _viewer->PlaybackPermitted.connect (bind(&DOMFrame::playback_permitted, this)); @@ -236,6 +304,74 @@ public: #endif } +#ifdef DCPOMATIC_PLAYER_STRESS_TEST + void stress (boost::filesystem::path script_file) + { + Bind (wxEVT_TIMER, boost::bind(&DOMFrame::check_commands, this)); + _timer.Start(STRESS_TEST_CHECK_INTERVAL); + vector lines; + string const script = dcp::file_to_string(script_file); + boost::split (lines, script, boost::is_any_of("\n")); + BOOST_FOREACH (string i, lines) { + _commands.push_back (Command(i)); + } + _current_command = _commands.begin(); + } + + void check_commands () + { + if (_stress_suspended) { + return; + } + + if (_current_command == _commands.end()) { + _timer.Stop (); + cout << "ST: finished.\n"; + return; + } + + switch (_current_command->type) { + case Command::OPEN: + load_dcp (_current_command->string_param); + ++_current_command; + break; + case Command::PLAY: + cout << "ST: play\n"; + _controls->play (); + ++_current_command; + break; + case Command::WAIT: + /* int_param here is the number of milliseconds to wait */ + if (_wait_remaining) { + _wait_remaining = *_wait_remaining - STRESS_TEST_CHECK_INTERVAL; + if (_wait_remaining < 0) { + cout << "ST: wait done.\n"; + _wait_remaining = optional(); + ++_current_command; + } + } else { + _wait_remaining = _current_command->int_param; + cout << "ST: waiting for " << *_wait_remaining << ".\n"; + } + break; + case Command::STOP: + cout << "ST: stop\n"; + _controls->stop (); + ++_current_command; + break; + case Command::NONE: + ++_current_command; + break; + case Command::SEEK: + /* int_param here is a number between 0 and 4095, corresponding to the possible slider positions */ + cout << "ST: seek to " << _current_command->int_param << "\n"; + _controls->seek (_current_command->int_param); + ++_current_command; + break; + } + } +#endif + #ifdef DCPOMATIC_VARIANT_SWAROOP void monitor_checker_state_changed () { @@ -372,8 +508,11 @@ public: reset_film (); try { + _stress_suspended = true; shared_ptr dcp (new DCPContent(dir)); - _film->examine_and_add_content (dcp, true); + shared_ptr job (new ExamineContentJob(_film, dcp)); + _examine_job_connection = job->Finished.connect(bind(&DOMFrame::add_dcp_to_film, this, weak_ptr(job), weak_ptr(dcp))); + JobManager::instance()->add (job); bool const ok = display_progress (_("DCP-o-matic Player"), _("Loading content")); if (!ok || !report_errors_from_last_job(this)) { return; @@ -386,6 +525,22 @@ public: } } + void add_dcp_to_film (weak_ptr weak_job, weak_ptr weak_content) + { + shared_ptr job = weak_job.lock (); + if (!job || !job->finished_ok()) { + return; + } + + shared_ptr content = weak_content.lock (); + if (!content) { + return; + } + + _film->add_content (content); + _stress_suspended = false; + } + void reset_film_weak (weak_ptr weak_film) { shared_ptr film = weak_film.lock (); @@ -999,16 +1154,28 @@ private: SystemInformationDialog* _system_information_dialog; boost::shared_ptr _film; boost::signals2::scoped_connection _config_changed_connection; + boost::signals2::scoped_connection _examine_job_connection; wxMenuItem* _file_add_ov; wxMenuItem* _file_add_kdm; wxMenuItem* _tools_verify; wxMenuItem* _view_full_screen; wxMenuItem* _view_dual_screen; +#ifdef DCPOMATIC_PLAYER_STRESS_TEST + wxTimer _timer; + list _commands; + list::const_iterator _current_command; + /** Remaining time that the script must wait, in milliseconds */ + optional _wait_remaining; + bool _stress_suspended; +#endif }; static const wxCmdLineEntryDesc command_line_description[] = { { wxCMD_LINE_PARAM, 0, 0, "DCP to load or create", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL }, { wxCMD_LINE_OPTION, "c", "config", "Directory containing config.xml", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL }, +#ifdef DCPOMATIC_PLAYER_STRESS_TEST + { wxCMD_LINE_OPTION, "s", "stress", "File containing description of stress test", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL }, +#endif { wxCMD_LINE_NONE, "", "", "", wxCmdLineParamType (0), 0 } }; @@ -1124,6 +1291,16 @@ private: } } +#ifdef DCPOMATIC_PLAYER_STRESS_TEST + if (_stress) { + try { + _frame->stress (_stress.get()); + } catch (exception& e) { + error_dialog (0, wxString::Format("Could not load stress test file %s", std_to_wx(*_stress))); + } + } +#endif + Bind (wxEVT_IDLE, boost::bind (&App::idle, this)); if (Config::instance()->check_for_updates ()) { @@ -1157,6 +1334,12 @@ private: if (parser.Found("c", &config)) { Config::override_path = wx_to_std (config); } +#ifdef DCPOMATIC_PLAYER_STRESS_TEST + wxString stress; + if (parser.Found("s", &stress)) { + _stress = wx_to_std (stress); + } +#endif return true; } @@ -1217,6 +1400,9 @@ private: DOMFrame* _frame; string _dcp_to_load; +#ifdef DCPOMATIC_PLAYER_STRESS_TEST + boost::optional _stress; +#endif }; IMPLEMENT_APP (App)