Various work on playlist editor.
authorCarl Hetherington <cth@carlh.net>
Wed, 14 Nov 2018 21:52:42 +0000 (21:52 +0000)
committerCarl Hetherington <cth@carlh.net>
Thu, 22 Nov 2018 23:25:40 +0000 (23:25 +0000)
12 files changed:
graphics/no_tick.png [new file with mode: 0644]
graphics/src/no_tick.svg [new file with mode: 0644]
graphics/src/tick.svg [new file with mode: 0644]
graphics/tick.png [new file with mode: 0644]
graphics/update
graphics/web/favicon-128x128.png
graphics/web/favicon-16x16.png
graphics/web/favicon-32x32.png
graphics/web/favicon-64x64.png
graphics/wscript
platform/windows/wscript
src/tools/dcpomatic_playlist.cc

diff --git a/graphics/no_tick.png b/graphics/no_tick.png
new file mode 100644 (file)
index 0000000..71ca653
Binary files /dev/null and b/graphics/no_tick.png differ
diff --git a/graphics/src/no_tick.svg b/graphics/src/no_tick.svg
new file mode 100644 (file)
index 0000000..82bd047
--- /dev/null
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="68mm"
+   height="68mm"
+   viewBox="0 0 68 68"
+   version="1.1"
+   id="svg8"
+   inkscape:version="0.92.3 (2405546, 2018-03-11)"
+   sodipodi:docname="no_tick.svg">
+  <defs
+     id="defs2" />
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="1.979899"
+     inkscape:cx="218.11091"
+     inkscape:cy="81.63874"
+     inkscape:document-units="mm"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     inkscape:window-width="1680"
+     inkscape:window-height="995"
+     inkscape:window-x="0"
+     inkscape:window-y="27"
+     inkscape:window-maximized="1" />
+  <metadata
+     id="metadata5">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(-38.743245,-53.688651)" />
+</svg>
diff --git a/graphics/src/tick.svg b/graphics/src/tick.svg
new file mode 100644 (file)
index 0000000..8ed6cc2
--- /dev/null
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="68mm"
+   height="68mm"
+   viewBox="0 0 68 68"
+   version="1.1"
+   id="svg8"
+   inkscape:version="0.92.3 (2405546, 2018-03-11)"
+   sodipodi:docname="tick.svg">
+  <defs
+     id="defs2" />
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="1.979899"
+     inkscape:cx="218.11091"
+     inkscape:cy="81.63874"
+     inkscape:document-units="mm"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     inkscape:window-width="1680"
+     inkscape:window-height="995"
+     inkscape:window-x="0"
+     inkscape:window-y="27"
+     inkscape:window-maximized="1" />
+  <metadata
+     id="metadata5">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(-38.743245,-53.688651)">
+    <path
+       style="fill:none;stroke:#000000;stroke-width:12.86499977;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 45.241267,93.524044 67.35192,115.25672 C 73.462403,94.316949 82.200179,75.575894 99.802375,60.6318"
+       id="path815"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccc" />
+  </g>
+</svg>
diff --git a/graphics/tick.png b/graphics/tick.png
new file mode 100644 (file)
index 0000000..8d64ba7
Binary files /dev/null and b/graphics/tick.png differ
index 33e6365d2cb6c3672c6824823602fcb0fe633119..95a762044eee0f388432b3b53840589aa7735903 100755 (executable)
@@ -70,6 +70,10 @@ else
         $INKSCAPE $i.png src/$i.svg -w 32 -h 32
     done
 
+    # Playlist editor tick/no-tick
+    $INKSCAPE tick.png src/tick.svg -w 16 -h 16
+    $INKSCAPE no_tick.png src/no_tick.svg -w 16 -h 16
+
     # favicon
     mkdir -p web
     convert src/web.png -resize 256x256 -transparent white web/favicon-256x256.png
index 483437a49cc2c94b4e323e3d01e82f3434c58c2f..19eda697142804cda31f0d4e62ee44c7a16ff895 100644 (file)
Binary files a/graphics/web/favicon-128x128.png and b/graphics/web/favicon-128x128.png differ
index 021d1516ce3fc7a6de19bd1d64129791b0ab7241..1574628d9e6d5ef304322451d97256c2a08ee643 100644 (file)
Binary files a/graphics/web/favicon-16x16.png and b/graphics/web/favicon-16x16.png differ
index 3b859ebd6adfb8e56acab442ccce93d4cb2748c9..fa76c31bdce91890f558294a2ed12eb16a25a5d3 100644 (file)
Binary files a/graphics/web/favicon-32x32.png and b/graphics/web/favicon-32x32.png differ
index 8ad96f6b7975e186784b3a426d623d9224100daa..dae734b5b633e5ae288cf6590223e93d1cce3722 100644 (file)
Binary files a/graphics/web/favicon-64x64.png and b/graphics/web/favicon-64x64.png differ
index 72418cb53420a7547024e41b2a8c5031178eb797..4be52af9a856610d2bd7f23530ff581488f4cc4a 100644 (file)
@@ -35,3 +35,5 @@ def build(bld):
         bld.install_files('${PREFIX}/share/dcpomatic2', 'select.png')
         bld.install_files('${PREFIX}/share/dcpomatic2', 'snap.png')
         bld.install_files('${PREFIX}/share/dcpomatic2', 'sequence.png')
