summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2025-06-21 13:25:20 +0200
committerCarl Hetherington <cth@carlh.net>2025-07-04 23:02:26 +0200
commitde8cd4118d57591804ccd63f979aa9e495df9c93 (patch)
tree82bd16a3a8cb44d34a21cd51581a1933a819018c
parent1650465106b7c20a7cc9ae5eec1cf9bf406c1dcf (diff)
Go back to the old way of handling KDM timing.
Once again the KDM gets its timezone from the cinema.
-rw-r--r--src/lib/kdm_cli.cc61
-rw-r--r--src/lib/screen.cc15
-rw-r--r--src/lib/screen.h4
-rw-r--r--src/tools/dcpomatic_kdm.cc1
-rw-r--r--src/wx/kdm_dialog.cc1
-rw-r--r--src/wx/kdm_timing_panel.cc73
-rw-r--r--src/wx/kdm_timing_panel.h15
-rw-r--r--test/kdm_cli_test.cc2
-rw-r--r--test/kdm_naming_test.cc14
9 files changed, 64 insertions, 122 deletions
diff --git a/src/lib/kdm_cli.cc b/src/lib/kdm_cli.cc
index 4c5eb46d3..50bf9ea51 100644
--- a/src/lib/kdm_cli.cc
+++ b/src/lib/kdm_cli.cc
@@ -73,8 +73,8 @@ 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 (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(" -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(" -t, --valid-to <time> valid to time (in local time zone of the cinema) (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");
@@ -110,6 +110,17 @@ 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)
{
@@ -204,8 +215,8 @@ from_film(
boost::filesystem::path output,
dcp::NameFormat container_name_format,
dcp::NameFormat filename_format,
- dcp::LocalTime valid_from,
- dcp::LocalTime valid_to,
+ boost::posix_time::ptime valid_from,
+ boost::posix_time::ptime valid_to,
dcp::Formulation formulation,
bool disable_forensic_marking_picture,
optional<int> disable_forensic_marking_audio,
@@ -365,8 +376,8 @@ from_dkdm(
boost::filesystem::path output,
dcp::NameFormat container_name_format,
dcp::NameFormat filename_format,
- dcp::LocalTime valid_from,
- dcp::LocalTime valid_to,
+ boost::posix_time::ptime valid_from,
+ boost::posix_time::ptime valid_to,
dcp::Formulation formulation,
bool disable_forensic_marking_picture,
optional<int> disable_forensic_marking_audio,
@@ -384,12 +395,15 @@ from_dkdm(
continue;
}
+ dcp::LocalTime begin(valid_from, screen_details.cinema.utc_offset);
+ dcp::LocalTime end(valid_to, screen_details.cinema.utc_offset);
+
auto const kdm = kdm_from_dkdm(
dkdm,
screen_details.screen.recipient().get(),
screen_details.screen.trusted_device_thumbprints(),
- valid_from,
- valid_to,
+ begin,
+ end,
formulation,
disable_forensic_marking_picture,
disable_forensic_marking_audio
@@ -399,8 +413,8 @@ from_dkdm(
name_values['c'] = screen_details.cinema.name;
name_values['s'] = screen_details.screen.name;
name_values['f'] = kdm.content_title_text();
- 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['b'] = begin.date() + " " + begin.time_of_day(true, false);
+ name_values['e'] = end.date() + " " + end.time_of_day(true, false);
name_values['i'] = kdm.cpl_id();
kdms.push_back(make_shared<KDMWithMetadata>(name_values, screen_details.cinema_id, screen_details.cinema.emails, kdm));
@@ -437,22 +451,6 @@ dump_dkdm_group(shared_ptr<DKDMGroup> group, int indent, std::function<void (str
}
-static
-dcp::LocalTime
-time_from_string(string time)
-{
- if (time == "now") {
- return {};
- }
-
- if (time.length() > 10 && time[10] == ' ') {
- time[10] = 'T';
- }
-
- return dcp::LocalTime(time);
-}
-
-
void
dump_decryption_certificate(std::function<void (string)> out)
{
@@ -482,8 +480,8 @@ try
/* trusted devices that we will use to make up a temporary cinema and screen */
vector<TrustedDevice> trusted_devices;
optional<dcp::EncryptedKDM> dkdm;
- optional<dcp::LocalTime> valid_from;
- optional<dcp::LocalTime> valid_to;
+ optional<boost::posix_time::ptime> valid_from;
+ optional<boost::posix_time::ptime> valid_to;
bool zip = false;
string command = "create";
optional<string> duration_string;
@@ -547,7 +545,7 @@ try
valid_from = time_from_string(optarg);
break;
case 't':
- valid_to = dcp::LocalTime(optarg);
+ valid_to = time_from_string(optarg);
break;
case 'd':
duration_string = optarg;
@@ -709,12 +707,11 @@ try
}
if (duration_string) {
- valid_to = valid_from.get();
- valid_to->add(duration_from_string(*duration_string));
+ valid_to = valid_from.get() + duration_from_string(*duration_string);
}
if (verbose) {
- out(String::compose("Making KDMs valid from %1 to %2", valid_from->as_string(), valid_to->as_string()));
+ 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())));
}
string const thing = argv[optind];
diff --git a/src/lib/screen.cc b/src/lib/screen.cc
index 304fb52f3..57e792672 100644
--- a/src/lib/screen.cc
+++ b/src/lib/screen.cc
@@ -57,8 +57,8 @@ kdm_for_screen (
CinemaID cinema_id,
Cinema const& cinema,
Screen const& screen,
- dcp::LocalTime valid_from,
- dcp::LocalTime valid_to,
+ boost::posix_time::ptime valid_from,
+ boost::posix_time::ptime valid_to,
dcp::Formulation formulation,
bool disable_forensic_marking_picture,
optional<int> disable_forensic_marking_audio,
@@ -69,14 +69,17 @@ kdm_for_screen (
return {};
}
- period_checks.push_back(check_kdm_and_certificate_validity_periods(cinema.name, screen.name, screen.recipient().get(), valid_from, valid_to));
+ dcp::LocalTime const begin(valid_from, cinema.utc_offset);
+ dcp::LocalTime const end (valid_to, cinema.utc_offset);
+
+ period_checks.push_back(check_kdm_and_certificate_validity_periods(cinema.name, screen.name, screen.recipient().get(), begin, end));
auto signer = Config::instance()->signer_chain();
if (!signer->valid()) {
throw InvalidSignerError();
}
- auto kdm = make_kdm(valid_from, valid_to).encrypt(
+ auto kdm = make_kdm(begin, end).encrypt(
signer, screen.recipient().get(), screen.trusted_device_thumbprints(), formulation, disable_forensic_marking_picture, disable_forensic_marking_audio
);
@@ -84,8 +87,8 @@ kdm_for_screen (
name_values['c'] = cinema.name;
name_values['s'] = screen.name;
name_values['f'] = kdm.content_title_text();
- 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['b'] = begin.date() + " " + begin.time_of_day(true, false);
+ name_values['e'] = end.date() + " " + end.time_of_day(true, false);
name_values['i'] = kdm.cpl_id();
return make_shared<KDMWithMetadata>(name_values, cinema_id, cinema.emails, kdm);
diff --git a/src/lib/screen.h b/src/lib/screen.h
index 326bc9403..d870f7ab3 100644
--- a/src/lib/screen.h
+++ b/src/lib/screen.h
@@ -88,8 +88,8 @@ kdm_for_screen (
CinemaID cinema_id,
Cinema const& cinema,
dcpomatic::Screen const& screen,
- dcp::LocalTime valid_from,
- dcp::LocalTime valid_to,
+ boost::posix_time::ptime valid_from,
+ boost::posix_time::ptime valid_to,
dcp::Formulation formulation,
bool disable_forensic_marking_picture,
boost::optional<int> disable_forensic_marking_audio,
diff --git a/src/tools/dcpomatic_kdm.cc b/src/tools/dcpomatic_kdm.cc
index 843684103..d596f8ca2 100644
--- a/src/tools/dcpomatic_kdm.cc
+++ b/src/tools/dcpomatic_kdm.cc
@@ -835,7 +835,6 @@ private:
void screens_changed()
{
- _timing->suggest_utc_offset(_screens->best_utc_offset());
setup_sensitivity();
}
diff --git a/src/wx/kdm_dialog.cc b/src/wx/kdm_dialog.cc
index f96c89c98..c2dce905f 100644
--- a/src/wx/kdm_dialog.cc
+++ b/src/wx/kdm_dialog.cc
@@ -143,7 +143,6 @@ KDMDialog::KDMDialog (wxWindow* parent, shared_ptr<const Film> film)
void
KDMDialog::screens_changed()
{
- _timing->suggest_utc_offset(_screens->best_utc_offset());
setup_sensitivity();
}
diff --git a/src/wx/kdm_timing_panel.cc b/src/wx/kdm_timing_panel.cc
index 03267102f..6c365e114 100644
--- a/src/wx/kdm_timing_panel.cc
+++ b/src/wx/kdm_timing_panel.cc
@@ -25,7 +25,6 @@
#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>
@@ -97,10 +96,6 @@ 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, {});
@@ -111,13 +106,6 @@ KDMTimingPanel::KDMTimingPanel (wxWindow* parent)
_warning->SetForegroundColour (wxColour (255, 0, 0));
_warning->SetFont(font);
- /* Default to UTC */
- auto const sel = get_offsets(_offsets);
- for (auto const& offset: _offsets) {
- _utc_offset->add_entry(offset.name);
- }
- _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.
*/
@@ -128,38 +116,32 @@ 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::utc_offset_changed, this);
SetSizer (overall_sizer);
}
-dcp::LocalTime
+boost::posix_time::ptime
KDMTimingPanel::from () const
{
- return local_time(_from_date, _from_time, utc_offset());
+ return posix_time(_from_date, _from_time);
}
-dcp::LocalTime
-KDMTimingPanel::local_time(wxDatePickerCtrl* date_picker, TimePicker* time_picker, dcp::UTCOffset offset)
+boost::posix_time::ptime
+KDMTimingPanel::posix_time(wxDatePickerCtrl* date_picker, TimePicker* time_picker)
{
- auto const date = date_picker->GetValue ();
- return dcp::LocalTime(
- date.GetYear(),
- date.GetMonth() + 1,
- date.GetDay(),
- time_picker->hours(),
- time_picker->minutes(),
- 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));
}
-dcp::LocalTime
+boost::posix_time::ptime
KDMTimingPanel::until () const
{
- return local_time(_until_date, _until_time, utc_offset());
+ return posix_time(_until_date, _until_time);
}
@@ -181,38 +163,3 @@ KDMTimingPanel::changed () const
TimingChanged ();
}
-
-
-dcp::UTCOffset
-KDMTimingPanel::utc_offset() const
-{
- auto const sel = _utc_offset->get();
- if (!sel || *sel >= int(_offsets.size())) {
- return {};
- }
-
- return _offsets[*sel].offset;
-}
-
-
-void
-KDMTimingPanel::utc_offset_changed()
-{
- _utc_offset_changed_once = true;
- changed();
-}
-
-
-void
-KDMTimingPanel::suggest_utc_offset(dcp::UTCOffset offset)
-{
- if (!_utc_offset_changed_once) {
- for (size_t i = 0; i < _offsets.size(); ++i) {
- if (_offsets[i].offset == offset) {
- _utc_offset->set(i);
- break;
- }
- }
- }
-}
-
diff --git a/src/wx/kdm_timing_panel.h b/src/wx/kdm_timing_panel.h
index a6199534a..21478b1ab 100644
--- a/src/wx/kdm_timing_panel.h
+++ b/src/wx/kdm_timing_panel.h
@@ -39,31 +39,22 @@ class KDMTimingPanel : public wxPanel
public:
explicit KDMTimingPanel (wxWindow* parent);
- dcp::LocalTime from() const;
- dcp::LocalTime until() const;
+ boost::posix_time::ptime from() const;
+ boost::posix_time::ptime until() const;
bool valid () const;
- /** Give a UTC offset from a cinema that the user just selected. If the user
- * never changed the UTC offset in the panel, the suggested UTC will be set.
- */
- void suggest_utc_offset(dcp::UTCOffset offset);
-
boost::signals2::signal<void ()> TimingChanged;
private:
void changed () const;
- void utc_offset_changed();
- dcp::UTCOffset utc_offset() const;
- static dcp::LocalTime local_time(wxDatePickerCtrl *, TimePicker *, dcp::UTCOffset offset);
+ static boost::posix_time::ptime posix_time(wxDatePickerCtrl *, TimePicker *);
wxDatePickerCtrl* _from_date;
wxDatePickerCtrl* _until_date;
TimePicker* _from_time;
TimePicker* _until_time;
- Choice* _utc_offset;
- bool _utc_offset_changed_once = false;
wxStaticText* _warning;
std::vector<Offset> _offsets;
};
diff --git a/test/kdm_cli_test.cc b/test/kdm_cli_test.cc
index a788a9642..4292da17e 100644
--- a/test/kdm_cli_test.cc
+++ b/test/kdm_cli_test.cc
@@ -317,7 +317,7 @@ BOOST_AUTO_TEST_CASE(kdm_cli_time)
vector<string> args = {
"kdm_cli",
"--verbose",
- "--valid-from", now.as_string(),
+ "--valid-from", "2025-01-28 01:41:51",
"--valid-duration", "2 weeks",
"-c", "Dean's Screens",
"-S", "Screen 2",
diff --git a/test/kdm_naming_test.cc b/test/kdm_naming_test.cc
index fe7da7f31..4735ef75e 100644
--- a/test/kdm_naming_test.cc
+++ b/test/kdm_naming_test.cc
@@ -101,6 +101,9 @@ BOOST_AUTO_TEST_CASE (single_kdm_naming_test)
dcp::LocalTime until = sign_cert.not_after();
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;
@@ -112,8 +115,8 @@ BOOST_AUTO_TEST_CASE (single_kdm_naming_test)
context.cinema_a,
*cinemas.cinema(context.cinema_a),
*cinemas.screen(context.cinema_a_screen_1),
- from,
- until,
+ boost::posix_time::time_from_string(from_string),
+ boost::posix_time::time_from_string(until_string),
dcp::Formulation::MODIFIED_TRANSITIONAL_1,
false,
optional<int>(),
@@ -165,6 +168,9 @@ BOOST_AUTO_TEST_CASE(directory_kdm_naming_test)
dcp::LocalTime until (sign_cert.not_after());
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);
+
vector<pair<CinemaID, ScreenID>> screens = {
{ context.cinema_a, context.cinema_a_screen_2 },
{ context.cinema_b, context.cinema_b_screen_x },
@@ -188,8 +194,8 @@ BOOST_AUTO_TEST_CASE(directory_kdm_naming_test)
screen.first,
*cinemas.cinema(screen.first),
*cinemas.screen(screen.second),
- from,
- until,
+ boost::posix_time::time_from_string(from_string),
+ boost::posix_time::time_from_string(until_string),
dcp::Formulation::MODIFIED_TRANSITIONAL_1,
false,
optional<int>(),