Basic jump to selected subtitle (#1200).
[dcpomatic.git] / src / wx / film_viewer.cc
index 11505e5101e1351699c38d12fcbd291a73dd8fec..9f42aaad25798c18729bab2b162693290e2c3319 100644 (file)
@@ -251,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));
@@ -373,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;
        }
@@ -421,6 +426,7 @@ FilmViewer::slider_moved (bool page)
        }
 
        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();
@@ -446,7 +452,9 @@ FilmViewer::panel_sized (wxSizeEvent& ev)
        _panel_size.height = ev.GetSize().GetHeight();
 
        calculate_sizes ();
-       quick_refresh ();
+       if (!quick_refresh()) {
+               slow_refresh ();
+       }
        update_position_label ();
        update_position_slider ();
 }
@@ -503,6 +511,10 @@ FilmViewer::check_play_state ()
 void
 FilmViewer::start ()
 {
+       if (!_film) {
+               return;
+       }
+
        if (_audio.isStreamOpen()) {
                _audio.setStreamTime (_video_position.seconds());
                _audio.startStream ();
@@ -574,7 +586,7 @@ FilmViewer::active_jobs_changed (optional<string> j)
 }
 
 DCPTime
-FilmViewer::nudge_amount (wxMouseEvent& ev)
+FilmViewer::nudge_amount (wxKeyboardState& ev)
 {
        DCPTime amount = one_video_frame ();
 
@@ -613,17 +625,35 @@ 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
@@ -639,6 +669,7 @@ FilmViewer::player_changed (int property, bool frequent)
        }
 
        calculate_sizes ();
+       bool refreshed = false;
        if (
                property == VideoContentProperty::CROP ||
                property == VideoContentProperty::SCALE ||
@@ -648,8 +679,10 @@ FilmViewer::player_changed (int property, bool frequent)
                property == PlayerProperty::VIDEO_CONTAINER_SIZE ||
                property == PlayerProperty::FILM_CONTAINER
                ) {
-               quick_refresh ();
-       } else {
+               refreshed = quick_refresh ();
+       }
+
+       if (!refreshed) {
                slow_refresh ();
        }
        update_position_label ();
@@ -696,16 +729,23 @@ FilmViewer::slow_refresh ()
        seek (_video_position, true);
 }
 
-/** Re-get the current frame quickly by resetting the metadata in the PlayerVideo that we used last time */
-void
+/** 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;
+               return false;
+       }
+
+       if (!_player_video.first->reset_metadata (_player->video_container_size(), _film->frame_size())) {
+               return false;
        }
 
-       _player_video.first->reset_metadata (_player->video_container_size(), _film->frame_size());
        display_player_video ();
+       return true;
 }
 
 void
@@ -717,6 +757,12 @@ FilmViewer::set_position (DCPTime p)
        update_position_slider ();
 }
 
+void
+FilmViewer::set_position (shared_ptr<Content> content, ContentTime t)
+{
+       set_position (_player->content_time_to_dcp (content, t));
+}
+
 void
 FilmViewer::set_coalesce_player_changes (bool c)
 {
@@ -784,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()) {