diff options
| author | Carl Hetherington <cth@carlh.net> | 2022-12-01 22:30:58 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2023-10-16 11:35:33 +0200 |
| commit | 1fe5683ddbd7f97f848061f8b83af1f1559368db (patch) | |
| tree | 634ace2419558de4c679480ac2feb762a9b447fc | |
| parent | 08a8e3ea02887d2f96719119c0a34bedcb19ab04 (diff) | |
Move UTC offset for KDMs from the cinema to the point of KDM creation (#2300).
| -rw-r--r-- | src/lib/cinema.cc | 24 | ||||
| -rw-r--r-- | src/lib/cinema.h | 23 | ||||
| -rw-r--r-- | src/lib/dkdm_recipient.cc | 13 | ||||
| -rw-r--r-- | src/lib/dkdm_recipient.h | 4 | ||||
| -rw-r--r-- | src/lib/kdm_cli.cc | 56 | ||||
| -rw-r--r-- | src/lib/screen.cc | 14 | ||||
| -rw-r--r-- | src/lib/screen.h | 7 | ||||
| -rw-r--r-- | src/wx/cinema_dialog.cc | 42 | ||||
| -rw-r--r-- | src/wx/cinema_dialog.h | 8 | ||||
| -rw-r--r-- | src/wx/dkdm_dialog.cc | 2 | ||||
| -rw-r--r-- | src/wx/kdm_timing_panel.cc | 57 | ||||
| -rw-r--r-- | src/wx/kdm_timing_panel.h | 20 | ||||
| -rw-r--r-- | src/wx/screens_panel.cc | 8 | ||||
| -rw-r--r-- | test/config_test.cc | 2 | ||||
| -rw-r--r-- | test/kdm_cli_test.cc | 41 | ||||
| -rw-r--r-- | test/kdm_naming_test.cc | 26 |
16 files changed, 158 insertions, 189 deletions
diff --git a/src/lib/cinema.cc b/src/lib/cinema.cc index 3b4b9d7b6..7388dbc2f 100644 --- a/src/lib/cinema.cc +++ b/src/lib/cinema.cc @@ -41,14 +41,6 @@ Cinema::Cinema (cxml::ConstNodePtr node) for (auto i: node->node_children("Email")) { emails.push_back (i->content ()); } - - if (node->optional_number_child<int>("UTCOffset")) { - _utc_offset_hour = node->number_child<int>("UTCOffset"); - } else { - _utc_offset_hour = node->optional_number_child<int>("UTCOffsetHour").get_value_or (0); - } - - _utc_offset_minute = node->optional_number_child<int>("UTCOffsetMinute").get_value_or (0); } /* This is necessary so that we can use shared_from_this in add_screen (which cannot be done from @@ -73,9 +65,6 @@ Cinema::as_xml (xmlpp::Element* parent) const parent->add_child("Notes")->add_child_text (notes); - parent->add_child("UTCOffsetHour")->add_child_text (raw_convert<string> (_utc_offset_hour)); - parent->add_child("UTCOffsetMinute")->add_child_text (raw_convert<string> (_utc_offset_minute)); - for (auto i: _screens) { i->as_xml (parent->add_child ("Screen")); } @@ -97,16 +86,3 @@ Cinema::remove_screen (shared_ptr<Screen> s) } } -void -Cinema::set_utc_offset_hour (int h) -{ - DCPOMATIC_ASSERT (h >= -11 && h <= 12); - _utc_offset_hour = h; -} - -void -Cinema::set_utc_offset_minute (int m) -{ - DCPOMATIC_ASSERT (m >= 0 && m <= 59); - _utc_offset_minute = m; -} diff --git a/src/lib/cinema.h b/src/lib/cinema.h index 6c202a7bf..7008659d7 100644 --- a/src/lib/cinema.h +++ b/src/lib/cinema.h @@ -44,12 +44,10 @@ namespace dcpomatic { class Cinema : public std::enable_shared_from_this<Cinema> { public: - Cinema(std::string const & name_, std::vector<std::string> const & e, std::string notes_, int utc_offset_hour, int utc_offset_minute) + Cinema(std::string const & name_, std::vector<std::string> const & e, std::string notes_) : name (name_) , emails (e) , notes (notes_) - , _utc_offset_hour (utc_offset_hour) - , _utc_offset_minute (utc_offset_minute) {} explicit Cinema (cxml::ConstNodePtr); @@ -61,33 +59,14 @@ public: void add_screen (std::shared_ptr<dcpomatic::Screen>); void remove_screen (std::shared_ptr<dcpomatic::Screen>); - void set_utc_offset_hour (int h); - void set_utc_offset_minute (int m); - std::string name; std::vector<std::string> emails; std::string notes; - int utc_offset_hour () const { - return _utc_offset_hour; - } - - int utc_offset_minute () const { - return _utc_offset_minute; - } - std::vector<std::shared_ptr<dcpomatic::Screen>> screens() const { return _screens; } private: std::vector<std::shared_ptr<dcpomatic::Screen>> _screens; - /** Offset such that the equivalent time in UTC can be determined - by subtracting the offset from the local time. - */ - int _utc_offset_hour; - /** Additional minutes to add to _utc_offset_hour if _utc_offset_hour is - positive, or to subtract if _utc_offset_hour is negative. - */ - int _utc_offset_minute; }; diff --git a/src/lib/dkdm_recipient.cc b/src/lib/dkdm_recipient.cc index c73379bed..c683151f2 100644 --- a/src/lib/dkdm_recipient.cc +++ b/src/lib/dkdm_recipient.cc @@ -65,29 +65,26 @@ kdm_for_dkdm_recipient ( shared_ptr<const Film> film, boost::filesystem::path cpl, shared_ptr<DKDMRecipient> recipient, - boost::posix_time::ptime valid_from, - boost::posix_time::ptime valid_to + dcp::LocalTime valid_from, + dcp::LocalTime valid_to ) { if (!recipient->recipient) { return {}; } - dcp::LocalTime const begin(valid_from, dcp::UTCOffset(recipient->utc_offset_hour, recipient->utc_offset_minute)); - dcp::LocalTime const end (valid_to, dcp::UTCOffset(recipient->utc_offset_hour, recipient->utc_offset_minute)); - auto signer = Config::instance()->signer_chain(); if (!signer->valid()) { throw InvalidSignerError(); } - auto const decrypted_kdm = film->make_kdm(cpl, begin, end); + auto const decrypted_kdm = film->make_kdm(cpl, valid_from, valid_to); auto const kdm = decrypted_kdm.encrypt(signer, recipient->recipient.get(), {}, dcp::Formulation::MODIFIED_TRANSITIONAL_1, true, 0); dcp::NameFormat::Map name_values; name_values['f'] = kdm.content_title_text(); - name_values['b'] = begin.date() + " " + begin.time_of_day(true, false); - name_values['e'] = end.date() + " " + end.time_of_day(true, false); + name_values['b'] = valid_from.date() + " " + valid_from.time_of_day(true, false); + name_values['e'] = valid_to.date() + " " + valid_to.time_of_day(true, false); name_values['i'] = kdm.cpl_id(); return make_shared<KDMWithMetadata>(name_values, nullptr, recipient->emails, kdm); diff --git a/src/lib/dkdm_recipient.h b/src/lib/dkdm_recipient.h index 7a0fa0185..4015a0b7d 100644 --- a/src/lib/dkdm_recipient.h +++ b/src/lib/dkdm_recipient.h @@ -60,7 +60,7 @@ kdm_for_dkdm_recipient ( std::shared_ptr<const Film> film, boost::filesystem::path cpl, std::shared_ptr<DKDMRecipient> recipient, - boost::posix_time::ptime valid_from, - boost::posix_time::ptime valid_to + dcp::LocalTime valid_from, + dcp::LocalTime valid_to ); diff --git a/src/lib/kdm_cli.cc b/src/lib/kdm_cli.cc index 5ea808967..239094b38 100644 --- a/src/lib/kdm_cli.cc +++ b/src/lib/kdm_cli.cc @@ -62,8 +62,10 @@ help (std::function<void (string)> out) out (" -o, --output <path> output file or directory"); out (" -K, --filename-format <format> filename format for KDMs"); out (" -Z, --container-name-format <format> filename format for ZIP containers"); - out (" -f, --valid-from <time> valid from time (in local time zone of the cinema) (e.g. \"2013-09-28 01:41:51\") or \"now\""); + out (" -f, --valid-from <time> valid from time (e.g. \"2013-09-2 01:41:51\") or \"now\""); out (" -t, --valid-to <time> valid to time (in local time zone of the cinema) (e.g. \"2014-09-28 01:41:51\")"); + out (" -f, --valid-from <time> valid from time (e.g. \"2013-09-28T01:41:51+04:00\", \"2018-01-01T12:00:30\") or \"now\""); + out (" -t, --valid-to <time> valid to time (e.g. \"2014-09-28T01:41:51\")"); out (" -d, --valid-duration <duration> valid duration (e.g. \"1 day\", \"4 hours\", \"2 weeks\")"); out (" -F, --formulation <formulation> modified-transitional-1, multiple-modified-transitional-1, dci-any or dci-specific [default modified-transitional-1]"); out (" -p, --disable-forensic-marking-picture disable forensic marking of pictures essences"); @@ -99,17 +101,6 @@ public: }; -static boost::posix_time::ptime -time_from_string (string t) -{ - if (t == "now") { - return boost::posix_time::second_clock::local_time (); - } - - return boost::posix_time::time_from_string (t); -} - - static boost::posix_time::time_duration duration_from_string (string d) { @@ -211,8 +202,8 @@ from_film ( boost::filesystem::path output, dcp::NameFormat container_name_format, dcp::NameFormat filename_format, - boost::posix_time::ptime valid_from, - boost::posix_time::ptime valid_to, + dcp::LocalTime valid_from, + dcp::LocalTime valid_to, dcp::Formulation formulation, bool disable_forensic_marking_picture, optional<int> disable_forensic_marking_audio, @@ -354,8 +345,8 @@ from_dkdm ( boost::filesystem::path output, dcp::NameFormat container_name_format, dcp::NameFormat filename_format, - boost::posix_time::ptime valid_from, - boost::posix_time::ptime valid_to, + dcp::LocalTime valid_from, + dcp::LocalTime valid_to, dcp::Formulation formulation, bool disable_forensic_marking_picture, optional<int> disable_forensic_marking_audio, @@ -373,18 +364,12 @@ from_dkdm ( continue; } - int const offset_hour = i->cinema ? i->cinema->utc_offset_hour() : 0; - int const offset_minute = i->cinema ? i->cinema->utc_offset_minute() : 0; - - dcp::LocalTime begin(valid_from, dcp::UTCOffset(offset_hour, offset_minute)); - dcp::LocalTime end(valid_to, dcp::UTCOffset(offset_hour, offset_minute)); - auto const kdm = kdm_from_dkdm( dkdm, i->recipient.get(), i->trusted_device_thumbprints(), - begin, - end, + valid_from, + valid_to, formulation, disable_forensic_marking_picture, disable_forensic_marking_audio @@ -394,8 +379,8 @@ from_dkdm ( name_values['c'] = i->cinema ? i->cinema->name : ""; name_values['s'] = i->name; name_values['f'] = kdm.content_title_text(); - name_values['b'] = begin.date() + " " + begin.time_of_day(true, false); - name_values['e'] = end.date() + " " + end.time_of_day(true, false); + name_values['b'] = valid_from.date() + " " + valid_from.time_of_day(true, false); + name_values['e'] = valid_to.date() + " " + valid_to.time_of_day(true, false); name_values['i'] = kdm.cpl_id(); kdms.push_back(make_shared<KDMWithMetadata>(name_values, i->cinema.get(), i->cinema ? i->cinema->emails : vector<string>(), kdm)); @@ -445,8 +430,8 @@ try optional<string> screen; vector<shared_ptr<Screen>> screens; optional<dcp::EncryptedKDM> dkdm; - optional<boost::posix_time::ptime> valid_from; - optional<boost::posix_time::ptime> valid_to; + optional<dcp::LocalTime> valid_from; + optional<dcp::LocalTime> valid_to; bool zip = false; bool list_cinemas = false; bool list_dkdm_cpls = false; @@ -509,10 +494,14 @@ try container_name_format = dcp::NameFormat (optarg); break; case 'f': - valid_from = time_from_string (optarg); + if (string(optarg) == "now") { + valid_from = dcp::LocalTime(); + } else { + valid_from = dcp::LocalTime(optarg); + } break; case 't': - valid_to = time_from_string (optarg); + valid_to = dcp::LocalTime(optarg); break; case 'd': duration_string = optarg; @@ -556,7 +545,7 @@ try (for lookup) and by creating a Cinema which the next Screen will be added to. */ cinema_name = optarg; - cinema = make_shared<Cinema>(optarg, vector<string>(), "", 0, 0); + cinema = make_shared<Cinema>(optarg, vector<string>(), ""); break; case 'S': /* Similarly, this could be the name of a new (temporary) screen or the name of a screen @@ -636,11 +625,12 @@ try } if (duration_string) { - valid_to = valid_from.get() + duration_from_string (*duration_string); + valid_to = valid_from.get(); + valid_to->add(duration_from_string(*duration_string)); } if (verbose) { - out (String::compose("Making KDMs valid from %1 to %2", boost::posix_time::to_simple_string(valid_from.get()), boost::posix_time::to_simple_string(valid_to.get()))); + out(String::compose("Making KDMs valid from %1 to %2", valid_from->as_string(), valid_to->as_string())); } string const thing = argv[optind]; diff --git a/src/lib/screen.cc b/src/lib/screen.cc index 097ff80b8..f3c59761a 100644 --- a/src/lib/screen.cc +++ b/src/lib/screen.cc @@ -77,8 +77,8 @@ KDMWithMetadataPtr kdm_for_screen ( std::function<dcp::DecryptedKDM (dcp::LocalTime, dcp::LocalTime)> make_kdm, shared_ptr<const dcpomatic::Screen> screen, - boost::posix_time::ptime valid_from, - boost::posix_time::ptime valid_to, + dcp::LocalTime valid_from, + dcp::LocalTime valid_to, dcp::Formulation formulation, bool disable_forensic_marking_picture, optional<int> disable_forensic_marking_audio, @@ -90,17 +90,15 @@ kdm_for_screen ( } auto cinema = screen->cinema; - dcp::LocalTime const begin(valid_from, dcp::UTCOffset(cinema ? cinema->utc_offset_hour() : 0, cinema ? cinema->utc_offset_minute() : 0)); - dcp::LocalTime const end (valid_to, dcp::UTCOffset(cinema ? cinema->utc_offset_hour() : 0, cinema ? cinema->utc_offset_minute() : 0)); - period_checks.push_back(check_kdm_and_certificate_validity_periods(screen->recipient.get(), begin, end)); + period_checks.push_back(check_kdm_and_certificate_validity_periods(screen->recipient.get(), valid_from, valid_to)); auto signer = Config::instance()->signer_chain(); if (!signer->valid()) { throw InvalidSignerError(); } - auto kdm = make_kdm(begin, end).encrypt( + auto kdm = make_kdm(valid_from, valid_to).encrypt( signer, screen->recipient.get(), screen->trusted_device_thumbprints(), formulation, disable_forensic_marking_picture, disable_forensic_marking_audio ); @@ -112,8 +110,8 @@ kdm_for_screen ( } name_values['s'] = screen->name; name_values['f'] = kdm.content_title_text(); - name_values['b'] = begin.date() + " " + begin.time_of_day(true, false); - name_values['e'] = end.date() + " " + end.time_of_day(true, false); + name_values['b'] = valid_from.date() + " " + valid_from.time_of_day(true, false); + name_values['e'] = valid_to.date() + " " + valid_to.time_of_day(true, false); name_values['i'] = kdm.cpl_id(); return make_shared<KDMWithMetadata>(name_values, cinema.get(), cinema ? cinema->emails : vector<string>(), kdm); diff --git a/src/lib/screen.h b/src/lib/screen.h index 7f01cdf27..0a275aa34 100644 --- a/src/lib/screen.h +++ b/src/lib/screen.h @@ -23,12 +23,13 @@ #define DCPOMATIC_SCREEN_H -#include "kdm_with_metadata.h" #include "kdm_recipient.h" #include "kdm_util.h" +#include "kdm_with_metadata.h" #include "trusted_device.h" #include <dcp/certificate.h> #include <dcp/decrypted_kdm.h> +#include <dcp/utc_offset.h> #include <libcxml/cxml.h> #include <boost/optional.hpp> #include <string> @@ -78,8 +79,8 @@ KDMWithMetadataPtr kdm_for_screen ( std::function<dcp::DecryptedKDM (dcp::LocalTime, dcp::LocalTime)> make_kdm, std::shared_ptr<const dcpomatic::Screen> screen, - boost::posix_time::ptime valid_from, - boost::posix_time::ptime valid_to, + dcp::LocalTime valid_from, + dcp::LocalTime valid_to, dcp::Formulation formulation, bool disable_forensic_marking_picture, boost::optional<int> disable_forensic_marking_audio, 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/dkdm_dialog.cc b/src/wx/dkdm_dialog.cc index 6a4913d86..6e1ef9745 100644 --- a/src/wx/dkdm_dialog.cc +++ b/src/wx/dkdm_dialog.cc @@ -160,7 +160,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/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 9d322e45e..2a82720b5 100644 --- a/src/wx/screens_panel.cc +++ b/src/wx/screens_panel.cc @@ -231,7 +231,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(); @@ -299,16 +299,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/test/config_test.cc b/test/config_test.cc index a43bb5ff6..00adb7b09 100644 --- a/test/config_test.cc +++ b/test/config_test.cc @@ -246,7 +246,7 @@ BOOST_AUTO_TEST_CASE (config_keep_cinemas_if_making_new_config) Config::instance()->write(); - Config::instance()->add_cinema(make_shared<Cinema>("My Great Cinema", vector<string>(), "", 0, 0)); + Config::instance()->add_cinema(make_shared<Cinema>("My Great Cinema", vector<string>(), "")); Config::instance()->write(); boost::filesystem::copy_file (dir / "cinemas.xml", dir / "backup_for_test.xml"); diff --git a/test/kdm_cli_test.cc b/test/kdm_cli_test.cc index 4114cebd4..96424cfee 100644 --- a/test/kdm_cli_test.cc +++ b/test/kdm_cli_test.cc @@ -85,13 +85,13 @@ setup_test_config() auto config = Config::instance(); auto const cert = dcp::Certificate(dcp::file_to_string("test/data/cert.pem")); - auto cinema_a = std::make_shared<Cinema>("Dean's Screens", vector<string>(), "", 0, 0); + auto cinema_a = std::make_shared<Cinema>("Dean's Screens", vector<string>(), ""); cinema_a->add_screen(std::make_shared<dcpomatic::Screen>("Screen 1", "", cert, boost::none, std::vector<TrustedDevice>())); cinema_a->add_screen(std::make_shared<dcpomatic::Screen>("Screen 2", "", cert, boost::none, std::vector<TrustedDevice>())); cinema_a->add_screen(std::make_shared<dcpomatic::Screen>("Screen 3", "", cert, boost::none, std::vector<TrustedDevice>())); config->add_cinema(cinema_a); - auto cinema_b = std::make_shared<Cinema>("Floyd's Celluloid", vector<string>(), "", 0, 0); + auto cinema_b = std::make_shared<Cinema>("Floyd's Celluloid", vector<string>(), ""); cinema_b->add_screen(std::make_shared<dcpomatic::Screen>("Foo", "", cert, boost::none, std::vector<TrustedDevice>())); cinema_b->add_screen(std::make_shared<dcpomatic::Screen>("Bar", "", cert, boost::none, std::vector<TrustedDevice>())); config->add_cinema(cinema_b); @@ -195,3 +195,40 @@ BOOST_AUTO_TEST_CASE(kdm_cli_specify_cinemas_file) BOOST_CHECK_EQUAL(output[2], "Great ()"); } + +BOOST_AUTO_TEST_CASE(kdm_cli_time) +{ + ConfigRestorer cr; + + setup_test_config(); + + boost::filesystem::path kdm_filename = "build/test/KDM_Test_FTR-1_F-133_XX-XX_MOS_2K_20220109_SMPTE_OV_Deans_Screens_Screen_2.xml"; + + boost::system::error_code ec; + boost::filesystem::remove(kdm_filename, ec); + + dcp::LocalTime now; + now.add_days(2); + + vector<string> args = { + "kdm_cli", + "--verbose", + "--valid-from", now.as_string(), + "--valid-duration", "2 weeks", + "-c", "Dean's Screens", + "-S", "Screen 2", + "-o", "build/test", + "test/data/dkdm.xml" + }; + + vector<string> output; + auto error = run(args, output); + BOOST_CHECK(!error); + + BOOST_REQUIRE_EQUAL(output.size(), 2U); + BOOST_CHECK(boost::algorithm::starts_with(output[0], "Making KDMs valid from")); + BOOST_CHECK_EQUAL(output[1], "Wrote 1 KDM files to build/test"); + + BOOST_CHECK(boost::filesystem::exists(kdm_filename)); +} + diff --git a/test/kdm_naming_test.cc b/test/kdm_naming_test.cc index 32500553e..0f44fe2ea 100644 --- a/test/kdm_naming_test.cc +++ b/test/kdm_naming_test.cc @@ -59,16 +59,14 @@ BOOST_AUTO_TEST_CASE (single_kdm_naming_test) auto crypt_cert = c->decryption_chain()->leaf(); - /* Cinema A: UTC +4:30 */ - auto cinema_a = make_shared<Cinema>("Cinema A", vector<string>(), "", 4, 30); + auto cinema_a = make_shared<Cinema>("Cinema A", vector<string>(), ""); cinema_a_screen_1 = std::make_shared<dcpomatic::Screen>("Screen 1", "", crypt_cert, boost::none, vector<TrustedDevice>()); cinema_a->add_screen (cinema_a_screen_1); cinema_a_screen_2 = std::make_shared<dcpomatic::Screen>("Screen 2", "", crypt_cert, boost::none, vector<TrustedDevice>()); cinema_a->add_screen (cinema_a_screen_2); c->add_cinema (cinema_a); - /* Cinema B: UTC -1:00 */ - auto cinema_b = make_shared<Cinema>("Cinema B", vector<string>(), "", -1, 0); + auto cinema_b = make_shared<Cinema>("Cinema B", vector<string>(), ""); cinema_b_screen_x = std::make_shared<dcpomatic::Screen>("Screen X", "", crypt_cert, boost::none, vector<TrustedDevice>()); cinema_b->add_screen (cinema_b_screen_x); cinema_b_screen_y = std::make_shared<dcpomatic::Screen>("Screen Y", "", crypt_cert, boost::none, vector<TrustedDevice>()); @@ -90,14 +88,13 @@ BOOST_AUTO_TEST_CASE (single_kdm_naming_test) auto sign_cert = c->signer_chain()->leaf(); - dcp::LocalTime from (sign_cert.not_before()); + dcp::LocalTime from = sign_cert.not_before(); + from.set_offset({ 4, 30 }); from.add_months (2); - dcp::LocalTime until (sign_cert.not_after()); + dcp::LocalTime until = sign_cert.not_after(); + until.set_offset({ 4, 30 }); until.add_months (-2); - auto const from_string = from.date() + " " + from.time_of_day(true, false); - auto const until_string = until.date() + " " + until.time_of_day(true, false); - std::vector<KDMCertificatePeriod> period_checks; auto cpl = cpls.front().cpl_file; @@ -107,8 +104,8 @@ BOOST_AUTO_TEST_CASE (single_kdm_naming_test) auto kdm = kdm_for_screen ( make_kdm, cinema_a_screen_1, - boost::posix_time::time_from_string(from_string), - boost::posix_time::time_from_string(until_string), + from, + until, dcp::Formulation::MODIFIED_TRANSITIONAL_1, false, optional<int>(), @@ -157,9 +154,6 @@ BOOST_AUTO_TEST_CASE (directory_kdm_naming_test, * boost::unit_test::depends_on( dcp::LocalTime until (sign_cert.not_after()); until.add_months (-2); - string const from_string = from.date() + " " + from.time_of_day(true, false); - string const until_string = until.date() + " " + until.time_of_day(true, false); - vector<shared_ptr<dcpomatic::Screen>> screens = { cinema_a_screen_2, cinema_b_screen_x, cinema_a_screen_1, (cinema_b_screen_z) }; @@ -178,8 +172,8 @@ BOOST_AUTO_TEST_CASE (directory_kdm_naming_test, * boost::unit_test::depends_on( auto kdm = kdm_for_screen ( make_kdm, i, - boost::posix_time::time_from_string(from_string), - boost::posix_time::time_from_string(until_string), + from, + until, dcp::Formulation::MODIFIED_TRANSITIONAL_1, false, optional<int>(), |
