X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Fwx%2Ffilm_viewer.cc;h=e8c3b8c71363292bccd5cbd8c1dea57bf26f0990;hb=1d2a51bdc8315fa7283be329669860e435a1513f;hp=3a593fc556b80cd1babfba5a6dcd5c69b272a07f;hpb=0b21bfba60be812a5d04cc5c10868e04b5579404;p=dcpomatic.git diff --git a/src/wx/film_viewer.cc b/src/wx/film_viewer.cc index 3a593fc55..e8c3b8c71 100644 --- a/src/wx/film_viewer.cc +++ b/src/wx/film_viewer.cc @@ -47,6 +47,7 @@ #include "lib/config.h" #include "lib/compose.hpp" #include "lib/dcpomatic_log.h" +#include "lib/text_content.h" extern "C" { #include } @@ -64,10 +65,13 @@ using std::list; using std::bad_alloc; using std::make_pair; using std::exception; -using boost::shared_ptr; -using boost::dynamic_pointer_cast; -using boost::weak_ptr; +using std::shared_ptr; +using std::dynamic_pointer_cast; +using std::weak_ptr; using boost::optional; +#if BOOST_VERSION >= 106100 +using namespace boost::placeholders; +#endif using dcp::Size; using namespace dcpomatic; @@ -89,9 +93,6 @@ FilmViewer::FilmViewer (wxWindow* p) , _closed_captions_dialog (new ClosedCaptionsDialog(p, this)) , _outline_content (false) , _pad_black (false) -#ifdef DCPOMATIC_VARIANT_SWAROOP - , _background_image (false) -#endif , _idle_get (false) { switch (Config::instance()->video_view_type()) { @@ -136,11 +137,11 @@ FilmViewer::idle_handler () return; } - if (_video_view->display_next_frame(true)) { - _idle_get = false; - } else { + if (_video_view->display_next_frame(true) == VideoView::AGAIN) { /* get() could not complete quickly so we'll try again later */ signal_manager->when_idle (boost::bind(&FilmViewer::idle_handler, this)); + } else { + _idle_get = false; } } @@ -164,7 +165,7 @@ FilmViewer::set_film (shared_ptr film) } try { - _player.reset (new Player (_film, _film->playlist ())); + _player.reset (new Player(_film)); _player->set_fast (); if (_dcp_decode_reduction) { _player->set_dcp_decode_reduction (_dcp_decode_reduction); @@ -179,6 +180,7 @@ FilmViewer::set_film (shared_ptr film) _player->set_play_referenced (); _film->Change.connect (boost::bind (&FilmViewer::film_change, this, _1, _2)); + _film->ContentChange.connect (boost::bind(&FilmViewer::content_change, this, _1, _3)); _film->LengthChange.connect (boost::bind(&FilmViewer::film_length_change, this)); _player->Change.connect (boost::bind (&FilmViewer::player_change, this, _1, _2, _3)); @@ -189,6 +191,8 @@ FilmViewer::set_film (shared_ptr film) /* Keep about 1 second's worth of history samples */ _latency_history_count = _film->audio_frame_rate() / _audio_block_size; + _closed_captions_dialog->update_tracks (_film); + recreate_butler (); calculate_sizes (); @@ -208,10 +212,12 @@ FilmViewer::recreate_butler () _butler.reset( new Butler( + _film, _player, Config::instance()->audio_mapping(_audio_channels), _audio_channels, bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), + VideoRange::FULL, false, true ) @@ -221,7 +227,7 @@ FilmViewer::recreate_butler () _butler->disable_audio (); } - _closed_captions_dialog->set_film_and_butler (_film, _butler); + _closed_captions_dialog->set_butler (_butler); resume (); } @@ -233,6 +239,15 @@ FilmViewer::set_outline_content (bool o) _video_view->update (); } + +void +FilmViewer::set_outline_subtitles (optional > rect) +{ + _outline_subtitles = rect; + _video_view->update (); +} + + void FilmViewer::set_eyes (Eyes e) { @@ -322,14 +337,20 @@ FilmViewer::start () idle_handler (); } + /* 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()); _audio.startStream (); } _playing = true; - _video_view->start (); + /* 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()); + _video_view->start (); } bool @@ -396,6 +417,8 @@ FilmViewer::film_change (ChangeType type, Film::Property p) _video_view->set_video_frame_rate (_film->video_frame_rate()); } else if (p == Film::THREE_D) { _video_view->set_three_d (_film->three_d()); + } else if (p == Film::CONTENT) { + _closed_captions_dialog->update_tracks (_film); } } @@ -419,10 +442,10 @@ FilmViewer::slow_refresh () bool FilmViewer::quick_refresh () { - if (!_video_view || !_film) { + if (!_video_view || !_film || !_player) { return true; } - return _video_view->refresh_metadata (_film, _player->video_container_size(), _film->frame_size()); + return _video_view->reset_metadata (_film, _player->video_container_size()); } void @@ -440,7 +463,7 @@ FilmViewer::set_coalesce_player_changes (bool c) _coalesce_player_changes = c; if (!c) { - BOOST_FOREACH (int i, _pending_player_changes) { + for (auto i: _pending_player_changes) { player_change (CHANGE_TYPE_DONE, i, false); } _pending_player_changes.clear (); @@ -459,7 +482,7 @@ FilmViewer::seek (DCPTime t, bool accurate) } if (t >= _film->length ()) { - t = _film->length (); + t = _film->length() - one_video_frame(); } suspend (); @@ -468,9 +491,15 @@ FilmViewer::seek (DCPTime t, bool accurate) _butler->seek (t, accurate); if (!_playing) { + /* We're not playing, so let the GUI thread get on and + come back later to get the next frame after the seek. + */ request_idle_display_next_frame (); } else { - while (!_video_view->display_next_frame(false)) {} + /* We're going to start playing again straight away + so wait for the seek to finish. + */ + while (_video_view->display_next_frame(false) == VideoView::AGAIN) {} } resume (); @@ -479,13 +508,6 @@ FilmViewer::seek (DCPTime t, bool accurate) void FilmViewer::config_changed (Config::Property p) { -#ifdef DCPOMATIC_VARIANT_SWAROOP - if (p == Config::PLAYER_BACKGROUND_IMAGE) { - _video_view->update (); - return; - } -#endif - if (p == Config::AUDIO_MAPPING) { recreate_butler (); return; @@ -503,8 +525,12 @@ FilmViewer::config_changed (Config::Property p) unsigned int st = 0; if (Config::instance()->sound_output()) { while (st < _audio.getDeviceCount()) { - if (_audio.getDeviceInfo(st).name == Config::instance()->sound_output().get()) { - break; + try { + if (_audio.getDeviceInfo(st).name == Config::instance()->sound_output().get()) { + break; + } + } catch (RtAudioError&) { + /* Something went wrong with that device so we don't want to use it anyway */ } ++st; } @@ -515,19 +541,15 @@ FilmViewer::config_changed (Config::Property p) st = _audio.getDefaultOutputDevice(); } - _audio_channels = _audio.getDeviceInfo(st).outputChannels; - - RtAudio::StreamParameters sp; - sp.deviceId = st; - sp.nChannels = _audio_channels; - sp.firstChannel = 0; try { + _audio_channels = _audio.getDeviceInfo(st).outputChannels; + RtAudio::StreamParameters sp; + sp.deviceId = st; + sp.nChannels = _audio_channels; + sp.firstChannel = 0; _audio.openStream (&sp, 0, RTAUDIO_FLOAT32, 48000, &_audio_block_size, &rtaudio_callback, this); -#ifdef DCPOMATIC_USE_RTERROR - } catch (RtError& e) { -#else } catch (RtAudioError& e) { -#endif + _audio_channels = 0; error_dialog ( _video_view->get(), _("Could not set up audio output. There will be no audio during the preview."), std_to_wx(e.what()) @@ -600,7 +622,7 @@ FilmViewer::average_latency () const } Frame total = 0; - BOOST_FOREACH (Frame i, _latency_history) { + for (auto i: _latency_history) { total += i; } @@ -670,6 +692,14 @@ FilmViewer::dropped () const return _video_view->dropped (); } + +int +FilmViewer::errored () const +{ + return _video_view->errored (); +} + + int FilmViewer::gets () const { @@ -677,3 +707,22 @@ FilmViewer::gets () const } +void +FilmViewer::content_change (ChangeType type, int property) +{ + if (type != CHANGE_TYPE_DONE) { + return; + } + + if (property == TextContentProperty::USE || property == TextContentProperty::TYPE || property == TextContentProperty::DCP_TRACK) { + _closed_captions_dialog->update_tracks (_film); + } +} + + +void +FilmViewer::image_changed (shared_ptr pv) +{ + emit (boost::bind(boost::ref(ImageChanged), pv)); +} +