Don't set up new film several times when setting up new SPL in player.
[dcpomatic.git] / src / tools / dcpomatic_player.cc
index 3eec00e51402725dbcf2074f7261bc69474b1bbb..a4333db827d4c4a9de2167e34559d00b07771b13 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"
 #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 <dcp/exceptions.h>
 #include <wx/wx.h>
 #include <wx/stdpaths.h>
 #include <wx/splash.h>
@@ -136,7 +141,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 +175,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,10 +203,55 @@ 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);
+               }
        }
 
+#ifdef DCPOMATIC_VARIANT_SWAROOP
+       void monitor_checker_state_changed ()
+       {
+               if (!MonitorChecker::instance()->ok()) {
+                       error_dialog (this, _("The required display devices are not connected correctly."));
+                       _viewer->stop ();
+               }
+       }
+#endif
+
        void setup_main_sizer (Config::PlayerMode mode)
        {
                wxSizer* main_sizer = new wxBoxSizer (wxVERTICAL);
@@ -213,6 +266,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 +335,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;
@@ -295,14 +362,18 @@ public:
 
        void load_dcp (boost::filesystem::path dir)
        {
-               dcp::DCP dcp (dir);
-               dcp.read ();
-               list<SPLEntry> spl;
-               BOOST_FOREACH (shared_ptr<dcp::CPL> j, dcp.cpls()) {
-                       spl.push_back (SPLEntry(j, dir));
+               try {
+                       dcp::DCP dcp (dir);
+                       dcp.read ();
+                       SPL spl;
+                       BOOST_FOREACH (shared_ptr<dcp::CPL> j, dcp.cpls()) {
+                               spl.playlist.push_back (SPLEntry(j, dir));
+                       }
+                       set_spl (spl);
+                       Config::instance()->add_to_player_history (dir);
+               } catch (dcp::DCPReadError& e) {
+                       error_dialog (this, wxString::Format(_("Could not load a DCP from %s"), std_to_wx(dir.string())), std_to_wx(e.what()));
                }
-               set_spl (spl);
-               Config::instance()->add_to_player_history (dir);
        }
 
 #ifdef DCPOMATIC_VARIANT_SWAROOP
@@ -334,29 +405,33 @@ public:
                        return optional<dcp::EncryptedKDM>();
                }
                for (directory_iterator i = directory_iterator(*kdm_dir); i != directory_iterator(); ++i) {
-                       if (file_size(i->path()) < MAX_KDM_SIZE) {
-                               try {
+                       try {
+                               if (file_size(i->path()) < MAX_KDM_SIZE) {
                                        dcp::EncryptedKDM kdm (dcp::file_to_string(i->path()));
                                        if (kdm.cpl_id() == dcp->cpl()) {
                                                return kdm;
                                        }
-                               } catch (std::exception& e) {
-                                       /* Hey well */
                                }
+                       } catch (std::exception& e) {
+                               /* Hey well */
                        }
                }
                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 +440,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));
@@ -424,20 +500,21 @@ public:
                                _film->set_three_d (true);
                        }
 
-                       _viewer->set_film (_film);
-                       _viewer->seek (DCPTime(), true);
-                       _info->triggered_update ();
-
-                       set_menu_sensitivity ();
                        _controls->log (wxString::Format(_("Load DCP %s"), i.directory.filename().string().c_str()));
                }
 
+               _viewer->set_film (_film);
+               _viewer->seek (DCPTime(), true);
+               _info->triggered_update ();
+
+               set_menu_sensitivity ();
+
                wxMenuItemList old = _cpl_menu->GetMenuItems();
                for (wxMenuItemList::iterator i = old.begin(); i != old.end(); ++i) {
                        _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 +893,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 +1133,8 @@ private:
                */
                Config::drop ();
 
+               signal_manager = new wxSignalManager (this);
+
                _frame = new DOMFrame ();
                SetTopWindow (_frame);
                _frame->Maximize ();
@@ -1062,8 +1143,6 @@ private:
                }
                _frame->Show ();
 
-               signal_manager = new wxSignalManager (this);
-
                PlayServer* server = new PlayServer (_frame);
                new thread (boost::bind (&PlayServer::run, server));