swaroop: restart playback after player crash.
[dcpomatic.git] / src / tools / dcpomatic_player.cc
index 1742f654051cfedb76d4d296458657be45519d77..e855a1cc6042dd582f7bcf19f15de724391117e5 100644 (file)
@@ -36,6 +36,8 @@
 #include "lib/compose.hpp"
 #include "lib/dcp_content.h"
 #include "lib/job_manager.h"
+#include "lib/spl.h"
+#include "lib/spl_entry.h"
 #include "lib/job.h"
 #include "lib/film.h"
 #include "lib/video_content.h"
@@ -47,7 +49,9 @@
 #include "lib/server.h"
 #include "lib/dcpomatic_socket.h"
 #include "lib/scoped_temporary.h"
+#include "lib/monitor_checker.h"
 #include <dcp/dcp.h>
+#include <dcp/raw_convert.h>
 #include <wx/wx.h>
 #include <wx/stdpaths.h>
 #include <wx/splash.h>
@@ -136,7 +140,7 @@ public:
                SetIcon (wxIcon (std_to_wx ("id")));
 #endif
 
-               _config_changed_connection = Config::instance()->Changed.connect (boost::bind (&DOMFrame::config_changed, this));
+               _config_changed_connection = Config::instance()->Changed.connect (boost::bind (&DOMFrame::config_changed, this, _1));
                update_from_config ();
 
                Bind (wxEVT_MENU, boost::bind (&DOMFrame::file_open, this), ID_file_open);
@@ -170,6 +174,9 @@ 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__
@@ -195,8 +202,51 @@ public:
 
                UpdateChecker::instance()->StateChanged.connect (boost::bind (&DOMFrame::update_checker_state_changed, this));
                _controls->SPLChanged.connect (boost::bind(&DOMFrame::set_spl, this, _1));
-
+#ifdef DCPOMATIC_VARIANT_SWAROOP
+               MonitorChecker::instance()->StateChanged.connect(boost::bind(&DOMFrame::monitor_checker_state_changed, this));
+               MonitorChecker::instance()->run ();
+#endif
                setup_screen ();
+
+#ifdef DCPOMATIC_VARIANT_SWAROOP
+               if (
+                       boost::filesystem::is_regular_file(Config::path("position")) &&
+                       boost::filesystem::is_regular_file(Config::path("spl.xml"))) {
+
+                       set_spl (SPL(Config::path("spl.xml")));
+                       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);
+                       }
+               }
+
+#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);
+               }
+       }
+
+       void monitor_checker_state_changed ()
+       {
+               if (!MonitorChecker::instance()->ok()) {
+                       error_dialog (this, _("The required display devices are not connected correctly."));
+                       _viewer->stop ();
+               }
        }
 
        void setup_main_sizer (Config::PlayerMode mode)
@@ -213,6 +263,12 @@ public:
 
        bool playback_permitted ()
        {
+#ifdef DCPOMATIC_VARIANT_SWAROOP
+               if (!MonitorChecker::instance()->ok()) {
+                       error_dialog (this, _("The required display devices are not connected correctly."));
+                       return false;
+               }
+#endif
                if (!_film || !Config::instance()->respect_kdm_validity_periods()) {
                        return true;
                }
@@ -276,6 +332,14 @@ public:
 
        void playback_stopped (DCPTime time)
        {
+#ifdef DCPOMATIC_VARIANT_SWAROOP
+               try {
+                       boost::filesystem::remove (Config::path("position"));
+               } catch (...) {
+                       /* Never mind */
+               }
+#endif
+
                optional<boost::filesystem::path> log = Config::instance()->player_log_file();
                if (!log) {
                        return;
@@ -297,9 +361,9 @@ public:
        {
                dcp::DCP dcp (dir);
                dcp.read ();
-               list<SPLEntry> spl;
+               SPL spl;
                BOOST_FOREACH (shared_ptr<dcp::CPL> j, dcp.cpls()) {
-                       spl.push_back (SPLEntry(j, dir));
+                       spl.playlist.push_back (SPLEntry(j, dir));
                }
                set_spl (spl);
                Config::instance()->add_to_player_history (dir);
@@ -348,15 +412,19 @@ public:
                return optional<dcp::EncryptedKDM>();
        }
 
-       void set_spl (list<SPLEntry> spl)
+       void set_spl (SPL spl)
        {
+#ifdef DCPOMATIC_VARIANT_SWAROOP
+               spl.as_xml (Config::path("spl.xml"));
+#endif
+
                if (_viewer->playing ()) {
                        _viewer->stop ();
                }
 
                _film.reset (new Film (optional<boost::filesystem::path>()));
 
-               if (spl.empty ()) {
+               if (spl.playlist.empty ()) {
                        _viewer->set_film (_film);
                        _info->triggered_update ();
                        return;
@@ -365,10 +433,11 @@ public:
                /* Start off as Flat */
                _film->set_container (Ratio::from_id("185"));
 
-               DCPTime position;
+               /* Put 1 frame of black at the start so when we seek to 0 we don't see anything */
+               DCPTime position = DCPTime::from_frames(1, _film->video_frame_rate());
                shared_ptr<DCPContent> first;
 
-               BOOST_FOREACH (SPLEntry i, spl) {
+               BOOST_FOREACH (SPLEntry i, spl.playlist) {
                        shared_ptr<DCPContent> dcp;
                        try {
                                dcp.reset (new DCPContent (_film, i.directory));
@@ -437,7 +506,7 @@ public:
                        _cpl_menu->Remove (*i);
                }
 
-               if (spl.size() == 1) {
+               if (spl.playlist.size() == 1) {
                        /* Offer a CPL menu */
                        DCPExaminer ex (first);
                        int id = ID_view_cpl;
@@ -816,19 +885,21 @@ private:
                _update_news_requested = false;
        }
 
-       void config_changed ()
+       void config_changed (Config::Property prop)
        {
                /* Instantly save any config changes when using the player GUI */
                try {
                        Config::instance()->write_config();
                } catch (FileError& e) {
-                       error_dialog (
-                               this,
-                               wxString::Format(
-                                       _("Could not write to config file at %s.  Your changes have not been saved."),
-                                       std_to_wx(e.file().string())
-                                       )
-                               );
+                       if (prop != Config::HISTORY) {
+                               error_dialog (
+                                       this,
+                                       wxString::Format(
+                                               _("Could not write to config file at %s.  Your changes have not been saved."),
+                                               std_to_wx(e.file().string())
+                                               )
+                                       );
+                       }
                } catch (exception& e) {
                        error_dialog (
                                this,
@@ -1054,6 +1125,8 @@ private:
                */
                Config::drop ();
 
+               signal_manager = new wxSignalManager (this);
+
                _frame = new DOMFrame ();
                SetTopWindow (_frame);
                _frame->Maximize ();
@@ -1062,8 +1135,6 @@ private:
                }
                _frame->Show ();
 
-               signal_manager = new wxSignalManager (this);
-
                PlayServer* server = new PlayServer (_frame);
                new thread (boost::bind (&PlayServer::run, server));