More player debugging for butler video-full states.
[dcpomatic.git] / src / tools / dcpomatic_player.cc
index d00129a4c6a10176b47228ed97c69ac3a5048a41..6e4f9960c167feb5d71db5ccd258b5d26dce2829 100644 (file)
@@ -27,7 +27,8 @@
 #include "wx/update_dialog.h"
 #include "wx/player_config_dialog.h"
 #include "wx/verify_dcp_dialog.h"
-#include "wx/controls.h"
+#include "wx/standard_controls.h"
+#include "wx/swaroop_controls.h"
 #include "lib/cross.h"
 #include "lib/config.h"
 #include "lib/util.h"
@@ -52,6 +53,7 @@
 #include "lib/lock_file_checker.h"
 #include "lib/ffmpeg_content.h"
 #include "lib/dcpomatic_log.h"
+#include "lib/file_log.h"
 #include <dcp/dcp.h>
 #include <dcp/raw_convert.h>
 #include <dcp/exceptions.h>
@@ -80,6 +82,7 @@ using std::list;
 using std::exception;
 using std::vector;
 using boost::shared_ptr;
+using boost::weak_ptr;
 using boost::scoped_array;
 using boost::optional;
 using boost::dynamic_pointer_cast;
@@ -128,9 +131,7 @@ public:
                , _view_full_screen (0)
                , _view_dual_screen (0)
        {
-               /* XXX */
                dcpomatic_log.reset (new NullLog());
-               cout << "here's the log " << dcpomatic_log.get() << "\n";
 
 #if defined(DCPOMATIC_WINDOWS)
                maybe_open_console ();
@@ -147,7 +148,7 @@ public:
 #endif
 
                _config_changed_connection = Config::instance()->Changed.connect (boost::bind (&DOMFrame::config_changed, this, _1));
-               update_from_config ();
+               update_from_config (Config::PLAYER_DEBUG_LOG);
 
                Bind (wxEVT_MENU, boost::bind (&DOMFrame::file_open, this), ID_file_open);
                Bind (wxEVT_MENU, boost::bind (&DOMFrame::file_add_ov, this), ID_file_add_ov);
@@ -174,15 +175,17 @@ public:
                _overall_panel = new wxPanel (this, wxID_ANY);
 
                _viewer.reset (new FilmViewer (_overall_panel));
-               _controls = new Controls (_overall_panel, _viewer, false);
+#ifdef DCPOMATIC_VARIANT_SWAROOP
+               SwaroopControls* sc = new SwaroopControls (_overall_panel, _viewer);
+               _controls = sc;
+               sc->ResetFilm.connect (bind(&DOMFrame::reset_film_weak, this, _1));
+#else
+               _controls = new StandardControls (_overall_panel, _viewer, false);
+#endif
                _viewer->set_dcp_decode_reduction (Config::instance()->decode_reduction ());
                _viewer->PlaybackPermitted.connect (bind(&DOMFrame::playback_permitted, this));
                _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__
@@ -218,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 ()
        {
@@ -315,13 +288,6 @@ public:
 
        void playback_started (DCPTime time)
        {
-               optional<boost::filesystem::path> log = Config::instance()->player_log_file();
-               if (!log) {
-                       return;
-               }
-
-               FILE* f = fopen_boost(*log, "a");
-
                /* XXX: this only logs the first piece of content; probably should be each piece? */
 
                shared_ptr<DCPContent> dcp = dynamic_pointer_cast<DCPContent>(_film->content().front());
@@ -335,40 +301,26 @@ public:
                        }
                        DCPOMATIC_ASSERT (playing_cpl);
 
-                       fprintf (
-                               f,
-                               "%s playback-started %s %s %s\n",
-                               dcp::LocalTime().as_string().c_str(),
-                               time.timecode(_film->video_frame_rate()).c_str(),
-                               dcp->directories().front().string().c_str(),
-                               playing_cpl->annotation_text().c_str()
+                       _controls->log (
+                               wxString::Format(
+                                       "playback-started %s %s %s",
+                                       time.timecode(_film->video_frame_rate()).c_str(),
+                                       dcp->directories().front().string().c_str(),
+                                       playing_cpl->annotation_text().c_str()
+                                       )
                                );
                }
 
                shared_ptr<FFmpegContent> ffmpeg = dynamic_pointer_cast<FFmpegContent>(_film->content().front());
                if (ffmpeg) {
-                       fprintf (
-                               f,
-                               "%s playback-started %s %s\n",
-                               dcp::LocalTime().as_string().c_str(),
-                               time.timecode(_film->video_frame_rate()).c_str(),
-                               ffmpeg->path(0).string().c_str()
+                       _controls->log (
+                               wxString::Format(
+                                       "playback-started %s %s",
+                                       time.timecode(_film->video_frame_rate()).c_str(),
+                                       ffmpeg->path(0).string().c_str()
+                                       )
                                );
                }
-
-               fclose (f);
-       }
-
-       void playback_seeked (DCPTime time)
-       {
-               optional<boost::filesystem::path> log = Config::instance()->player_log_file();
-               if (!log) {
-                       return;
-               }
-
-               FILE* f = fopen_boost(*log, "a");
-               fprintf (f, "%s playback-seeked %s\n", dcp::LocalTime().as_string().c_str(), time.timecode(_film->video_frame_rate()).c_str());
-               fclose (f);
        }
 
        void playback_stopped (DCPTime time)
@@ -381,14 +333,7 @@ public:
                }
 #endif
 
-               optional<boost::filesystem::path> log = Config::instance()->player_log_file();
-               if (!log) {
-                       return;
-               }
-
-               FILE* f = fopen_boost(*log, "a");
-               fprintf (f, "%s playback-stopped %s\n", dcp::LocalTime().as_string().c_str(), time.timecode(_film->video_frame_rate()).c_str());
-               fclose (f);
+               _controls->log (wxString::Format("playback-stopped %s", time.timecode(_film->video_frame_rate()).c_str()));
        }
 
        void set_decode_reduction (optional<int> reduction)
