Fix crash when adding cinemas while a search is in force (#2378).
[dcpomatic.git] / src / wx / film_viewer.cc
index c56e2f5d26f89a3478e3e2385ddd99ee5dd82dd2..fb02f0a0ff41074015ebc9c6b9b939aa5698f6b1 100644 (file)
@@ -160,15 +160,17 @@ FilmViewer::set_film (shared_ptr<Film> film)
        _video_view->clear ();
        _closed_captions_dialog->clear ();
 
+       destroy_butler();
+
        if (!_film) {
-               _player.reset ();
-               recreate_butler ();
+               _player = boost::none;
+               resume();
                _video_view->update ();
                return;
        }
 
        try {
-               _player = make_shared<Player>(_film, _optimise_for_j2k ? Image::Alignment::COMPACT : Image::Alignment::PADDED);
+               _player.emplace(_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);
@@ -176,6 +178,7 @@ FilmViewer::set_film (shared_ptr<Film> film)
        } catch (bad_alloc &) {
                error_dialog (_video_view->get(), _("There is not enough free memory to do that."));
                _film.reset ();
+               resume();
                return;
        }
 
@@ -195,7 +198,7 @@ FilmViewer::set_film (shared_ptr<Film> film)
 
        _closed_captions_dialog->update_tracks (_film);
 
-       recreate_butler ();
+       create_butler();
 
        calculate_sizes ();
        slow_refresh ();
@@ -203,25 +206,41 @@ FilmViewer::set_film (shared_ptr<Film> film)
 
 
 void
-FilmViewer::recreate_butler ()
+FilmViewer::destroy_butler()
 {
        suspend ();
        _butler.reset ();
+}
+
+
+void
+FilmViewer::destroy_and_maybe_create_butler()
+{
+       destroy_butler();
 
        if (!_film) {
                resume ();
                return;
        }
 
+       create_butler();
+}
+
+
+void
+FilmViewer::create_butler()
+{
 #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
 
+       DCPOMATIC_ASSERT(_player);
+
        _butler = std::make_shared<Butler>(
                _film,
-               _player,
+               *_player,
                Config::instance()->audio_mapping(_audio_channels),
                _audio_channels,
                boost::bind(&PlayerVideo::force, AV_PIX_FMT_RGB24),
@@ -474,7 +493,7 @@ FilmViewer::film_change (ChangeType type, Film::Property p)
        }
 
        if (p == Film::Property::AUDIO_CHANNELS) {
-               recreate_butler ();
+               destroy_and_maybe_create_butler();
        } else if (p == Film::Property::VIDEO_FRAME_RATE) {
                _video_view->set_video_frame_rate (_film->video_frame_rate());
        } else if (p == Film::Property::THREE_D) {
@@ -517,6 +536,7 @@ FilmViewer::quick_refresh ()
 void
 FilmViewer::seek (shared_ptr<Content> content, ContentTime t, bool accurate)
 {
+       DCPOMATIC_ASSERT(_player);
        auto dt = _player->content_time_to_dcp (content, t);
        if (dt) {
                seek (*dt, accurate);
@@ -576,7 +596,7 @@ void
 FilmViewer::config_changed (Config::Property p)
 {
        if (p == Config::AUDIO_MAPPING) {
-               recreate_butler ();
+               destroy_and_maybe_create_butler();
                return;
        }
 
@@ -622,11 +642,11 @@ FilmViewer::config_changed (Config::Property p)
                                _("Could not set up audio output.  There will be no audio during the preview."), std_to_wx(e.what())
                                );
                }
-               recreate_butler ();
+               destroy_and_maybe_create_butler();
 
        } else {
                _audio_channels = 0;
-               recreate_butler ();
+               destroy_and_maybe_create_butler();
        }
 }
 
@@ -722,6 +742,7 @@ FilmViewer::dcp_decode_reduction () const
 optional<ContentTime>
 FilmViewer::position_in_content (shared_ptr<const Content> content) const
 {
+       DCPOMATIC_ASSERT(_player);
        return _player->dcp_to_content_time (content, position());
 }