Rename Film::player to reflect the fact that it creates a new Player on each call.
[dcpomatic.git] / src / wx / film_viewer.cc
index f64020ba7817f6bb5bbf4fb3b57ca3b1370a5bd6..d42829880876959638afabcfdcf1d202a0c6d7fa 100644 (file)
@@ -47,6 +47,7 @@ using std::min;
 using std::max;
 using std::cout;
 using std::list;
+using std::make_pair;
 using boost::shared_ptr;
 using boost::dynamic_pointer_cast;
 using boost::weak_ptr;
@@ -67,9 +68,7 @@ FilmViewer::FilmViewer (shared_ptr<Film> f, wxWindow* p)
        _panel->SetDoubleBuffered (true);
 #endif
        
-#if wxMAJOR_VERSION == 2 && wxMINOR_VERSION >= 9
        _panel->SetBackgroundStyle (wxBG_STYLE_PAINT);
-#endif 
        
        _v_sizer = new wxBoxSizer (wxVERTICAL);
        SetSizer (_v_sizer);
@@ -121,17 +120,19 @@ FilmViewer::set_film (shared_ptr<Film> f)
        _film = f;
 
        _frame.reset ();
+       _queue.clear ();
 
        if (!_film) {
                return;
        }
 
-       _player = f->player ();
+       _player = f->make_player ();
        _player->disable_audio ();
-       _player->Video.connect (boost::bind (&FilmViewer::process_video, this, _1, _2, _3));
-       _player->Changed.connect (boost::bind (&FilmViewer::player_changed, this));
+       _player->Video.connect (boost::bind (&FilmViewer::process_video, this, _1, _3));
+       _player->Changed.connect (boost::bind (&FilmViewer::player_changed, this, _1));
 
        calculate_sizes ();
+       fetch_current_frame_again ();
 }
 
 void
@@ -141,9 +142,16 @@ FilmViewer::fetch_current_frame_again ()
                return;
        }
 
-       Time const t = _film->video_frames_to_time (1);
-       
-       _player->seek (_player->video_position() - t * 1.5, true);
+       /* Player::video_position is the time after the last frame that we received.
+          We want to see it again, so seek back one frame.
+       */
+
+       Time p = _player->video_position() - _film->video_frames_to_time (1);
+       if (p < 0) {
+               p = 0;
+       }
+
+       _player->seek (p, true);
        fetch_next_frame ();
 }
 
@@ -175,7 +183,7 @@ FilmViewer::paint_panel (wxPaintEvent &)
                return;
        }
 
-       shared_ptr<SimpleImage> packed_frame (new SimpleImage (_frame, false));
+       shared_ptr<Image> packed_frame (new Image (_frame, false));
 
        wxImage frame (_out_size.width, _out_size.height, packed_frame->data()[0], true);
        wxBitmap frame_bitmap (frame);
@@ -267,10 +275,15 @@ FilmViewer::check_play_state ()
 }
 
 void
-FilmViewer::process_video (shared_ptr<const Image> image, bool, Time t)
+FilmViewer::process_video (shared_ptr<const Image> image, Time t)
 {
+       if (_got_frame) {
+               /* This is an additional frame emitted by a single pass.  Store it. */
+               _queue.push_front (make_pair (image, t));
+               return;
+       }
+       
        _frame = image;
-
        _got_frame = true;
 
        double const fps = _film->dcp_video_frame_rate ();
@@ -299,13 +312,19 @@ FilmViewer::fetch_next_frame ()
                return;
        }
 
-       try {
-               _got_frame = false;
-               while (!_got_frame && !_player->pass ()) {}
-       } catch (DecodeError& e) {
-               _play_button->SetValue (false);
-               check_play_state ();
-               error_dialog (this, wxString::Format (_("Could not decode video for view (%s)"), std_to_wx(e.what()).data()));
+       _got_frame = false;
+       
+       if (!_queue.empty ()) {
+               process_video (_queue.back().first, _queue.back().second);
+               _queue.pop_back ();
+       } else {
+               try {
+                       while (!_got_frame && !_player->pass ()) {}
+               } catch (DecodeError& e) {
+                       _play_button->SetValue (false);
+                       check_play_state ();
+                       error_dialog (this, wxString::Format (_("Could not decode video for view (%s)"), std_to_wx(e.what()).data()));
+               }
        }
 
        _panel->Refresh ();
@@ -339,9 +358,11 @@ FilmViewer::back_clicked (wxCommandEvent &)
                return;
        }
 
-       Time const t = _film->video_frames_to_time (1);
+       /* Player::video_position is the time after the last frame that we received.
+          We want to see the one before it, so we need to go back 2.
+       */
        
-       _player->seek (_player->video_position() - t * 2.5, true);
+       _player->seek (_player->video_position() - _film->video_frames_to_time(2), true);
        fetch_next_frame ();
 }
 
@@ -356,8 +377,12 @@ FilmViewer::forward_clicked (wxCommandEvent &)
 }
 
 void
-FilmViewer::player_changed ()
+FilmViewer::player_changed (bool frequent)
 {
+       if (frequent) {
+               return;
+       }
+       
        calculate_sizes ();
        fetch_current_frame_again ();
 }