Fix typo in log message.
[dcpomatic.git] / src / lib / butler.cc
index ca0887a4cc3cb05410c8d88b47005aac69188db8..ce35b1f39aff61da043aa71e0a3d5fad0e963f11 100644 (file)
 
 
 #include "butler.h"
-#include "player.h"
-#include "util.h"
-#include "log.h"
-#include "dcpomatic_log.h"
-#include "cross.h"
 #include "compose.hpp"
+#include "cross.h"
+#include "dcpomatic_log.h"
 #include "exceptions.h"
+#include "log.h"
+#include "player.h"
+#include "util.h"
 #include "video_content.h"
 
 
 using std::cout;
-using std::pair;
+using std::function;
 using std::make_pair;
+using std::pair;
+using std::shared_ptr;
 using std::string;
 using std::weak_ptr;
-using std::shared_ptr;
 using boost::bind;
 using boost::optional;
-using std::function;
 using namespace dcpomatic;
 #if BOOST_VERSION >= 106100
 using namespace boost::placeholders;
@@ -57,7 +57,7 @@ using namespace boost::placeholders;
 
 /** @param pixel_format Pixel format functor that will be used when calling ::image on PlayerVideos coming out of this
  *  butler.  This will be used (where possible) to prepare the PlayerVideos so that calling image() on them is quick.
- *  @param aligned Same as above for the `aligned' flag.
+ *  @param alignment Same as above for the `alignment' value.
  *  @param fast Same as above for the `fast' flag.
  */
 Butler::Butler (
@@ -67,9 +67,10 @@ Butler::Butler (
        int audio_channels,
        function<AVPixelFormat (AVPixelFormat)> pixel_format,
        VideoRange video_range,
-       bool aligned,
+       Image::Alignment alignment,
        bool fast,
-       bool prepare_only_proxy
+       bool prepare_only_proxy,
+       Audio audio
        )
        : _film (film)
        , _player (player)
@@ -81,10 +82,10 @@ Butler::Butler (
        , _stop_thread (false)
        , _audio_mapping (audio_mapping)
        , _audio_channels (audio_channels)
-       , _disable_audio (false)
+       , _disable_audio (audio == Audio::DISABLED)
        , _pixel_format (pixel_format)
        , _video_range (video_range)
-       , _aligned (aligned)
+       , _alignment (alignment)
        , _fast (fast)
        , _prepare_only_proxy (prepare_only_proxy)
 {
@@ -149,7 +150,7 @@ Butler::should_run () const
 
        if (_audio.size() >= MAXIMUM_AUDIO_READAHEAD * 10) {
                /* This is way too big */
-               optional<DCPTime> pos = _audio.peek();
+               auto pos = _audio.peek();
                if (pos) {
                        throw ProgrammingError
                                (__FILE__, __LINE__, String::compose ("Butler audio buffers reached %1 frames at %2 (video is %3)", _audio.size(), pos->get(), _video.size()));
@@ -238,30 +239,30 @@ try
 }
 
 
-/** @param blocking true if we should block until video is available.  If blocking is false
+/** @param behaviour BLOCKING if we should block until video is available.  If behaviour is NON_BLOCKING
  *  and no video is immediately available the method will return a 0 PlayerVideo and the error AGAIN.
  *  @param e if non-0 this is filled with an error code (if an error occurs) or is untouched if no error occurs.
  */
 pair<shared_ptr<PlayerVideo>, DCPTime>
-Butler::get_video (bool blocking, Error* e)
+Butler::get_video (Behaviour behaviour, Error* e)
 {
        boost::mutex::scoped_lock lm (_mutex);
 
        auto setup_error = [this](Error* e, Error::Code fallback) {
                if (e) {
                        if (_died) {
-                               e->code = Error::DIED;
+                               e->code = Error::Code::DIED;
                                e->message = _died_message;
                        } else if (_finished) {
-                               e->code = Error::FINISHED;
+                               e->code = Error::Code::FINISHED;
                        } else {
                                e->code = fallback;
                        }
                }
        };
 
-       if (_video.empty() && (_finished || _died || (_suspended && !blocking))) {
-               setup_error (e, Error::AGAIN);
+       if (_video.empty() && (_finished || _died || (_suspended && behaviour == Behaviour::NON_BLOCKING))) {
+               setup_error (e, Error::Code::AGAIN);
                return make_pair(shared_ptr<PlayerVideo>(), DCPTime());
        }
 
@@ -271,7 +272,7 @@ Butler::get_video (bool blocking, Error* e)
        }
 
        if (_video.empty()) {
-               setup_error (e, Error::NONE);
+               setup_error (e, Error::Code::NONE);
                return make_pair(shared_ptr<PlayerVideo>(), DCPTime());
        }
 
@@ -325,7 +326,7 @@ try
        /* If the weak_ptr cannot be locked the video obviously no longer requires any work */
        if (video) {
                LOG_TIMING("start-prepare in %1", thread_id());
-               video->prepare (_pixel_format, _video_range, _aligned, _fast, _prepare_only_proxy);
+               video->prepare (_pixel_format, _video_range, _alignment, _fast, _prepare_only_proxy);
                LOG_TIMING("finish-prepare in %1", thread_id());
        }
 }
@@ -373,27 +374,27 @@ Butler::audio (shared_ptr<AudioBuffers> audio, DCPTime time, int frame_rate)
 }
 
 
-/** Try to get `frames' frames of audio and copy it into `out'.  Silence
- *  will be filled if no audio is available.
- *  @return time of this audio, or unset if there was a buffer underrun.
+/** Try to get `frames' frames of audio and copy it into `out'.
+ *  @param behaviour BLOCKING if we should block until audio is available.  If behaviour is NON_BLOCKING
+ *  and no audio is immediately available the buffer will be filled with silence and boost::none
+ *  will be returned.
+ *  @return time of this audio, or unset if blocking was false and no data was available.
  */
 optional<DCPTime>
-Butler::get_audio (float* out, Frame frames)
+Butler::get_audio (Behaviour behaviour, float* out, Frame frames)
 {
+       boost::mutex::scoped_lock lm (_mutex);
+
+       while (behaviour == Behaviour::BLOCKING && !_finished && !_died && _audio.size() < frames) {
+               _arrived.wait (lm);
+       }
+
        auto t = _audio.get (out, _audio_channels, frames);
        _summon.notify_all ();
        return t;
 }
 
 
-void
-Butler::disable_audio ()
-{
-       boost::mutex::scoped_lock lm (_mutex);
-       _disable_audio = true;
-}
-
-
 pair<size_t, string>
 Butler::memory_used () const
 {
@@ -467,13 +468,13 @@ Butler::Error::summary () const
 {
        switch (code)
        {
-               case Error::NONE:
+               case Error::Code::NONE:
                        return "No error registered";
-               case Error::AGAIN:
+               case Error::Code::AGAIN:
                        return "Butler not ready";
-               case Error::DIED:
+               case Error::Code::DIED:
                        return String::compose("Butler died (%1)", message);
-               case Error::FINISHED:
+               case Error::Code::FINISHED:
                        return "Butler finished";
        }