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;
_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 */
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;
+}
REEL_TYPE,
REEL_LENGTH,
UPLOAD_AFTER_MAKE_DCP,
- REENCODE_J2K
+ REENCODE_J2K,
+ MARKERS
};
return _reencode_j2k;
}
+ boost::optional<DCPTime> marker (dcp::Marker type) const;
/* SET */
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;
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;
/** 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;
/*
- 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.
#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"
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);
_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);
_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 ()));
_standard_label->Show (full);
_standard->Show (full);
_upload_after_make_dcp->Show (full);
+ _markers->Show (full);
_reencode_j2k->Show (full);
_encrypted->Show (full);
_grid->Add (_upload_after_make_dcp, wxGBPosition (r, 0), wxGBSpan (1, 2));
++r;
+
+ _grid->Add (_markers, wxGBPosition(r, 0), wxGBSpan(1, 2));
+ ++r;
}
}
_film->set_upload_after_make_dcp (_upload_after_make_dcp->GetValue ());
}
+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)
{
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 ()) {
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;
_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());
/*
- 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.
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);
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 ();
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;
};
_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 (
--- /dev/null
+/*
+ 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);
+}
--- /dev/null
+/*
+ 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;
+};
kdm_timing_panel.cc
key_dialog.cc
make_chain_dialog.cc
+ markers_dialog.cc
message_dialog.cc
monitor_dialog.cc
move_to_dialog.cc