From 23583dfb56181c76126e652042e9d1940367aa27 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Mon, 10 Sep 2018 22:02:09 +0100 Subject: [PATCH] Partial split of film viewer. --- src/tools/dcpomatic.cc | 6 +- src/tools/dcpomatic_player.cc | 7 +- src/wx/content_panel.cc | 6 +- src/wx/content_panel.h | 8 +- src/wx/control_film_viewer.cc | 327 ++++++++++++++++++++++++++++++++ src/wx/control_film_viewer.h | 64 +++++++ src/wx/film_editor.cc | 10 +- src/wx/film_editor.h | 4 +- src/wx/film_viewer.cc | 283 ++------------------------- src/wx/film_viewer.h | 41 ++-- src/wx/player_information.cc | 2 +- src/wx/player_information.h | 4 +- src/wx/text_view.cc | 6 +- src/wx/text_view.h | 11 +- src/wx/timing_panel.cc | 2 +- src/wx/timing_panel.h | 4 +- src/wx/video_waveform_dialog.cc | 2 +- src/wx/video_waveform_dialog.h | 6 +- src/wx/video_waveform_plot.cc | 6 +- src/wx/video_waveform_plot.h | 2 +- src/wx/wscript | 1 + 21 files changed, 462 insertions(+), 340 deletions(-) create mode 100644 src/wx/control_film_viewer.cc create mode 100644 src/wx/control_film_viewer.h diff --git a/src/tools/dcpomatic.cc b/src/tools/dcpomatic.cc index 330935ba2..7392c830c 100644 --- a/src/tools/dcpomatic.cc +++ b/src/tools/dcpomatic.cc @@ -22,7 +22,7 @@ * @brief The main DCP-o-matic GUI. */ -#include "wx/film_viewer.h" +#include "wx/control_film_viewer.h" #include "wx/film_editor.h" #include "wx/job_manager_view.h" #include "wx/full_config_dialog.h" @@ -317,7 +317,7 @@ public: */ wxPanel* overall_panel = new wxPanel (this, wxID_ANY); - _film_viewer = new FilmViewer (overall_panel); + _film_viewer = new ControlFilmViewer (overall_panel); _film_editor = new FilmEditor (overall_panel, _film_viewer); JobManagerView* job_manager_view = new JobManagerView (overall_panel, false); @@ -1307,7 +1307,7 @@ private: } FilmEditor* _film_editor; - FilmViewer* _film_viewer; + ControlFilmViewer* _film_viewer; VideoWaveformDialog* _video_waveform_dialog; HintsDialog* _hints_dialog; ServersListDialog* _servers_list_dialog; diff --git a/src/tools/dcpomatic_player.cc b/src/tools/dcpomatic_player.cc index 513a5c4e7..03ace74c9 100644 --- a/src/tools/dcpomatic_player.cc +++ b/src/tools/dcpomatic_player.cc @@ -26,6 +26,7 @@ #include "lib/dcp_content.h" #include "lib/job_manager.h" #include "lib/job.h" +#include "lib/film.h" #include "lib/video_content.h" #include "lib/text_content.h" #include "lib/ratio.h" @@ -38,7 +39,7 @@ #include "wx/wx_util.h" #include "wx/about_dialog.h" #include "wx/report_problem_dialog.h" -#include "wx/film_viewer.h" +#include "wx/control_film_viewer.h" #include "wx/player_information.h" #include "wx/update_dialog.h" #include "wx/player_config_dialog.h" @@ -150,7 +151,7 @@ public: */ wxPanel* overall_panel = new wxPanel (this, wxID_ANY); - _viewer = new FilmViewer (overall_panel, false, false); + _viewer = new ControlFilmViewer (overall_panel, false, false); _viewer->set_dcp_decode_reduction (Config::instance()->decode_reduction ()); _info = new PlayerInformation (overall_panel, _viewer); wxSizer* main_sizer = new wxBoxSizer (wxVERTICAL); @@ -648,7 +649,7 @@ private: int _history_items; int _history_position; wxMenuItem* _history_separator; - FilmViewer* _viewer; + ControlFilmViewer* _viewer; boost::shared_ptr _film; boost::signals2::scoped_connection _config_changed_connection; wxMenuItem* _file_add_ov; diff --git a/src/wx/content_panel.cc b/src/wx/content_panel.cc index 4e6cdb2f2..e5990a564 100644 --- a/src/wx/content_panel.cc +++ b/src/wx/content_panel.cc @@ -26,7 +26,7 @@ #include "timing_panel.h" #include "timeline_dialog.h" #include "image_sequence_dialog.h" -#include "film_viewer.h" +#include "control_film_viewer.h" #include "lib/audio_content.h" #include "lib/text_content.h" #include "lib/video_content.h" @@ -61,7 +61,7 @@ using boost::optional; #define LOG_GENERAL(...) _film->log()->log (String::compose (__VA_ARGS__), LogEntry::TYPE_GENERAL); -ContentPanel::ContentPanel (wxNotebook* n, boost::shared_ptr film, FilmViewer* viewer) +ContentPanel::ContentPanel (wxNotebook* n, boost::shared_ptr film, ControlFilmViewer* viewer) : _video_panel (0) , _audio_panel (0) , _timeline_dialog (0) @@ -302,7 +302,7 @@ ContentPanel::check_selection () } if (go_to && Config::instance()->jump_to_selected() && signal_manager) { - signal_manager->when_idle(boost::bind(&FilmViewer::set_position, _film_viewer, go_to.get().ceil(_film->video_frame_rate()))); + signal_manager->when_idle(boost::bind(&ControlFilmViewer::set_position, _film_viewer, go_to.get().ceil(_film->video_frame_rate()))); } if (_timeline_dialog) { diff --git a/src/wx/content_panel.h b/src/wx/content_panel.h index 33a7866e4..e9f942d09 100644 --- a/src/wx/content_panel.h +++ b/src/wx/content_panel.h @@ -37,12 +37,12 @@ class VideoPanel; class AudioPanel; class TimingPanel; class Film; -class FilmViewer; +class ControlFilmViewer; class ContentPanel : public boost::noncopyable { public: - ContentPanel (wxNotebook *, boost::shared_ptr, FilmViewer* viewer); + ContentPanel (wxNotebook *, boost::shared_ptr, ControlFilmViewer* viewer); boost::shared_ptr film () const { return _film; @@ -74,7 +74,7 @@ public: bool remove_clicked (bool hotkey); void timeline_clicked (); - FilmViewer* film_viewer () const { + ControlFilmViewer* film_viewer () const { return _film_viewer; } @@ -120,7 +120,7 @@ private: wxWindow* _last_selected_tab; boost::shared_ptr _film; - FilmViewer* _film_viewer; + ControlFilmViewer* _film_viewer; bool _generally_sensitive; bool _ignore_deselect; }; diff --git a/src/wx/control_film_viewer.cc b/src/wx/control_film_viewer.cc new file mode 100644 index 000000000..44f374f71 --- /dev/null +++ b/src/wx/control_film_viewer.cc @@ -0,0 +1,327 @@ +#include "control_film_viewer.h" +#include "film_viewer.h" +#include "wx_util.h" +#include +#include + +using std::string; +using boost::optional; + +ControlFilmViewer::ControlFilmViewer (wxWindow* parent, bool outline_content, bool jump_to_selected) + : wxPanel (parent) + , _viewer (new FilmViewer(this, outline_content, jump_to_selected)) + , _slider (new wxSlider (this, wxID_ANY, 0, 0, 4096)) + , _rewind_button (new wxButton (this, wxID_ANY, wxT("|<"))) + , _back_button (new wxButton (this, wxID_ANY, wxT("<"))) + , _forward_button (new wxButton (this, wxID_ANY, wxT(">"))) + , _frame_number (new wxStaticText (this, wxID_ANY, wxT(""))) + , _timecode (new wxStaticText (this, wxID_ANY, wxT(""))) + , _play_button (new wxToggleButton (this, wxID_ANY, _("Play"))) +{ + _v_sizer = new wxBoxSizer (wxVERTICAL); + SetSizer (_v_sizer); + _v_sizer->Add (_viewer->panel(), 1, wxEXPAND); + + wxBoxSizer* view_options = new wxBoxSizer (wxHORIZONTAL); + if (outline_content) { + _outline_content = new wxCheckBox (this, wxID_ANY, _("Outline content")); + view_options->Add (_outline_content, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, DCPOMATIC_SIZER_GAP); + } + + _eye = new wxChoice (this, wxID_ANY); + _eye->Append (_("Left")); + _eye->Append (_("Right")); + _eye->SetSelection (0); + view_options->Add (_eye, 0, wxLEFT | wxRIGHT | wxALIGN_CENTER_VERTICAL, DCPOMATIC_SIZER_GAP); + + if (jump_to_selected) { + _jump_to_selected = new wxCheckBox (this, wxID_ANY, _("Jump to selected content")); + view_options->Add (_jump_to_selected, 0, wxLEFT | wxRIGHT | wxALIGN_CENTER_VERTICAL, DCPOMATIC_SIZER_GAP); + } + + _v_sizer->Add (view_options, 0, wxALL, DCPOMATIC_SIZER_GAP); + + wxBoxSizer* h_sizer = new wxBoxSizer (wxHORIZONTAL); + + wxBoxSizer* time_sizer = new wxBoxSizer (wxVERTICAL); + time_sizer->Add (_frame_number, 0, wxEXPAND); + time_sizer->Add (_timecode, 0, wxEXPAND); + + h_sizer->Add (_rewind_button, 0, wxALL, 2); + h_sizer->Add (_back_button, 0, wxALL, 2); + h_sizer->Add (time_sizer, 0, wxEXPAND); + h_sizer->Add (_forward_button, 0, wxALL, 2); + h_sizer->Add (_play_button, 0, wxEXPAND); + h_sizer->Add (_slider, 1, wxEXPAND); + + _v_sizer->Add (h_sizer, 0, wxEXPAND | wxALL, 6); + + _frame_number->SetMinSize (wxSize (84, -1)); + _rewind_button->SetMinSize (wxSize (32, -1)); + _back_button->SetMinSize (wxSize (32, -1)); + _forward_button->SetMinSize (wxSize (32, -1)); + + _eye->Bind (wxEVT_CHOICE, boost::bind (&FilmViewer::slow_refresh, _viewer.get())); + _slider->Bind (wxEVT_SCROLL_THUMBTRACK, boost::bind (&ControlFilmViewer::slider_moved, this, false)); + _slider->Bind (wxEVT_SCROLL_PAGEUP, boost::bind (&ControlFilmViewer::slider_moved, this, true)); + _slider->Bind (wxEVT_SCROLL_PAGEDOWN, boost::bind (&ControlFilmViewer::slider_moved, this, true)); + _slider->Bind (wxEVT_SCROLL_THUMBRELEASE, boost::bind (&ControlFilmViewer::slider_released, this)); + _play_button->Bind (wxEVT_TOGGLEBUTTON, boost::bind (&ControlFilmViewer::play_clicked, this)); + _rewind_button->Bind (wxEVT_LEFT_DOWN, boost::bind (&ControlFilmViewer::rewind_clicked, this, _1)); + _back_button->Bind (wxEVT_LEFT_DOWN, boost::bind (&ControlFilmViewer::back_clicked, this, _1)); + _forward_button->Bind (wxEVT_LEFT_DOWN, boost::bind (&ControlFilmViewer::forward_clicked, this, _1)); + _frame_number->Bind (wxEVT_LEFT_DOWN, boost::bind (&ControlFilmViewer::frame_number_clicked, this)); + _timecode->Bind (wxEVT_LEFT_DOWN, boost::bind (&ControlFilmViewer::timecode_clicked, this)); + if (_jump_to_selected) { + _jump_to_selected->Bind (wxEVT_CHECKBOX, boost::bind (&ControlFilmViewer::jump_to_selected_clicked, this)); + _jump_to_selected->SetValue (Config::instance()->jump_to_selected ()); + } +} + +/** @param page true if this was a PAGEUP/PAGEDOWN event for which we won't receive a THUMBRELEASE */ +void +ControlFilmViewer::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() - _viewer->one_video_frame(); + } + _viewer->seek (t, false); + update_position_label (); +} + +void +ControlFilmViewer::slider_released () +{ + if (_was_running_before_slider) { + /* Restart after a drag */ + start (); + } + _slider_being_moved = false; +} + +void +ControlFilmViewer::play_clicked () +{ + check_play_state (); +} + +void +ControlFilmViewer::check_play_state () +{ + if (!_film || _film->video_frame_rate() == 0) { + return; + } + + if (_play_button->GetValue()) { + start (); + } else { + stop (); + } +} + +void +ControlFilmViewer::update_position_slider () +{ + if (!_film) { + _slider->SetValue (0); + return; + } + + DCPTime const len = _film->length (); + + if (len.get ()) { + int const new_slider_position = 4096 * _viewer->video_position().get() / len.get(); + if (new_slider_position != _slider->GetValue()) { + _slider->SetValue (new_slider_position); + } + } +} + +void +ControlFilmViewer::update_position_label () +{ + if (!_film) { + _frame_number->SetLabel ("0"); + _timecode->SetLabel ("0:0:0.0"); + return; + } + + double const fps = _film->video_frame_rate (); + /* Count frame number from 1 ... not sure if this is the best idea */ + _frame_number->SetLabel (wxString::Format (wxT("%ld"), lrint (_viewer->video_position().seconds() * fps) + 1)); + _timecode->SetLabel (time_to_timecode (_viewer->video_position(), fps)); +} + +void +ControlFilmViewer::active_jobs_changed (optional j) +{ + /* examine content is the only job which stops the viewer working */ + bool const a = !j || *j != "examine_content"; + _slider->Enable (a); + _play_button->Enable (a); +} + +DCPTime +ControlFilmViewer::nudge_amount (wxKeyboardState& ev) +{ + DCPTime amount = _viewer->one_video_frame (); + + if (ev.ShiftDown() && !ev.ControlDown()) { + amount = DCPTime::from_seconds (1); + } else if (!ev.ShiftDown() && ev.ControlDown()) { + amount = DCPTime::from_seconds (10); + } else if (ev.ShiftDown() && ev.ControlDown()) { + amount = DCPTime::from_seconds (60); + } + + return amount; +} + +void +ControlFilmViewer::rewind_clicked (wxMouseEvent& ev) +{ + _viewer->go_to (DCPTime()); + ev.Skip(); +} + +void +ControlFilmViewer::back_frame () +{ + _viewer->move (-_viewer->one_video_frame()); +} + +void +ControlFilmViewer::forward_frame () +{ + _viewer->move (_viewer->one_video_frame()); +} + +void +ControlFilmViewer::back_clicked (wxKeyboardState& ev) +{ + _viewer->move (-nudge_amount(ev)); +} + +void +ControlFilmViewer::forward_clicked (wxKeyboardState& ev) +{ + _viewer->move (nudge_amount(ev)); +} + +void +ControlFilmViewer::setup_sensitivity () +{ + bool const c = _film && !_film->content().empty (); + + _slider->Enable (c); + _rewind_button->Enable (c); + _back_button->Enable (c); + _forward_button->Enable (c); + _play_button->Enable (c); + if (_outline_content) { + _outline_content->Enable (c); + } + _frame_number->Enable (c); + _timecode->Enable (c); + if (_jump_to_selected) { + _jump_to_selected->Enable (c); + } + + _eye->Enable (c && _film->three_d ()); +} + +void +ControlFilmViewer::timecode_clicked () +{ + PlayheadToTimecodeDialog* dialog = new PlayheadToTimecodeDialog (this, _film->video_frame_rate ()); + if (dialog->ShowModal() == wxID_OK) { + _viewer->go_to (dialog->get ()); + } + dialog->Destroy (); +} + +void +ControlFilmViewer::frame_number_clicked () +{ + PlayheadToFrameDialog* dialog = new PlayheadToFrameDialog (this, _film->video_frame_rate ()); + if (dialog->ShowModal() == wxID_OK) { + _viewer->go_to (dialog->get ()); + } + dialog->Destroy (); +} + +void +ControlFilmViewer::jump_to_selected_clicked () +{ + Config::instance()->set_jump_to_selected (_jump_to_selected->GetValue ()); +} + +void +ControlFilmViewer::set_film (shared_ptr film) +{ + _viewer->set_film (film); + + if (_film == film) { + return; + } + + _film = film; + + update_position_slider (); + update_position_label (); +} + +void +ControlFilmViewer::set_position (DCPTime p) +{ + _viewer->set_position (p); +} + +void +ControlFilmViewer::set_position (shared_ptr content, ContentTime t) +{ + _viewer->set_position (content, t); +} + +void +ControlFilmViewer::set_dcp_decode_reduction (boost::optional reduction) +{ + _viewer->set_dcp_decode_reduction (reduction); +} + +void +ControlFilmViewer::show_closed_captions () +{ + _viewer->show_closed_captions (); +} + +void +ControlFilmViewer::start () +{ + _viewer->start (); +} + +bool +ControlFilmViewer::stop () +{ + return _viewer->stop (); +} + +bool +ControlFilmViewer::playing () const +{ + return _viewer->playing (); +} diff --git a/src/wx/control_film_viewer.h b/src/wx/control_film_viewer.h new file mode 100644 index 000000000..3de316d65 --- /dev/null +++ b/src/wx/control_film_viewer.h @@ -0,0 +1,64 @@ +#include "lib/dcpomatic_time.h" +#include +#include + +class FilmViewer; +class Film; +class ClosedCaptionsDialog; +class Content; +class wxToggleButton; + +class ControlFilmViewer : public wxPanel +{ +public: + ControlFilmViewer (wxWindow* parent, bool outline_content = true, bool jump_to_selected = true); + + void set_film (boost::shared_ptr film); + + /* FilmViewer proxies */ + void set_position (DCPTime p); + void set_position (boost::shared_ptr content, ContentTime p); + void set_dcp_decode_reduction (boost::optional reduction); + void show_closed_captions (); + void start (); + bool stop (); + bool playing () const; + void back_frame (); + void forward_frame (); + +private: + void update_position_label (); + void update_position_slider (); + void rewind_clicked (wxMouseEvent &); + void back_clicked (wxKeyboardState& s); + void forward_clicked (wxKeyboardState &); + void slider_moved (bool page); + void slider_released (); + void play_clicked (); + void frame_number_clicked (); + void jump_to_selected_clicked (); + void setup_sensitivity (); + void timecode_clicked (); + void check_play_state (); + void active_jobs_changed (boost::optional); + + boost::shared_ptr _film; + boost::shared_ptr _viewer; + + wxSizer* _v_sizer; + bool _slider_being_moved; + bool _was_running_before_slider; + + wxCheckBox* _outline_content; + wxChoice* _eye; + wxCheckBox* _jump_to_selected; + wxSlider* _slider; + wxButton* _rewind_button; + wxButton* _back_button; + wxButton* _forward_button; + wxStaticText* _frame_number; + wxStaticText* _timecode; + wxToggleButton* _play_button; + + ClosedCaptionsDialog* _closed_captions_dialog; +}; diff --git a/src/wx/film_editor.cc b/src/wx/film_editor.cc index 1e06bf4a9..965497234 100644 --- a/src/wx/film_editor.cc +++ b/src/wx/film_editor.cc @@ -22,14 +22,14 @@ * @brief FilmEditor class. */ -#include "lib/film.h" -#include "lib/job_manager.h" -#include "lib/content.h" -#include "lib/dcp_content.h" #include "wx_util.h" #include "film_editor.h" #include "dcp_panel.h" #include "content_panel.h" +#include "lib/film.h" +#include "lib/job_manager.h" +#include "lib/content.h" +#include "lib/dcp_content.h" #include #include #include @@ -41,7 +41,7 @@ using std::list; using boost::shared_ptr; using boost::optional; -FilmEditor::FilmEditor (wxWindow* parent, FilmViewer* viewer) +FilmEditor::FilmEditor (wxWindow* parent, ControlFilmViewer* viewer) : wxPanel (parent) { wxBoxSizer* s = new wxBoxSizer (wxVERTICAL); diff --git a/src/wx/film_editor.h b/src/wx/film_editor.h index cbc8f92be..48e944fc6 100644 --- a/src/wx/film_editor.h +++ b/src/wx/film_editor.h @@ -30,7 +30,7 @@ class wxNotebook; class Film; class ContentPanel; class DCPPanel; -class FilmViewer; +class ControlFilmViewer; /** @class FilmEditor * @brief A wx widget to edit a film's metadata, and perform various functions. @@ -38,7 +38,7 @@ class FilmViewer; class FilmEditor : public wxPanel { public: - FilmEditor (wxWindow *, FilmViewer* viewer); + FilmEditor (wxWindow *, ControlFilmViewer* viewer); void set_film (boost::shared_ptr); diff --git a/src/wx/film_viewer.cc b/src/wx/film_viewer.cc index d954e1818..3113a1e05 100644 --- a/src/wx/film_viewer.cc +++ b/src/wx/film_viewer.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2017 Carl Hetherington + Copyright (C) 2012-2018 Carl Hetherington This file is part of DCP-o-matic. @@ -74,18 +74,10 @@ rtaudio_callback (void* out, void *, unsigned int frames, double, RtAudioStreamS } FilmViewer::FilmViewer (wxWindow* p, bool outline_content, bool jump_to_selected) - : wxPanel (p) - , _panel (new wxPanel (this)) + : _panel (new wxPanel (p)) , _outline_content (0) , _eye (0) , _jump_to_selected (0) - , _slider (new wxSlider (this, wxID_ANY, 0, 0, 4096)) - , _rewind_button (new wxButton (this, wxID_ANY, wxT("|<"))) - , _back_button (new wxButton (this, wxID_ANY, wxT("<"))) - , _forward_button (new wxButton (this, wxID_ANY, wxT(">"))) - , _frame_number (new wxStaticText (this, wxID_ANY, wxT(""))) - , _timecode (new wxStaticText (this, wxID_ANY, wxT(""))) - , _play_button (new wxToggleButton (this, wxID_ANY, _("Play"))) , _coalesce_player_changes (false) , _slider_being_moved (false) , _was_running_before_slider (false) @@ -103,71 +95,12 @@ FilmViewer::FilmViewer (wxWindow* p, bool outline_content, bool jump_to_selected _panel->SetBackgroundStyle (wxBG_STYLE_PAINT); - _v_sizer = new wxBoxSizer (wxVERTICAL); - SetSizer (_v_sizer); - - _v_sizer->Add (_panel, 1, wxEXPAND); - - wxBoxSizer* view_options = new wxBoxSizer (wxHORIZONTAL); - if (outline_content) { - _outline_content = new wxCheckBox (this, wxID_ANY, _("Outline content")); - view_options->Add (_outline_content, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, DCPOMATIC_SIZER_GAP); - } - - _eye = new wxChoice (this, wxID_ANY); - _eye->Append (_("Left")); - _eye->Append (_("Right")); - _eye->SetSelection (0); - view_options->Add (_eye, 0, wxLEFT | wxRIGHT | wxALIGN_CENTER_VERTICAL, DCPOMATIC_SIZER_GAP); - - if (jump_to_selected) { - _jump_to_selected = new wxCheckBox (this, wxID_ANY, _("Jump to selected content")); - view_options->Add (_jump_to_selected, 0, wxLEFT | wxRIGHT | wxALIGN_CENTER_VERTICAL, DCPOMATIC_SIZER_GAP); - } - - _v_sizer->Add (view_options, 0, wxALL, DCPOMATIC_SIZER_GAP); - - wxBoxSizer* h_sizer = new wxBoxSizer (wxHORIZONTAL); - - wxBoxSizer* time_sizer = new wxBoxSizer (wxVERTICAL); - time_sizer->Add (_frame_number, 0, wxEXPAND); - time_sizer->Add (_timecode, 0, wxEXPAND); - - h_sizer->Add (_rewind_button, 0, wxALL, 2); - h_sizer->Add (_back_button, 0, wxALL, 2); - h_sizer->Add (time_sizer, 0, wxEXPAND); - h_sizer->Add (_forward_button, 0, wxALL, 2); - h_sizer->Add (_play_button, 0, wxEXPAND); - h_sizer->Add (_slider, 1, wxEXPAND); - - _v_sizer->Add (h_sizer, 0, wxEXPAND | wxALL, 6); - - _frame_number->SetMinSize (wxSize (84, -1)); - _rewind_button->SetMinSize (wxSize (32, -1)); - _back_button->SetMinSize (wxSize (32, -1)); - _forward_button->SetMinSize (wxSize (32, -1)); - _panel->Bind (wxEVT_PAINT, boost::bind (&FilmViewer::paint_panel, this)); _panel->Bind (wxEVT_SIZE, boost::bind (&FilmViewer::panel_sized, this, _1)); if (_outline_content) { _outline_content->Bind (wxEVT_CHECKBOX, boost::bind (&FilmViewer::refresh_panel, this)); } - _eye->Bind (wxEVT_CHOICE, 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, 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)); - _back_button->Bind (wxEVT_LEFT_DOWN, boost::bind (&FilmViewer::back_clicked, this, _1)); - _forward_button->Bind (wxEVT_LEFT_DOWN, boost::bind (&FilmViewer::forward_clicked, this, _1)); - _frame_number->Bind (wxEVT_LEFT_DOWN, boost::bind (&FilmViewer::frame_number_clicked, this)); - _timecode->Bind (wxEVT_LEFT_DOWN, boost::bind (&FilmViewer::timecode_clicked, this)); - if (_jump_to_selected) { - _jump_to_selected->Bind (wxEVT_CHECKBOX, boost::bind (&FilmViewer::jump_to_selected_clicked, this)); - _jump_to_selected->SetValue (Config::instance()->jump_to_selected ()); - } set_film (shared_ptr ()); @@ -198,9 +131,6 @@ FilmViewer::set_film (shared_ptr film) _frame.reset (); _closed_captions_dialog->clear (); - update_position_slider (); - update_position_label (); - if (!_film) { _player.reset (); recreate_butler (); @@ -425,40 +355,6 @@ 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 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 (); -} - -void -FilmViewer::slider_released () -{ - if (_was_running_before_slider) { - /* Restart after a drag */ - start (); - } - _slider_being_moved = false; -} - void FilmViewer::panel_sized (wxSizeEvent& ev) { @@ -502,26 +398,6 @@ FilmViewer::calculate_sizes () _player->set_video_container_size (_out_size); } -void -FilmViewer::play_clicked () -{ - check_play_state (); -} - -void -FilmViewer::check_play_state () -{ - if (!_film || _film->video_frame_rate() == 0) { - return; - } - - if (_play_button->GetValue()) { - start (); - } else { - stop (); - } -} - void FilmViewer::start () { @@ -557,64 +433,6 @@ FilmViewer::stop () return true; } -void -FilmViewer::update_position_slider () -{ - if (!_film) { - _slider->SetValue (0); - return; - } - - DCPTime const len = _film->length (); - - if (len.get ()) { - int const new_slider_position = 4096 * _video_position.get() / len.get(); - if (new_slider_position != _slider->GetValue()) { - _slider->SetValue (new_slider_position); - } - } -} - -void -FilmViewer::update_position_label () -{ - if (!_film) { - _frame_number->SetLabel ("0"); - _timecode->SetLabel ("0:0:0.0"); - return; - } - - double const fps = _film->video_frame_rate (); - /* Count frame number from 1 ... not sure if this is the best idea */ - _frame_number->SetLabel (wxString::Format (wxT("%ld"), lrint (_video_position.seconds() * fps) + 1)); - _timecode->SetLabel (time_to_timecode (_video_position, fps)); -} - -void -FilmViewer::active_jobs_changed (optional j) -{ - /* examine content is the only job which stops the viewer working */ - bool const a = !j || *j != "examine_content"; - _slider->Enable (a); - _play_button->Enable (a); -} - -DCPTime -FilmViewer::nudge_amount (wxKeyboardState& ev) -{ - DCPTime amount = one_video_frame (); - - if (ev.ShiftDown() && !ev.ControlDown()) { - amount = DCPTime::from_seconds (1); - } else if (!ev.ShiftDown() && ev.ControlDown()) { - amount = DCPTime::from_seconds (10); - } else if (ev.ShiftDown() && ev.ControlDown()) { - amount = DCPTime::from_seconds (60); - } - - return amount; -} - void FilmViewer::go_to (DCPTime t) { @@ -631,45 +449,6 @@ FilmViewer::go_to (DCPTime t) update_position_slider (); } -void -FilmViewer::rewind_clicked (wxMouseEvent& ev) -{ - go_to(DCPTime()); - ev.Skip(); -} - -void -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)); -} - -void -FilmViewer::forward_clicked (wxKeyboardState& ev) -{ - go_to (_video_position + nudge_amount (ev)); -} - void FilmViewer::player_change (ChangeType type, int property, bool frequent) { @@ -703,28 +482,6 @@ FilmViewer::player_change (ChangeType type, int property, bool frequent) update_position_slider (); } -void -FilmViewer::setup_sensitivity () -{ - bool const c = _film && !_film->content().empty (); - - _slider->Enable (c); - _rewind_button->Enable (c); - _back_button->Enable (c); - _forward_button->Enable (c); - _play_button->Enable (c); - if (_outline_content) { - _outline_content->Enable (c); - } - _frame_number->Enable (c); - _timecode->Enable (c); - if (_jump_to_selected) { - _jump_to_selected->Enable (c); - } - - _eye->Enable (c && _film->three_d ()); -} - void FilmViewer::film_change (ChangeType type, Film::Property p) { @@ -796,32 +553,6 @@ FilmViewer::set_coalesce_player_changes (bool c) } } -void -FilmViewer::timecode_clicked () -{ - PlayheadToTimecodeDialog* dialog = new PlayheadToTimecodeDialog (this, _film->video_frame_rate ()); - if (dialog->ShowModal() == wxID_OK) { - go_to (dialog->get ()); - } - dialog->Destroy (); -} - -void -FilmViewer::frame_number_clicked () -{ - PlayheadToFrameDialog* dialog = new PlayheadToFrameDialog (this, _film->video_frame_rate ()); - if (dialog->ShowModal() == wxID_OK) { - go_to (dialog->get ()); - } - dialog->Destroy (); -} - -void -FilmViewer::jump_to_selected_clicked () -{ - Config::instance()->set_jump_to_selected (_jump_to_selected->GetValue ()); -} - void FilmViewer::seek (DCPTime t, bool accurate) { @@ -979,3 +710,13 @@ FilmViewer::show_closed_captions () { _closed_captions_dialog->Show(); } + +void +FilmViewer::back_frame (DCPTime by) +{ + if (!_film) { + return; + } + + go_to (_video_position + by); +} diff --git a/src/wx/film_viewer.h b/src/wx/film_viewer.h index 0e7da10b1..ea203d052 100644 --- a/src/wx/film_viewer.h +++ b/src/wx/film_viewer.h @@ -40,12 +40,16 @@ class ClosedCaptionsDialog; /** @class FilmViewer * @brief A wx widget to view a preview of a Film. */ -class FilmViewer : public wxPanel +class FilmViewer { public: FilmViewer (wxWindow *, bool outline_content = true, bool jump_to_selected = true); ~FilmViewer (); + wxPanel* panel () const { + return _panel; + } + void set_film (boost::shared_ptr); boost::shared_ptr film () const { return _film; @@ -75,8 +79,12 @@ public: return _playing; } - void back_frame (); - void forward_frame (); + void move (DCPTime by); + DCPTime one_video_frame () const; + void seek (DCPTime t, bool accurate); + DCPTime video_position () const { + return _video_position; + } int audio_callback (void* out, unsigned int frames); @@ -87,58 +95,31 @@ public: private: void paint_panel (); void panel_sized (wxSizeEvent &); - void slider_moved (bool page); - void slider_released (); - void play_clicked (); void timer (); void calculate_sizes (); void check_play_state (); - void active_jobs_changed (boost::optional); - void rewind_clicked (wxMouseEvent &); - void back_clicked (wxKeyboardState& s); - void forward_clicked (wxKeyboardState &); void player_change (ChangeType type, int, bool); - void update_position_label (); - void update_position_slider (); void get (); void display_player_video (); - void seek (DCPTime t, bool accurate); void refresh_panel (); - void setup_sensitivity (); void film_change (ChangeType, Film::Property); DCPTime nudge_amount (wxKeyboardState &); void timecode_clicked (); - void frame_number_clicked (); void go_to (DCPTime t); - void jump_to_selected_clicked (); void recreate_butler (); void config_changed (Config::Property); DCPTime time () const; DCPTime uncorrected_time () const; Frame average_latency () const; - DCPTime one_video_frame () const; boost::shared_ptr _film; boost::shared_ptr _player; - wxSizer* _v_sizer; /** The area that we put our image in */ wxPanel* _panel; - wxCheckBox* _outline_content; - wxChoice* _eye; - wxCheckBox* _jump_to_selected; - wxSlider* _slider; - wxButton* _rewind_button; - wxButton* _back_button; - wxButton* _forward_button; - wxStaticText* _frame_number; - wxStaticText* _timecode; - wxToggleButton* _play_button; wxTimer _timer; bool _coalesce_player_changes; std::list _pending_player_changes; - bool _slider_being_moved; - bool _was_running_before_slider; std::pair, DCPTime> _player_video; boost::shared_ptr _frame; diff --git a/src/wx/player_information.cc b/src/wx/player_information.cc index dbb394c64..36fb0e0ca 100644 --- a/src/wx/player_information.cc +++ b/src/wx/player_information.cc @@ -36,7 +36,7 @@ using boost::optional; /* This should be even */ static int const dcp_lines = 6; -PlayerInformation::PlayerInformation (wxWindow* parent, FilmViewer* viewer) +PlayerInformation::PlayerInformation (wxWindow* parent, ControlFilmViewer* viewer) : wxPanel (parent) , _viewer (viewer) , _sizer (new wxBoxSizer (wxHORIZONTAL)) diff --git a/src/wx/player_information.h b/src/wx/player_information.h index 747cd5a20..84daf020d 100644 --- a/src/wx/player_information.h +++ b/src/wx/player_information.h @@ -26,7 +26,7 @@ class FilmViewer; class PlayerInformation : public wxPanel { public: - PlayerInformation (wxWindow* parent, FilmViewer* viewer); + PlayerInformation (wxWindow* parent, ControlFilmViewer* viewer); void triggered_update (); @@ -34,7 +34,7 @@ private: void periodic_update (); - FilmViewer* _viewer; + ControlFilmViewer* _viewer; wxSizer* _sizer; wxStaticText** _dcp; wxStaticText* _dropped; diff --git a/src/wx/text_view.cc b/src/wx/text_view.cc index 2106a3dec..442335b92 100644 --- a/src/wx/text_view.cc +++ b/src/wx/text_view.cc @@ -27,7 +27,7 @@ #include "lib/string_text_file_content.h" #include "lib/text_decoder.h" #include "text_view.h" -#include "film_viewer.h" +#include "control_film_viewer.h" #include "wx_util.h" using std::list; @@ -35,7 +35,9 @@ using boost::shared_ptr; using boost::bind; using boost::dynamic_pointer_cast; -TextView::TextView (wxWindow* parent, shared_ptr film, shared_ptr content, shared_ptr text, shared_ptr decoder, FilmViewer* viewer) +TextView::TextView ( + wxWindow* parent, shared_ptr film, shared_ptr content, shared_ptr text, shared_ptr decoder, ControlFilmViewer* viewer + ) : wxDialog (parent, wxID_ANY, _("Captions"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) , _content (content) , _film_viewer (viewer) diff --git a/src/wx/text_view.h b/src/wx/text_view.h index 8cec8d284..12cbb6d08 100644 --- a/src/wx/text_view.h +++ b/src/wx/text_view.h @@ -24,13 +24,18 @@ #include class Decoder; -class FilmViewer; +class ControlFilmViewer; class TextView : public wxDialog { public: TextView ( - wxWindow *, boost::shared_ptr, boost::shared_ptr content, boost::shared_ptr caption, boost::shared_ptr, FilmViewer* viewer + wxWindow *, + boost::shared_ptr, + boost::shared_ptr content, + boost::shared_ptr caption, + boost::shared_ptr, + ControlFilmViewer* viewer ); private: @@ -44,5 +49,5 @@ private: boost::optional _last_count; std::vector _start_times; boost::weak_ptr _content; - FilmViewer* _film_viewer; + ControlFilmViewer* _film_viewer; }; diff --git a/src/wx/timing_panel.cc b/src/wx/timing_panel.cc index fac6bced9..f64a84f7a 100644 --- a/src/wx/timing_panel.cc +++ b/src/wx/timing_panel.cc @@ -44,7 +44,7 @@ using boost::dynamic_pointer_cast; using boost::optional; using dcp::locale_convert; -TimingPanel::TimingPanel (ContentPanel* p, FilmViewer* viewer) +TimingPanel::TimingPanel (ContentPanel* p, ControlFilmViewer* viewer) /* horrid hack for apparent lack of context support with wxWidgets i18n code */ /// TRANSLATORS: translate the word "Timing" here; do not include the "Timing|" prefix : ContentSubPanel (p, S_("Timing|Timing")) diff --git a/src/wx/timing_panel.h b/src/wx/timing_panel.h index 961f04a40..1a9f5d3fd 100644 --- a/src/wx/timing_panel.h +++ b/src/wx/timing_panel.h @@ -26,7 +26,7 @@ class FilmViewer; class TimingPanel : public ContentSubPanel { public: - TimingPanel (ContentPanel *, FilmViewer* viewer); + TimingPanel (ContentPanel *, ControlFilmViewer* viewer); void film_changed (Film::Property); void film_content_changed (int); @@ -48,7 +48,7 @@ private: void setup_sensitivity (); void add_to_grid (); - FilmViewer* _viewer; + ControlFilmViewer* _viewer; wxStaticText* _h_label; wxStaticText* _m_label; diff --git a/src/wx/video_waveform_dialog.cc b/src/wx/video_waveform_dialog.cc index c38dbf65d..5e3b95008 100644 --- a/src/wx/video_waveform_dialog.cc +++ b/src/wx/video_waveform_dialog.cc @@ -29,7 +29,7 @@ using std::cout; using boost::bind; using boost::weak_ptr; -VideoWaveformDialog::VideoWaveformDialog (wxWindow* parent, weak_ptr film, FilmViewer* viewer) +VideoWaveformDialog::VideoWaveformDialog (wxWindow* parent, weak_ptr film, ControlFilmViewer* viewer) : wxDialog ( parent, wxID_ANY, diff --git a/src/wx/video_waveform_dialog.h b/src/wx/video_waveform_dialog.h index aa134f7a5..1cfbb73b7 100644 --- a/src/wx/video_waveform_dialog.h +++ b/src/wx/video_waveform_dialog.h @@ -22,13 +22,13 @@ #include class VideoWaveformPlot; -class FilmViewer; +class ControlFilmViewer; class Film; class VideoWaveformDialog : public wxDialog { public: - VideoWaveformDialog (wxWindow* parent, boost::weak_ptr film, FilmViewer* viewer); + VideoWaveformDialog (wxWindow* parent, boost::weak_ptr film, ControlFilmViewer* viewer); private: void shown (wxShowEvent &); @@ -36,7 +36,7 @@ private: void contrast_changed (); void mouse_moved (int x1, int x2, int y1, int y2); - FilmViewer* _viewer; + ControlFilmViewer* _viewer; VideoWaveformPlot* _plot; wxChoice* _component; wxSlider* _contrast; diff --git a/src/wx/video_waveform_plot.cc b/src/wx/video_waveform_plot.cc index ad0498057..c3d44a0cd 100644 --- a/src/wx/video_waveform_plot.cc +++ b/src/wx/video_waveform_plot.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2015 Carl Hetherington + Copyright (C) 2015-2018 Carl Hetherington This file is part of DCP-o-matic. @@ -19,7 +19,7 @@ */ #include "video_waveform_plot.h" -#include "film_viewer.h" +#include "control_film_viewer.h" #include "wx_util.h" #include "lib/image.h" #include "lib/dcp_video.h" @@ -42,7 +42,7 @@ int const VideoWaveformPlot::_vertical_margin = 8; int const VideoWaveformPlot::_pixel_values = 4096; int const VideoWaveformPlot::_x_axis_width = 52; -VideoWaveformPlot::VideoWaveformPlot (wxWindow* parent, weak_ptr film, FilmViewer* viewer) +VideoWaveformPlot::VideoWaveformPlot (wxWindow* parent, weak_ptr film, ControlFilmViewer* viewer) : wxPanel (parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE) , _film (film) , _dirty (true) diff --git a/src/wx/video_waveform_plot.h b/src/wx/video_waveform_plot.h index 7e9dbf709..023a698a8 100644 --- a/src/wx/video_waveform_plot.h +++ b/src/wx/video_waveform_plot.h @@ -35,7 +35,7 @@ class FilmViewer; class VideoWaveformPlot : public wxPanel { public: - VideoWaveformPlot (wxWindow* parent, boost::weak_ptr film, FilmViewer* viewer); + VideoWaveformPlot (wxWindow* parent, boost::weak_ptr film, ControlFilmViewer* viewer); void set_enabled (bool e); void set_component (int c); diff --git a/src/wx/wscript b/src/wx/wscript index 7679406e6..4877a4106 100644 --- a/src/wx/wscript +++ b/src/wx/wscript @@ -47,6 +47,7 @@ sources = """ content_panel.cc content_properties_dialog.cc content_sub_panel.cc + control_film_viewer.cc closed_captions_dialog.cc dcp_panel.cc email_dialog.cc -- 2.30.2