+2014-05-28 Carl Hetherington <cth@carlh.net>
+
+ * Rework KDM generation to be about CPLs rather than DCPs,
+ and allow specification of any CPL to generate KDMs for.
+
+ Requested-by: Richard Turner
+
2014-05-27 Carl Hetherington <cth@carlh.net>
* Version 1.69.15 released.
return file (p);
}
-/** @return List of subdirectories (not full paths) containing DCPs that can be successfully libdcp::DCP::read() */
-list<boost::filesystem::path>
-Film::dcps () const
+/** Find all the DCPs in our directory that can be libdcp::DCP::read() and return details of their CPLs */
+vector<CPLSummary>
+Film::cpls () const
{
- list<boost::filesystem::path> out;
+ vector<CPLSummary> out;
boost::filesystem::path const dir = directory ();
for (boost::filesystem::directory_iterator i = boost::filesystem::directory_iterator(dir); i != boost::filesystem::directory_iterator(); ++i) {
try {
libdcp::DCP dcp (*i);
dcp.read ();
- out.push_back (i->path().leaf ());
+ out.push_back (
+ CPLSummary (
+ i->path().leaf().string(), dcp.cpls().front()->id(), dcp.cpls().front()->name(), dcp.cpls().front()->filename()
+ )
+ );
} catch (...) {
}
libdcp::KDM
Film::make_kdm (
shared_ptr<libdcp::Certificate> target,
- boost::filesystem::path dcp_dir,
+ boost::filesystem::path cpl_file,
boost::posix_time::ptime from,
boost::posix_time::ptime until
) const
{
shared_ptr<const Signer> signer = make_signer ();
- libdcp::DCP dcp (dir (dcp_dir.string ()));
-
- try {
- dcp.read ();
- } catch (...) {
- throw KDMError (_("Could not read DCP to make KDM for"));
- }
-
time_t now = time (0);
struct tm* tm = localtime (&now);
string const issue_date = libdcp::tm_to_string (tm);
- dcp.cpls().front()->set_mxf_keys (key ());
-
- return libdcp::KDM (dcp.cpls().front(), signer, target, from, until, "DCP-o-matic", issue_date);
+ return libdcp::KDM (cpl_file, signer, target, key (), from, until, "DCP-o-matic", issue_date);
}
list<libdcp::KDM>
libdcp::Size full_frame () const;
libdcp::Size frame_size () const;
- std::list<boost::filesystem::path> dcps () const;
+ std::vector<CPLSummary> cpls () const;
boost::shared_ptr<Player> make_player () const;
boost::shared_ptr<Playlist> playlist () const;
libdcp::KDM
make_kdm (
boost::shared_ptr<libdcp::Certificate> target,
- boost::filesystem::path dcp,
+ boost::filesystem::path cpl_file,
boost::posix_time::ptime from,
boost::posix_time::ptime until
) const;
std::list<libdcp::KDM> make_kdms (
std::list<boost::shared_ptr<Screen> >,
- boost::filesystem::path dcp,
+ boost::filesystem::path cpl_file,
boost::posix_time::ptime from,
boost::posix_time::ptime until
) const;
make_screen_kdms (
shared_ptr<const Film> film,
list<shared_ptr<Screen> > screens,
- boost::filesystem::path dcp,
+ boost::filesystem::path cpl,
boost::posix_time::ptime from,
boost::posix_time::ptime to
)
{
- list<libdcp::KDM> kdms = film->make_kdms (screens, dcp, from, to);
+ list<libdcp::KDM> kdms = film->make_kdms (screens, cpl, from, to);
list<ScreenKDM> screen_kdms;
make_cinema_kdms (
shared_ptr<const Film> film,
list<shared_ptr<Screen> > screens,
- boost::filesystem::path dcp,
+ boost::filesystem::path cpl,
boost::posix_time::ptime from,
boost::posix_time::ptime to
)
{
- list<ScreenKDM> screen_kdms = make_screen_kdms (film, screens, dcp, from, to);
+ list<ScreenKDM> screen_kdms = make_screen_kdms (film, screens, cpl, from, to);
list<CinemaKDMs> cinema_kdms;
while (!screen_kdms.empty ()) {
write_kdm_files (
shared_ptr<const Film> film,
list<shared_ptr<Screen> > screens,
- boost::filesystem::path dcp,
+ boost::filesystem::path cpl,
boost::posix_time::ptime from,
boost::posix_time::ptime to,
boost::filesystem::path directory
)
{
- list<ScreenKDM> screen_kdms = make_screen_kdms (film, screens, dcp, from, to);
+ list<ScreenKDM> screen_kdms = make_screen_kdms (film, screens, cpl, from, to);
/* Write KDMs to the specified directory */
for (list<ScreenKDM>::iterator i = screen_kdms.begin(); i != screen_kdms.end(); ++i) {
write_kdm_zip_files (
shared_ptr<const Film> film,
list<shared_ptr<Screen> > screens,
- boost::filesystem::path dcp,
+ boost::filesystem::path cpl,
boost::posix_time::ptime from,
boost::posix_time::ptime to,
boost::filesystem::path directory
)
{
- list<CinemaKDMs> cinema_kdms = make_cinema_kdms (film, screens, dcp, from, to);
+ list<CinemaKDMs> cinema_kdms = make_cinema_kdms (film, screens, cpl, from, to);
for (list<CinemaKDMs>::const_iterator i = cinema_kdms.begin(); i != cinema_kdms.end(); ++i) {
boost::filesystem::path path = directory;
email_kdms (
shared_ptr<const Film> film,
list<shared_ptr<Screen> > screens,
- boost::filesystem::path dcp,
+ boost::filesystem::path cpl,
boost::posix_time::ptime from,
boost::posix_time::ptime to
)
{
- list<CinemaKDMs> cinema_kdms = make_cinema_kdms (film, screens, dcp, from, to);
+ list<CinemaKDMs> cinema_kdms = make_cinema_kdms (film, screens, cpl, from, to);
for (list<CinemaKDMs>::const_iterator i = cinema_kdms.begin(); i != cinema_kdms.end(); ++i) {
extern void write_kdm_files (
boost::shared_ptr<const Film> film,
std::list<boost::shared_ptr<Screen> > screens,
- boost::filesystem::path dcp,
+ boost::filesystem::path cpl,
boost::posix_time::ptime from,
boost::posix_time::ptime to,
boost::filesystem::path directory
extern void write_kdm_zip_files (
boost::shared_ptr<const Film> film,
std::list<boost::shared_ptr<Screen> > screens,
- boost::filesystem::path dcp,
+ boost::filesystem::path cpl,
boost::posix_time::ptime from,
boost::posix_time::ptime to,
boost::filesystem::path directory
extern void email_kdms (
boost::shared_ptr<const Film> film,
std::list<boost::shared_ptr<Screen> > screens,
- boost::filesystem::path dcp,
+ boost::filesystem::path cpl,
boost::posix_time::ptime from,
boost::posix_time::ptime to
);
void as_xml (xmlpp::Node *) const;
};
+struct CPLSummary
+{
+ CPLSummary (std::string d, std::string i, std::string a, boost::filesystem::path f)
+ : dcp_directory (d)
+ , cpl_id (i)
+ , cpl_annotation_text (a)
+ , cpl_file (f)
+ {}
+
+ std::string dcp_directory;
+ std::string cpl_id;
+ std::string cpl_annotation_text;
+ boost::filesystem::path cpl_file;
+};
+
extern bool operator== (Crop const & a, Crop const & b);
extern bool operator!= (Crop const & a, Crop const & b);
#include <wx/stdpaths.h>
#include <wx/cmdline.h>
#include <wx/preferences.h>
+#include <libdcp/exceptions.h>
#include "wx/film_viewer.h"
#include "wx/film_editor.h"
#include "wx/job_manager_view.h"
#define ALWAYS 0x0
#define NEEDS_FILM 0x1
#define NOT_DURING_DCP_CREATION 0x2
-#define NEEDS_DCP 0x4
+#define NEEDS_CPL 0x4
map<wxMenuItem*, int> menu_items;
++i;
}
bool const dcp_creation = (i != jobs.end ()) && !(*i)->finished ();
- bool const have_dcp = film && !film->dcps().empty ();
+ bool const have_cpl = film && !film->cpls().empty ();
for (map<wxMenuItem*, int>::iterator j = menu_items.begin(); j != menu_items.end(); ++j) {
enabled = false;
}
- if ((j->second & NEEDS_DCP) && !have_dcp) {
+ if ((j->second & NEEDS_CPL) && !have_cpl) {
enabled = false;
}
jobs_menu = new wxMenu;
add_item (jobs_menu, _("&Make DCP"), ID_jobs_make_dcp, NEEDS_FILM | NOT_DURING_DCP_CREATION);
- add_item (jobs_menu, _("Make &KDMs..."), ID_jobs_make_kdms, NEEDS_FILM | NEEDS_DCP);
- add_item (jobs_menu, _("&Send DCP to TMS"), ID_jobs_send_dcp_to_tms, NEEDS_FILM | NOT_DURING_DCP_CREATION | NEEDS_DCP);
- add_item (jobs_menu, _("S&how DCP"), ID_jobs_show_dcp, NEEDS_FILM | NOT_DURING_DCP_CREATION | NEEDS_DCP);
+ add_item (jobs_menu, _("Make &KDMs..."), ID_jobs_make_kdms, NEEDS_FILM);
+ add_item (jobs_menu, _("&Send DCP to TMS"), ID_jobs_send_dcp_to_tms, NEEDS_FILM | NOT_DURING_DCP_CREATION | NEEDS_CPL);
+ add_item (jobs_menu, _("S&how DCP"), ID_jobs_show_dcp, NEEDS_FILM | NOT_DURING_DCP_CREATION | NEEDS_CPL);
wxMenu* tools = new wxMenu;
add_item (tools, _("Hints..."), ID_tools_hints, 0);
try {
if (d->write_to ()) {
- write_kdm_files (film, d->screens (), d->dcp (), d->from (), d->until (), d->directory ());
+ write_kdm_files (film, d->screens (), d->cpl (), d->from (), d->until (), d->directory ());
} else {
JobManager::instance()->add (
- shared_ptr<Job> (new SendKDMEmailJob (film, d->screens (), d->dcp (), d->from (), d->until ()))
+ shared_ptr<Job> (new SendKDMEmailJob (film, d->screens (), d->cpl (), d->from (), d->until ()))
);
}
+ } catch (libdcp::NotEncryptedError& e) {
+ error_dialog (this, _("CPL's content is not encrypted."));
} catch (exception& e) {
error_dialog (this, e.what ());
} catch (...) {
/*
- Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
using std::cout;
using std::cerr;
using std::list;
+using std::vector;
using boost::shared_ptr;
static string program_name;
}
/* XXX: allow specification of this */
- list<boost::filesystem::path> dcps = film->dcps ();
- if (dcps.empty ()) {
- error ("no DCPs found in film");
- } else if (dcps.size() > 1) {
- error ("more than one DCP found in film");
+ vector<CPLSummary> cpls = film->cpls ();
+ if (cpls.empty ()) {
+ error ("no CPLs found in film");
+ } else if (cpls.size() > 1) {
+ error ("more than one CPL found in film");
}
- boost::filesystem::path dcp = dcps.front ();
+ boost::filesystem::path cpl = cpls.front().cpl_file;
if (cinema_name.empty ()) {
}
shared_ptr<libdcp::Certificate> certificate (new libdcp::Certificate (boost::filesystem::path (certificate_file)));
- libdcp::KDM kdm = film->make_kdm (certificate, dcp, valid_from.get(), valid_to.get());
+ libdcp::KDM kdm = film->make_kdm (certificate, cpl, valid_from.get(), valid_to.get());
kdm.as_xml (output);
if (verbose) {
cout << "Generated KDM " << output << " for certificate.\n";
try {
if (zip) {
- write_kdm_zip_files (film, (*i)->screens(), dcp, valid_from.get(), valid_to.get(), output);
+ write_kdm_zip_files (film, (*i)->screens(), cpl, valid_from.get(), valid_to.get(), output);
if (verbose) {
cout << "Wrote ZIP files to " << output << "\n";
}
} else {
- write_kdm_files (film, (*i)->screens(), dcp, valid_from.get(), valid_to.get(), output);
+ write_kdm_files (film, (*i)->screens(), cpl, valid_from.get(), valid_to.get(), output);
if (verbose) {
cout << "Wrote KDM files to " << output << "\n";
}
#include <wx/timectrl.h>
#include <wx/stdpaths.h>
#include <wx/listctrl.h>
+#include <libcxml/cxml.h>
#include "lib/cinema.h"
#include "lib/config.h"
#include "lib/film.h"
using std::list;
using std::pair;
using std::cout;
+using std::vector;
using std::make_pair;
using boost::shared_ptr;
KDMDialog::KDMDialog (wxWindow* parent, boost::shared_ptr<const Film> film)
: wxDialog (parent, wxID_ANY, _("Make KDMs"))
{
+ /* Main sizer */
wxBoxSizer* vertical = new wxBoxSizer (wxVERTICAL);
- wxBoxSizer* targets = new wxBoxSizer (wxHORIZONTAL);
+
+ /* Font for sub-headings */
+ wxFont subheading_font (*wxNORMAL_FONT);
+ subheading_font.SetWeight (wxFONTWEIGHT_BOLD);
+
+
+ /* Sub-heading: Screens */
+ wxStaticText* h = new wxStaticText (this, wxID_ANY, _("Screens"));
+ h->SetFont (subheading_font);
+ vertical->Add (h, 0, wxALIGN_CENTER_VERTICAL);
+ wxBoxSizer* targets = new wxBoxSizer (wxHORIZONTAL);
_targets = new wxTreeCtrl (this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTR_HIDE_ROOT | wxTR_MULTIPLE | wxTR_HAS_BUTTONS);
- targets->Add (_targets, 1, wxEXPAND | wxALL, 6);
+ targets->Add (_targets, 1, wxEXPAND | wxTOP | wxRIGHT, DCPOMATIC_SIZER_GAP);
_root = _targets->AddRoot ("Foo");
wxBoxSizer* target_buttons = new wxBoxSizer (wxVERTICAL);
_add_cinema = new wxButton (this, wxID_ANY, _("Add Cinema..."));
- target_buttons->Add (_add_cinema, 1, wxEXPAND, 6);
+ target_buttons->Add (_add_cinema, 1, wxEXPAND | wxALL, DCPOMATIC_BUTTON_STACK_GAP);
_edit_cinema = new wxButton (this, wxID_ANY, _("Edit Cinema..."));
- target_buttons->Add (_edit_cinema, 1, wxEXPAND, 6);
+ target_buttons->Add (_edit_cinema, 1, wxEXPAND | wxALL, DCPOMATIC_BUTTON_STACK_GAP);
_remove_cinema = new wxButton (this, wxID_ANY, _("Remove Cinema"));
- target_buttons->Add (_remove_cinema, 1, wxEXPAND, 6);
+ target_buttons->Add (_remove_cinema, 1, wxEXPAND | wxALL, DCPOMATIC_BUTTON_STACK_GAP);
_add_screen = new wxButton (this, wxID_ANY, _("Add Screen..."));
- target_buttons->Add (_add_screen, 1, wxEXPAND, 6);
+ target_buttons->Add (_add_screen, 1, wxEXPAND | wxALL, DCPOMATIC_BUTTON_STACK_GAP);
_edit_screen = new wxButton (this, wxID_ANY, _("Edit Screen..."));
- target_buttons->Add (_edit_screen, 1, wxEXPAND, 6);
+ target_buttons->Add (_edit_screen, 1, wxEXPAND | wxALL, DCPOMATIC_BUTTON_STACK_GAP);
_remove_screen = new wxButton (this, wxID_ANY, _("Remove Screen"));
- target_buttons->Add (_remove_screen, 1, wxEXPAND, 6);
+ target_buttons->Add (_remove_screen, 1, wxEXPAND | wxALL, DCPOMATIC_BUTTON_STACK_GAP);
+
+ targets->Add (target_buttons, 0, 0);
- targets->Add (target_buttons, 0, 0, 6);
+ vertical->Add (targets, 1, wxEXPAND);
- vertical->Add (targets, 1, wxEXPAND | wxALL, 6);
- wxFlexGridSizer* table = new wxFlexGridSizer (3, 2, 6);
+ /* Sub-heading: Timing */
+ h = new wxStaticText (this, wxID_ANY, _("Timing"));
+ h->SetFont (subheading_font);
+ vertical->Add (h, 0, wxALIGN_CENTER_VERTICAL | wxTOP, DCPOMATIC_SIZER_Y_GAP * 2);
+
+ wxFlexGridSizer* table = new wxFlexGridSizer (3, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
add_label_to_sizer (table, this, _("From"), true);
wxDateTime from;
from.SetToCurrent ();
_until_time = new wxTimePickerCtrl (this, wxID_ANY, to);
table->Add (_until_time, 1, wxEXPAND);
- vertical->Add (table, 0, wxEXPAND | wxALL, 6);
+ vertical->Add (table, 0, wxEXPAND | wxTOP, DCPOMATIC_SIZER_GAP);
+
- _dcps = new wxListCtrl (this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_REPORT | wxLC_SINGLE_SEL);
- wxListItem ip;
- ip.SetId (0);
- ip.SetText (_("DCP"));
- ip.SetWidth (400);
- _dcps->InsertColumn (0, ip);
- vertical->Add (_dcps, 0, wxEXPAND | wxALL, 6);
+ /* Sub-heading: CPL */
+ h = new wxStaticText (this, wxID_ANY, _("CPL"));
+ h->SetFont (subheading_font);
+ vertical->Add (h, 0, wxALIGN_CENTER_VERTICAL | wxTOP, DCPOMATIC_SIZER_Y_GAP * 2);
- list<boost::filesystem::path> dcps = film->dcps ();
- for (list<boost::filesystem::path>::const_iterator i = dcps.begin(); i != dcps.end(); ++i) {
- wxListItem item;
- int const n = _dcps->GetItemCount ();
- item.SetId (n);
- _dcps->InsertItem (item);
- _dcps->SetItem (n, 0, std_to_wx (i->string ()));
-
- if (dcps.size() == 1 || i->string() == film->dcp_name ()) {
- _dcps->SetItemState (n, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
- }
- }
+ /* CPL choice */
+ wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
+ add_label_to_sizer (s, this, _("CPL"), true);
+ _cpl = new wxChoice (this, wxID_ANY);
+ s->Add (_cpl, 1, wxEXPAND);
+ _cpl_browse = new wxButton (this, wxID_ANY, _("Browse..."));
+ s->Add (_cpl_browse, 0);
+ vertical->Add (s, 0, wxEXPAND | wxTOP, DCPOMATIC_SIZER_GAP + 2);
+
+ /* CPL details */
+ table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
+ add_label_to_sizer (table, this, _("DCP directory"), true);
+ _dcp_directory = new wxStaticText (this, wxID_ANY, "");
+ table->Add (_dcp_directory);
+ add_label_to_sizer (table, this, _("CPL ID"), true);
+ _cpl_id = new wxStaticText (this, wxID_ANY, "");
+ table->Add (_cpl_id);
+ add_label_to_sizer (table, this, _("CPL annotation text"), true);
+ _cpl_annotation_text = new wxStaticText (this, wxID_ANY, "");
+ table->Add (_cpl_annotation_text);
+ vertical->Add (table, 0, wxEXPAND | wxTOP, DCPOMATIC_SIZER_GAP + 2);
+
+ _cpls = film->cpls ();
+ update_cpl_choice ();
- table = new wxFlexGridSizer (2, 2, 6);
+
+ /* Sub-heading: Output */
+ h = new wxStaticText (this, wxID_ANY, _("Output"));
+ h->SetFont (subheading_font);
+ vertical->Add (h, 0, wxALIGN_CENTER_VERTICAL | wxTOP, DCPOMATIC_SIZER_Y_GAP * 2);
+
+ table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, 0);
_write_to = new wxRadioButton (this, wxID_ANY, _("Write to"));
table->Add (_write_to, 1, wxEXPAND);
table->Add (_email, 1, wxEXPAND);
table->AddSpacer (0);
- vertical->Add (table, 0, wxEXPAND | wxALL, 6);
+ vertical->Add (table, 0, wxEXPAND | wxTOP, DCPOMATIC_SIZER_GAP);
+
+ /* Make an overall sizer to get a nice border, and put some buttons in */
+
+ wxBoxSizer* overall_sizer = new wxBoxSizer (wxVERTICAL);
+ overall_sizer->Add (vertical, 0, wxEXPAND | wxTOP | wxLEFT | wxRIGHT, DCPOMATIC_DIALOG_BORDER);
wxSizer* buttons = CreateSeparatedButtonSizer (wxOK | wxCANCEL);
if (buttons) {
- vertical->Add (buttons, wxSizerFlags().Expand().DoubleBorder());
+ overall_sizer->Add (buttons, 0, wxEXPAND | wxTOP, DCPOMATIC_SIZER_Y_GAP);
}
_write_to->SetValue (true);
+ /* Bind */
+
_targets->Bind (wxEVT_COMMAND_TREE_SEL_CHANGED, boost::bind (&KDMDialog::setup_sensitivity, this));
_add_cinema->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&KDMDialog::add_cinema_clicked, this));
_edit_screen->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&KDMDialog::edit_screen_clicked, this));
_remove_screen->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&KDMDialog::remove_screen_clicked, this));
- _dcps->Bind (wxEVT_COMMAND_LIST_ITEM_SELECTED, boost::bind (&KDMDialog::setup_sensitivity, this));
- _dcps->Bind (wxEVT_COMMAND_LIST_ITEM_DESELECTED, boost::bind (&KDMDialog::setup_sensitivity, this));
+ _cpl->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&KDMDialog::update_cpl_summary, this));
+ _cpl_browse->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&KDMDialog::cpl_browse_clicked, this));
_write_to->Bind (wxEVT_COMMAND_RADIOBUTTON_SELECTED, boost::bind (&KDMDialog::setup_sensitivity, this));
_email->Bind (wxEVT_COMMAND_RADIOBUTTON_SELECTED, boost::bind (&KDMDialog::setup_sensitivity, this));
setup_sensitivity ();
-
- SetSizer (vertical);
- vertical->Layout ();
- vertical->SetSizeHints (this);
+
+ SetSizer (overall_sizer);
+ overall_sizer->Layout ();
+ overall_sizer->SetSizeHints (this);
}
list<pair<wxTreeItemId, shared_ptr<Cinema> > >
{
bool const sc = selected_cinemas().size() == 1;
bool const ss = selected_screens().size() == 1;
- bool const sd = _dcps->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED) != -1;
+ bool const sd = _cpl->GetSelection() != -1;
_edit_cinema->Enable (sc);
_remove_cinema->Enable (sc);
}
boost::filesystem::path
-KDMDialog::dcp () const
+KDMDialog::cpl () const
{
- int const item = _dcps->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
+ int const item = _cpl->GetSelection ();
assert (item >= 0);
- return wx_to_std (_dcps->GetItemText (item));
+ return _cpls[item].cpl_file;
}
boost::filesystem::path
{
return _write_to->GetValue ();
}
+
+void
+KDMDialog::update_cpl_choice ()
+{
+ _cpl->Clear ();
+
+ for (vector<CPLSummary>::const_iterator i = _cpls.begin(); i != _cpls.end(); ++i) {
+ _cpl->Append (std_to_wx (i->cpl_id));
+
+ if (_cpls.size() > 0) {
+ _cpl->SetSelection (0);
+ }
+ }
+
+ update_cpl_summary ();
+}
+
+void
+KDMDialog::update_cpl_summary ()
+{
+ int const n = _cpl->GetSelection();
+ if (n == wxNOT_FOUND) {
+ return;
+ }
+
+ _dcp_directory->SetLabel (std_to_wx (_cpls[n].dcp_directory));
+ _cpl_id->SetLabel (std_to_wx (_cpls[n].cpl_id));
+ _cpl_annotation_text->SetLabel (std_to_wx (_cpls[n].cpl_annotation_text));
+}
+
+void
+KDMDialog::cpl_browse_clicked ()
+{
+ wxFileDialog d (this, _("Select CPL XML file"), wxEmptyString, wxEmptyString, "*.xml");
+ if (d.ShowModal() == wxID_CANCEL) {
+ return;
+ }
+
+ boost::filesystem::path cpl_file (wx_to_std (d.GetPath ()));
+ boost::filesystem::path dcp_dir = cpl_file.parent_path ();
+
+ /* XXX: hack alert */
+ cxml::Document cpl_document ("CompositionPlaylist");
+ cpl_document.read_file (cpl_file);
+
+ try {
+ _cpls.push_back (
+ CPLSummary (
+ dcp_dir.filename().string(),
+ cpl_document.string_child("Id").substr (9),
+ cpl_document.string_child ("ContentTitleText"),
+ cpl_file
+ )
+ );
+ } catch (cxml::Error) {
+ error_dialog (this, _("This is not a valid CPL file"));
+ return;
+ }
+
+ update_cpl_choice ();
+ _cpl->SetSelection (_cpls.size() - 1);
+ update_cpl_summary ();
+}
/** @return KDM until time in local time */
boost::posix_time::ptime until () const;
- boost::filesystem::path dcp () const;
+ boost::filesystem::path cpl () const;
boost::filesystem::path directory () const;
bool write_to () const;
std::list<std::pair<wxTreeItemId, boost::shared_ptr<Cinema> > > selected_cinemas () const;
std::list<std::pair<wxTreeItemId, boost::shared_ptr<Screen> > > selected_screens () const;
void setup_sensitivity ();
+ void update_cpl_choice ();
+ void update_cpl_summary ();
+ void cpl_browse_clicked ();
static boost::posix_time::ptime posix_time (wxDatePickerCtrl *, wxTimePickerCtrl *);
wxDatePickerCtrl* _until_date;
wxTimePickerCtrl* _from_time;
wxTimePickerCtrl* _until_time;
- wxListCtrl* _dcps;
+ wxChoice* _cpl;
+ wxButton* _cpl_browse;
+ wxStaticText* _dcp_directory;
+ wxStaticText* _cpl_id;
+ wxStaticText* _cpl_annotation_text;
wxRadioButton* _write_to;
#ifdef DCPOMATIC_USE_OWN_DIR_PICKER
DirPickerCtrl* _folder;
wxTreeItemId _root;
std::map<wxTreeItemId, boost::shared_ptr<Cinema> > _cinemas;
std::map<wxTreeItemId, boost::shared_ptr<Screen> > _screens;
+ std::vector<CPLSummary> _cpls;
};
#define DCPOMATIC_SIZER_X_GAP 8
#define DCPOMATIC_SIZER_Y_GAP 8
+#define DCPOMATIC_SIZER_GAP 8
#define DCPOMATIC_DIALOG_BORDER 12
+/** Spacing to use between buttons in a vertical line */
+#define DCPOMATIC_BUTTON_STACK_GAP 2
/** @file src/wx/wx_util.h
* @brief Some utility functions and classes.
wait_for_jobs ();
}
-/** Test Film::have_dcp(). Requires the output from ffmpeg_dcp_test above */
+/** Briefly test Film::cpls(). Requires the output from ffmpeg_dcp_test above */
BOOST_AUTO_TEST_CASE (ffmpeg_have_dcp_test)
{
boost::filesystem::path p = test_film_dir ("ffmpeg_dcp_test");
shared_ptr<Film> f (new Film (p.string ()));
f->read_metadata ();
- BOOST_CHECK (!f->dcps().empty());
+ BOOST_CHECK (!f->cpls().empty());
p /= f->dcp_name();
p /= f->video_mxf_filename();
boost::filesystem::remove (p);
- BOOST_CHECK (f->dcps().empty());
+ BOOST_CHECK (f->cpls().empty());
}