Report better errors when the butler dies.
authorCarl Hetherington <cth@carlh.net>
Mon, 17 Aug 2020 13:44:58 +0000 (15:44 +0200)
committerCarl Hetherington <cth@carlh.net>
Mon, 17 Aug 2020 13:44:58 +0000 (15:44 +0200)
Adapted from d23f55d8cd73adda823d0a2fcabc129b8845a81 in master.

src/lib/butler.cc
src/lib/butler.h
src/lib/ffmpeg_encoder.cc
src/wx/video_view.cc

index df23580863a800e41c2f5c2561719822605966a3..33938ece4025bd1e059715ac916002874245ab55 100644 (file)
@@ -208,6 +208,12 @@ try
        boost::mutex::scoped_lock lm (_mutex);
        _finished = true;
        _arrived.notify_all ();
+} catch (std::exception& e) {
+       store_current ();
+       boost::mutex::scoped_lock lm (_mutex);
+       _died = true;
+       _died_message = e.what ();
+       _arrived.notify_all ();
 } catch (...) {
        store_current ();
        boost::mutex::scoped_lock lm (_mutex);
@@ -226,7 +232,7 @@ Butler::get_video (bool blocking, Error* e)
 
        if (_suspended || (_video.empty() && !blocking)) {
                if (e) {
-                       *e = AGAIN;
+                       e->code = Error::AGAIN;
                }
                return make_pair(shared_ptr<PlayerVideo>(), DCPTime());
        }
@@ -239,11 +245,12 @@ Butler::get_video (bool blocking, Error* e)
        if (_video.empty()) {
                if (e) {
                        if (_died) {
-                               *e = DIED;
+                               e->code = Error::DIED;
+                               e->message = _died_message;
                        } else if (_finished) {
-                               *e = FINISHED;
+                               e->code = Error::FINISHED;
                        } else {
-                               *e = NONE;
+                               e->code = Error::NONE;
                        }
                }
                return make_pair(shared_ptr<PlayerVideo>(), DCPTime());
@@ -299,6 +306,13 @@ try
                LOG_TIMING("finish-prepare in %1", thread_id());
        }
 }
+catch (std::exception& e)
+{
+       store_current ();
+       boost::mutex::scoped_lock lm (_mutex);
+       _died = true;
+       _died_message = e.what ();
+}
 catch (...)
 {
        store_current ();
@@ -406,3 +420,22 @@ Butler::text (PlayerText pt, TextType type, optional<DCPTextTrack> track, DCPTim
 
        _closed_caption.put (pt, *track, period);
 }
+
+string
+Butler::Error::summary () const
+{
+       switch (code)
+       {
+               case Error::NONE:
+                       return "No error registered";
+               case Error::AGAIN:
+                       return "Butler not ready";
+               case Error::DIED:
+                       return String::compose("Butler died (%1)", message);
+               case Error::FINISHED:
+                       return "Butler finished";
+       }
+
+       return "";
+}
+
index 6263d61431d6e9fff81d7886d5e134d3a1a00c18..e13843c90e9c14833704cde408e65de072e8e5c9 100644 (file)
@@ -49,11 +49,23 @@ public:
 
        void seek (dcpomatic::DCPTime position, bool accurate);
 
-       enum Error {
-               NONE,
-               AGAIN,
-               DIED,
-               FINISHED
+       class Error {
+       public:
+               enum Code{
+                       NONE,
+                       AGAIN,
+                       DIED,
+                       FINISHED
+               };
+
+               Error()
+                       : code (NONE)
+               {}
+
+               Code code;
+               std::string message;
+
+               std::string summary () const;
        };
 
        std::pair<boost::shared_ptr<PlayerVideo>, dcpomatic::DCPTime> get_video (bool blocking, Error* e = 0);
@@ -94,6 +106,7 @@ private:
        int _suspended;
        bool _finished;
        bool _died;
+       std::string _died_message;
        bool _stop_thread;
 
        AudioMapping _audio_mapping;
index cf91a9fae6ae0b19849347899071bed925e25980..cd03c7b93a1cf762b88add85347525b5bb0d9d40 100644 (file)
@@ -174,7 +174,7 @@ FFmpegEncoder::go ()
                        pair<shared_ptr<PlayerVideo>, DCPTime> v = _butler->get_video (true, &e);
                        _butler->rethrow ();
                        if (!v.first) {
-                               throw ProgrammingError(__FILE__, __LINE__, String::compose("butler returned no video; error was %1", static_cast<int>(e)));
+                               throw ProgrammingError(__FILE__, __LINE__, String::compose("butler returned no video; error was %1", e.summary()));
                        }
                        shared_ptr<FFmpegFileEncoder> fe = encoder->get (v.first->eyes());
                        if (fe) {
index b0e16737c9c91ebbe88c4b4c8777869c1c0aef9d..7eea4b786fba72917e3f9285997767545e88ea74 100644 (file)
@@ -22,6 +22,7 @@
 #include "wx_util.h"
 #include "film_viewer.h"
 #include "lib/butler.h"
+#include "lib/dcpomatic_log.h"
 #include <boost/optional.hpp>
 
 using std::pair;
@@ -74,7 +75,10 @@ VideoView::get_next_frame (bool non_blocking)
        do {
                Butler::Error e;
                pair<shared_ptr<PlayerVideo>, dcpomatic::DCPTime> pv = butler->get_video (!non_blocking, &e);
-               if (!pv.first && e == Butler::AGAIN) {
+               if (e.code == Butler::Error::DIED) {
+                       LOG_ERROR ("Butler died with %1", e.summary());
+               }
+               if (!pv.first && e.code == Butler::Error::AGAIN) {
                        return false;
                }
                _player_video = pv;