@@ -405,65 +350,34 @@ public:
                reset_film ();
                try {
                        shared_ptr<DCPContent> dcp (new DCPContent(dir));
-                       _film->examine_and_add_content (dcp);
+                       _film->examine_and_add_content (dcp, true);
                        bool const ok = display_progress (_("DCP-o-matic Player"), _("Loading content"));
                        if (!ok || !report_errors_from_last_job(this)) {
                                return;
                        }
+#ifndef DCPOMATIC_VARIANT_SWAROOP
                        Config::instance()->add_to_player_history (dir);
+#endif
                } 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()));
                }
        }
 
-#ifdef DCPOMATIC_VARIANT_SWAROOP
-       optional<dcp::EncryptedKDM> get_kdm_from_url (shared_ptr<DCPContent> dcp)
+       void reset_film_weak (weak_ptr<Film> weak_film)
        {
-               ScopedTemporary temp;
-               string url = Config::instance()->kdm_server_url();
-               boost::algorithm::replace_all (url, "{CPL}", *dcp->cpl());
-               optional<dcp::EncryptedKDM> kdm;
-               if (dcp->cpl() && !get_from_url(url, false, temp)) {
-                       try {
-                               kdm = dcp::EncryptedKDM (dcp::file_to_string(temp.file()));
-                               if (kdm->cpl_id() != dcp->cpl()) {
-                                       kdm = boost::none;
-                               }
-                       } catch (std::exception& e) {
-                               /* Hey well */
-                       }
-               }
-               return kdm;
-       }
-#endif
-
-       optional<dcp::EncryptedKDM> get_kdm_from_directory (shared_ptr<DCPContent> dcp)
-       {
-               using namespace boost::filesystem;
-               optional<path> kdm_dir = Config::instance()->player_kdm_directory();
-               if (!kdm_dir) {
-                       return optional<dcp::EncryptedKDM>();
-               }
-               for (directory_iterator i = directory_iterator(*kdm_dir); i != directory_iterator(); ++i) {
-                       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 */
-                       }
+               shared_ptr<Film> film = weak_film.lock ();
+               if (film) {
+                       reset_film (film);
                }
-               return optional<dcp::EncryptedKDM>();
        }
 
        void reset_film (shared_ptr<Film> film = shared_ptr<Film>(new Film(optional<boost::filesystem::path>())))
        {
                _film = film;
                _viewer->set_film (_film);
+               _controls->set_film (_film);
                _film->Change.connect (bind(&DOMFrame::film_changed, this, _1, _2));
+               _info->triggered_update ();
        }
 
        void film_changed (ChangeType type, Film::Property property)
