Fix macOS build.
[dcpomatic.git] / src / wx / film_viewer.cc
index 77c2e85d690a6cb7055dc02063412812abd1b22b..0e6e908b3245c88fb8e9851e4e898a452c8d64bb 100644 (file)
 #include "playhead_to_timecode_dialog.h"
 #include "simple_video_view.h"
 #include "wx_util.h"
-#include "lib/film.h"
-#include "lib/ratio.h"
-#include "lib/util.h"
-#include "lib/job_manager.h"
-#include "lib/image.h"
-#include "lib/exceptions.h"
+#include "lib/butler.h"
+#include "lib/compose.hpp"
+#include "lib/config.h"
+#include "lib/dcpomatic_log.h"
 #include "lib/examine_content_job.h"
+#include "lib/exceptions.h"
+#include "lib/film.h"
 #include "lib/filter.h"
+#include "lib/image.h"
+#include "lib/job_manager.h"
+#include "lib/log.h"
 #include "lib/player.h"
 #include "lib/player_video.h"
+#include "lib/ratio.h"
+#include "lib/text_content.h"
+#include "lib/timer.h"
+#include "lib/util.h"
 #include "lib/video_content.h"
 #include "lib/video_decoder.h"
-#include "lib/timer.h"
-#include "lib/butler.h"
-#include "lib/log.h"
-#include "lib/config.h"
-#include "lib/compose.hpp"
-#include "lib/dcpomatic_log.h"
-#include "lib/text_content.h"
+#include <dcp/exceptions.h>
+#include <dcp/warnings.h>
 extern "C" {
 #include <libavutil/pixfmt.h>
 }
-#include <dcp/exceptions.h>
+LIBDCP_DISABLE_WARNINGS
 #include <wx/tglbtn.h>
-#include <iostream>
+LIBDCP_ENABLE_WARNINGS
 #include <iomanip>
 
 
 using std::bad_alloc;
-using std::cout;
 using std::dynamic_pointer_cast;
-using std::exception;
-using std::list;
-using std::make_pair;
 using std::make_shared;
 using std::max;
-using std::min;
-using std::pair;
 using std::shared_ptr;
 using std::string;
 using std::vector;
-using std::weak_ptr;
 using boost::optional;
 #if BOOST_VERSION >= 106100
 using namespace boost::placeholders;
@@ -94,6 +89,7 @@ FilmViewer::FilmViewer (wxWindow* p)
        : _audio (DCPOMATIC_RTAUDIO_API)
        , _closed_captions_dialog (new ClosedCaptionsDialog(p, this))
 {
+#if wxCHECK_VERSION(3, 1, 0)
        switch (Config::instance()->video_view_type()) {
        case Config::VIDEO_VIEW_OPENGL:
                _video_view = std::make_shared<GLVideoView>(this, p);
@@ -102,6 +98,9 @@ FilmViewer::FilmViewer (wxWindow* p)
                _video_view = std::make_shared<SimpleVideoView>(this, p);
                break;
        }
+#else
+       _video_view = std::make_shared<SimpleVideoView>(this, p);
+#endif
 
        _video_view->Sized.connect (boost::bind(&FilmViewer::video_view_sized, this));
        _video_view->TooManyDropped.connect (boost::bind(boost::ref(TooManyDropped)));
@@ -119,7 +118,7 @@ FilmViewer::~FilmViewer ()
 }
 
 
-/** Ask for ::get() to be called next time we are idle */
+/** Ask for ::idle_handler() to be called next time we are idle */
 void
 FilmViewer::request_idle_display_next_frame ()
 {
@@ -169,7 +168,7 @@ FilmViewer::set_film (shared_ptr<Film> film)
        }
 
        try {
-               _player = make_shared<Player>(_film);
+               _player = make_shared<Player>(_film, _optimise_for_j2k ? Image::Alignment::COMPACT : Image::Alignment::PADDED);
                _player->set_fast ();
                if (_dcp_decode_reduction) {
                        _player->set_dcp_decode_reduction (_dcp_decode_reduction);
@@ -214,15 +213,22 @@ FilmViewer::recreate_butler ()
                return;
        }
 
+#if wxCHECK_VERSION(3, 1, 0)
+       auto const j2k_gl_optimised = dynamic_pointer_cast<GLVideoView>(_video_view) && _optimise_for_j2k;
+#else
+       auto const j2k_gl_optimised = false;
+#endif
+
        _butler = std::make_shared<Butler>(
                _film,
                _player,
                Config::instance()->audio_mapping(_audio_channels),
                _audio_channels,
-               bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24),
+               boost::bind(&PlayerVideo::force, AV_PIX_FMT_RGB24),
                VideoRange::FULL,
-               false,
-               true
+               j2k_gl_optimised ? Image::Alignment::COMPACT : Image::Alignment::PADDED,
+               true,
+               j2k_gl_optimised
                );
 
        if (!Config::instance()->sound() && !_audio.isStreamOpen()) {
@@ -278,17 +284,21 @@ FilmViewer::calculate_sizes ()
 
        auto const container = _film->container ();
 
-       auto const view_ratio = float(_video_view->get()->GetSize().x) / _video_view->get()->GetSize().y;
+       auto const scale = dpi_scale_factor (_video_view->get());
+       int const video_view_width = std::round(_video_view->get()->GetSize().x * scale);
+       int const video_view_height = std::round(_video_view->get()->GetSize().y * scale);
+
+       auto const view_ratio = float(video_view_width) / video_view_height;
        auto const film_ratio = container ? container->ratio () : 1.78;
 
        dcp::Size out_size;
        if (view_ratio < film_ratio) {
                /* panel is less widscreen than the film; clamp width */
-               out_size.width = _video_view->get()->GetSize().x;
+               out_size.width = video_view_width;
                out_size.height = lrintf (out_size.width / film_ratio);
        } else {
                /* panel is more widescreen than the film; clamp height */
-               out_size.height = _video_view->get()->GetSize().y;
+               out_size.height = video_view_height;
                out_size.width = lrintf (out_size.height * film_ratio);
        }
 
@@ -310,16 +320,31 @@ FilmViewer::suspend ()
 }
 
 
