From 1b4d5951147bc88d771d0afaa98bbfa4ed85a822 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Thu, 15 Nov 2018 22:07:13 +0000 Subject: [PATCH] Basic save/load of playlists. --- src/tools/dcpomatic_playlist.cc | 77 +++++++++++++++++++++++++++++++-- src/wx/content_view.cc | 13 ++++++ src/wx/content_view.h | 2 + 3 files changed, 89 insertions(+), 3 deletions(-) diff --git a/src/tools/dcpomatic_playlist.cc b/src/tools/dcpomatic_playlist.cc index 04beb0250..43cb70550 100644 --- a/src/tools/dcpomatic_playlist.cc +++ b/src/tools/dcpomatic_playlist.cc @@ -32,6 +32,7 @@ using std::exception; using std::cout; +using std::string; using boost::optional; using boost::shared_ptr; using boost::weak_ptr; @@ -45,22 +46,49 @@ public: : skippable (false) , disable_timeline (false) , stop_after_play (false) + { + construct (content); + } + + PlaylistEntry (boost::shared_ptr content, cxml::ConstNodePtr node) + : skippable (node->bool_child("Skippable")) + , disable_timeline (node->bool_child("DisableTimeline")) + , stop_after_play (node->bool_child("StopAfterPlay")) + { + construct (content); + } + + void construct (shared_ptr content) { shared_ptr dcp = dynamic_pointer_cast (content); + digest = content->digest (); if (dcp) { name = dcp->name (); - cpl_id = dcp->cpl().get_value_or(""); + DCPOMATIC_ASSERT (dcp->cpl()); + id = *dcp->cpl(); kind = dcp->content_kind().get_value_or(dcp::FEATURE); type = DCP; encrypted = dcp->encrypted (); } else { name = content->path(0).filename().string(); type = ECINEMA; + kind = dcp::FEATURE; } } + void as_xml (xmlpp::Element* e) + { + e->add_child("Digest")->add_child_text(digest); + e->add_child("Skippable")->add_child_text(skippable ? "1" : "0"); + e->add_child("DisableTimeline")->add_child_text(disable_timeline ? "1" : "0"); + e->add_child("StopAfterPlay")->add_child_text(stop_after_play ? "1" : "0"); + } + std::string name; - std::string cpl_id; + /** Digest of this content */ + std::string digest; + /** CPL ID or something else for MP4 (?) */ + std::string id; dcp::ContentKind kind; enum Type { DCP, @@ -100,6 +128,11 @@ public: return _content_view->selected (); } + shared_ptr get (string digest) const + { + return _content_view->get (digest); + } + private: ContentView* _content_view; }; @@ -175,6 +208,8 @@ public: _down->Bind (wxEVT_BUTTON, bind(&DOMFrame::down_clicked, this)); _add->Bind (wxEVT_BUTTON, bind(&DOMFrame::add_clicked, this)); _remove->Bind (wxEVT_BUTTON, bind(&DOMFrame::remove_clicked, this)); + _save->Bind (wxEVT_BUTTON, bind(&DOMFrame::save_clicked, this)); + _load->Bind (wxEVT_BUTTON, bind(&DOMFrame::load_clicked, this)); setup_sensitivity (); } @@ -198,7 +233,7 @@ private: void set_item (long N, PlaylistEntry e) { _list->SetItem (N, 0, std_to_wx(e.name)); - _list->SetItem (N, 1, std_to_wx(e.cpl_id)); + _list->SetItem (N, 1, std_to_wx(e.id)); _list->SetItem (N, 2, std_to_wx(dcp::content_kind_to_string(e.kind))); _list->SetItem (N, 3, e.type == PlaylistEntry::DCP ? _("DCP") : _("E-cinema")); _list->SetItem (N, 4, e.encrypted ? _("Y") : _("N")); @@ -302,6 +337,42 @@ private: _list->DeleteItem (s); } + void save_clicked () + { + wxFileDialog* d = new wxFileDialog (this, _("Select playlist file"), wxEmptyString, wxEmptyString, wxT("XML files (*.xml)|*.xml"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT); + if (d->ShowModal() == wxID_OK) { + xmlpp::Document doc; + xmlpp::Element* root = doc.create_root_node ("SPL"); + BOOST_FOREACH (PlaylistEntry i, _playlist) { + i.as_xml (root->add_child("Entry")); + } + doc.write_to_file_formatted (wx_to_std(d->GetPath())); + } + } + + void load_clicked () + { + wxFileDialog* d = new wxFileDialog (this, _("Select playlist file"), wxEmptyString, wxEmptyString, wxT("XML files (*.xml)|*.xml")); + if (d->ShowModal() == wxID_OK) { + _list->DeleteAllItems (); + _playlist.clear (); + cxml::Document doc ("SPL"); + doc.read_file (wx_to_std(d->GetPath())); + bool missing = false; + BOOST_FOREACH (cxml::ConstNodePtr i, doc.node_children("Entry")) { + shared_ptr c = _content_dialog->get(i->string_child("Digest")); + if (c) { + add (PlaylistEntry(c, i)); + } else { + missing = true; + } + } + if (missing) { + error_dialog (this, _("Some content in this playlist was not found.")); + } + } + } + wxListCtrl* _list; wxButton* _up; wxButton* _down; diff --git a/src/wx/content_view.cc b/src/wx/content_view.cc index 4eab80339..aeefb65df 100644 --- a/src/wx/content_view.cc +++ b/src/wx/content_view.cc @@ -32,6 +32,7 @@ #include #include +using std::string; using boost::shared_ptr; using boost::weak_ptr; using boost::optional; @@ -145,3 +146,15 @@ ContentView::add (shared_ptr content) it.SetText(std_to_wx(content->summary())); SetItem(it); } + +shared_ptr +ContentView::get (string digest) const +{ + BOOST_FOREACH (shared_ptr i, _content) { + if (i->digest() == digest) { + return i; + } + } + + return shared_ptr(); +} diff --git a/src/wx/content_view.h b/src/wx/content_view.h index 0da53f636..ac64600e1 100644 --- a/src/wx/content_view.h +++ b/src/wx/content_view.h @@ -34,6 +34,8 @@ public: boost::shared_ptr selected () const; void update (); + boost::shared_ptr get (std::string digest) const; + private: void add (boost::shared_ptr content); -- 2.30.2