@@ -472,8 +386,6 @@ public:
                        return;
                }
 
-               _film->write_metadata (Config::path("spl.xml"));
-
                if (_viewer->playing ()) {
                        _viewer->stop ();
                }
@@ -483,20 +395,6 @@ public:
 
                BOOST_FOREACH (shared_ptr<Content> i, _film->content()) {
                        shared_ptr<DCPContent> dcp = dynamic_pointer_cast<DCPContent>(i);
-                       if (dcp && dcp->needs_kdm()) {
-                               optional<dcp::EncryptedKDM> kdm;
-#ifdef DCPOMATIC_VARIANT_SWAROOP
-                               kdm = get_kdm_from_url (dcp);
-#endif
-                               if (!kdm) {
-                                       kdm = get_kdm_from_directory (dcp);
-                               }
-
-                               if (kdm) {
-                                       dcp->add_kdm (*kdm);
-                                       dcp->examine (_film, shared_ptr<Job>());
-                               }
-                       }
 
                        BOOST_FOREACH (shared_ptr<TextContent> j, i->text) {
                                j->set_use (true);
@@ -796,7 +694,6 @@ private:
        void setup_screen ()
        {
                _controls->Show (_mode != Config::PLAYER_MODE_FULL);
-               _controls->show_extended_player_controls (_mode == Config::PLAYER_MODE_DUAL);
                _info->Show (_mode != Config::PLAYER_MODE_FULL);
                _overall_panel->SetBackgroundColour (_mode == Config::PLAYER_MODE_FULL ? wxColour(0, 0, 0) : wxNullColour);
                ShowFullScreen (_mode == Config::PLAYER_MODE_FULL);
@@ -930,10 +827,10 @@ private:
                                );
                }
 
-               update_from_config ();
+               update_from_config (prop);
        }
 
-       void update_from_config ()
+       void update_from_config (Config::Property prop)
        {
                for (int i = 0; i < _history_items; ++i) {
                        delete _file_menu->Remove (ID_file_history + i);
@@ -964,6 +861,16 @@ private:
                }
 
                _history_items = history.size ();
+
+               if (prop == Config::PLAYER_DEBUG_LOG) {
+                       optional<boost::filesystem::path> p = Config::instance()->player_debug_log_file();
+                       if (p) {
+                               dcpomatic_log.reset (new FileLog(*p));
+                       } else {
+                               dcpomatic_log.reset (new NullLog());
+                       }
+                       dcpomatic_log->set_types (LogEntry::TYPE_GENERAL | LogEntry::TYPE_WARNING | LogEntry::TYPE_ERROR | LogEntry::TYPE_DEBUG_PLAYER);
+               }
        }
 
        void set_menu_sensitivity ()
@@ -1020,6 +927,7 @@ private:
 
 static const wxCmdLineEntryDesc command_line_description[] = {
        { wxCMD_LINE_PARAM, 0, 0, "DCP to load or create", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL },
+       { wxCMD_LINE_OPTION, "c", "config", "Directory containing config.xml", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL },
        { wxCMD_LINE_NONE, "", "", "", wxCmdLineParamType (0), 0 }
 };
 
@@ -1063,85 +971,90 @@ public:
 private:
 
        bool OnInit ()
