swaroop: fix up restart-after-crash. v2.13.84
authorCarl Hetherington <cth@carlh.net>
Fri, 14 Dec 2018 00:58:48 +0000 (00:58 +0000)
committerCarl Hetherington <cth@carlh.net>
Fri, 14 Dec 2018 00:58:48 +0000 (00:58 +0000)
src/lib/content.h
src/lib/playlist.cc
src/lib/playlist.h
src/lib/spl.cc
src/lib/spl.h
src/lib/wscript
src/tools/dcpomatic_player.cc
src/wx/swaroop_controls.cc
src/wx/swaroop_controls.h

index 55cf4acaef643114ab5de6c7c672438243bdc378..96359fadb5fa256d67a1ce51f948ad00cf633269 100644 (file)
@@ -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<void (ChangeType, boost::weak_ptr<Content>, int, bool)> Change;
 
        boost::shared_ptr<VideoContent> video;
index c10235f9beb4e91a03d7cfc7adca9d4025dddf78..f530d2ee3826d5eead2b4c1b061f96184b7118be 100644 (file)
@@ -68,6 +68,13 @@ Playlist::~Playlist ()
 void
 Playlist::content_change (weak_ptr<const Film> weak_film, ChangeType type, weak_ptr<Content> 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<const Film> film = weak_film.lock ();
        DCPOMATIC_ASSERT (film);
 
index d9140bdfb6d87ead55318bf8ffbac1a6c81dd92e..dd43ed2e36813a0dcb207b22fe968e095d35feae 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2013-2016 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2013-2018 Carl Hetherington <cth@carlh.net>
 
     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 <libcxml/cxml.h>
 #include <boost/shared_ptr.hpp>
 #include <boost/signals2.hpp>
@@ -90,6 +91,7 @@ private:
        bool _sequence;
        bool _sequencing;
        std::list<boost::signals2::connection> _content_connections;
+       AtomicityChecker _checker;
 };
 
 #endif
index 2cba229c10962f4ee4c3ccb48f8db26c58ce392c..cd33c4047815386ec7ef524872e2fd06619e198e 100644 (file)
@@ -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<Content> 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"));
        }
index b94c0857197f63791e34cfc795e2b1b5c5ee32e0..b19ef7e7a1c9f9d7e267a2aab9a9e1ad18a87b93 100644 (file)
@@ -22,6 +22,7 @@
 #define DCPOMATIC_SPL_H
 
 #include "spl_entry.h"
+#include <dcp/util.h>
 
 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<SPLEntry> _spl;
        /** true if any content was missing when read() was last called on this SPL */
index e2aeb7107ec8db83bc4410758d4fd89be51cb635..62881e95d4c00e82081928d678e0897f08f094c4 100644 (file)
@@ -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
index 550b89ed425944aa2ea6890bb3210ccae8d9f9ca..d61c8a5e07ca62248ac8097e8c636a5b3c026f1e 100644 (file)
@@ -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> film (new Film(boost::optional<boost::filesystem::path>()));
-                       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<string> (_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 ();
                }
index 6a40e1fc0ca12284c581b677764467e88ecf7e0a..6e3d052eb40a92ac4ec1e824b3f3ec8f2deb40bf 100644 (file)
@@ -26,6 +26,8 @@
 #include "static_text.h"
 #include "lib/player_video.h"
 #include "lib/dcp_content.h"
+#include "lib/cross.h"
+#include <dcp/raw_convert.h>
 #include <wx/listctrl.h>
 #include <wx/progdlg.h>
 
@@ -106,6 +108,7 @@ SwaroopControls::SwaroopControls (wxWindow* parent, shared_ptr<FilmViewer> 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<FilmViewer> 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<string>(_selected_playlist_position)
+                       + " " + dcp::raw_convert<string>(_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;
index 2d0d14a67763b1437cb1baa8ae7f9017feeb2d0e..f09344d1aea8aac00733e9c3e39ce18eb136364d 100644 (file)
@@ -27,6 +27,7 @@ public:
 
        void log (wxString s);
        void set_film (boost::shared_ptr<Film> 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 ();