diff options
| author | Carl Hetherington <cth@carlh.net> | 2019-03-15 00:52:56 +0000 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2019-04-08 00:22:39 +0100 |
| commit | d75f1675570dff034912934a9a446d6c45d02f80 (patch) | |
| tree | ddbd6e03b9a048332f19f00f7931299b857ec3b2 | |
| parent | b3a4d915b52e524660fd5de02250288fc5be73a0 (diff) | |
Basics of setting and storing SMPTE CPL markers.
| -rw-r--r-- | src/lib/film.cc | 35 | ||||
| -rw-r--r-- | src/lib/film.h | 8 | ||||
| -rw-r--r-- | src/wx/dcp_panel.cc | 35 | ||||
| -rw-r--r-- | src/wx/dcp_panel.h | 10 | ||||
| -rw-r--r-- | src/wx/film_editor.cc | 2 | ||||
| -rw-r--r-- | src/wx/markers_dialog.cc | 127 | ||||
| -rw-r--r-- | src/wx/markers_dialog.h | 38 | ||||
| -rw-r--r-- | src/wx/wscript | 1 |
8 files changed, 248 insertions, 8 deletions
diff --git a/src/lib/film.cc b/src/lib/film.cc index c70e82cda..eb6872367 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -403,6 +403,11 @@ Film::metadata (bool with_content_paths) const root->add_child("UploadAfterMakeDCP")->add_child_text (_upload_after_make_dcp ? "1" : "0"); root->add_child("ReencodeJ2K")->add_child_text (_reencode_j2k ? "1" : "0"); root->add_child("UserExplicitVideoFrameRate")->add_child_text(_user_explicit_video_frame_rate ? "1" : "0"); + for (map<dcp::Marker, DCPTime>::const_iterator i = _markers.begin(); i != _markers.end(); ++i) { + xmlpp::Element* m = root->add_child("Marker"); + m->set_attribute("Type", dcp::marker_to_string(i->first)); + m->add_child_text(raw_convert<string>(i->second.get())); + } _playlist->as_xml (root->add_child ("Playlist"), with_content_paths); return doc; @@ -537,6 +542,12 @@ Film::read_metadata (optional<boost::filesystem::path> path) _reencode_j2k = f.optional_bool_child("ReencodeJ2K").get_value_or(false); _user_explicit_video_frame_rate = f.optional_bool_child("UserExplicitVideoFrameRate").get_value_or(false); + BOOST_FOREACH (cxml::ConstNodePtr i, f.node_children("Marker")) { + _markers[dcp::marker_from_string(i->string_attribute("Type"))] = DCPTime(dcp::raw_convert<DCPTime::Type>(i->content())); + } + + list<string> notes; + /* This method is the only one that can return notes (so far) */ _playlist->set_from_xml (shared_from_this(), f.node_child ("Playlist"), _state_version, notes); /* Write backtraces to this film's directory, until another film is loaded */ @@ -1680,3 +1691,27 @@ Film::closed_caption_tracks () const return tt; } + +void +Film::set_marker (dcp::Marker type, DCPTime time) +{ + ChangeSignaller<Film> ch (this, MARKERS); + _markers[type] = time; +} + +void +Film::unset_marker (dcp::Marker type) +{ + ChangeSignaller<Film> ch (this, MARKERS); + _markers.erase (type); +} + +optional<DCPTime> +Film::marker (dcp::Marker type) const +{ + map<dcp::Marker, DCPTime>::const_iterator i = _markers.find (type); + if (i == _markers.end()) { + return optional<DCPTime>(); + } + return i->second; +} diff --git a/src/lib/film.h b/src/lib/film.h index b77ce7a76..dd69c9e68 100644 --- a/src/lib/film.h +++ b/src/lib/film.h @@ -200,7 +200,8 @@ public: REEL_TYPE, REEL_LENGTH, UPLOAD_AFTER_MAKE_DCP, - REENCODE_J2K + REENCODE_J2K, + MARKERS }; @@ -296,6 +297,7 @@ public: return _reencode_j2k; } + boost::optional<DCPTime> marker (dcp::Marker type) const; /* SET */ @@ -327,6 +329,8 @@ public: void set_reel_length (int64_t); void set_upload_after_make_dcp (bool); void set_reencode_j2k (bool); + void set_marker (dcp::Marker type, DCPTime time); + void unset_marker (dcp::Marker type); /** Emitted when some property has of the Film is about to change or has changed */ mutable boost::signals2::signal<void (ChangeType, Property)> Change; @@ -406,6 +410,7 @@ private: bool _reencode_j2k; /** true if the user has ever explicitly set the video frame rate of this film */ bool _user_explicit_video_frame_rate; + std::map<dcp::Marker, DCPTime> _markers; int _state_version; @@ -414,7 +419,6 @@ private: /** film being used as a template, or 0 */ boost::shared_ptr<Film> _template_film; - boost::signals2::scoped_connection _playlist_change_connection; boost::signals2::scoped_connection _playlist_order_changed_connection; boost::signals2::scoped_connection _playlist_content_change_connection; diff --git a/src/wx/dcp_panel.cc b/src/wx/dcp_panel.cc index 3defe75e4..85ed81e46 100644 --- a/src/wx/dcp_panel.cc +++ b/src/wx/dcp_panel.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2018 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2019 Carl Hetherington <cth@carlh.net> This file is part of DCP-o-matic. @@ -28,6 +28,7 @@ #include "static_text.h" #include "check_box.h" #include "dcpomatic_button.h" +#include "markers_dialog.h" #include "lib/ratio.h" #include "lib/config.h" #include "lib/dcp_content_type.h" @@ -58,11 +59,14 @@ using std::max; using std::make_pair; using boost::lexical_cast; using boost::shared_ptr; +using boost::weak_ptr; using dcp::locale_convert; -DCPPanel::DCPPanel (wxNotebook* n, boost::shared_ptr<Film> film) +DCPPanel::DCPPanel (wxNotebook* n, shared_ptr<Film> film, weak_ptr<FilmViewer> viewer) : _audio_dialog (0) + , _markers_dialog (0) , _film (film) + , _viewer (viewer) , _generally_sensitive (true) { _panel = new wxPanel (n); @@ -114,6 +118,8 @@ DCPPanel::DCPPanel (wxNotebook* n, boost::shared_ptr<Film> film) _upload_after_make_dcp = new CheckBox (_panel, _("Upload DCP to TMS after it is made")); + _markers = new Button (_panel, _("Edit markers...")); + _notebook = new wxNotebook (_panel, wxID_ANY); _sizer->Add (_notebook, 1, wxEXPAND | wxTOP, 6); @@ -132,6 +138,7 @@ DCPPanel::DCPPanel (wxNotebook* n, boost::shared_ptr<Film> film) _reel_length->Bind (wxEVT_SPINCTRL, boost::bind (&DCPPanel::reel_length_changed, this)); _standard->Bind (wxEVT_CHOICE, boost::bind (&DCPPanel::standard_changed, this)); _upload_after_make_dcp->Bind (wxEVT_CHECKBOX, boost::bind (&DCPPanel::upload_after_make_dcp_changed, this)); + _markers->Bind (wxEVT_BUTTON, boost::bind (&DCPPanel::markers_clicked, this)); BOOST_FOREACH (DCPContentType const * i, DCPContentType::all()) { _dcp_content_type->Append (std_to_wx (i->pretty_name ())); @@ -213,6 +220,7 @@ DCPPanel::add_to_grid () _standard_label->Show (full); _standard->Show (full); _upload_after_make_dcp->Show (full); + _markers->Show (full); _reencode_j2k->Show (full); _encrypted->Show (full); @@ -245,6 +253,9 @@ DCPPanel::add_to_grid () _grid->Add (_upload_after_make_dcp, wxGBPosition (r, 0), wxGBSpan (1, 2)); ++r; + + _grid->Add (_markers, wxGBPosition(r, 0), wxGBSpan(1, 2)); + ++r; } } @@ -366,6 +377,18 @@ DCPPanel::upload_after_make_dcp_changed () } void +DCPPanel::markers_clicked () +{ + if (_markers_dialog) { + _markers_dialog->Destroy (); + _markers_dialog = 0; + } + + _markers_dialog = new MarkersDialog (_panel, _film, _viewer); + _markers_dialog->Show(); +} + +void DCPPanel::film_changed (int p) { switch (p) { @@ -458,6 +481,7 @@ DCPPanel::film_changed (int p) case Film::INTEROP: checked_set (_standard, _film->interop() ? 1 : 0); setup_dcp_name (); + _markers->Enable (!_film->interop()); break; case Film::AUDIO_PROCESSOR: if (_film->audio_processor ()) { @@ -558,11 +582,15 @@ DCPPanel::dcp_content_type_changed () void DCPPanel::set_film (shared_ptr<Film> film) { - /* We are changing film, so destroy any audio dialog for the old one */ + /* We are changing film, so destroy any dialogs for the old one */ if (_audio_dialog) { _audio_dialog->Destroy (); _audio_dialog = 0; } + if (_markers_dialog) { + _markers_dialog->Destroy (); + _markers_dialog = 0; + } _film = film; @@ -626,6 +654,7 @@ DCPPanel::setup_sensitivity () _reel_type->Enable (_generally_sensitive && _film && !_film->references_dcp_video() && !_film->references_dcp_audio()); _reel_length->Enable (_generally_sensitive && _film && _film->reel_type() == REELTYPE_BY_LENGTH); _upload_after_make_dcp->Enable (_generally_sensitive); + _markers->Enable (_generally_sensitive); _frame_rate_choice->Enable (_generally_sensitive && _film && !_film->references_dcp_video()); _frame_rate_spin->Enable (_generally_sensitive && _film && !_film->references_dcp_video()); _audio_channels->Enable (_generally_sensitive && _film && !_film->references_dcp_audio()); diff --git a/src/wx/dcp_panel.h b/src/wx/dcp_panel.h index c43311429..27049962c 100644 --- a/src/wx/dcp_panel.h +++ b/src/wx/dcp_panel.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2018 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2019 Carl Hetherington <cth@carlh.net> This file is part of DCP-o-matic. @@ -35,13 +35,15 @@ class wxSizer; class wxGridBagSizer; class AudioDialog; +class MarkersDialog; class Film; +class FilmViewer; class Ratio; class DCPPanel : public boost::noncopyable { public: - DCPPanel (wxNotebook *, boost::shared_ptr<Film>); + DCPPanel (wxNotebook *, boost::shared_ptr<Film>, boost::weak_ptr<FilmViewer> viewer); void set_film (boost::shared_ptr<Film>); void set_general_sensitivity (bool); @@ -77,6 +79,7 @@ private: void reel_type_changed (); void reel_length_changed (); void upload_after_make_dcp_changed (); + void markers_clicked (); void reencode_j2k_changed (); void setup_frame_rate_widget (); @@ -144,9 +147,12 @@ private: wxStaticText* _reel_length_gb_label; wxSpinCtrl* _reel_length; wxCheckBox* _upload_after_make_dcp; + wxButton* _markers; AudioDialog* _audio_dialog; + MarkersDialog* _markers_dialog; boost::shared_ptr<Film> _film; + boost::weak_ptr<FilmViewer> _viewer; bool _generally_sensitive; }; diff --git a/src/wx/film_editor.cc b/src/wx/film_editor.cc index a017175f5..ae0868f27 100644 --- a/src/wx/film_editor.cc +++ b/src/wx/film_editor.cc @@ -52,7 +52,7 @@ FilmEditor::FilmEditor (wxWindow* parent, weak_ptr<FilmViewer> viewer) _content_panel = new ContentPanel (_main_notebook, _film, viewer); _main_notebook->AddPage (_content_panel->window(), _("Content"), true); - _dcp_panel = new DCPPanel (_main_notebook, _film); + _dcp_panel = new DCPPanel (_main_notebook, _film, viewer); _main_notebook->AddPage (_dcp_panel->panel (), _("DCP"), false); JobManager::instance()->ActiveJobsChanged.connect ( diff --git a/src/wx/markers_dialog.cc b/src/wx/markers_dialog.cc new file mode 100644 index 000000000..724cb7d9e --- /dev/null +++ b/src/wx/markers_dialog.cc @@ -0,0 +1,127 @@ +/* + Copyright (C) 2019 Carl Hetherington <cth@carlh.net> + + This file is part of DCP-o-matic. + + DCP-o-matic is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DCP-o-matic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "markers_dialog.h" +#include "wx_util.h" +#include "timecode.h" +#include "static_text.h" +#include "dcpomatic_button.h" +#include "check_box.h" +#include "film_viewer.h" +#include "lib/film.h" +#include <dcp/types.h> +#include <wx/gbsizer.h> +#include <boost/bind.hpp> +#include <iostream> + +using std::cout; +using boost::bind; +using boost::shared_ptr; +using boost::weak_ptr; +using boost::optional; + +class Marker +{ +public: + Marker (wxWindow* parent, wxGridBagSizer* grid, int row, weak_ptr<Film> film_, weak_ptr<FilmViewer> viewer_, wxString name, dcp::Marker type_) + : film (film_) + , viewer (viewer_) + , type (type_) + { + checkbox = new CheckBox(parent, name); + grid->Add (checkbox, wxGBPosition(row, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL); + timecode = new Timecode<DCPTime> (parent); + grid->Add (timecode, wxGBPosition(row, 1)); + set_button = new Button (parent, _("Set from current position")); + grid->Add (set_button, wxGBPosition(row, 2)); + + shared_ptr<Film> f = film.lock (); + DCPOMATIC_ASSERT (f); + + optional<DCPTime> t = f->marker (type); + checkbox->SetValue (static_cast<bool>(t)); + if (t) { + timecode->set (*t, f->video_frame_rate()); + } + + set_sensitivity (); + + set_button->Bind (wxEVT_BUTTON, bind(&Marker::set, this)); + checkbox->Bind (wxEVT_CHECKBOX, bind(&Marker::set_sensitivity, this)); + timecode->Changed.connect (bind(&Marker::changed, this)); + } + +private: + void set_sensitivity () + { + timecode->Enable (checkbox->GetValue()); + set_button->Enable (checkbox->GetValue()); + } + + void set () + { + shared_ptr<Film> f = film.lock (); + DCPOMATIC_ASSERT (f); + shared_ptr<FilmViewer> v = viewer.lock (); + DCPOMATIC_ASSERT (v); + timecode->set (v->position(), f->video_frame_rate()); + } + + void changed () + { + shared_ptr<Film> f = film.lock (); + DCPOMATIC_ASSERT (f); + if (checkbox->GetValue()) { + f->set_marker (type, timecode->get(f->video_frame_rate())); + } else { + f->unset_marker (type); + } + } + + weak_ptr<Film> film; + weak_ptr<FilmViewer> viewer; + dcp::Marker type; + CheckBox* checkbox; + Timecode<DCPTime>* timecode; + Button* set_button; +}; + +MarkersDialog::MarkersDialog (wxWindow* parent, weak_ptr<Film> film, weak_ptr<FilmViewer> viewer) + : wxDialog (parent, wxID_ANY, _("Markers")) + , _film (film) +{ + wxSizer* sizer = new wxBoxSizer (wxVERTICAL); + wxGridBagSizer* grid = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP); + + int r = 0; + _markers.push_back (shared_ptr<Marker>(new Marker(this, grid, r++, film, viewer, _("First frame of composition"), dcp::FFOC))); + _markers.push_back (shared_ptr<Marker>(new Marker(this, grid, r++, film, viewer, _("Last frame of composition"), dcp::LFOC))); + _markers.push_back (shared_ptr<Marker>(new Marker(this, grid, r++, film, viewer, _("First frame of title credits"), dcp::FFTC))); + _markers.push_back (shared_ptr<Marker>(new Marker(this, grid, r++, film, viewer, _("Last frame of title credits"), dcp::LFTC))); + _markers.push_back (shared_ptr<Marker>(new Marker(this, grid, r++, film, viewer, _("First frame of intermission"), dcp::FFOI))); + _markers.push_back (shared_ptr<Marker>(new Marker(this, grid, r++, film, viewer, _("Last frame of intermission"), dcp::LFOI))); + _markers.push_back (shared_ptr<Marker>(new Marker(this, grid, r++, film, viewer, _("First frame of end credits"), dcp::FFEC))); + _markers.push_back (shared_ptr<Marker>(new Marker(this, grid, r++, film, viewer, _("Last frame of end credits"), dcp::LFEC))); + _markers.push_back (shared_ptr<Marker>(new Marker(this, grid, r++, film, viewer, _("First frame of moving credits"), dcp::FFMC))); + _markers.push_back (shared_ptr<Marker>(new Marker(this, grid, r++, film, viewer, _("Last frame of moving credits"), dcp::LFMC))); + + sizer->Add (grid, 0, wxALL, 8); + SetSizerAndFit (sizer); +} diff --git a/src/wx/markers_dialog.h b/src/wx/markers_dialog.h new file mode 100644 index 000000000..fbbaa1aee --- /dev/null +++ b/src/wx/markers_dialog.h @@ -0,0 +1,38 @@ +/* + Copyright (C) 2019 Carl Hetherington <cth@carlh.net> + + This file is part of DCP-o-matic. + + DCP-o-matic is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DCP-o-matic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include <wx/wx.h> +#include <boost/shared_ptr.hpp> +#include <boost/weak_ptr.hpp> +#include <list> + +class Marker; +class Film; +class FilmViewer; + +class MarkersDialog : public wxDialog +{ +public: + MarkersDialog (wxWindow* parent, boost::weak_ptr<Film> film, boost::weak_ptr<FilmViewer> viewer); + +private: + std::list<boost::shared_ptr<Marker> > _markers; + boost::weak_ptr<Film> _film; +}; diff --git a/src/wx/wscript b/src/wx/wscript index 183466106..7f953df49 100644 --- a/src/wx/wscript +++ b/src/wx/wscript @@ -84,6 +84,7 @@ sources = """ kdm_timing_panel.cc key_dialog.cc make_chain_dialog.cc + markers_dialog.cc message_dialog.cc monitor_dialog.cc move_to_dialog.cc |
