diff options
| author | Carl Hetherington <cth@carlh.net> | 2022-07-20 00:51:23 +0200 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2022-07-20 10:18:17 +0200 |
| commit | 4bdaccb5ede7d9a1066e0a0665fcfce9b1e3241e (patch) | |
| tree | e8473bb1a1b4736e88a973dc25bcfa369c3ad000 /src/tools | |
| parent | 6d101863c87b34af5c3992168182e80445e56ec7 (diff) | |
Allow multiple DCPs to be written to a disk (#1756).
Diffstat (limited to 'src/tools')
| -rw-r--r-- | src/tools/dcpomatic_disk.cc | 93 | ||||
| -rw-r--r-- | src/tools/dcpomatic_disk_writer.cc | 32 |
2 files changed, 78 insertions, 47 deletions
diff --git a/src/tools/dcpomatic_disk.cc b/src/tools/dcpomatic_disk.cc index e4cc6c264..a517dde65 100644 --- a/src/tools/dcpomatic_disk.cc +++ b/src/tools/dcpomatic_disk.cc @@ -21,6 +21,7 @@ #include "wx/disk_warning_dialog.h" #include "wx/drive_wipe_warning_dialog.h" +#include "wx/editable_list.h" #include "wx/job_manager_view.h" #include "wx/message_dialog.h" #include "wx/try_unmount_dialog.h" @@ -57,6 +58,7 @@ using std::exception; using std::make_shared; using std::shared_ptr; using std::string; +using std::vector; using boost::optional; #if BOOST_VERSION >= 106100 using namespace boost::placeholders; @@ -70,6 +72,33 @@ enum { #endif +class DirDialogWrapper : public wxDirDialog +{ +public: + DirDialogWrapper (wxWindow* parent) + : wxDirDialog (parent, _("Choose a DCP folder"), wxT(""), wxDD_DIR_MUST_EXIST) + { + + } + + boost::optional<boost::filesystem::path> get () const + { + auto const dcp = boost::filesystem::path(wx_to_std(GetPath())); + if (!boost::filesystem::exists(dcp / "ASSETMAP") && !boost::filesystem::exists(dcp / "ASSETMAP.xml")) { + error_dialog (nullptr, _("No ASSETMAP or ASSETMAP.xml found in this folder. Please choose a DCP folder.")); + return {}; + } + + return dcp; + } + + void set (boost::filesystem::path) + { + /* Not used */ + } +}; + + class DOMFrame : public wxFrame { public: @@ -99,12 +128,19 @@ public: int r = 0; add_label_to_sizer (grid, overall_panel, _("DCP"), true, wxGBPosition(r, 0)); - auto dcp_name_sizer = new wxBoxSizer (wxHORIZONTAL); - _dcp_name = new wxStaticText (overall_panel, wxID_ANY, wxEmptyString); - dcp_name_sizer->Add (_dcp_name, 1, wxALIGN_CENTER_VERTICAL | wxRIGHT, DCPOMATIC_SIZER_X_GAP); - _dcp_open = new wxButton (overall_panel, wxID_ANY, _("Open...")); - dcp_name_sizer->Add (_dcp_open, 0); - grid->Add (dcp_name_sizer, wxGBPosition(r, 1), wxDefaultSpan, wxEXPAND); + auto dcp_sizer = new wxBoxSizer (wxHORIZONTAL); + auto dcps = new EditableList<boost::filesystem::path, DirDialogWrapper>( + overall_panel, + { EditableListColumn(_("DCP"), 300, true) }, + boost::bind(&DOMFrame::dcp_paths, this), + boost::bind(&DOMFrame::set_dcp_paths, this, _1), + [](boost::filesystem::path p, int) { return p.filename().string(); }, + false, + EditableListButton::NEW | EditableListButton::REMOVE + ); + + dcp_sizer->Add(dcps, 1, wxALIGN_CENTER_VERTICAL, DCPOMATIC_SIZER_X_GAP); + grid->Add(dcp_sizer, wxGBPosition(r, 1), wxDefaultSpan, wxEXPAND); ++r; add_label_to_sizer (grid, overall_panel, _("Drive"), true, wxGBPosition(r, 0)); @@ -126,7 +162,6 @@ public: grid->AddGrowableCol (1); - _dcp_open->Bind (wxEVT_BUTTON, boost::bind(&DOMFrame::open, this)); _copy->Bind (wxEVT_BUTTON, boost::bind(&DOMFrame::copy, this)); _drive->Bind (wxEVT_CHOICE, boost::bind(&DOMFrame::setup_sensitivity, this)); _drive_refresh->Bind (wxEVT_BUTTON, boost::bind(&DOMFrame::drive_refresh, this)); @@ -180,18 +215,18 @@ public: dcpomatic_sleep_seconds (1); } - void set_dcp (boost::filesystem::path dcp) + void set_dcp_paths (vector<boost::filesystem::path> dcps) { - if (!boost::filesystem::exists(dcp / "ASSETMAP") && !boost::filesystem::exists(dcp / "ASSETMAP.xml")) { - error_dialog (nullptr, _("No ASSETMAP or ASSETMAP.xml found in this folder. Please choose a DCP folder.")); - return; - } - - _dcp_path = dcp; - _dcp_name->SetLabel (std_to_wx(dcp.filename().string())); + _dcp_paths = dcps; + setup_sensitivity(); } private: + vector<boost::filesystem::path> dcp_paths() const + { + return _dcp_paths; + } + void sized (wxSizeEvent& ev) { _sizer->Layout (); @@ -236,22 +271,6 @@ private: ev.Skip (); } - - void open () - { - auto d = new wxDirDialog (this, _("Choose a DCP folder"), wxT(""), wxDD_DIR_MUST_EXIST); - int r = d->ShowModal (); - boost::filesystem::path const path (wx_to_std(d->GetPath())); - d->Destroy (); - - if (r != wxID_OK) { - return; - } - - set_dcp (path); - setup_sensitivity (); - } - void copy () { /* Check that the selected drive still exists and update its properties if so */ @@ -262,7 +281,7 @@ private: } DCPOMATIC_ASSERT (_drive->GetSelection() != wxNOT_FOUND); - DCPOMATIC_ASSERT (static_cast<bool>(_dcp_path)); + DCPOMATIC_ASSERT (!_dcp_paths.empty()); auto ping = [this](int attempt) { if (_nanomsg.send(DISK_WRITER_PING "\n", 1000)) { @@ -356,7 +375,7 @@ private: return; } - JobManager::instance()->add(make_shared<CopyToDriveJob>(*_dcp_path, _drives[_drive->GetSelection()], _nanomsg)); + JobManager::instance()->add(make_shared<CopyToDriveJob>(_dcp_paths, _drives[_drive->GetSelection()], _nanomsg)); setup_sensitivity (); } @@ -385,16 +404,14 @@ private: void setup_sensitivity () { - _copy->Enable (static_cast<bool>(_dcp_path) && _drive->GetSelection() != wxNOT_FOUND && !JobManager::instance()->work_to_do()); + _copy->Enable (!_dcp_paths.empty() && _drive->GetSelection() != wxNOT_FOUND && !JobManager::instance()->work_to_do()); } - wxStaticText* _dcp_name; - wxButton* _dcp_open; wxChoice* _drive; wxButton* _drive_refresh; wxButton* _copy; JobManagerView* _jobs; - boost::optional<boost::filesystem::path> _dcp_path; + std::vector<boost::filesystem::path> _dcp_paths; std::vector<Drive> _drives; #ifndef DCPOMATIC_OSX boost::process::child* _writer; @@ -474,7 +491,7 @@ public: _frame->Show (); if (_dcp_to_write) { - _frame->set_dcp (*_dcp_to_write); + _frame->set_dcp_paths({*_dcp_to_write}); } signal_manager = new wxSignalManager (this); diff --git a/src/tools/dcpomatic_disk_writer.cc b/src/tools/dcpomatic_disk_writer.cc index dca09f729..ef3bf2f77 100644 --- a/src/tools/dcpomatic_disk_writer.cc +++ b/src/tools/dcpomatic_disk_writer.cc @@ -195,16 +195,27 @@ try } }); } else if (*s == DISK_WRITER_WRITE) { - auto dcp_path_opt = nanomsg->receive (LONG_TIMEOUT); auto device_opt = nanomsg->receive (LONG_TIMEOUT); - if (!dcp_path_opt || !device_opt) { + if (!device_opt) { LOG_DISK_NC("Failed to receive write request"); throw CommunicationFailedError(); } - - auto dcp_path = *dcp_path_opt; auto device = *device_opt; + vector<boost::filesystem::path> dcp_paths; + while (true) { + auto dcp_path_opt = nanomsg->receive (LONG_TIMEOUT); + if (!dcp_path_opt) { + LOG_DISK_NC("Failed to receive write request"); + throw CommunicationFailedError(); + } + if (*dcp_path_opt != "") { + dcp_paths.push_back(*dcp_path_opt); + } else { + break; + } + } + /* Do some basic sanity checks; this is a bit belt-and-braces but it can't hurt... */ #ifdef DCPOMATIC_OSX @@ -249,11 +260,14 @@ try return true; } - LOG_DISK ("Here we go writing %1 to %2", dcp_path, device); + LOG_DISK("Here we go writing these to %1", device); + for (auto dcp: dcp_paths) { + LOG_DISK(" %1", dcp); + } request_privileges ( "com.dcpomatic.write-drive", - [dcp_path, device]() { + [dcp_paths, device]() { #if defined(DCPOMATIC_LINUX) auto posix_partition = device; /* XXX: don't know if this logic is sensible */ @@ -262,12 +276,12 @@ try } else { posix_partition += "1"; } - dcpomatic::write (dcp_path, device, posix_partition, nanomsg); + dcpomatic::write (dcp_paths, device, posix_partition, nanomsg); #elif defined(DCPOMATIC_OSX) auto fast_device = boost::algorithm::replace_first_copy (device, "/dev/disk", "/dev/rdisk"); - dcpomatic::write (dcp_path, fast_device, fast_device + "s1", nanomsg); + dcpomatic::write (dcp_paths, fast_device, fast_device + "s1", nanomsg); #elif defined(DCPOMATIC_WINDOWS) - dcpomatic::write (dcp_path, device, "", nanomsg); + dcpomatic::write (dcp_paths, device, "", nanomsg); #endif }, []() { |
