return reinterpret_cast<FilmViewer*>(data)->audio_callback (out, frames);
}
-FilmViewer::FilmViewer (wxWindow* p)
+FilmViewer::FilmViewer (wxWindow* p, bool outline_content, bool jump_to_selected)
: wxPanel (p)
, _panel (new wxPanel (this))
, _outline_content (new wxCheckBox (this, wxID_ANY, _("Outline content")))
, _audio_block_size (1024)
, _playing (false)
, _latency_history_count (0)
+ , _dropped (0)
{
#ifndef __WXOSX__
_panel->SetDoubleBuffered (true);
_v_sizer->Add (_panel, 1, wxEXPAND);
wxBoxSizer* view_options = new wxBoxSizer (wxHORIZONTAL);
- view_options->Add (_outline_content, 0, wxRIGHT, DCPOMATIC_SIZER_GAP);
+ if (outline_content) {
+ view_options->Add (_outline_content, 0, wxRIGHT, DCPOMATIC_SIZER_GAP);
+ }
view_options->Add (_left_eye, 0, wxLEFT | wxRIGHT, DCPOMATIC_SIZER_GAP);
view_options->Add (_right_eye, 0, wxLEFT | wxRIGHT, DCPOMATIC_SIZER_GAP);
- view_options->Add (_jump_to_selected, 0, wxLEFT | wxRIGHT, DCPOMATIC_SIZER_GAP);
+ if (jump_to_selected) {
+ view_options->Add (_jump_to_selected, 0, wxLEFT | wxRIGHT, DCPOMATIC_SIZER_GAP);
+ }
_v_sizer->Add (view_options, 0, wxALL, DCPOMATIC_SIZER_GAP);
wxBoxSizer* h_sizer = new wxBoxSizer (wxHORIZONTAL);
_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));
- _slider->Bind (wxEVT_SCROLL_THUMBTRACK, boost::bind (&FilmViewer::slider_moved, this));
- _slider->Bind (wxEVT_SCROLL_PAGEUP, boost::bind (&FilmViewer::slider_moved, this));
- _slider->Bind (wxEVT_SCROLL_PAGEDOWN, boost::bind (&FilmViewer::slider_moved, 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));
_play_button->Bind (wxEVT_TOGGLEBUTTON, boost::bind (&FilmViewer::play_clicked, this));
_timer.Bind (wxEVT_TIMER, boost::bind (&FilmViewer::timer, this));
_back_button->Bind (wxEVT_LEFT_DOWN, boost::bind (&FilmViewer::back_clicked, this, _1));
map.set (2, 1, 1 / sqrt(2)); // C -> R
}
- _butler.reset (new Butler (_film, _player, map, _audio_channels));
+ _butler.reset (new Butler (_player, _film->log(), map, _audio_channels));
if (!Config::instance()->preview_sound()) {
_butler->disable_audio ();
}
return;
}
+ if ((time() - 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;
+ ++_dropped;
+ return;
+ }
+
/* In an ideal world, what we would do here is:
*
* 1. convert to XYZ exactly as we do in the DCP creation path.
get ();
update_position_label ();
update_position_slider ();
- DCPTime const next = _video_position + DCPTime::from_frames (1, _film->video_frame_rate ());
+ DCPTime const next = _video_position + one_video_frame();
if (next >= _film->length()) {
stop ();
}
- _timer.Start (max ((next.seconds() - time().seconds()) * 1000, 0.0), wxTIMER_ONE_SHOT);
+ _timer.Start (max ((next.seconds() - time().seconds()) * 1000, 1.0), wxTIMER_ONE_SHOT);
if (_butler) {
_butler->rethrow ();
}
void
-FilmViewer::slider_moved ()
+FilmViewer::slider_moved (bool update_slider)
{
if (!_film) {
return;
}
+
DCPTime t (_slider->GetValue() * _film->length().get() / 4096);
/* Ensure that we hit the end of the film at the end of the slider */
if (t >= _film->length ()) {
- t = _film->length() - DCPTime::from_frames (1, _film->video_frame_rate ());
+ t = _film->length() - one_video_frame();
}
seek (t, false);
update_position_label ();
+ if (update_slider) {
+ update_position_slider ();
+ }
}
void
}
_playing = true;
- _timer.Start (0, wxTIMER_ONE_SHOT);
+ _dropped = 0;
+ timer ();
}
bool
DCPTime
FilmViewer::nudge_amount (wxMouseEvent& ev)
{
- DCPTime amount = DCPTime::from_frames (1, _film->video_frame_rate ());
+ DCPTime amount = one_video_frame ();
if (ev.ShiftDown() && !ev.ControlDown()) {
amount = DCPTime::from_seconds (1);
return total / _latency_history.size();
}
+
+void
+FilmViewer::set_dcp_decode_reduction (optional<int> reduction)
+{
+ _player->set_dcp_decode_reduction (reduction);
+}
+
+DCPTime
+FilmViewer::one_video_frame () const
+{
+ return DCPTime::from_frames (1, _film->video_frame_rate());
+}