X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Fwx%2Ffilm_viewer.cc;h=9f42aaad25798c18729bab2b162693290e2c3319;hb=e00b9850a7336b7db0aee058fe12f576db5f84a3;hp=ebd929ff9197af966dec8c786479497f4c3b03cb;hpb=f1dbcec7552052856369631e77c5eb160badd619;p=dcpomatic.git diff --git a/src/wx/film_viewer.cc b/src/wx/film_viewer.cc index ebd929ff9..9f42aaad2 100644 --- a/src/wx/film_viewer.cc +++ b/src/wx/film_viewer.cc @@ -87,7 +87,8 @@ FilmViewer::FilmViewer (wxWindow* p, bool outline_content, bool jump_to_selected , _timecode (new wxStaticText (this, wxID_ANY, wxT(""))) , _play_button (new wxToggleButton (this, wxID_ANY, _("Play"))) , _coalesce_player_changes (false) - , _pending_player_change (false) + , _slider_being_moved (false) + , _was_running_before_slider (false) , _audio (DCPOMATIC_RTAUDIO_API) , _audio_channels (0) , _audio_block_size (1024) @@ -144,12 +145,12 @@ FilmViewer::FilmViewer (wxWindow* p, bool outline_content, bool jump_to_selected if (_outline_content) { _outline_content->Bind (wxEVT_CHECKBOX, boost::bind (&FilmViewer::refresh_panel, this)); } - _left_eye->Bind (wxEVT_RADIOBUTTON, boost::bind (&FilmViewer::refresh, this)); - _right_eye->Bind (wxEVT_RADIOBUTTON, boost::bind (&FilmViewer::refresh, this)); + _left_eye->Bind (wxEVT_RADIOBUTTON, boost::bind (&FilmViewer::slow_refresh, this)); + _right_eye->Bind (wxEVT_RADIOBUTTON, boost::bind (&FilmViewer::slow_refresh, this)); _slider->Bind (wxEVT_SCROLL_THUMBTRACK, boost::bind (&FilmViewer::slider_moved, this, false)); - _slider->Bind (wxEVT_SCROLL_PAGEUP, boost::bind (&FilmViewer::slider_moved, this, false)); - _slider->Bind (wxEVT_SCROLL_PAGEDOWN, boost::bind (&FilmViewer::slider_moved, this, false)); - _slider->Bind (wxEVT_SCROLL_CHANGED, boost::bind (&FilmViewer::slider_moved, this, true)); + _slider->Bind (wxEVT_SCROLL_PAGEUP, boost::bind (&FilmViewer::slider_moved, this, true)); + _slider->Bind (wxEVT_SCROLL_PAGEDOWN, boost::bind (&FilmViewer::slider_moved, this, true)); + _slider->Bind (wxEVT_SCROLL_THUMBRELEASE, boost::bind (&FilmViewer::slider_released, this)); _play_button->Bind (wxEVT_TOGGLEBUTTON, boost::bind (&FilmViewer::play_clicked, this)); _timer.Bind (wxEVT_TIMER, boost::bind (&FilmViewer::timer, this)); _rewind_button->Bind (wxEVT_LEFT_DOWN, boost::bind (&FilmViewer::rewind_clicked, this, _1)); @@ -220,7 +221,7 @@ FilmViewer::set_film (shared_ptr film) _player->set_play_referenced (); _film->Changed.connect (boost::bind (&FilmViewer::film_changed, this, _1)); - _player->Changed.connect (boost::bind (&FilmViewer::player_changed, this, _1)); + _player->Changed.connect (boost::bind (&FilmViewer::player_changed, this, _1, _2)); /* Keep about 1 second's worth of history samples */ _latency_history_count = _film->audio_frame_rate() / _audio_block_size; @@ -228,7 +229,7 @@ FilmViewer::set_film (shared_ptr film) recreate_butler (); calculate_sizes (); - refresh (); + slow_refresh (); setup_sensitivity (); } @@ -250,13 +251,18 @@ FilmViewer::recreate_butler () map.set (i, i, 1); } } else { - /* Special case: stereo output, at least 3 channel input, map L+R to L/R and - C to both, all 3dB down. + /* Special case: stereo output, at least 3 channel input. + Map so that Lt = L(-3dB) + Ls(-3dB) + C(-6dB) + Lfe(-10dB) + Rt = R(-3dB) + Rs(-3dB) + C(-6dB) + Lfe(-10dB) */ - map.set (0, 0, 1 / sqrt(2)); // L -> L - map.set (1, 1, 1 / sqrt(2)); // R -> R - map.set (2, 0, 1 / sqrt(2)); // C -> L - map.set (2, 1, 1 / sqrt(2)); // C -> R + map.set (dcp::LEFT, 0, 1 / sqrt(2)); // L -> Lt + map.set (dcp::RIGHT, 1, 1 / sqrt(2)); // R -> Rt + map.set (dcp::CENTRE, 0, 1 / 2.0); // C -> Lt + map.set (dcp::CENTRE, 1, 1 / 2.0); // C -> Rt + map.set (dcp::LFE, 0, 1 / sqrt(10)); // Lfe -> Lt + map.set (dcp::LFE, 1, 1 / sqrt(10)); // Lfe -> Rt + map.set (dcp::LS, 0, 1 / sqrt(2)); // Ls -> Lt + map.set (dcp::RS, 1, 1 / sqrt(2)); // Rs -> Rt } _butler.reset (new Butler (_player, _film->log(), map, _audio_channels)); @@ -281,27 +287,32 @@ FilmViewer::get () { DCPOMATIC_ASSERT (_butler); - pair, DCPTime> video; do { - video = _butler->get_video (); + _player_video = _butler->get_video (); } while ( _film->three_d() && - ((_left_eye->GetValue() && video.first->eyes() == EYES_RIGHT) || (_right_eye->GetValue() && video.first->eyes() == EYES_LEFT)) + ((_left_eye->GetValue() && _player_video.first->eyes() == EYES_RIGHT) || (_right_eye->GetValue() && _player_video.first->eyes() == EYES_LEFT)) ); _butler->rethrow (); - if (!video.first) { + display_player_video (); +} + +void +FilmViewer::display_player_video () +{ + if (!_player_video.first) { _frame.reset (); refresh_panel (); return; } - if (_playing && (time() - video.second) > one_video_frame()) { + if (_playing && (time() - _player_video.second) > one_video_frame()) { /* Too late; just drop this frame before we try to get its image (which will be the time-consuming part if this frame is J2K). */ - _video_position = video.second; + _video_position = _player_video.second; ++_dropped; return; } @@ -324,17 +335,17 @@ FilmViewer::get () * image and convert it (from whatever the user has said it is) to RGB. */ - _frame = video.first->image ( + _frame = _player_video.first->image ( bind (&Log::dcp_log, _film->log().get(), _1, _2), bind (&PlayerVideo::always_rgb, _1), false, true ); - ImageChanged (video.first); + ImageChanged (_player_video.first); - _video_position = video.second; - _inter_position = video.first->inter_position (); - _inter_size = video.first->inter_size (); + _video_position = _player_video.second; + _inter_position = _player_video.first->inter_position (); + _inter_size = _player_video.first->inter_size (); refresh_panel (); } @@ -367,7 +378,7 @@ FilmViewer::paint_panel () { wxPaintDC dc (_panel); - if (!_frame || !_film || !_out_size.width || !_out_size.height) { + if (!_frame || !_film || !_out_size.width || !_out_size.height || _out_size != _frame->size()) { dc.Clear (); return; } @@ -400,24 +411,38 @@ FilmViewer::paint_panel () } } +/** @param page true if this was a PAGEUP/PAGEDOWN event for which we won't receive a THUMBRELEASE */ void -FilmViewer::slider_moved (bool update_slider) +FilmViewer::slider_moved (bool page) { if (!_film) { return; } + if (!page && !_slider_being_moved) { + /* This is the first event of a drag; stop playback for the duration of the drag */ + _was_running_before_slider = stop (); + _slider_being_moved = true; + } DCPTime t (_slider->GetValue() * _film->length().get() / 4096); + t = t.round (_film->video_frame_rate()); /* Ensure that we hit the end of the film at the end of the slider */ if (t >= _film->length ()) { t = _film->length() - one_video_frame(); } seek (t, false); update_position_label (); - if (update_slider) { - update_position_slider (); +} + +void +FilmViewer::slider_released () +{ + if (_was_running_before_slider) { + /* Restart after a drag */ + start (); } + _slider_being_moved = false; } void @@ -427,7 +452,9 @@ FilmViewer::panel_sized (wxSizeEvent& ev) _panel_size.height = ev.GetSize().GetHeight(); calculate_sizes (); - refresh (); + if (!quick_refresh()) { + slow_refresh (); + } update_position_label (); update_position_slider (); } @@ -484,6 +511,10 @@ FilmViewer::check_play_state () void FilmViewer::start () { + if (!_film) { + return; + } + if (_audio.isStreamOpen()) { _audio.setStreamTime (_video_position.seconds()); _audio.startStream (); @@ -492,13 +523,14 @@ FilmViewer::start () _playing = true; _dropped = 0; timer (); + _play_button->SetValue (true); } bool FilmViewer::stop () { if (_audio.isStreamRunning()) { - /* stop stream and discard any remainig queued samples */ + /* stop stream and discard any remaining queued samples */ _audio.abortStream (); } @@ -554,7 +586,7 @@ FilmViewer::active_jobs_changed (optional j) } DCPTime -FilmViewer::nudge_amount (wxMouseEvent& ev) +FilmViewer::nudge_amount (wxKeyboardState& ev) { DCPTime amount = one_video_frame (); @@ -593,33 +625,66 @@ FilmViewer::rewind_clicked (wxMouseEvent& ev) } void -FilmViewer::back_clicked (wxMouseEvent& ev) +FilmViewer::back_frame () +{ + if (!_film) { + return; + } + + go_to (_video_position - one_video_frame()); +} + +void +FilmViewer::forward_frame () +{ + if (!_film) { + return; + } + + go_to (_video_position + one_video_frame()); +} + +void +FilmViewer::back_clicked (wxKeyboardState& ev) { go_to (_video_position - nudge_amount (ev)); - ev.Skip (); } void -FilmViewer::forward_clicked (wxMouseEvent& ev) +FilmViewer::forward_clicked (wxKeyboardState& ev) { go_to (_video_position + nudge_amount (ev)); - ev.Skip (); } void -FilmViewer::player_changed (bool frequent) +FilmViewer::player_changed (int property, bool frequent) { if (frequent) { return; } if (_coalesce_player_changes) { - _pending_player_change = true; + _pending_player_changes.push_back (property); return; } calculate_sizes (); - refresh (); + bool refreshed = false; + if ( + property == VideoContentProperty::CROP || + property == VideoContentProperty::SCALE || + property == VideoContentProperty::FADE_IN || + property == VideoContentProperty::FADE_OUT || + property == VideoContentProperty::COLOUR_CONVERSION || + property == PlayerProperty::VIDEO_CONTAINER_SIZE || + property == PlayerProperty::FILM_CONTAINER + ) { + refreshed = quick_refresh (); + } + + if (!refreshed) { + slow_refresh (); + } update_position_label (); update_position_slider (); } @@ -652,16 +717,37 @@ FilmViewer::film_changed (Film::Property p) { if (p == Film::CONTENT || p == Film::THREE_D) { setup_sensitivity (); + } else if (p == Film::AUDIO_CHANNELS) { + recreate_butler (); } } -/** Re-get the current frame */ +/** Re-get the current frame slowly by seeking */ void -FilmViewer::refresh () +FilmViewer::slow_refresh () { seek (_video_position, true); } +/** Try to re-get the current frame quickly by resetting the metadata + * in the PlayerVideo that we used last time. + * @return true if this was possible, false if not. + */ +bool +FilmViewer::quick_refresh () +{ + if (!_player_video.first) { + return false; + } + + if (!_player_video.first->reset_metadata (_player->video_container_size(), _film->frame_size())) { + return false; + } + + display_player_video (); + return true; +} + void FilmViewer::set_position (DCPTime p) { @@ -671,17 +757,22 @@ FilmViewer::set_position (DCPTime p) update_position_slider (); } +void +FilmViewer::set_position (shared_ptr content, ContentTime t) +{ + set_position (_player->content_time_to_dcp (content, t)); +} + void FilmViewer::set_coalesce_player_changes (bool c) { _coalesce_player_changes = c; - if (c) { - _pending_player_change = false; - } else { - if (_pending_player_change) { - player_changed (false); + if (!c) { + BOOST_FOREACH (int i, _pending_player_changes) { + player_changed (i, false); } + _pending_player_changes.clear (); } } @@ -739,7 +830,7 @@ FilmViewer::config_changed (Config::Property p) _audio.closeStream (); } - if (Config::instance()->sound()) { + if (Config::instance()->sound() && _audio.getDeviceCount() > 0) { unsigned int st = 0; if (Config::instance()->sound_output()) { while (st < _audio.getDeviceCount()) {