-       try
        {
-               wxInitAllImageHandlers ();
+               wxSplashScreen* splash = 0;
+               try {
+                       wxInitAllImageHandlers ();
 
-               Config::FailedToLoad.connect (boost::bind (&App::config_failed_to_load, this));
-               Config::Warning.connect (boost::bind (&App::config_warning, this, _1));
+                       Config::FailedToLoad.connect (boost::bind (&App::config_failed_to_load, this));
+                       Config::Warning.connect (boost::bind (&App::config_warning, this, _1));
 
-               wxSplashScreen* splash = maybe_show_splash ();
+                       splash = maybe_show_splash ();
 
-               SetAppName (_("DCP-o-matic Player"));
+                       SetAppName (_("DCP-o-matic Player"));
 
-               if (!wxApp::OnInit()) {
-                       return false;
-               }
+                       if (!wxApp::OnInit()) {
+                               return false;
+                       }
 
 #ifdef DCPOMATIC_LINUX
-               unsetenv ("UBUNTU_MENUPROXY");
+                       unsetenv ("UBUNTU_MENUPROXY");
 #endif
 
 #ifdef __WXOSX__
-               ProcessSerialNumber serial;
-               GetCurrentProcess (&serial);
-               TransformProcessType (&serial, kProcessTransformToForegroundApplication);
+                       ProcessSerialNumber serial;
+                       GetCurrentProcess (&serial);
+                       TransformProcessType (&serial, kProcessTransformToForegroundApplication);
 #endif
 
-               dcpomatic_setup_path_encoding ();
-
-               /* Enable i18n; this will create a Config object
-                  to look for a force-configured language.  This Config
-                  object will be wrong, however, because dcpomatic_setup
-                  hasn't yet been called and there aren't any filters etc.
-                  set up yet.
-               */
-               dcpomatic_setup_i18n ();
-
-               /* Set things up, including filters etc.
-                  which will now be internationalised correctly.
-               */
-               dcpomatic_setup ();
-
-               /* Force the configuration to be re-loaded correctly next
-                  time it is needed.
-               */
-               Config::drop ();
+                       dcpomatic_setup_path_encoding ();
+
+                       /* Enable i18n; this will create a Config object
+                          to look for a force-configured language.  This Config
+                          object will be wrong, however, because dcpomatic_setup
+                          hasn't yet been called and there aren't any filters etc.
+                          set up yet.
+                       */
+                       dcpomatic_setup_i18n ();
+
+                       /* Set things up, including filters etc.
+                          which will now be internationalised correctly.
+                       */
+                       dcpomatic_setup ();
+
+                       /* Force the configuration to be re-loaded correctly next
+                          time it is needed.
+                       */
+                       Config::drop ();
+
+                       signal_manager = new wxSignalManager (this);
+
+                       _frame = new DOMFrame ();
+                       SetTopWindow (_frame);
+                       _frame->Maximize ();
+                       if (splash) {
+                               splash->Destroy ();
+                               splash = 0;
+                       }
+                       _frame->Show ();
 
-               signal_manager = new wxSignalManager (this);
+                       PlayServer* server = new PlayServer (_frame);
+                       new thread (boost::bind (&PlayServer::run, server));
 
-               _frame = new DOMFrame ();
-               SetTopWindow (_frame);
-               _frame->Maximize ();
-               if (splash) {
-                       splash->Destroy ();
-               }
-               _frame->Show ();
+                       if (!_dcp_to_load.empty() && boost::filesystem::is_directory (_dcp_to_load)) {
+                               try {
+                                       _frame->load_dcp (_dcp_to_load);
+                               } catch (exception& e) {
+                                       error_dialog (0, std_to_wx (String::compose (wx_to_std (_("Could not load DCP %1.")), _dcp_to_load)), std_to_wx(e.what()));
+                               }
+                       }
 
-               PlayServer* server = new PlayServer (_frame);
-               new thread (boost::bind (&PlayServer::run, server));
+                       Bind (wxEVT_IDLE, boost::bind (&App::idle, this));
 
-               if (!_dcp_to_load.empty() && boost::filesystem::is_directory (_dcp_to_load)) {
-                       try {
-                               _frame->load_dcp (_dcp_to_load);
-                       } catch (exception& e) {
-                               error_dialog (0, std_to_wx (String::compose (wx_to_std (_("Could not load DCP %1.")), _dcp_to_load)), std_to_wx(e.what()));
+                       if (Config::instance()->check_for_updates ()) {
+                               UpdateChecker::instance()->run ();
                        }
                }
-
-               Bind (wxEVT_IDLE, boost::bind (&App::idle, this));
-
-               if (Config::instance()->check_for_updates ()) {
-                       UpdateChecker::instance()->run ();
+               catch (exception& e)
+               {
+                       if (splash) {
+                               splash->Destroy ();
+                       }
+                       error_dialog (0, _("DCP-o-matic Player could not start."), std_to_wx(e.what()));
                }
 
                return true;
        }
-       catch (exception& e)
-       {
-               error_dialog (0, _("DCP-o-matic Player could not start."), std_to_wx(e.what()));
-               return true;
-       }
 
        void OnInitCmdLine (wxCmdLineParser& parser)
        {
@@ -1155,6 +1068,11 @@ private:
                        _dcp_to_load = wx_to_std (parser.GetParam (0));
                }
 
+               wxString config;
+               if (parser.Found("c", &config)) {
+                       Config::override_path = wx_to_std (config);
+               }
+
                return true;
        }