+        bld.install_files('${PREFIX}/share/dcpomatic2', 'tick.png')
+        bld.install_files('${PREFIX}/share/dcpomatic2', 'no_tick.png')
index 881b4c73ed14411e281e343ec2bf78b7d65456a2..c87521b045dd4d6f39721c8698126a5e5948790d 100644 (file)
@@ -296,6 +296,8 @@ File "%graphics%/zoom_all.png"
 File "%graphics%/select.png"
 File "%graphics%/snap.png"
 File "%graphics%/sequence.png"
+File "%graphics%/tick.png"
+File "%graphics%/no_tick.png"
 
 SectionEnd
     """, file=f)
index 889ed6b1701826d082d67ecf44467beaf8ac4d83..ec8c1efd8ed8c2d79bde8d608e5cc27569be29d9 100644 (file)
 #include "../wx/wx_signal_manager.h"
 #include "../lib/util.h"
 #include "../lib/config.h"
+#include "../lib/cross.h"
 #include <wx/wx.h>
 #include <wx/listctrl.h>
 #include <wx/imaglist.h>
 
 using std::exception;
+using std::cout;
+using boost::optional;
+
+class PlaylistEntry
+{
+public:
+       std::string name;
+       std::string cpl_id;
+       dcp::ContentKind kind;
+       enum Type {
+               DCP,
+               ECINEMA
+       };
+       Type type;
+       bool encrypted;
+       bool skippable;
+       bool disable_timeline;
+       bool stop_after_play;
+};
+
 
 class DOMFrame : public wxFrame
 {
@@ -46,45 +67,143 @@ public:
 
                _list->AppendColumn (_("Name"), wxLIST_FORMAT_LEFT, 400);
                _list->AppendColumn (_("CPL"), wxLIST_FORMAT_LEFT, 400);
-               _list->AppendColumn (_("Type"), wxLIST_FORMAT_LEFT, 75);
-               _list->AppendColumn (_("Format"), wxLIST_FORMAT_LEFT, 75);
-               _list->AppendColumn (_("Encrypted"), wxLIST_FORMAT_LEFT, 90);
-               _list->AppendColumn (_("Skippable"), wxLIST_FORMAT_LEFT, 90);
-               _list->AppendColumn (_("Disable timeline"), wxLIST_FORMAT_LEFT, 125);
-               _list->AppendColumn (_("Stop after play"), wxLIST_FORMAT_LEFT, 125);
-
-               /*
+               _list->AppendColumn (_("Type"), wxLIST_FORMAT_CENTRE, 75);
+               _list->AppendColumn (_("Format"), wxLIST_FORMAT_CENTRE, 75);
+               _list->AppendColumn (_("Encrypted"), wxLIST_FORMAT_CENTRE, 90);
+               _list->AppendColumn (_("Skippable"), wxLIST_FORMAT_CENTRE, 90);
+               _list->AppendColumn (_("Disable timeline"), wxLIST_FORMAT_CENTRE, 125);
+               _list->AppendColumn (_("Stop after play"), wxLIST_FORMAT_CENTRE, 125);
+
                wxImageList* images = new wxImageList (16, 16);
-               wxIcon icon;
-               icon.LoadFile ("test.png", wxBITMAP_TYPE_PNG);
-               images->Add (icon);
-               _list->SetImageList (images, wxIMAGE_LIST_SMALL);
-               */
+               wxIcon tick_icon;
+               wxIcon no_tick_icon;
+#ifdef DCPOMATIX_OSX
+               tick_icon.LoadFile ("tick.png", wxBITMAP_TYPE_PNG_RESOURCE);
+               no_tick_icon.LoadFile ("no_tick.png", wxBITMAP_TYPE_PNG_RESOURCE);
+#else
+               boost::filesystem::path tick_path = shared_path() / "tick.png";
+               tick_icon.LoadFile (std_to_wx(tick_path.string()));
+               boost::filesystem::path no_tick_path = shared_path() / "no_tick.png";
+               no_tick_icon.LoadFile (std_to_wx(no_tick_path.string()));
+#endif
+               images->Add (tick_icon);
+               images->Add (no_tick_icon);
 
-               wxListItem item;
-               item.SetId (0);
-               item.SetImage (0);
-               _list->InsertItem (item);
+               _list->SetImageList (images, wxIMAGE_LIST_SMALL);
 
                main_sizer->Add (_list, 1, wxEXPAND | wxALL, DCPOMATIC_SIZER_GAP);
 
                wxBoxSizer* button_sizer = new wxBoxSizer (wxVERTICAL);
                _up = new wxButton (overall_panel, wxID_ANY, _("Up"));
-               button_sizer->Add (_up, 0, wxALL, DCPOMATIC_SIZER_GAP);
+               _down = new wxButton (overall_panel, wxID_ANY, _("Down"));
+               _add = new wxButton (overall_panel, wxID_ANY, _("Add"));
+               _remove = new wxButton (overall_panel, wxID_ANY, _("Remove"));
+               _save = new wxButton (overall_panel, wxID_ANY, _("Save playlist"));
+               _load = new wxButton (overall_panel, wxID_ANY, _("Load playlist"));
+               button_sizer->Add (_up, 0, wxEXPAND | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
+               button_sizer->Add (_down, 0, wxEXPAND | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
+               button_sizer->Add (_add, 0, wxEXPAND | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
+               button_sizer->Add (_remove, 0, wxEXPAND | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
+               button_sizer->Add (_save, 0, wxEXPAND | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
+               button_sizer->Add (_load, 0, wxEXPAND | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
 
                main_sizer->Add (button_sizer, 0, wxALL, DCPOMATIC_SIZER_GAP);
                overall_panel->SetSizer (main_sizer);
 
+               _list->Bind (wxEVT_LEFT_DOWN, bind(&DOMFrame::list_left_click, this, _1));
+
+               PlaylistEntry pe;
+               pe.name = "Shit";
+               pe.cpl_id = "sh-1t";
+               pe.kind = dcp::FEATURE;
+               pe.type = PlaylistEntry::ECINEMA;
+               pe.encrypted = true;
+               pe.disable_timeline = false;
+               pe.stop_after_play = true;
+               add (pe);
+
                setup_sensitivity ();
        }
 
+private:
+
+       void add (PlaylistEntry e)
+       {
+               wxListItem item;
+               item.SetId (0);
+               long const N = _list->InsertItem (item);
+               set_item (N, e);
+               _playlist.push_back (e);
+       }
+
+       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, 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"));
+               _list->SetItem (N, COLUMN_SKIPPABLE, wxEmptyString, e.skippable ? 0 : 1);
+               _list->SetItem (N, COLUMN_DISABLE_TIMELINE, wxEmptyString, e.disable_timeline ? 0 : 1);
+               _list->SetItem (N, COLUMN_STOP_AFTER_PLAY, wxEmptyString, e.stop_after_play ? 0 : 1);
+       }
+
        void setup_sensitivity ()
        {
+               int const selected = _list->GetSelectedItemCount ();
+               _up->Enable (selected > 0);
+               _down->Enable (selected > 0);
+               _remove->Enable (selected > 0);
+       }
 
+       void list_left_click (wxMouseEvent& ev)
+       {
+               int flags;
+               long item = _list->HitTest (ev.GetPosition(), flags, 0);
+               int x = ev.GetPosition().x;
+               optional<int> column;
+               for (int i = 0; i < _list->GetColumnCount(); ++i) {
+                       x -= _list->GetColumnWidth (i);
+                       if (x < 0) {
+                               column = i;
+                               break;
+                       }
+               }
+
+               if (item != -1 && column) {
+                       switch (*column) {
+                       case COLUMN_SKIPPABLE:
+                               _playlist[item].skippable = !_playlist[item].skippable;
+                               break;
+                       case COLUMN_DISABLE_TIMELINE:
+                               _playlist[item].disable_timeline = !_playlist[item].disable_timeline;
+                               break;
+                       case COLUMN_STOP_AFTER_PLAY:
+                               _playlist[item].stop_after_play = !_playlist[item].stop_after_play;
+                               break;
+                       default:
+                               ev.Skip ();
+                       }
+                       set_item (item, _playlist[item]);
+               } else {
+                       ev.Skip ();
+               }
        }
 
        wxListCtrl* _list;
        wxButton* _up;
+       wxButton* _down;
+       wxButton* _add;
+       wxButton* _remove;
+       wxButton* _save;
+       wxButton* _load;
+       std::vector<PlaylistEntry> _playlist;
+
+       enum {
+               COLUMN_SKIPPABLE = 5,
+               COLUMN_DISABLE_TIMELINE = 6,
+               COLUMN_STOP_AFTER_PLAY = 7
+       };
 };
 
 /** @class App