From ed227b4fdba9b4fc7f06f6db4830219f14bad358 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Fri, 14 Dec 2018 00:58:48 +0000 Subject: [PATCH 1/1] swaroop: fix up restart-after-crash. --- src/lib/content.h | 2 +- src/lib/playlist.cc | 7 ++++++ src/lib/playlist.h | 4 ++- src/lib/spl.cc | 2 ++ src/lib/spl.h | 9 ++++++- src/lib/wscript | 1 + src/tools/dcpomatic_player.cc | 37 +-------------------------- src/wx/swaroop_controls.cc | 47 ++++++++++++++++++++++++++++++++++- src/wx/swaroop_controls.h | 2 ++ 9 files changed, 71 insertions(+), 40 deletions(-) diff --git a/src/lib/content.h b/src/lib/content.h index 55cf4acae..96359fadb 100644 --- a/src/lib/content.h +++ b/src/lib/content.h @@ -184,7 +184,7 @@ public: std::string calculate_digest () const; - /* CHANGE_PENDING and CHANGE_CANCELLED may be emitted from any thread; CHANGE_DONE always from GUI thread */ + /* CHANGE_TYPE_PENDING and CHANGE_TYPE_CANCELLED may be emitted from any thread; CHANGE_TYPE_DONE always from GUI thread */ boost::signals2::signal, int, bool)> Change; boost::shared_ptr video; diff --git a/src/lib/playlist.cc b/src/lib/playlist.cc index c10235f9b..f530d2ee3 100644 --- a/src/lib/playlist.cc +++ b/src/lib/playlist.cc @@ -68,6 +68,13 @@ Playlist::~Playlist () void Playlist::content_change (weak_ptr weak_film, ChangeType type, weak_ptr content, int property, bool frequent) { + /* Make sure we only hear about atomic changes (e.g. a PENDING always with the DONE/CANCELLED) + Ignore any DONE/CANCELLED that arrives without a PENDING. + */ + if (_checker.send (type, property)) { + return; + } + shared_ptr film = weak_film.lock (); DCPOMATIC_ASSERT (film); diff --git a/src/lib/playlist.h b/src/lib/playlist.h index d9140bdfb..dd43ed2e3 100644 --- a/src/lib/playlist.h +++ b/src/lib/playlist.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2013-2016 Carl Hetherington + Copyright (C) 2013-2018 Carl Hetherington This file is part of DCP-o-matic. @@ -23,6 +23,7 @@ #include "util.h" #include "frame_rate_change.h" +#include "atomicity_checker.h" #include #include #include @@ -90,6 +91,7 @@ private: bool _sequence; bool _sequencing; std::list _content_connections; + AtomicityChecker _checker; }; #endif diff --git a/src/lib/spl.cc b/src/lib/spl.cc index 2cba229c1..cd33c4047 100644 --- a/src/lib/spl.cc +++ b/src/lib/spl.cc @@ -35,6 +35,7 @@ SPL::read (boost::filesystem::path path, ContentStore* store) _missing = false; cxml::Document doc ("SPL"); doc.read_file (path); + _id = doc.string_child("Id"); BOOST_FOREACH (cxml::ConstNodePtr i, doc.node_children("Entry")) { shared_ptr c = store->get(i->string_child("Digest")); if (c) { @@ -52,6 +53,7 @@ SPL::write (boost::filesystem::path path) const { xmlpp::Document doc; xmlpp::Element* root = doc.create_root_node ("SPL"); + root->add_child("Id")->add_child_text (_id); BOOST_FOREACH (SPLEntry i, _spl) { i.as_xml (root->add_child("Entry")); } diff --git a/src/lib/spl.h b/src/lib/spl.h index b94c08571..b19ef7e7a 100644 --- a/src/lib/spl.h +++ b/src/lib/spl.h @@ -22,6 +22,7 @@ #define DCPOMATIC_SPL_H #include "spl_entry.h" +#include class ContentStore; @@ -29,7 +30,8 @@ class SPL { public: SPL () - : _missing (false) + : _id (dcp::make_uuid()) + , _missing (false) {} void add (SPLEntry e) { @@ -55,6 +57,10 @@ public: void read (boost::filesystem::path path, ContentStore* store); void write (boost::filesystem::path path) const; + std::string id () const { + return _id; + } + std::string name () const { return _name; } @@ -64,6 +70,7 @@ public: } private: + std::string _id; std::string _name; std::vector _spl; /** true if any content was missing when read() was last called on this SPL */ diff --git a/src/lib/wscript b/src/lib/wscript index e2aeb7107..62881e95d 100644 --- a/src/lib/wscript +++ b/src/lib/wscript @@ -24,6 +24,7 @@ sources = """ active_text.cc analyse_audio_job.cc atmos_mxf_content.cc + atomicity_checker.cc audio_analysis.cc audio_buffers.cc audio_content.cc diff --git a/src/tools/dcpomatic_player.cc b/src/tools/dcpomatic_player.cc index 550b89ed4..d61c8a5e0 100644 --- a/src/tools/dcpomatic_player.cc +++ b/src/tools/dcpomatic_player.cc @@ -186,9 +186,6 @@ public: _viewer->Started.connect (bind(&DOMFrame::playback_started, this, _1)); _viewer->Seeked.connect (bind(&DOMFrame::playback_seeked, this, _1)); _viewer->Stopped.connect (bind(&DOMFrame::playback_stopped, this, _1)); -#ifdef DCPOMATIC_VARIANT_SWAROOP - _viewer->PositionChanged.connect (bind(&DOMFrame::position_changed, this)); -#endif _info = new PlayerInformation (_overall_panel, _viewer); setup_main_sizer (Config::instance()->player_mode()); #ifdef __WXOSX__ @@ -224,40 +221,10 @@ public: setup_screen (); #ifdef DCPOMATIC_VARIANT_SWAROOP - if ( - boost::filesystem::is_regular_file(Config::path("position")) && - boost::filesystem::is_regular_file(Config::path("spl.xml"))) { - - shared_ptr film (new Film(boost::optional())); - film->read_metadata (Config::path("spl.xml")); - reset_film (film); - FILE* f = fopen_boost (Config::path("position"), "r"); - if (f) { - char buffer[64]; - fscanf (f, "%63s", buffer); - _viewer->seek (DCPTime(atoi(buffer)), true); - _viewer->start (); - fclose (f); - } - } - + sc->check_restart (); #endif } - void position_changed () - { - if (!_viewer->playing() || _viewer->position().get() % DCPTime::HZ) { - return; - } - - FILE* f = fopen_boost (Config::path("position"), "w"); - if (f) { - string const p = dcp::raw_convert (_viewer->position().get()); - fwrite (p.c_str(), p.length(), 1, f); - fclose (f); - } - } - #ifdef DCPOMATIC_VARIANT_SWAROOP void monitor_checker_state_changed () { @@ -488,8 +455,6 @@ public: return; } - _film->write_metadata (Config::path("spl.xml")); - if (_viewer->playing ()) { _viewer->stop (); } diff --git a/src/wx/swaroop_controls.cc b/src/wx/swaroop_controls.cc index 6a40e1fc0..6e3d052eb 100644 --- a/src/wx/swaroop_controls.cc +++ b/src/wx/swaroop_controls.cc @@ -26,6 +26,8 @@ #include "static_text.h" #include "lib/player_video.h" #include "lib/dcp_content.h" +#include "lib/cross.h" +#include #include #include @@ -106,6 +108,7 @@ SwaroopControls::SwaroopControls (wxWindow* parent, shared_ptr viewe _spl_view->Bind (wxEVT_LIST_ITEM_SELECTED, boost::bind(&SwaroopControls::spl_selection_changed, this)); _spl_view->Bind (wxEVT_LIST_ITEM_DESELECTED, boost::bind(&SwaroopControls::spl_selection_changed, this)); _viewer->Finished.connect (boost::bind(&SwaroopControls::viewer_finished, this)); + _viewer->PositionChanged.connect (boost::bind(&SwaroopControls::viewer_position_changed, this)); _refresh_spl_view->Bind (wxEVT_BUTTON, boost::bind(&SwaroopControls::update_playlist_directory, this)); _refresh_content_view->Bind (wxEVT_BUTTON, boost::bind(&ContentView::update, _content_view)); @@ -113,6 +116,49 @@ SwaroopControls::SwaroopControls (wxWindow* parent, shared_ptr viewe update_playlist_directory (); } +void +SwaroopControls::check_restart () +{ + FILE* f = fopen_boost (Config::path("position"), "r"); + if (!f) { + return; + } + + char id[64]; + int index; + int64_t time; + fscanf (f, "%63s %d %ld", id, &index, &time); + + for (size_t i = 0; i < _playlists.size(); ++i) { + if (_playlists[i].id() == id) { + _selected_playlist = i; + _selected_playlist_position = index; + update_current_content (); + _viewer->seek (DCPTime(time), false); + } + } + + fclose (f); +} + +void +SwaroopControls::viewer_position_changed () +{ + if (!_selected_playlist || !_viewer->playing() || _viewer->position().get() % DCPTime::HZ) { + return; + } + + FILE* f = fopen_boost (Config::path("position"), "w"); + if (f) { + string const p = _playlists[*_selected_playlist].id() + + " " + dcp::raw_convert(_selected_playlist_position) + + " " + dcp::raw_convert(_viewer->position().get()); + + fwrite (p.c_str(), p.length(), 1, f); + fclose (f); + } +} + void SwaroopControls::started () { @@ -274,7 +320,6 @@ SwaroopControls::spl_selection_changed () return; } - _current_spl_view->DeleteAllItems (); int N = 0; diff --git a/src/wx/swaroop_controls.h b/src/wx/swaroop_controls.h index 2d0d14a67..f09344d1a 100644 --- a/src/wx/swaroop_controls.h +++ b/src/wx/swaroop_controls.h @@ -27,6 +27,7 @@ public: void log (wxString s); void set_film (boost::shared_ptr film); + void check_restart (); /** This is so that we can tell our parent player to reset the film when we have created one from a SPL. We could call a method @@ -49,6 +50,7 @@ private: void setup_sensitivity (); void config_changed (int); void viewer_finished (); + void viewer_position_changed (); void reset_film (); void update_current_content (); bool can_do_previous (); -- 2.30.2