Better error when trying to load a DCP from a non-DCP directory in the player.
[dcpomatic.git] / src / tools / dcpomatic_player.cc
index 5bc9ace36fe6deb4e7fc5cf9747448a18d5d177d..237b769bbf610c82bc6f369272c42cb2651e32e6 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"
@@ -49,6 +51,8 @@
 #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>
@@ -137,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);
@@ -171,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__
@@ -201,8 +208,41 @@ public:
                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()) {
@@ -210,6 +250,7 @@ public:
                        _viewer->stop ();
                }
        }
+#endif
 
        void setup_main_sizer (Config::PlayerMode mode)
        {
@@ -294,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;
@@ -313,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
@@ -366,15 +419,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;
@@ -383,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));
@@ -455,7 +513,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;
@@ -834,19 +892,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,
@@ -1072,6 +1132,8 @@ private:
                */
                Config::drop ();
 
+               signal_manager = new wxSignalManager (this);
+
                _frame = new DOMFrame ();
                SetTopWindow (_frame);
                _frame->Maximize ();
@@ -1080,8 +1142,6 @@ private:
                }
                _frame->Show ();
 
-               signal_manager = new wxSignalManager (this);
-
                PlayServer* server = new PlayServer (_frame);
                new thread (boost::bind (&PlayServer::run, server));