Add options to write KDMs to separate directories / ZIP files.
authorCarl Hetherington <cth@carlh.net>
Fri, 3 Mar 2017 19:55:41 +0000 (19:55 +0000)
committerCarl Hetherington <cth@carlh.net>
Fri, 3 Mar 2017 19:55:41 +0000 (19:55 +0000)
ChangeLog
src/lib/cinema_kdms.cc
src/lib/cinema_kdms.h
src/lib/config.cc
src/lib/config.h
src/tools/dcpomatic_kdm_cli.cc
src/wx/kdm_dialog.cc
src/wx/kdm_output_panel.cc
src/wx/kdm_output_panel.h
src/wx/name_format_editor.cc

index 8a9d86d..5e38fc7 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2017-03-03  Carl Hetherington  <cth@carlh.net>
+
+       * Add option to write KDMs to separate folders
+       or ZIP files.
+
 2017-02-28  Carl Hetherington  <cth@carlh.net>
 
        * Updated de_DE translation from Carsten Kurz.
index e82a987..8cac65f 100644 (file)
@@ -37,6 +37,7 @@ using std::cout;
 using std::string;
 using std::runtime_error;
 using boost::shared_ptr;
+using boost::function;
 
 void
 CinemaKDMs::make_zip_file (boost::filesystem::path zip_file, dcp::NameFormat name_format, dcp::NameFormat::Map name_values) const
@@ -113,24 +114,67 @@ CinemaKDMs::collect (list<ScreenKDM> screen_kdms)
        return cinema_kdms;
 }
 
+/** Write one directory per cinema into another directory */
+int
+CinemaKDMs::write_directories (
+       list<CinemaKDMs> cinema_kdms,
+       boost::filesystem::path directory,
+       dcp::NameFormat container_name_format,
+       dcp::NameFormat filename_format,
+       dcp::NameFormat::Map name_values,
+       function<bool (boost::filesystem::path)> confirm_overwrite
+       )
+{
+       /* No specific screen */
+       name_values['s'] = "";
+
+       int written = 0;
+
+       BOOST_FOREACH (CinemaKDMs const & i, cinema_kdms) {
+               boost::filesystem::path path = directory;
+               name_values['c'] = i.cinema->name;
+               path /= container_name_format.get(name_values, "");
+               if (!boost::filesystem::exists (path) || confirm_overwrite (path)) {
+                       boost::filesystem::create_directories (path);
+                       ScreenKDM::write_files (i.screen_kdms, path, filename_format, name_values, confirm_overwrite);
+               }
+               written += i.screen_kdms.size();
+       }
+
+       return written;
+}
+
 /** Write one ZIP file per cinema into a directory */