+void
+FilmViewer::start_audio_stream_if_open ()
+{
+       if (_audio.isStreamOpen()) {
+               _audio.setStreamTime (_video_view->position().seconds());
+               try {
+                       _audio.startStream ();
+               } catch (RtAudioError& e) {
+                       _audio_channels = 0;
+                       error_dialog (
+                               _video_view->get(),
+                               _("There was a problem starting audio playback.  Please try another audio output device in Preferences."), std_to_wx(e.what())
+                               );
+               }
+       }
+}
+
+
 void
 FilmViewer::resume ()
 {
        DCPOMATIC_ASSERT (_suspended > 0);
        --_suspended;
        if (_playing && !_suspended) {
-               if (_audio.isStreamOpen()) {
-                       _audio.setStreamTime (_video_view->position().seconds());
-                       _audio.startStream ();
-               }
+               start_audio_stream_if_open ();
                _video_view->start ();
        }
 }
@@ -349,24 +374,13 @@ FilmViewer::start ()
        /* Take the video view's idea of position as our `playhead' and start the
           audio stream (which is the timing reference) there.
          */
-       if (_audio.isStreamOpen()) {
-               _audio.setStreamTime (_video_view->position().seconds());
-               try {
-                       _audio.startStream ();
-               } catch (RtAudioError& e) {
-                       _audio_channels = 0;
-                       error_dialog (
-                               _video_view->get(),
-                               _("There was a problem starting audio playback.  Please try another audio output device in Preferences."), std_to_wx(e.what())
-                               );
-               }
-       }
+       start_audio_stream_if_open ();
 
        _playing = true;
        /* Calling start() below may directly result in Stopped being emitted, and if that
         * happens we want it to come after the Started signal, so do that first.
         */
-       Started (position());
+       Started ();
        _video_view->start ();
 }
 
@@ -385,7 +399,7 @@ FilmViewer::stop ()
 
        _playing = false;
        _video_view->stop ();
-       Stopped (position());
+       Stopped ();
 
        _video_view->rethrow ();
        return true;
@@ -644,7 +658,7 @@ int
 FilmViewer::audio_callback (void* out_p, unsigned int frames)
 {
        while (true) {
-               auto t = _butler->get_audio (reinterpret_cast<float*> (out_p), frames);
+               auto t = _butler->get_audio (Butler::Behaviour::NON_BLOCKING, reinterpret_cast<float*> (out_p), frames);
                if (!t || DCPTime(uncorrected_time() - *t) < one_video_frame()) {
                        /* There was an underrun or this audio is on time; carry on */
                        break;
@@ -698,6 +712,13 @@ FilmViewer::dcp_decode_reduction () const
 }
 
 
+optional<ContentTime>
+FilmViewer::position_in_content (shared_ptr<const Content> content) const
+{
+       return _player->dcp_to_content_time (content, position());
+}
+
+
 DCPTime
 FilmViewer::one_video_frame () const
 {
@@ -772,3 +793,30 @@ FilmViewer::image_changed (shared_ptr<PlayerVideo> pv)
 {
        emit (boost::bind(boost::ref(ImageChanged), pv));
 }
+
+
+void
+FilmViewer::set_optimise_for_j2k (bool o)
+{
+       _optimise_for_j2k = o;
+       _video_view->set_optimise_for_j2k (o);
+}
+
+
+void
+FilmViewer::set_crop_guess (dcpomatic::Rect<float> crop)
+{
+       if (crop != _crop_guess) {
+               _crop_guess = crop;
+               _video_view->update ();
+       }
+}
+
+
+void
+FilmViewer::unset_crop_guess ()
+{
+       _crop_guess = {};
+       _video_view->update ();
+}
+