Replace May/Done/NotDone signal sets with one signal and extend
[dcpomatic.git] / src / wx / film_viewer.cc
index 18d16a461789c9bd93b6e1784d0718eefcb5d184..463854992f16347c875e738565d74221501b65e1 100644 (file)
@@ -26,6 +26,7 @@
 #include "playhead_to_timecode_dialog.h"
 #include "playhead_to_frame_dialog.h"
 #include "wx_util.h"
+#include "closed_captions_dialog.h"
 #include "lib/film.h"
 #include "lib/ratio.h"
 #include "lib/util.h"
@@ -94,6 +95,7 @@ FilmViewer::FilmViewer (wxWindow* p, bool outline_content, bool jump_to_selected
        , _playing (false)
        , _latency_history_count (0)
        , _dropped (0)
+       , _closed_captions_dialog (new ClosedCaptionsDialog(GetParent()))
 {
 #ifndef __WXOSX__
        _panel->SetDoubleBuffered (true);
@@ -194,6 +196,7 @@ FilmViewer::set_film (shared_ptr<Film> film)
        _film = film;
 
        _frame.reset ();
+       _closed_captions_dialog->clear ();
 
        update_position_slider ();
        update_position_label ();
@@ -218,11 +221,11 @@ FilmViewer::set_film (shared_ptr<Film> film)
                return;
        }
 
-       _player->set_always_burn_open_captions ();
+       _player->set_always_burn_open_subtitles ();
        _player->set_play_referenced ();
 
        _film->Changed.connect (boost::bind (&FilmViewer::film_changed, this, _1));
-       _player->Changed.connect (boost::bind (&FilmViewer::player_changed, this, _1, _2));
+       _player->Change.connect (boost::bind (&FilmViewer::player_change, this, _1, _2, _3));
 
        /* Keep about 1 second's worth of history samples */
        _latency_history_count = _film->audio_frame_rate() / _audio_block_size;
@@ -271,6 +274,8 @@ FilmViewer::recreate_butler ()
                _butler->disable_audio ();
        }
 
+       _closed_captions_dialog->set_butler (_butler);
+
        if (was_running) {
                start ();
        }
@@ -349,6 +354,8 @@ FilmViewer::display_player_video ()
        _inter_size = _player_video.first->inter_size ();
 
        refresh_panel ();
+
+       _closed_captions_dialog->update (time());
 }
 
 void
@@ -658,9 +665,9 @@ FilmViewer::forward_clicked (wxKeyboardState& ev)
 }
 
 void
-FilmViewer::player_changed (int property, bool frequent)
+FilmViewer::player_change (ChangeType type, int property, bool frequent)
 {
-       if (frequent) {
+       if (type != CHANGE_TYPE_DONE || frequent) {
                return;
        }
 
@@ -760,7 +767,10 @@ FilmViewer::set_position (DCPTime p)
 void
 FilmViewer::set_position (shared_ptr<Content> content, ContentTime t)
 {
-       set_position (_player->content_time_to_dcp (content, t));
+       optional<DCPTime> dt = _player->content_time_to_dcp (content, t);
+       if (dt) {
+               set_position (*dt);
+       }
 }
 
 void
@@ -770,7 +780,7 @@ FilmViewer::set_coalesce_player_changes (bool c)
 
        if (!c) {
                BOOST_FOREACH (int i, _pending_player_changes) {
-                       player_changed (i, false);
+                       player_change (CHANGE_TYPE_DONE, i, false);
                }
                _pending_player_changes.clear ();
        }
@@ -811,6 +821,7 @@ FilmViewer::seek (DCPTime t, bool accurate)
 
        bool const was_running = stop ();
 
+       _closed_captions_dialog->clear ();
        _butler->seek (t, accurate);
        get ();
 
@@ -872,6 +883,16 @@ FilmViewer::config_changed (Config::Property p)
        }
 }
 
+DCPTime
+FilmViewer::uncorrected_time () const
+{
+       if (_audio.isStreamRunning ()) {
+               return DCPTime::from_seconds (const_cast<RtAudio*>(&_audio)->getStreamTime());
+       }
+
+       return _video_position;
+}
+
 DCPTime
 FilmViewer::time () const
 {
@@ -886,7 +907,14 @@ FilmViewer::time () const
 int
 FilmViewer::audio_callback (void* out_p, unsigned int frames)
 {
-       _butler->get_audio (reinterpret_cast<float*> (out_p), frames);
+       while (true) {
+               optional<DCPTime> t = _butler->get_audio (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;
+               }
+               /* The audio we just got was (very) late; drop it and get some more. */
+       }
 
         boost::mutex::scoped_lock lm (_latency_history_mutex, boost::try_to_lock);
         if (lm) {
@@ -935,3 +963,9 @@ FilmViewer::one_video_frame () const
 {
        return DCPTime::from_frames (1, _film->video_frame_rate());
 }
+
+void
+FilmViewer::show_closed_captions ()
+{
+       _closed_captions_dialog->Show();
+}