-void
+int
 CinemaKDMs::write_zip_files (
        list<CinemaKDMs> cinema_kdms,
        boost::filesystem::path directory,
-       dcp::NameFormat name_format,
-       dcp::NameFormat::Map name_values
+       dcp::NameFormat container_name_format,
+       dcp::NameFormat filename_format,
+       dcp::NameFormat::Map name_values,
+       function<bool (boost::filesystem::path)> confirm_overwrite
        )
 {
        /* No specific screen */
        name_values['s'] = "";
 
+       int written = 0;
+
        BOOST_FOREACH (CinemaKDMs const & i, cinema_kdms) {
                boost::filesystem::path path = directory;
                name_values['c'] = i.cinema->name;
-               path /= name_format.get(name_values, ".zip");
-               i.make_zip_file (path, name_format, name_values);
+               path /= container_name_format.get(name_values, ".zip");
+               if (!boost::filesystem::exists (path) || confirm_overwrite (path)) {
+                       if (boost::filesystem::exists (path)) {
+                               /* Creating a new zip file over an existing one is an error */
+                               boost::filesystem::remove (path);
+                       }
+                       i.make_zip_file (path, filename_format, name_values);
+                       written += i.screen_kdms.size();
+               }
        }
+
+       return written;
 }
 
 /** Email one ZIP file per cinema to the cinema.
index e29fa5c..98cb845 100644 (file)
@@ -31,11 +31,22 @@ public:
 
        static std::list<CinemaKDMs> collect (std::list<ScreenKDM> kdms);
 
-       static void write_zip_files (
+       static int write_directories (
                std::list<CinemaKDMs> cinema_kdms,
                boost::filesystem::path directory,
-               dcp::NameFormat name_format,
-               dcp::NameFormat::Map name_values
+               dcp::NameFormat container_name_format,
+               dcp::NameFormat filename_format,
+               dcp::NameFormat::Map name_values,
+               boost::function<bool (boost::filesystem::path)> confirm_overwrite
+               );
+
+       static int write_zip_files (
+               std::list<CinemaKDMs> cinema_kdms,
+               boost::filesystem::path directory,
+               dcp::NameFormat container_name_format,
+               dcp::NameFormat filename_format,
+               dcp::NameFormat::Map name_values,
+               boost::function<bool (boost::filesystem::path)> confirm_overwrite
                );
 
        static void email (
index 031c046..a7ef7d2 100644 (file)
@@ -111,6 +111,7 @@ Config::set_defaults ()
        _cinemas_file = path ("cinemas.xml");
        _show_hints_before_make_dcp = true;
        _confirm_kdm_email = true;
+       _kdm_container_name_format = dcp::NameFormat ("KDM %f %c");
        _kdm_filename_format = dcp::NameFormat ("KDM %f %c %s");
        _dcp_metadata_filename_format = dcp::NameFormat ("%t");
        _dcp_asset_filename_format = dcp::NameFormat ("%t");
@@ -302,6 +303,7 @@ try
        _cinemas_file = f.optional_string_child("CinemasFile").get_value_or (path ("cinemas.xml").string ());
        _show_hints_before_make_dcp = f.optional_bool_child("ShowHintsBeforeMakeDCP").get_value_or (true);
        _confirm_kdm_email = f.optional_bool_child("ConfirmKDMEmail").get_value_or (true);
+       _kdm_container_name_format = dcp::NameFormat (f.optional_string_child("KDMContainerNameFormat").get_value_or ("KDM %f %c"));
        _kdm_filename_format = dcp::NameFormat (f.optional_string_child("KDMFilenameFormat").get_value_or ("KDM %f %c %s"));
        _dcp_metadata_filename_format = dcp::NameFormat (f.optional_string_child("DCPMetadataFilenameFormat").get_value_or ("%t"));
        _dcp_asset_filename_format = dcp::NameFormat (f.optional_string_child("DCPAssetFilenameFormat").get_value_or ("%t"));
@@ -469,6 +471,7 @@ Config::write_config_xml () const
        root->add_child("ShowHintsBeforeMakeDCP")->add_child_text (_show_hints_before_make_dcp ? "1" : "0");
        root->add_child("ConfirmKDMEmail")->add_child_text (_confirm_kdm_email ? "1" : "0");
        root->add_child("KDMFilenameFormat")->add_child_text (_kdm_filename_format.specification ());
+       root->add_child("KDMContainerNameFormat")->add_child_text (_kdm_container_name_format.specification ());
        root->add_child("DCPMetadataFilenameFormat")->add_child_text (_dcp_metadata_filename_format.specification ());
        root->add_child("DCPAssetFilenameFormat")->add_child_text (_dcp_asset_filename_format.specification ());
 
index 8b8d7c3..5bd8df9 100644 (file)
@@ -285,6 +285,10 @@ public:
                return _confirm_kdm_email;
        }
 
+       dcp::NameFormat kdm_container_name_format () const {
+               return _kdm_container_name_format;
+       }
+
        dcp::NameFormat kdm_filename_format () const {
                return _kdm_filename_format;
        }
@@ -512,6 +516,10 @@ public:
                maybe_set (_confirm_kdm_email, s);
        }
 
+       void set_kdm_container_name_format (dcp::NameFormat n) {
+               maybe_set (_kdm_container_name_format, n);
+       }
+
        void set_kdm_filename_format (dcp::NameFormat n) {
                maybe_set (_kdm_filename_format, n);
        }
@@ -649,6 +657,7 @@ private:
        bool _show_hints_before_make_dcp;
        bool _confirm_kdm_email;
        dcp::NameFormat _kdm_filename_format;
+       dcp::NameFormat _kdm_container_name_format;
        dcp::NameFormat _dcp_metadata_filename_format;
        dcp::NameFormat _dcp_asset_filename_format;
 
index 7cfcaa1..e06b984 100644 (file)
@@ -302,24 +302,26 @@ int main (int argc, char* argv[])
                                );
 
                        if (zip) {
-                               CinemaKDMs::write_zip_files (
+                               int const N = CinemaKDMs::write_zip_files (
                                        CinemaKDMs::collect (screen_kdms),
                                        output,
+                                       Config::instance()->kdm_container_name_format(),
                                        Config::instance()->kdm_filename_format(),
-                                       values
+                                       values,
+                                       bind (&always_overwrite)
                                        );
 
                                if (verbose) {
-                                       cout << "Wrote ZIP files to " << output << "\n";
+                                       cout << "Wrote " << N << " ZIP files to " << output << "\n";
                                }
                        } else {
-                               ScreenKDM::write_files (
+                               int const N = ScreenKDM::write_files (
                                        screen_kdms, output, Config::instance()->kdm_filename_format(), values,
                                        bind (&always_overwrite)
                                        );
 
                                if (verbose) {
-                                       cout << "Wrote KDM files to " << output << "\n";
+                                       cout << "Wrote " << N << " KDM files to " << output << "\n";
                                }
                        }
                } catch (FileError& e) {
index 223a183..5679cf0 100644 (file)
@@ -147,4 +147,13 @@ KDMDialog::make_clicked ()
        if (result.first) {
                JobManager::instance()->add (result.first);
        }
+
+       if (result.second > 0) {
+               /* XXX: proper plural form support in wxWidgets? */
+               wxString s = result.second == 1 ? _("%d KDM written to %s") : _("%d KDMs written to %s");
+               message_dialog (
+                       this,
+                       wxString::Format (s, result.second, std_to_wx(_output->directory().string()).data())
+                       );
+       }
 }
