summaryrefslogtreecommitdiff
path: root/src/wx
diff options
context:
space:
mode:
Diffstat (limited to 'src/wx')
-rw-r--r--src/wx/about_dialog.cc3
-rw-r--r--src/wx/audio_panel.cc57
-rw-r--r--src/wx/audio_panel.h3
-rw-r--r--src/wx/check_box.cc7
-rw-r--r--src/wx/check_box.h1
-rw-r--r--src/wx/cinema_dialog.cc42
-rw-r--r--src/wx/cinema_dialog.h8
-rw-r--r--src/wx/content_sub_panel.cc23
-rw-r--r--src/wx/content_sub_panel.h1
-rw-r--r--src/wx/dcp_panel.cc37
-rw-r--r--src/wx/dcp_referencing_dialog.cc231
-rw-r--r--src/wx/dcp_referencing_dialog.h70
-rw-r--r--src/wx/dkdm_dialog.cc2
-rw-r--r--src/wx/film_editor.cc33
-rw-r--r--src/wx/film_editor.h8
-rw-r--r--src/wx/full_config_dialog.cc6
-rw-r--r--src/wx/grok/gpu_config_panel.h227
-rw-r--r--src/wx/kdm_timing_panel.cc57
-rw-r--r--src/wx/kdm_timing_panel.h20
-rw-r--r--src/wx/screens_panel.cc8
-rw-r--r--src/wx/text_panel.cc53
-rw-r--r--src/wx/text_panel.h3
-rw-r--r--src/wx/video_panel.cc56
-rw-r--r--src/wx/video_panel.h3
-rw-r--r--src/wx/wscript1
25 files changed, 675 insertions, 285 deletions
diff --git a/src/wx/about_dialog.cc b/src/wx/about_dialog.cc
index adbe2eb7b..59760be98 100644
--- a/src/wx/about_dialog.cc
+++ b/src/wx/about_dialog.cc
@@ -86,7 +86,7 @@ AboutDialog::AboutDialog (wxWindow* parent)
t = new StaticText (
this,
- _("(C) 2012-2024 Carl Hetherington, Terrence Meiczinger\n Ole Laursen"),
+ _("(C) 2012-2024 Carl Hetherington, Terrence Meiczinger\nOle Laursen, Aaron Boxer"),
wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER
);
@@ -99,6 +99,7 @@ AboutDialog::AboutDialog (wxWindow* parent)
written_by.Add (wxT ("Terrence Meiczinger"));
written_by.Add (wxT ("Mart Jansink"));
written_by.Add (wxT ("Ole Laursen"));
+ written_by.Add (wxT ("Aaron Boxer"));
add_section (_("Written by"), written_by);
wxArrayString with_help_from;
diff --git a/src/wx/audio_panel.cc b/src/wx/audio_panel.cc
index f0863431a..d7deeec41 100644
--- a/src/wx/audio_panel.cc
+++ b/src/wx/audio_panel.cc
@@ -71,14 +71,6 @@ AudioPanel::AudioPanel (ContentPanel* p)
void
AudioPanel::create ()
{
- _reference = new CheckBox (this, _("Use this DCP's audio as OV and make VF"));
- _reference_note = new StaticText (this, wxT(""));
- _reference_note->Wrap (200);
- auto font = _reference_note->GetFont();
- font.SetStyle(wxFONTSTYLE_ITALIC);
- font.SetPointSize(font.GetPointSize() - 1);
- _reference_note->SetFont(font);
-
_show = new Button (this, _("Show graph of audio levels..."));
_peak = new StaticText (this, wxT (""));
@@ -121,6 +113,9 @@ AudioPanel::create ()
_description = new StaticText (this, wxT(" \n"), wxDefaultPosition, wxDefaultSize);
_sizer->Add (_description, 0, wxALL, 12);
+ auto font = _description->GetFont();
+ font.SetStyle(wxFONTSTYLE_ITALIC);
+ font.SetPointSize(font.GetPointSize() - 1);
_description->SetFont (font);
_gain->wrapped()->SetRange (-60, 60);
@@ -133,7 +128,6 @@ AudioPanel::create ()
film_changed(FilmProperty::VIDEO_FRAME_RATE);
film_changed(FilmProperty::REEL_TYPE);
- _reference->bind(&AudioPanel::reference_clicked, this);
_show->Bind (wxEVT_BUTTON, boost::bind (&AudioPanel::show_clicked, this));
_gain_calculate_button->Bind (wxEVT_BUTTON, boost::bind (&AudioPanel::gain_calculate_button_clicked, this));
@@ -155,12 +149,6 @@ AudioPanel::add_to_grid ()
{
int r = 0;
- auto reference_sizer = new wxBoxSizer (wxVERTICAL);
- reference_sizer->Add (_reference, 0);
- reference_sizer->Add (_reference_note, 0);
- _grid->Add (reference_sizer, wxGBPosition(r, 0), wxGBSpan(1, 4));
- ++r;
-
_grid->Add (_show, wxGBPosition (r, 0), wxGBSpan (1, 2));
_grid->Add (_peak, wxGBPosition (r, 2), wxGBSpan (1, 2), wxALIGN_CENTER_VERTICAL);
++r;
@@ -257,15 +245,6 @@ AudioPanel::film_content_changed (int property)
/* This is a bit aggressive but probably not so bad */
_peak_cache.clear();
setup_peak ();
- } else if (property == DCPContentProperty::REFERENCE_AUDIO) {
- if (ac.size() == 1) {
- shared_ptr<DCPContent> dcp = dynamic_pointer_cast<DCPContent> (ac.front ());
- checked_set (_reference, dcp ? dcp->reference_audio () : false);
- } else {
- checked_set (_reference, false);
- }
-
- setup_sensitivity ();
} else if (property == ContentProperty::VIDEO_FRAME_RATE) {
setup_description ();
} else if (property == AudioContentProperty::FADE_IN) {
@@ -383,19 +362,8 @@ AudioPanel::setup_sensitivity ()
dcp = dynamic_pointer_cast<DCPContent> (sel.front ());
}
- string why_not;
- bool const can_reference = dcp && dcp->can_reference_audio (_parent->film(), why_not);
- wxString cannot;
- if (why_not.empty()) {
- cannot = _("Cannot reference this DCP's audio.");
- } else {
- cannot = _("Cannot reference this DCP's audio: ") + std_to_wx(why_not);
- }
- setup_refer_button (_reference, _reference_note, dcp, can_reference, cannot);
-
- auto const ref = _reference->GetValue();
+ auto const ref = dcp && dcp->reference_audio();
auto const single = sel.size() == 1;
-
auto const all_have_video = std::all_of(sel.begin(), sel.end(), [](shared_ptr<const Content> c) { return static_cast<bool>(c->video); });
_gain->wrapped()->Enable (!ref);
@@ -500,23 +468,6 @@ AudioPanel::active_jobs_changed (optional<string> old_active, optional<string> n
void
-AudioPanel::reference_clicked ()
-{
- auto c = _parent->selected ();
- if (c.size() != 1) {
- return;
- }
-
- auto d = dynamic_pointer_cast<DCPContent>(c.front());
- if (!d) {
- return;
- }
-
- d->set_reference_audio (_reference->GetValue ());
-}
-
-
-void
AudioPanel::set_film (shared_ptr<Film>)
{
/* We are changing film, so destroy any audio dialog for the old one */
diff --git a/src/wx/audio_panel.h b/src/wx/audio_panel.h
index 61dd2783a..d25f7e247 100644
--- a/src/wx/audio_panel.h
+++ b/src/wx/audio_panel.h
@@ -54,15 +54,12 @@ private:
void setup_peak ();
void active_jobs_changed (boost::optional<std::string>, boost::optional<std::string>);
void setup_sensitivity ();
- void reference_clicked ();
void add_to_grid () override;
boost::optional<float> peak () const;
void fade_in_changed ();
void fade_out_changed ();
void use_same_fades_as_video_changed ();
- CheckBox* _reference;
- wxStaticText* _reference_note;
wxButton* _show;
wxStaticText* _gain_label;
wxStaticText* _gain_db_label;
diff --git a/src/wx/check_box.cc b/src/wx/check_box.cc
index baec651c1..c18ceba47 100644
--- a/src/wx/check_box.cc
+++ b/src/wx/check_box.cc
@@ -53,3 +53,10 @@ CheckBox::get() const
return GetValue();
}
+
+void
+CheckBox::set(bool state)
+{
+ SetValue(state);
+}
+
diff --git a/src/wx/check_box.h b/src/wx/check_box.h
index 4b3fddb9f..d9feb00c9 100644
--- a/src/wx/check_box.h
+++ b/src/wx/check_box.h
@@ -39,6 +39,7 @@ public:
void set_text (wxString text) override;
wxString get_text () const override;
bool get() const;
+ void set(bool state);
template <typename... Args>
void bind(Args... args) {
diff --git a/src/wx/cinema_dialog.cc b/src/wx/cinema_dialog.cc
index 84fde5f41..771a59892 100644
--- a/src/wx/cinema_dialog.cc
+++ b/src/wx/cinema_dialog.cc
@@ -36,7 +36,7 @@ using namespace boost::placeholders;
#endif
-CinemaDialog::CinemaDialog(wxWindow* parent, wxString title, string name, vector<string> emails, string notes, int utc_offset_hour, int utc_offset_minute)
+CinemaDialog::CinemaDialog(wxWindow* parent, wxString title, string name, vector<string> emails, string notes)
: wxDialog (parent, wxID_ANY, title)
{
auto overall_sizer = new wxBoxSizer (wxVERTICAL);
@@ -50,11 +50,6 @@ CinemaDialog::CinemaDialog(wxWindow* parent, wxString title, string name, vector
sizer->Add (_name, wxGBPosition(r, 1));
++r;
- add_label_to_sizer (sizer, this, _("UTC offset (time zone)"), true, wxGBPosition(r, 0));
- _utc_offset = new wxChoice (this, wxID_ANY);
- sizer->Add (_utc_offset, wxGBPosition(r, 1));
- ++r;
-
add_label_to_sizer (sizer, this, _("Notes"), true, wxGBPosition(r, 0));
_notes = new wxTextCtrl (this, wxID_ANY, std_to_wx(notes), wxDefaultPosition, wxSize(500, -1));
sizer->Add (_notes, wxGBPosition(r, 1));
@@ -83,17 +78,6 @@ CinemaDialog::CinemaDialog(wxWindow* parent, wxString title, string name, vector
overall_sizer->Add (buttons, wxSizerFlags().Expand().DoubleBorder());
}
- /* Default to UTC */
- size_t sel = get_offsets (_offsets);
- for (size_t i = 0; i < _offsets.size(); ++i) {
- _utc_offset->Append (_offsets[i].name);
- if (_offsets[i].hour == utc_offset_hour && _offsets[i].minute == utc_offset_minute) {
- sel = i;
- }
- }
-
- _utc_offset->SetSelection (sel);
-
overall_sizer->Layout ();
overall_sizer->SetSizeHints (this);
@@ -122,30 +106,6 @@ CinemaDialog::emails() const
}
-int
-CinemaDialog::utc_offset_hour () const
-{
- int const sel = _utc_offset->GetSelection();
- if (sel < 0 || sel > int(_offsets.size())) {
- return 0;
- }
-
- return _offsets[sel].hour;
-}
-
-
-int
-CinemaDialog::utc_offset_minute () const
-{
- int const sel = _utc_offset->GetSelection();
- if (sel < 0 || sel > int(_offsets.size())) {
- return 0;
- }
-
- return _offsets[sel].minute;
-}
-
-
string
CinemaDialog::notes () const
{
diff --git a/src/wx/cinema_dialog.h b/src/wx/cinema_dialog.h
index 0b8362843..cd90f6dea 100644
--- a/src/wx/cinema_dialog.h
+++ b/src/wx/cinema_dialog.h
@@ -38,16 +38,12 @@ public:
wxString,
std::string name = "",
std::vector<std::string> emails = std::vector<std::string>(),
- std::string notes = "",
- int utc_offset_hour = 0,
- int utc_offset_minute = 0
+ std::string notes = ""
);
std::string name () const;
std::string notes () const;
std::vector<std::string> emails () const;
- int utc_offset_hour () const;
- int utc_offset_minute () const;
private:
void set_emails (std::vector<std::string>);
@@ -56,6 +52,4 @@ private:
wxTextCtrl* _notes;
EditableList<std::string, EmailDialog>* _email_list;
std::vector<std::string> _emails;
- wxChoice* _utc_offset;
- std::vector<Offset> _offsets;
};
diff --git a/src/wx/content_sub_panel.cc b/src/wx/content_sub_panel.cc
index 6bbc9a51f..10fdfa232 100644
--- a/src/wx/content_sub_panel.cc
+++ b/src/wx/content_sub_panel.cc
@@ -53,29 +53,6 @@ ContentSubPanel::ContentSubPanel (ContentPanel* p, wxString name)
}
void
-ContentSubPanel::setup_refer_button (wxCheckBox* button, wxStaticText* note, shared_ptr<DCPContent> dcp, bool can_reference, wxString cannot)
-{
- button->Enable (can_reference);
-
- if (dcp && !can_reference) {
- note->SetLabel (cannot);
- } else {
- note->SetLabel (wxT(""));
- }
-
- note->Wrap (400);
-
- if (cannot.IsEmpty()) {
- note->Hide ();
- } else {
- note->Show ();
- }
-
- layout ();
-}
-
-
-void
ContentSubPanel::layout ()
{
int x;
diff --git a/src/wx/content_sub_panel.h b/src/wx/content_sub_panel.h
index a3916817e..48970e6a9 100644
--- a/src/wx/content_sub_panel.h
+++ b/src/wx/content_sub_panel.h
@@ -55,7 +55,6 @@ public:
protected:
- void setup_refer_button (wxCheckBox* button, wxStaticText* note, std::shared_ptr<DCPContent> dcp, bool can_reference, wxString cannot);
void layout ();
virtual void add_to_grid () = 0;
diff --git a/src/wx/dcp_panel.cc b/src/wx/dcp_panel.cc
index f4ba74cde..d81e7bf95 100644
--- a/src/wx/dcp_panel.cc
+++ b/src/wx/dcp_panel.cc
@@ -97,10 +97,6 @@ DCPPanel::DCPPanel(wxNotebook* n, shared_ptr<Film> film, FilmViewer& viewer)
wxALIGN_CENTRE_HORIZONTAL | wxST_NO_AUTORESIZE | wxST_ELLIPSIZE_MIDDLE
);
- _enable_audio_language = new CheckBox(_panel, _("Audio language"));
- _audio_language = new wxStaticText (_panel, wxID_ANY, wxT(""));
- _edit_audio_language = new Button (_panel, _("Edit..."));
-
_dcp_content_type_label = create_label (_panel, _("Content Type"), true);
_dcp_content_type = new Choice(_panel);
@@ -139,9 +135,6 @@ DCPPanel::DCPPanel(wxNotebook* n, shared_ptr<Film> film, FilmViewer& viewer)
_standard->Bind (wxEVT_CHOICE, boost::bind(&DCPPanel::standard_changed, this));
_markers->Bind (wxEVT_BUTTON, boost::bind(&DCPPanel::markers_clicked, this));
_metadata->Bind (wxEVT_BUTTON, boost::bind(&DCPPanel::metadata_clicked, this));
- _enable_audio_language->bind(&DCPPanel::enable_audio_language_toggled, this);
- _edit_audio_language->Bind (wxEVT_BUTTON, boost::bind(&DCPPanel::edit_audio_language_clicked, this));
-
for (auto i: DCPContentType::all()) {
_dcp_content_type->add(i->pretty_name());
}
@@ -155,7 +148,7 @@ DCPPanel::DCPPanel(wxNotebook* n, shared_ptr<Film> film, FilmViewer& viewer)
_reel_length->SetRange (1, 64);
add_standards();
- _standard->SetToolTip(_("Which standard the DCP should use. Interop is older and SMPTE is the modern standard. If in doubt, choose 'SMPTE'"));
+ _standard->SetToolTip(_("The standard that the DCP should use. Interop is older, and SMPTE is the newer (current) standard. If in doubt, choose 'SMPTE'"));
Config::instance()->Changed.connect (boost::bind(&DCPPanel::config_changed, this, _1));
@@ -241,15 +234,6 @@ DCPPanel::add_to_grid ()
_grid->Add (_dcp_name, wxGBPosition(r, 0), wxGBSpan(1, 2), wxALIGN_CENTER_VERTICAL | wxEXPAND);
++r;
- {
- auto s = new wxBoxSizer (wxHORIZONTAL);
- s->Add (_enable_audio_language, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, DCPOMATIC_SIZER_GAP);
- s->Add (_audio_language, 1, wxALIGN_CENTER_VERTICAL | wxBOTTOM, DCPOMATIC_CHECKBOX_BOTTOM_PAD);
- s->Add (_edit_audio_language, 0, wxALIGN_CENTER_VERTICAL | wxBOTTOM, DCPOMATIC_CHECKBOX_BOTTOM_PAD);
- _grid->Add (s, wxGBPosition(r, 0), wxGBSpan(1, 2), wxEXPAND | wxALIGN_CENTER_VERTICAL);
- }
- ++r;
-
add_label_to_sizer (_grid, _dcp_content_type_label, true, wxGBPosition(r, 0));
_grid->Add (_dcp_content_type, wxGBPosition(r, 1));
++r;
@@ -511,6 +495,7 @@ DCPPanel::film_changed(FilmProperty p)
checked_set (_audio_language, al ? std_to_wx(al->to_string()) : wxT(""));
setup_dcp_name ();
setup_sensitivity ();
+ _audio_panel_sizer->Layout();
break;
}
case FilmProperty::AUDIO_FRAME_RATE:
@@ -953,6 +938,10 @@ DCPPanel::make_audio_panel ()
_audio_processor = new Choice(panel);
add_audio_processors ();
+ _enable_audio_language = new CheckBox(panel, _("Language"));
+ _audio_language = new wxStaticText(panel, wxID_ANY, wxT(""));
+ _edit_audio_language = new Button(panel, _("Edit..."));
+
_show_audio = new Button (panel, _("Show graph of audio levels..."));
_audio_channels->Bind (wxEVT_CHOICE, boost::bind (&DCPPanel::audio_channels_changed, this));
@@ -960,6 +949,10 @@ DCPPanel::make_audio_panel ()
_audio_sample_rate->Bind (wxEVT_CHOICE, boost::bind(&DCPPanel::audio_sample_rate_changed, this));
}
_audio_processor->Bind (wxEVT_CHOICE, boost::bind (&DCPPanel::audio_processor_changed, this));
+
+ _enable_audio_language->bind(&DCPPanel::enable_audio_language_toggled, this);
+ _edit_audio_language->Bind(wxEVT_BUTTON, boost::bind(&DCPPanel::edit_audio_language_clicked, this));
+
_show_audio->Bind (wxEVT_BUTTON, boost::bind (&DCPPanel::show_audio_clicked, this));
if (_audio_sample_rate) {
@@ -992,6 +985,16 @@ DCPPanel::add_audio_panel_to_grid ()
_audio_grid->Add (_audio_processor, wxGBPosition (r, 1));
++r;
+ {
+ auto s = new wxBoxSizer (wxHORIZONTAL);
+ s->Add(_enable_audio_language, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, DCPOMATIC_SIZER_GAP);
+ s->Add(_audio_language, 1, wxALIGN_CENTER_VERTICAL | wxBOTTOM, DCPOMATIC_CHECKBOX_BOTTOM_PAD);
+ s->Add(DCPOMATIC_SIZER_X_GAP, 0);
+ s->Add(_edit_audio_language, 0, wxALIGN_CENTER_VERTICAL | wxBOTTOM, DCPOMATIC_CHECKBOX_BOTTOM_PAD);
+ _audio_grid->Add(s, wxGBPosition(r, 0), wxGBSpan(1, 2), wxEXPAND | wxALIGN_CENTER_VERTICAL);
+ }
+ ++r;
+
_audio_grid->Add (_show_audio, wxGBPosition (r, 0), wxGBSpan (1, 2));
++r;
}
diff --git a/src/wx/dcp_referencing_dialog.cc b/src/wx/dcp_referencing_dialog.cc
new file mode 100644
index 000000000..853391bd3
--- /dev/null
+++ b/src/wx/dcp_referencing_dialog.cc
@@ -0,0 +1,231 @@
+/*
+ Copyright (C) 2023 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 "check_box.h"
+#include "dcp_referencing_dialog.h"
+#include "static_text.h"
+#include "wx_util.h"
+#include "lib/dcp_content.h"
+#include "lib/film.h"
+#include "lib/types.h"
+#include <wx/gbsizer.h>
+#include <wx/wx.h>
+
+
+using std::dynamic_pointer_cast;
+using std::shared_ptr;
+using std::string;
+using std::vector;
+using std::weak_ptr;
+#if BOOST_VERSION >= 106100
+using namespace boost::placeholders;
+#endif
+
+
+DCPReferencingDialog::DCPReferencingDialog(wxWindow* parent, shared_ptr<const Film> film)
+ : wxDialog(parent, wxID_ANY, _("Version file (VF) setup"))
+ , _film(film)
+ , _dcp_grid(new wxGridBagSizer(DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP))
+ , _overall_sizer(new wxBoxSizer(wxVERTICAL))
+{
+ _film_connection = film->Change.connect(boost::bind(&DCPReferencingDialog::film_changed, this, _1, _2));
+ _film_content_connection = film->ContentChange.connect(boost::bind(&DCPReferencingDialog::film_content_changed, this, _1, _3));
+
+ _overall_sizer->Add(_dcp_grid, 1, wxALL, DCPOMATIC_DIALOG_BORDER);
+ SetSizer(_overall_sizer);
+
+ auto buttons = CreateSeparatedButtonSizer(wxOK);
+ if (buttons) {
+ _overall_sizer->Add(buttons, wxSizerFlags().Expand().DoubleBorder());
+ }
+
+ setup();
+}
+
+
+void
+DCPReferencingDialog::film_changed(ChangeType type, FilmProperty property)
+{
+ if (type != ChangeType::DONE) {
+ return;
+ }
+
+ if (
+ property == FilmProperty::INTEROP ||
+ property == FilmProperty::RESOLUTION ||
+ property == FilmProperty::CONTAINER ||
+ property == FilmProperty::REEL_TYPE ||
+ property == FilmProperty::VIDEO_FRAME_RATE ||
+ property == FilmProperty::CONTENT) {
+ setup();
+ }
+}
+
+
+void
+DCPReferencingDialog::film_content_changed(ChangeType type, int property)
+{
+ if (type != ChangeType::DONE) {
+ return;
+ }
+
+ if (
+ property != DCPContentProperty::REFERENCE_VIDEO &&
+ property != DCPContentProperty::REFERENCE_AUDIO &&
+ property != DCPContentProperty::REFERENCE_TEXT) {
+ setup();
+ }
+}
+
+
+void
+DCPReferencingDialog::setup()
+{
+ _dcps.clear();
+ _dcp_grid->Clear(true);
+
+ int column = 0;
+ for (auto const& heading: { _("DCP"), _("Picture"), _("Sound"), _("Subtitles"), _("Closed captions") }) {
+ auto text = new StaticText(this, heading);
+ wxFont font(*wxNORMAL_FONT);
+ font.SetWeight(wxFONTWEIGHT_BOLD);
+ text->SetFont(font);
+ _dcp_grid->Add(text, wxGBPosition(0, column), wxDefaultSpan, wxALL, DCPOMATIC_SIZER_GAP);
+ ++column;
+ };
+
+ auto const all_parts = { Part::VIDEO, Part::AUDIO, Part::SUBTITLES, Part::CLOSED_CAPTIONS };
+
+ int row = 1;
+ for (auto& content: _film->content()) {
+ auto dcp_content = dynamic_pointer_cast<DCPContent>(content);
+ if (!dcp_content) {
+ continue;
+ }
+
+ DCP record;
+ record.content = dcp_content;
+ _dcp_grid->Add(new StaticText(this, std_to_wx(dcp_content->name())), wxGBPosition(row, 0));
+ column = 1;
+ for (auto const& part: all_parts) {
+ record.check_box[part] = new CheckBox(this, wxT(""));
+ switch (part) {
+ case Part::VIDEO:
+ record.check_box[part]->set(dcp_content->reference_video());
+ break;
+ case Part::AUDIO:
+ record.check_box[part]->set(dcp_content->reference_audio());
+ break;
+ case Part::SUBTITLES:
+ record.check_box[part]->set(dcp_content->reference_text(TextType::OPEN_SUBTITLE));
+ break;
+ case Part::CLOSED_CAPTIONS:
+ record.check_box[part]->set(dcp_content->reference_text(TextType::CLOSED_CAPTION));
+ break;
+ default:
+ DCPOMATIC_ASSERT(false);
+ }
+ record.check_box[part]->bind(&DCPReferencingDialog::checkbox_changed, this, weak_ptr<DCPContent>(dcp_content), record.check_box[part], part);
+ _dcp_grid->Add(record.check_box[part], wxGBPosition(row, column++), wxDefaultSpan, wxALIGN_CENTER);
+ }
+ ++row;
+
+ auto add_problem = [this, &row](wxString const& cannot, string why_not) {
+ auto reason = new StaticText(this, cannot + wxT(": ") + std_to_wx(why_not));
+ wxFont font(*wxNORMAL_FONT);
+ font.SetStyle(wxFONTSTYLE_ITALIC);
+ reason->SetFont(font);
+ _dcp_grid->Add(reason, wxGBPosition(row, 0), wxGBSpan(1, 5), wxLEFT, DCPOMATIC_SIZER_X_GAP * 4);
+ ++row;
+ };
+
+ string why_not;
+
+ if (!dcp_content->can_reference_anything(_film, why_not)) {
+ for (auto const& part: all_parts) {
+ record.check_box[part]->Enable(false);
+ }
+ add_problem(_("Cannot reference this DCP"), why_not);
+ } else {
+ if (!dcp_content->can_reference_video(_film, why_not)) {
+ record.check_box[Part::VIDEO]->Enable(false);
+ if (dcp_content->video) {
+ add_problem(_("Cannot reference this DCP's video"), why_not);
+ }
+ }
+
+ if (!dcp_content->can_reference_audio(_film, why_not)) {
+ record.check_box[Part::AUDIO]->Enable(false);
+ if (dcp_content->audio) {
+ add_problem(_("Cannot reference this DCP's audio"), why_not);
+ }
+ }
+
+ if (!dcp_content->can_reference_text(_film, TextType::OPEN_SUBTITLE, why_not)) {
+ record.check_box[Part::SUBTITLES]->Enable(false);
+ if (dcp_content->text_of_original_type(TextType::OPEN_SUBTITLE)) {
+ add_problem(_("Cannot reference this DCP's subtitles"), why_not);
+ }
+ }
+
+ if (!dcp_content->can_reference_text(_film, TextType::CLOSED_CAPTION, why_not)) {
+ record.check_box[Part::CLOSED_CAPTIONS]->Enable(false);
+ if (dcp_content->text_of_original_type(TextType::CLOSED_CAPTION)) {
+ add_problem(_("Cannot reference this DCP's closed captions"), why_not);
+ }
+ }
+ }
+
+ _dcps.push_back(record);
+ }
+
+ _dcp_grid->Layout();
+ _overall_sizer->Layout();
+ _overall_sizer->SetSizeHints(this);
+}
+
+
+void
+DCPReferencingDialog::checkbox_changed(weak_ptr<DCPContent> weak_content, CheckBox* check_box, Part part)
+{
+ auto content = weak_content.lock();
+ if (!content) {
+ return;
+ }
+
+ switch (part) {
+ case Part::VIDEO:
+ content->set_reference_video(check_box->get());
+ break;
+ case Part::AUDIO:
+ content->set_reference_audio(check_box->get());
+ break;
+ case Part::SUBTITLES:
+ content->set_reference_text(TextType::OPEN_SUBTITLE, check_box->get());
+ break;
+ case Part::CLOSED_CAPTIONS:
+ content->set_reference_text(TextType::CLOSED_CAPTION, check_box->get());
+ break;
+ default:
+ DCPOMATIC_ASSERT(false);
+ }
+}
+
diff --git a/src/wx/dcp_referencing_dialog.h b/src/wx/dcp_referencing_dialog.h
new file mode 100644
index 000000000..e49292c22
--- /dev/null
+++ b/src/wx/dcp_referencing_dialog.h
@@ -0,0 +1,70 @@
+/*
+ Copyright (C) 2023 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 "lib/enum_indexed_vector.h"
+#include "lib/film.h"
+#include <wx/wx.h>
+#include <memory>
+#include <vector>
+
+
+class CheckBox;
+class DCPContent;
+class Film;
+class wxBoxSizer;
+class wxGridBagSizer;
+
+
+class DCPReferencingDialog : public wxDialog
+{
+public:
+ DCPReferencingDialog(wxWindow* parent, std::shared_ptr<const Film> film);
+
+private:
+ enum class Part {
+ VIDEO,
+ AUDIO,
+ SUBTITLES,
+ CLOSED_CAPTIONS,
+ COUNT
+ };
+
+ void setup();
+ void checkbox_changed(std::weak_ptr<DCPContent> content, CheckBox* check_box, Part part);
+ void film_changed(ChangeType type, FilmProperty property);
+ void film_content_changed(ChangeType type, int property);
+
+ std::shared_ptr<const Film> _film;
+
+ wxGridBagSizer* _dcp_grid;
+ wxBoxSizer* _overall_sizer;
+
+ struct DCP {
+ std::shared_ptr<DCPContent> content;
+ EnumIndexedVector<CheckBox*, Part> check_box;
+ };
+
+ std::vector<DCP> _dcps;
+
+ boost::signals2::scoped_connection _film_connection;
+ boost::signals2::scoped_connection _film_content_connection;
+};
+
diff --git a/src/wx/dkdm_dialog.cc b/src/wx/dkdm_dialog.cc
index 26f521573..8da3090c5 100644
--- a/src/wx/dkdm_dialog.cc
+++ b/src/wx/dkdm_dialog.cc
@@ -161,7 +161,7 @@ DKDMDialog::make_clicked ()
list<KDMWithMetadataPtr> kdms;
try {
for (auto i: _recipients->recipients()) {
- auto p = kdm_for_dkdm_recipient (film, _cpl->cpl(), i, _timing->from(), _timing->until());
+ auto p = kdm_for_dkdm_recipient(film, _cpl->cpl(), i, _timing->from(), _timing->until());
if (p) {
kdms.push_back (p);
}
diff --git a/src/wx/film_editor.cc b/src/wx/film_editor.cc
index 9f54db58e..fae02787a 100644
--- a/src/wx/film_editor.cc
+++ b/src/wx/film_editor.cc
@@ -54,13 +54,15 @@ FilmEditor::FilmEditor(wxWindow* parent, FilmViewer& viewer)
{
auto s = new wxBoxSizer (wxVERTICAL);
- auto notebook = new wxNotebook(this, wxID_ANY);
- s->Add(notebook, 1, wxEXPAND);
+ _notebook = new wxNotebook(this, wxID_ANY);
+ s->Add(_notebook, 1, wxEXPAND);
- _content_panel = new ContentPanel(notebook, _film, viewer);
- notebook->AddPage(_content_panel->window(), _("Content"), true);
- _dcp_panel = new DCPPanel(notebook, _film, viewer);
- notebook->AddPage(_dcp_panel->panel (), _("DCP"), false);
+ _content_panel = new ContentPanel(_notebook, _film, viewer);
+ _notebook->AddPage(_content_panel->window(), _("Content"), true);
+ _dcp_panel = new DCPPanel(_notebook, _film, viewer);
+ _notebook->AddPage(_dcp_panel->panel (), _("DCP"), false);
+
+ _notebook->Bind(wxEVT_NOTEBOOK_PAGE_CHANGED, boost::bind(&FilmEditor::page_changed, this, _1));
JobManager::instance()->ActiveJobsChanged.connect (
bind(&FilmEditor::active_jobs_changed, this, _2)
@@ -71,6 +73,18 @@ FilmEditor::FilmEditor(wxWindow* parent, FilmViewer& viewer)
}
+void
+FilmEditor::page_changed(wxBookCtrlEvent& ev)
+{
+ /* One of these events arrives early on with GetOldSelection() being a non-existent tab,
+ * and we want to ignore that.
+ */
+ if (_film && ev.GetOldSelection() < 2) {
+ _film->set_ui_state("FilmEditorTab", ev.GetSelection() == 0 ? "content" : "dcp");
+ }
+}
+
+
/** Called when the metadata stored in the Film object has changed;
* so that we can update the GUI.
* @param p Property of the Film that has changed.
@@ -144,6 +158,13 @@ FilmEditor::set_film (shared_ptr<Film> film)
if (!_film->content().empty()) {
_content_panel->set_selection (_film->content().front());
}
+
+ auto tab = _film->ui_state("FilmEditorTab").get_value_or("content");
+ if (tab == "content") {
+ _notebook->SetSelection(0);
+ } else if (tab == "dcp") {
+ _notebook->SetSelection(1);
+ }
}
diff --git a/src/wx/film_editor.h b/src/wx/film_editor.h
index a3df266ad..54d639ef5 100644
--- a/src/wx/film_editor.h
+++ b/src/wx/film_editor.h
@@ -32,11 +32,12 @@ LIBDCP_ENABLE_WARNINGS
#include <boost/signals2.hpp>
-class wxNotebook;
-class Film;
class ContentPanel;
class DCPPanel;
+class Film;
class FilmViewer;
+class wxBookCtrlEvent;
+class wxNotebook;
/** @class FilmEditor
@@ -71,6 +72,9 @@ private:
void set_general_sensitivity (bool);
void active_jobs_changed (boost::optional<std::string>);
+ void page_changed(wxBookCtrlEvent& ev);
+
+ wxNotebook* _notebook;
ContentPanel* _content_panel;
DCPPanel* _dcp_panel;
diff --git a/src/wx/full_config_dialog.cc b/src/wx/full_config_dialog.cc
index 4c26d038c..66dbae63e 100644
--- a/src/wx/full_config_dialog.cc
+++ b/src/wx/full_config_dialog.cc
@@ -45,6 +45,9 @@
#include "send_test_email_dialog.h"
#include "server_dialog.h"
#include "static_text.h"
+#ifdef DCPOMATIC_GROK
+#include "grok/gpu_config_panel.h"
+#endif
#include "wx_util.h"
#include "lib/config.h"
#include "lib/cross.h"
@@ -1946,6 +1949,9 @@ create_full_config_dialog ()
e->AddPage (new SoundPage (ps, border));
e->AddPage (new DefaultsPage (ps, border));
e->AddPage (new EncodingServersPage(ps, border));
+#ifdef DCPOMATIC_GROK
+ e->AddPage (new GPUPage (ps, border));
+#endif
e->AddPage (new KeysPage (ps, border));
e->AddPage (new TMSPage (ps, border));
e->AddPage (new EmailPage (ps, border));
diff --git a/src/wx/grok/gpu_config_panel.h b/src/wx/grok/gpu_config_panel.h
new file mode 100644
index 000000000..cbf037592
--- /dev/null
+++ b/src/wx/grok/gpu_config_panel.h
@@ -0,0 +1,227 @@
+/*
+ Copyright (C) 2023 Grok Image Compression Inc.
+
+ 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/>.
+
+*/
+
+
+#pragma once
+
+static std::vector<std::string> get_gpu_names(boost::filesystem::path binary, boost::filesystem::path filename)
+{
+ // Execute the GPU listing program and redirect its output to a file
+ if (std::system((binary.string() + " > " + filename.string()).c_str()) < 0) {
+ return {};
+ }
+
+ std::vector<std::string> gpu_names;
+ std::ifstream file(filename.c_str());
+ if (file.is_open())
+ {
+ std::string line;
+ while (std::getline(file, line))
+ gpu_names.push_back(line);
+ file.close();
+ }
+
+ return gpu_names;
+}
+
+
+class GpuList : public wxPanel
+{
+public:
+ GpuList(wxPanel* parent)
+ : wxPanel(parent, wxID_ANY)
+ {
+ _combo_box = new wxComboBox(this, wxID_ANY, "", wxDefaultPosition, wxSize(400, -1));
+ _combo_box->Bind(wxEVT_COMBOBOX, &GpuList::OnComboBox, this);
+ update();
+
+ auto sizer = new wxBoxSizer(wxHORIZONTAL);
+ sizer->Add(_combo_box, 0, wxALIGN_CENTER_VERTICAL);
+ SetSizerAndFit(sizer);
+ }
+
+ void update()
+ {
+ auto grok = Config::instance()->grok().get_value_or({});
+ auto lister_binary = grok.binary_location / "gpu_lister";
+ auto lister_file = grok.binary_location / "gpus.txt";
+ if (boost::filesystem::exists(lister_binary)) {
+ auto gpu_names = get_gpu_names(lister_binary, lister_file);
+
+ _combo_box->Clear();
+ for (auto const& name: gpu_names) {
+ _combo_box->Append(name);
+ }
+ }
+ }
+
+ void set_selection(int sel)
+ {
+ if (sel < static_cast<int>(_combo_box->GetCount())) {
+ _combo_box->SetSelection(sel);
+ }
+ }
+
+private:
+ void OnComboBox(wxCommandEvent&)
+ {
+ auto selection = _combo_box->GetSelection();
+ if (selection != wxNOT_FOUND) {
+ auto grok = Config::instance()->grok().get_value_or({});
+ grok.selected = selection;
+ Config::instance()->set_grok(grok);
+ }
+ }
+
+ wxComboBox* _combo_box;
+ int _selection = 0;
+};
+
+
+class GPUPage : public Page
+{
+public:
+ GPUPage(wxSize panel_size, int border)
+ : Page(panel_size, border)
+ {}
+
+ wxString GetName() const override
+ {
+ return _("GPU");
+ }
+
+#ifdef DCPOMATIC_OSX
+ /* XXX: this icon does not exist */
+ wxBitmap GetLargeIcon() const override
+ {
+ return wxBitmap(icon_path("gpu"), wxBITMAP_TYPE_PNG);
+ }
+#endif
+
+private:
+ void setup() override
+ {
+ _enable_gpu = new CheckBox(_panel, _("Enable GPU acceleration"));
+ _panel->GetSizer()->Add(_enable_gpu, 0, wxALL | wxEXPAND, _border);
+
+ wxFlexGridSizer* table = new wxFlexGridSizer(2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
+ table->AddGrowableCol(1, 1);
+ _panel->GetSizer()->Add(table, 1, wxALL | wxEXPAND, _border);
+
+ add_label_to_sizer(table, _panel, _("Acceleration binary folder"), true, 0, wxLEFT | wxLEFT | wxALIGN_CENTRE_VERTICAL);
+ _binary_location = new wxDirPickerCtrl(_panel, wxDD_DIR_MUST_EXIST);
+ table->Add(_binary_location, 1, wxEXPAND);
+
+ add_label_to_sizer(table, _panel, _("GPU selection"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
+ _gpu_list_control = new GpuList(_panel);
+ table->Add(_gpu_list_control, 1, wxEXPAND);
+
+ add_label_to_sizer(table, _panel, _("License server"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
+ _server = new wxTextCtrl(_panel, wxID_ANY);
+ table->Add(_server, 1, wxEXPAND | wxALL);
+
+ add_label_to_sizer(table, _panel, _("Port"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
+ _port = new wxSpinCtrl(_panel, wxID_ANY);
+ _port->SetRange(0, 65535);
+ table->Add(_port);
+
+ add_label_to_sizer(table, _panel, _("License"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
+ _licence = new PasswordEntry(_panel);
+ table->Add(_licence->get_panel(), 1, wxEXPAND | wxALL);
+
+ _enable_gpu->bind(&GPUPage::enable_gpu_changed, this);
+ _binary_location->Bind(wxEVT_DIRPICKER_CHANGED, boost::bind (&GPUPage::binary_location_changed, this));
+ _server->Bind(wxEVT_TEXT, boost::bind(&GPUPage::server_changed, this));
+ _port->Bind(wxEVT_SPINCTRL, boost::bind(&GPUPage::port_changed, this));
+ _licence->Changed.connect(boost::bind(&GPUPage::licence_changed, this));
+
+ setup_sensitivity();
+ }
+
+ void setup_sensitivity()
+ {
+ auto grok = Config::instance()->grok().get_value_or({});
+
+ _binary_location->Enable(grok.enable);
+ _gpu_list_control->Enable(grok.enable);
+ _server->Enable(grok.enable);
+ _port->Enable(grok.enable);
+ _licence->get_panel()->Enable(grok.enable);
+ }
+
+ void config_changed() override
+ {
+ auto grok = Config::instance()->grok().get_value_or({});
+
+ checked_set(_enable_gpu, grok.enable);
+ _binary_location->SetPath(std_to_wx(grok.binary_location.string()));
+ _gpu_list_control->update();
+ _gpu_list_control->set_selection(grok.selected);
+ checked_set(_server, grok.licence_server);
+ checked_set(_port, grok.licence_port);
+ checked_set(_licence, grok.licence);
+ }
+
+ void enable_gpu_changed()
+ {
+ auto grok = Config::instance()->grok().get_value_or({});
+ grok.enable = _enable_gpu->GetValue();
+ Config::instance()->set_grok(grok);
+
+ setup_sensitivity();
+ }
+
+ void binary_location_changed()
+ {
+ auto grok = Config::instance()->grok().get_value_or({});
+ grok.binary_location = wx_to_std(_binary_location->GetPath());
+ Config::instance()->set_grok(grok);
+
+ _gpu_list_control->update();
+ }
+
+ void server_changed()
+ {
+ auto grok = Config::instance()->grok().get_value_or({});
+ grok.licence_server = wx_to_std(_server->GetValue());
+ Config::instance()->set_grok(grok);
+ }
+
+ void port_changed()
+ {
+ auto grok = Config::instance()->grok().get_value_or({});
+ grok.licence_port = _port->GetValue();
+ Config::instance()->set_grok(grok);
+ }
+
+ void licence_changed()
+ {
+ auto grok = Config::instance()->grok().get_value_or({});
+ grok.licence = wx_to_std(_licence->get());
+ Config::instance()->set_grok(grok);
+ }
+
+ CheckBox* _enable_gpu = nullptr;
+ wxDirPickerCtrl* _binary_location = nullptr;
+ GpuList* _gpu_list_control = nullptr;
+ wxTextCtrl* _server = nullptr;
+ wxSpinCtrl* _port = nullptr;
+ PasswordEntry* _licence = nullptr;
+};
diff --git a/src/wx/kdm_timing_panel.cc b/src/wx/kdm_timing_panel.cc
index 0fd00de93..7759d3949 100644
--- a/src/wx/kdm_timing_panel.cc
+++ b/src/wx/kdm_timing_panel.cc
@@ -19,11 +19,13 @@
*/
+#include "dcpomatic_choice.h"
#include "kdm_timing_panel.h"
#include "static_text.h"
#include "time_picker.h"
#include "wx_util.h"
#include "lib/config.h"
+#include <dcp/utc_offset.h>
#include <dcp/warnings.h>
LIBDCP_DISABLE_WARNINGS
#include <wx/datectrl.h>
@@ -105,6 +107,10 @@ KDMTimingPanel::KDMTimingPanel (wxWindow* parent)
table->Add (_until_time, 0, wxALIGN_CENTER_VERTICAL);
+ add_label_to_sizer(table, this, _("UTC offset (time zone)"), true, 1, wxALIGN_CENTRE_VERTICAL);
+ _utc_offset = new Choice(this);
+ table->Add(_utc_offset, 0, wxALIGN_CENTRE_VERTICAL | wxLEFT, DCPOMATIC_SIZER_X_GAP);
+
overall_sizer->Add (table, 0, wxTOP, DCPOMATIC_SIZER_GAP);
_warning = new StaticText (this, wxT(""));
@@ -115,6 +121,17 @@ KDMTimingPanel::KDMTimingPanel (wxWindow* parent)
_warning->SetForegroundColour (wxColour (255, 0, 0));
_warning->SetFont(font);
+ /* Default to UTC */
+ size_t sel = 0;
+ for (size_t i = 0; i < _offsets.size(); ++i) {
+ _utc_offset->add(_offsets[i].name);
+ if (_offsets[i].hour == 0 && _offsets[i].minute == 0) {
+ sel = i;
+ }
+ }
+
+ _utc_offset->set(sel);
+
/* I said I've been to the year 3000. Not much has changed but they live underwater. And your In-in-in-interop DCP
is pretty fine.
*/
@@ -125,33 +142,38 @@ KDMTimingPanel::KDMTimingPanel (wxWindow* parent)
_until_date->Bind (wxEVT_DATE_CHANGED, bind (&KDMTimingPanel::changed, this));
_from_time->Changed.connect (bind (&KDMTimingPanel::changed, this));
_until_time->Changed.connect (bind (&KDMTimingPanel::changed, this));
+ _utc_offset->bind(&KDMTimingPanel::changed, this);
SetSizer (overall_sizer);
}
-boost::posix_time::ptime
+dcp::LocalTime
KDMTimingPanel::from () const
{
- return posix_time (_from_date, _from_time);
+ return local_time(_from_date, _from_time, utc_offset());
}
-boost::posix_time::ptime
-KDMTimingPanel::posix_time (wxDatePickerCtrl* date_picker, TimePicker* time_picker)
+dcp::LocalTime
+KDMTimingPanel::local_time(wxDatePickerCtrl* date_picker, TimePicker* time_picker, dcp::UTCOffset offset)
{
auto const date = date_picker->GetValue ();
- return boost::posix_time::ptime (
- boost::gregorian::date (date.GetYear(), date.GetMonth() + 1, date.GetDay()),
- boost::posix_time::time_duration (time_picker->hours(), time_picker->minutes(), 0)
+ return dcp::LocalTime(
+ date.GetYear(),
+ date.GetMonth() + 1,
+ date.GetDay(),
+ time_picker->hours(),
+ time_picker->minutes(),
+ offset
);
}
-boost::posix_time::ptime
+dcp::LocalTime
KDMTimingPanel::until () const
{
- return posix_time (_until_date, _until_time);
+ return local_time(_until_date, _until_time, utc_offset());
}
@@ -173,3 +195,20 @@ KDMTimingPanel::changed () const
TimingChanged ();
}
+
+
+dcp::UTCOffset
+KDMTimingPanel::utc_offset() const
+{
+ auto const sel = _utc_offset->get();
+ if (!sel || *sel >= int(_offsets.size())) {
+ return {};
+ }
+
+ auto const& offset = _offsets[*sel];
+ int const minute_scale = offset.hour < 0 ? -1 : 1;
+
+ return { offset.hour, minute_scale * offset.minute };
+}
+
+
diff --git a/src/wx/kdm_timing_panel.h b/src/wx/kdm_timing_panel.h
index 7221ba722..f847992a7 100644
--- a/src/wx/kdm_timing_panel.h
+++ b/src/wx/kdm_timing_panel.h
@@ -18,6 +18,9 @@
*/
+
+#include "wx_util.h"
+#include <dcp/utc_offset.h>
#include <dcp/warnings.h>
LIBDCP_DISABLE_WARNINGS
#include <wx/wx.h>
@@ -25,18 +28,19 @@ LIBDCP_ENABLE_WARNINGS
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/signals2.hpp>
-class wxDatePickerCtrl;
+
+class Choice;
class TimePicker;
+class wxDatePickerCtrl;
+
class KDMTimingPanel : public wxPanel
{
public:
explicit KDMTimingPanel (wxWindow* parent);
- /** @return KDM from time in local time */
- boost::posix_time::ptime from () const;
- /** @return KDM until time in local time */
- boost::posix_time::ptime until () const;
+ dcp::LocalTime from() const;
+ dcp::LocalTime until() const;
bool valid () const;
@@ -44,11 +48,15 @@ public:
private:
void changed () const;
- static boost::posix_time::ptime posix_time (wxDatePickerCtrl *, TimePicker *);
+ dcp::UTCOffset utc_offset() const;
+
+ static dcp::LocalTime local_time(wxDatePickerCtrl *, TimePicker *, dcp::UTCOffset offset);
wxDatePickerCtrl* _from_date;
wxDatePickerCtrl* _until_date;
TimePicker* _from_time;
TimePicker* _until_time;
+ Choice* _utc_offset;
wxStaticText* _warning;
+ std::vector<Offset> _offsets;
};
diff --git a/src/wx/screens_panel.cc b/src/wx/screens_panel.cc
index d3b1db77d..62f8688a9 100644
--- a/src/wx/screens_panel.cc
+++ b/src/wx/screens_panel.cc
@@ -252,7 +252,7 @@ ScreensPanel::add_cinema_clicked ()
CinemaDialog dialog(GetParent(), _("Add Cinema"));
if (dialog.ShowModal() == wxID_OK) {
- auto cinema = make_shared<Cinema>(dialog.name(), dialog.emails(), dialog.notes(), dialog.utc_offset_hour(), dialog.utc_offset_minute());
+ auto cinema = make_shared<Cinema>(dialog.name(), dialog.emails(), dialog.notes());
auto cinemas = sorted_cinemas();
@@ -320,16 +320,12 @@ ScreensPanel::edit_cinema_clicked ()
void
ScreensPanel::edit_cinema(shared_ptr<Cinema> cinema)
{
- CinemaDialog dialog(
- GetParent(), _("Edit cinema"), cinema->name, cinema->emails, cinema->notes, cinema->utc_offset_hour(), cinema->utc_offset_minute()
- );
+ CinemaDialog dialog(GetParent(), _("Edit cinema"), cinema->name, cinema->emails, cinema->notes);
if (dialog.ShowModal() == wxID_OK) {
cinema->name = dialog.name();
cinema->emails = dialog.emails();
cinema->notes = dialog.notes();
- cinema->set_utc_offset_hour(dialog.utc_offset_hour());
- cinema->set_utc_offset_minute(dialog.utc_offset_minute());
notify_cinemas_changed();
auto item = cinema_to_item(cinema);
DCPOMATIC_ASSERT(item);
diff --git a/src/wx/text_panel.cc b/src/wx/text_panel.cc
index 78c024565..c3a5706b0 100644
--- a/src/wx/text_panel.cc
+++ b/src/wx/text_panel.cc
@@ -84,14 +84,6 @@ TextPanel::create ()
refer = _("Use this DCP's closed caption as OV and make VF");
}
- _reference = new CheckBox (this, refer);
- _reference_note = new StaticText (this, wxT(""));
- _reference_note->Wrap (200);
- auto font = _reference_note->GetFont();
- font.SetStyle(wxFONTSTYLE_ITALIC);
- font.SetPointSize(font.GetPointSize() - 1);
- _reference_note->SetFont(font);
-
_use = new CheckBox (this, _("Use as"));
_type = new wxChoice (this, wxID_ANY);
_type->Append (_("open subtitles"));
@@ -132,7 +124,6 @@ TextPanel::create ()
_y_scale->SetRange (0, 1000);
_line_spacing->SetRange (0, 1000);
- _reference->bind(&TextPanel::reference_clicked, this);
_use->bind(&TextPanel::use_toggled, this);
_type->Bind (wxEVT_CHOICE, boost::bind (&TextPanel::type_changed, this));
_burn->bind(&TextPanel::burn_toggled, this);
@@ -232,12 +223,6 @@ TextPanel::add_to_grid ()
{
int r = 0;
- auto reference_sizer = new wxBoxSizer (wxVERTICAL);
- reference_sizer->Add (_reference, 0);
- reference_sizer->Add (_reference_note, 0);
- _grid->Add (reference_sizer, wxGBPosition(r, 0), wxGBSpan(1, 4));
- ++r;
-
auto use = new wxBoxSizer (wxHORIZONTAL);
use->Add (_use, 0, wxEXPAND | wxRIGHT, DCPOMATIC_SIZER_GAP);
use->Add (_type, 1, wxEXPAND, 0);
@@ -496,15 +481,6 @@ TextPanel::film_content_changed (int property)
if (_language_type) {
_language_type->SetSelection (text ? (text->language_is_additional() ? 1 : 0) : 0);
}
- } else if (property == DCPContentProperty::REFERENCE_TEXT) {
- if (scs) {
- auto dcp = dynamic_pointer_cast<DCPContent> (scs);
- checked_set (_reference, dcp ? dcp->reference_text(_original_type) : false);
- } else {
- checked_set (_reference, false);
- }
-
- setup_sensitivity ();
} else if (property == DCPContentProperty::TEXTS) {
setup_sensitivity ();
} else if (property == ContentProperty::TRIM_START) {
@@ -593,17 +569,7 @@ TextPanel::setup_sensitivity ()
dcp = dynamic_pointer_cast<DCPContent>(sel.front());
}
- string why_not;
- bool const can_reference = dcp && dcp->can_reference_text (_parent->film(), _original_type, why_not);
- wxString cannot;
- if (why_not.empty()) {
- cannot = _("Cannot reference this DCP's subtitles or captions.");
- } else {
- cannot = _("Cannot reference this DCP's subtitles or captions: ") + std_to_wx(why_not);
- }
- setup_refer_button (_reference, _reference_note, dcp, can_reference, cannot);
-
- bool const reference = _reference->GetValue ();
+ auto const reference = dcp && dcp->reference_text(_original_type);
auto const type = current_type ();
@@ -763,23 +729,6 @@ TextPanel::fonts_dialog_clicked ()
void
-TextPanel::reference_clicked ()
-{
- auto c = _parent->selected ();
- if (c.size() != 1) {
- return;
- }
-
- auto d = dynamic_pointer_cast<DCPContent> (c.front ());
- if (!d) {
- return;
- }
-
- d->set_reference_text (_original_type, _reference->GetValue ());
-}
-
-
-void
TextPanel::appearance_dialog_clicked ()
{
auto c = _parent->selected_text ();
diff --git a/src/wx/text_panel.h b/src/wx/text_panel.h
index 5adad5a3e..a2afba439 100644
--- a/src/wx/text_panel.h
+++ b/src/wx/text_panel.h
@@ -56,7 +56,6 @@ private:
void stream_changed ();
void text_view_clicked ();
void fonts_dialog_clicked ();
- void reference_clicked ();
void appearance_dialog_clicked ();
void outline_subtitles_changed ();
TextType current_type () const;
@@ -74,8 +73,6 @@ private:
void update_outline_subtitles_in_viewer ();
void clear_outline_subtitles ();
- CheckBox* _reference;
- wxStaticText* _reference_note;
CheckBox* _outline_subtitles = nullptr;
CheckBox* _use;
wxChoice* _type;
diff --git a/src/wx/video_panel.cc b/src/wx/video_panel.cc
index 8a02dff25..f78da05d9 100644
--- a/src/wx/video_panel.cc
+++ b/src/wx/video_panel.cc
@@ -76,14 +76,6 @@ VideoPanel::VideoPanel (ContentPanel* p)
void
VideoPanel::create ()
{
- _reference = new CheckBox (this, _("Use this DCP's video as OV and make VF"));
- _reference_note = new StaticText (this, wxT(""));
- _reference_note->Wrap (200);
- auto font = _reference_note->GetFont();
- font.SetStyle(wxFONTSTYLE_ITALIC);
- font.SetPointSize(font.GetPointSize() - 1);
- _reference_note->SetFont(font);
-
_type_label = create_label (this, _("Type"), true);
_frame_type = new ContentChoice<VideoContent, VideoFrameType> (
this,
@@ -201,6 +193,9 @@ VideoPanel::create ()
_range->Append (_("Video (MPEG, 16-235)"));
_description = new StaticText (this, wxT ("\n \n \n \n \n"), wxDefaultPosition, wxDefaultSize);
+ auto font = _description->GetFont();
+ font.SetStyle(wxFONTSTYLE_ITALIC);
+ font.SetPointSize(font.GetPointSize() - 1);
_description->SetFont(font);
_left_crop->wrapped()->SetRange (0, 4096);
@@ -221,7 +216,6 @@ VideoPanel::create ()
_fade_in->Changed.connect (boost::bind (&VideoPanel::fade_in_changed, this));
_fade_out->Changed.connect (boost::bind (&VideoPanel::fade_out_changed, this));
- _reference->bind(&VideoPanel::reference_clicked, this);
_scale_fit->Bind (wxEVT_RADIOBUTTON, boost::bind (&VideoPanel::scale_fit_clicked, this));
_scale_custom->Bind (wxEVT_RADIOBUTTON, boost::bind (&VideoPanel::scale_custom_clicked, this));
_scale_custom_edit->Bind (wxEVT_BUTTON, boost::bind (&VideoPanel::scale_custom_edit_clicked, this));
@@ -242,12 +236,6 @@ VideoPanel::add_to_grid ()
{
int r = 0;
- auto reference_sizer = new wxBoxSizer (wxVERTICAL);
- reference_sizer->Add (_reference, 0);
- reference_sizer->Add (_reference_note, 0);
- _grid->Add (reference_sizer, wxGBPosition(r, 0), wxGBSpan(1, 3));
- ++r;
-
add_label_to_sizer (_grid, _type_label, true, wxGBPosition(r, 0));
_frame_type->add (_grid, wxGBPosition(r, 1), wxGBSpan(1, 2));
++r;
@@ -456,15 +444,6 @@ VideoPanel::film_content_changed (int property)
} else {
_fade_out->clear ();
}
- } else if (property == DCPContentProperty::REFERENCE_VIDEO) {
- if (vc.size() == 1) {
- shared_ptr<DCPContent> dcp = dynamic_pointer_cast<DCPContent> (vc.front ());
- checked_set (_reference, dcp ? dcp->reference_video () : false);
- } else {
- checked_set (_reference, false);
- }
-
- setup_sensitivity ();
} else if (property == VideoContentProperty::RANGE) {
if (vcs) {
checked_set (_range, vcs->video->range() == VideoRange::FULL ? 0 : 1);
@@ -592,15 +571,7 @@ VideoPanel::setup_sensitivity ()
dcp = dynamic_pointer_cast<DCPContent> (sel.front ());
}
- string why_not;
- bool const can_reference = dcp && dcp->can_reference_video (_parent->film(), why_not);
- wxString cannot;
- if (why_not.empty()) {
- cannot = _("Cannot reference this DCP's video.");
- } else {
- cannot = _("Cannot reference this DCP's video: ") + std_to_wx(why_not);
- }
- setup_refer_button (_reference, _reference_note, dcp, can_reference, cannot);
+ bool const reference = dcp && dcp->reference_video();
bool any_use = false;
for (auto i: _parent->selected_video()) {
@@ -609,7 +580,7 @@ VideoPanel::setup_sensitivity ()
}
}
- bool const enable = !_reference->GetValue() && any_use;
+ bool const enable = !reference && any_use;
if (!enable) {
_frame_type->wrapped()->Enable (false);
@@ -682,23 +653,6 @@ VideoPanel::fade_out_changed ()
void
-VideoPanel::reference_clicked ()
-{
- auto c = _parent->selected ();
- if (c.size() != 1) {
- return;
- }
-
- auto d = dynamic_pointer_cast<DCPContent> (c.front ());
- if (!d) {
- return;
- }
-
- d->set_reference_video (_reference->GetValue ());
-}
-
-
-void
VideoPanel::scale_fit_clicked ()
{
for (auto i: _parent->selected_video()) {
diff --git a/src/wx/video_panel.h b/src/wx/video_panel.h
index 686d1b99b..e6b689b03 100644
--- a/src/wx/video_panel.h
+++ b/src/wx/video_panel.h
@@ -53,7 +53,6 @@ public:
void content_selection_changed () override;
private:
- void reference_clicked ();
void colour_conversion_changed ();
void edit_colour_conversion_clicked ();
void range_changed ();
@@ -73,8 +72,6 @@ private:
void setup_description ();
void setup_sensitivity ();
- CheckBox* _reference;
- wxStaticText* _reference_note;
wxStaticText* _type_label;
ContentChoice<VideoContent, VideoFrameType>* _frame_type;
wxStaticText* _crop_label;
diff --git a/src/wx/wscript b/src/wx/wscript
index 9c6ea6b84..7dbd214c6 100644
--- a/src/wx/wscript
+++ b/src/wx/wscript
@@ -53,6 +53,7 @@ sources = """
controls.cc
credentials_download_certificate_panel.cc
custom_scale_dialog.cc
+ dcp_referencing_dialog.cc
dcp_panel.cc
dcp_text_track_dialog.cc
dcpomatic_button.cc