index c6845f7..f9078ea 100644 (file)
@@ -62,6 +62,20 @@ KDMOutputPanel::KDMOutputPanel (wxWindow* parent, bool interop)
 
        {
                int flags = wxALIGN_TOP | wxTOP | wxLEFT | wxRIGHT;
+               wxString t = _("Folder / ZIP name format");
+#ifdef __WXOSX__
+               flags |= wxALIGN_RIGHT;
+               t += wxT (":");
+#endif
+               wxStaticText* m = new wxStaticText (this, wxID_ANY, t);
+               table->Add (m, 0, flags, DCPOMATIC_SIZER_Y_GAP);
+       }
+
+       _container_name_format = new NameFormatEditor (this, Config::instance()->kdm_container_name_format(), dcp::NameFormat::Map(), dcp::NameFormat::Map(), "");
+       table->Add (_container_name_format->panel(), 1, wxEXPAND);
+
+       {
+               int flags = wxALIGN_TOP | wxTOP | wxLEFT | wxRIGHT;
                wxString t = _("Filename format");
 #ifdef __WXOSX__
                flags |= wxALIGN_RIGHT;
@@ -104,6 +118,16 @@ KDMOutputPanel::KDMOutputPanel (wxWindow* parent, bool interop)
 
        table->Add (_folder, 1, wxEXPAND);
 
+       wxSizer* write_options = new wxBoxSizer(wxVERTICAL);
+       _write_flat = new wxRadioButton (this, wxID_ANY, _("Write all KDMs to the same folder"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP);
+       write_options->Add (_write_flat);
+       _write_folder = new wxRadioButton (this, wxID_ANY, _("Write a folder for each cinema's KDMs"));
+       write_options->Add (_write_folder);
+       _write_zip = new wxRadioButton (this, wxID_ANY, _("Write a ZIP file for each cinema's KDMs"));
+       write_options->Add (_write_zip);
+       table->AddSpacer (0);
+       table->Add (write_options);
+
        _email = new wxCheckBox (this, wxID_ANY, _("Send by email"));
        table->Add (_email, 1, wxEXPAND);
        table->AddSpacer (0);
@@ -119,7 +143,11 @@ KDMOutputPanel::KDMOutputPanel (wxWindow* parent, bool interop)
 void
 KDMOutputPanel::setup_sensitivity ()
 {
-       _folder->Enable (_write_to->GetValue ());
+       bool const write = _write_to->GetValue ();
+       _folder->Enable (write);
+       _write_flat->Enable (write);
+       _write_folder->Enable (write);
+       _write_zip->Enable (write);
 }
 
 pair<shared_ptr<Job>, int>
@@ -138,14 +166,34 @@ KDMOutputPanel::make (
                name_values['b'] = dcp::LocalTime(timing->from()).date() + " " + dcp::LocalTime(timing->from()).time_of_day();
                name_values['e'] = dcp::LocalTime(timing->until()).date() + " " + dcp::LocalTime(timing->until()).time_of_day();
 
-               if (_write_to->GetValue ()) {
-                       written = ScreenKDM::write_files (
-                               screen_kdms,
-                               directory(),
-                               _filename_format->get(),
-                               name_values,
-                               confirm_overwrite
-                               );
+               if (_write_to->GetValue()) {
+                       if (_write_flat->GetValue()) {
+                               written = ScreenKDM::write_files (
+                                       screen_kdms,
+                                       directory(),
+                                       _filename_format->get(),
+                                       name_values,
+                                       confirm_overwrite
+                                       );
+                       } else if (_write_folder->GetValue()) {
+                               written = CinemaKDMs::write_directories (
+                                       CinemaKDMs::collect (screen_kdms),
+                                       directory(),
+                                       _container_name_format->get(),
+                                       _filename_format->get(),
+                                       name_values,
+                                       confirm_overwrite
+                                       );
+                       } else if (_write_zip->GetValue()) {
+                               written = CinemaKDMs::write_zip_files (
+                                       CinemaKDMs::collect (screen_kdms),
+                                       directory(),
+                                       _container_name_format->get(),
+                                       _filename_format->get(),
+                                       name_values,
+                                       confirm_overwrite
+                                       );
+                       }
                }
 
                if (_email->GetValue ()) {
index 772c12a..cb6f9a1 100644 (file)
@@ -25,6 +25,7 @@
 #include <wx/wx.h>
 #include <boost/filesystem.hpp>
 
+class wxRadioButton;
 class wxDirPickerCtrl;
 class DirPickerCtrl;
 class KDMTimingPanel;
@@ -51,6 +52,7 @@ public:
 
 private:
        wxChoice* _type;
+       NameFormatEditor* _container_name_format;
        NameFormatEditor* _filename_format;
        wxCheckBox* _write_to;
 #ifdef DCPOMATIC_USE_OWN_PICKER
@@ -58,5 +60,8 @@ private:
 #else
        wxDirPickerCtrl* _folder;
 #endif
+       wxRadioButton* _write_flat;
+       wxRadioButton* _write_folder;
+       wxRadioButton* _write_zip;
        wxCheckBox* _email;
 };
index 1f7ca10..82adc3f 100644 (file)
@@ -34,7 +34,9 @@ NameFormatEditor::NameFormatEditor (wxWindow* parent, dcp::NameFormat name, dcp:
        , _suffix (suffix)
 {
        _sizer->Add (_specification, 0, wxEXPAND, DCPOMATIC_SIZER_Y_GAP);
-       _sizer->Add (_example, 0, wxBOTTOM, DCPOMATIC_SIZER_Y_GAP);
+       if (!_examples.empty ()) {
+               _sizer->Add (_example, 0, wxBOTTOM, DCPOMATIC_SIZER_Y_GAP);
+       }
        _panel->SetSizer (_sizer);
 
        for (dcp::NameFormat::Map::const_iterator i = titles.begin(); i != titles.end(); ++i) {
@@ -63,6 +65,10 @@ NameFormatEditor::changed ()
 void
 NameFormatEditor::update_example ()
 {
+       if (_examples.empty ()) {
+               return;
+       }
+
        _name.set_specification (careful_string_filter (wx_to_std (_specification->GetValue ())));
 
        wxString example = wxString::Format (_("e.g. %s"), std_to_wx (_name.get (_examples, _suffix)));