Plot video and subtitle on one track and audio on the rest in the timeline.
authorCarl Hetherington <cth@carlh.net>
Thu, 25 Feb 2016 17:06:44 +0000 (17:06 +0000)
committerCarl Hetherington <cth@carlh.net>
Thu, 25 Feb 2016 17:06:44 +0000 (17:06 +0000)
16 files changed:
src/lib/rect.h
src/wx/timeline.cc
src/wx/timeline_audio_content_view.h
src/wx/timeline_content_view.cc
src/wx/timeline_content_view.h
src/wx/timeline_reels_view.cc
src/wx/timeline_reels_view.h
src/wx/timeline_subtitle_content_view.cc
src/wx/timeline_subtitle_content_view.h
src/wx/timeline_time_axis_view.cc
src/wx/timeline_time_axis_view.h
src/wx/timeline_video_content_view.h
src/wx/timeline_view.cc
src/wx/timeline_view.h
test/rect_test.cc [new file with mode: 0644]
test/wscript

index 5758dd04e4496955af9b7cc994c492bf785c40b6..602acfc4b8bb5cd6fb691c21861e5a19a54a2248 100644 (file)
@@ -21,6 +21,7 @@
 #define DCPOMATIC_RECT_H
 
 #include "position.h"
+#include <boost/optional.hpp>
 #include <algorithm>
 
 /* Put this inside a namespace as Apple put a Rect in the global namespace */
@@ -67,16 +68,24 @@ public:
                return Position<T> (x, y);
        }
 
-       Rect<T> intersection (Rect<T> const & other) const
+       boost::optional<Rect<T> > intersection (Rect<T> const & other) const
        {
-               T const tx = max (x, other.x);
-               T const ty = max (y, other.y);
+               /* This isn't exactly the paragon of mathematical precision */
 
-               return Rect (
+               T const tx = std::max (x, other.x);
+               T const ty = std::max (y, other.y);
+
+               Rect r (
                        tx, ty,
-                       min (x + width, other.x + other.width) - tx,
-                       min (y + height, other.y + other.height) - ty
+                       std::min (x + width, other.x + other.width) - tx,
+                       std::min (y + height, other.y + other.height) - ty
                        );
+
+               if (r.width < 0 || r.height < 0) {
+                       return boost::optional<Rect<T> > ();
+               }
+
+               return r;
        }
 
        void extend (Rect<T> const & other)
index 62b812c8b92a4c6d8e168bccc8d36bac3afa4397..de20705316d04419df7c389e04d02b28735f97f5 100644 (file)
@@ -89,8 +89,26 @@ Timeline::paint ()
                return;
        }
 
-       for (TimelineViewList::iterator i = _views.begin(); i != _views.end(); ++i) {
-               (*i)->paint (gc);
+
+       BOOST_FOREACH (shared_ptr<TimelineView> i, _views) {
+
+               shared_ptr<TimelineContentView> ic = dynamic_pointer_cast<TimelineContentView> (i);
+
+               /* Find areas of overlap */
+               list<dcpomatic::Rect<int> > overlaps;
+               BOOST_FOREACH (shared_ptr<TimelineView> j, _views) {
+                       shared_ptr<TimelineContentView> jc = dynamic_pointer_cast<TimelineContentView> (j);
+                       if (!ic || !jc || i == j || ic->track() != jc->track() || !ic->active() || !jc->active()) {
+                               continue;
+                       }
+
+                       optional<dcpomatic::Rect<int> > r = j->bbox().intersection (i->bbox());
+                       if (r) {
+                               overlaps.push_back (r.get ());
+                       }
+               }
+
+               i->paint (gc, overlaps);
        }
 
        delete gc;
@@ -169,14 +187,12 @@ Timeline::assign_tracks ()
                        continue;
                }
 
-               shared_ptr<Content> content = cv->content();
-
-               if (dynamic_pointer_cast<VideoContent> (content)) {
+               if (dynamic_pointer_cast<TimelineVideoContentView> (*i)) {
                        /* Video on track 0 */
                        cv->set_track (0);
                        _tracks = max (_tracks, 1);
                        continue;
-               } else if (dynamic_pointer_cast<SubtitleContent> (content)) {
+               } else if (dynamic_pointer_cast<TimelineSubtitleContentView> (*i)) {
                        /* Subtitles on track 1 */
                        cv->set_track (1);
                        _tracks = max (_tracks, 2);
@@ -186,6 +202,7 @@ Timeline::assign_tracks ()
                /* Audio on tracks 2 and up */
                int t = 2;
 
+               shared_ptr<Content> content = cv->content();
                DCPTimePeriod content_period (content->position(), content->end());
 
                while (true) {
index 3d034eed4c192e6fe6a07deeb727fa7df5384433..f24037c34673a6904c82492d4fafe9dedaa418b1 100644 (file)
@@ -28,6 +28,9 @@ public:
        TimelineAudioContentView (Timeline& tl, boost::shared_ptr<Content> c);
 
 private:
+       bool active () const {
+               return true;
+       }
        wxColour background_colour () const;
        wxColour foreground_colour () const;
 };
index ed7e1d3d04ac4c13abd145f881360b861dc55593..b520b5ceb2bd40e292709c0ffe254232d016a6ec 100644 (file)
@@ -24,6 +24,7 @@
 #include <wx/graphics.h>
 #include <boost/foreach.hpp>
 
+using std::list;
 using boost::shared_ptr;
 
 TimelineContentView::TimelineContentView (Timeline& tl, shared_ptr<Content> c)
@@ -91,7 +92,7 @@ TimelineContentView::track () const
 }
 
 void
-TimelineContentView::do_paint (wxGraphicsContext* gc)
+TimelineContentView::do_paint (wxGraphicsContext* gc, list<dcpomatic::Rect<int> > overlaps)
 {
        DCPOMATIC_ASSERT (_track);
 
@@ -132,6 +133,12 @@ TimelineContentView::do_paint (wxGraphicsContext* gc)
                gc->StrokePath (path);
        }
 
+       /* Overlaps */
+       gc->SetBrush (*wxTheBrushList->FindOrCreateBrush (foreground_colour(), wxBRUSHSTYLE_CROSSDIAG_HATCH));
+       for (list<dcpomatic::Rect<int> >::const_iterator i = overlaps.begin(); i != overlaps.end(); ++i) {
+               gc->DrawRectangle (i->x, i->y + 4, i->width, i->height - 8);
+       }
+
        /* Label text */
        wxString name = std_to_wx (cont->summary());
        wxDouble name_width;
index 07bfb25759a4e73839e98778597c3d9026dc6209..b1b8ecd5d44ffa0510e8c9272d8c887f60b5d1de 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2013-2015 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2013-2016 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
@@ -43,12 +43,13 @@ public:
        void unset_track ();
        boost::optional<int> track () const;
 
+       virtual bool active () const = 0;
        virtual wxColour background_colour () const = 0;
        virtual wxColour foreground_colour () const = 0;
 
 private:
 
-       void do_paint (wxGraphicsContext* gc);
+       void do_paint (wxGraphicsContext* gc, std::list<dcpomatic::Rect<int> > overlaps);
        int y_pos (int t) const;
        void content_changed (int p);
 
index cc9d401cf1430bb700ed97d190e2b56429b2fc6d..6c3da465e93dc4600f77d03e7c0b38f25bdbc036 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2015 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2015-2016 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
@@ -24,6 +24,7 @@
 #include <boost/foreach.hpp>
 
 using std::min;
+using std::list;
 
 TimelineReelsView::TimelineReelsView (Timeline& tl, int y)
        : TimelineView (tl)
@@ -46,7 +47,7 @@ TimelineReelsView::set_y (int y)
 }
 
 void
-TimelineReelsView::do_paint (wxGraphicsContext* gc)
+TimelineReelsView::do_paint (wxGraphicsContext* gc, list<dcpomatic::Rect<int> >)
 {
        if (!_timeline.pixels_per_second()) {
                return;
index b357be23c1a559316293c867bf9bc7c43ee8097b..5f8ae1d387966d15496b32e0fdec2cef06a0e509 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2015 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2015-2016 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
@@ -28,7 +28,7 @@ public:
        void set_y (int y);
 
 private:
-       void do_paint (wxGraphicsContext* gc);
+       void do_paint (wxGraphicsContext* gc, std::list<dcpomatic::Rect<int> > overlaps);
 
 private:
        int _y;
index 559fc7f4d2a93834f07ddbb2578e750e70109ded..2b6f8c4a9273ad901ae8ac611b350529ce2a2809 100644 (file)
@@ -33,7 +33,7 @@ wxColour
 TimelineSubtitleContentView::background_colour () const
 {
        shared_ptr<SubtitleContent> sc = _subtitle_content.lock ();
-       if (!sc || !sc->use_subtitles ()) {
+       if (!active ()) {
                return wxColour (210, 210, 210, 128);
        }
 
@@ -44,9 +44,16 @@ wxColour
 TimelineSubtitleContentView::foreground_colour () const
 {
        shared_ptr<SubtitleContent> sc = _subtitle_content.lock ();
-       if (!sc || !sc->use_subtitles ()) {
+       if (!active ()) {
                return wxColour (180, 180, 180, 128);
        }
 
        return wxColour (0, 0, 0, 255);
 }
+
+bool
+TimelineSubtitleContentView::active () const
+{
+       shared_ptr<SubtitleContent> sc = _subtitle_content.lock ();
+       return sc && sc->use_subtitles();
+}
index 42ba432f382e7400ab7ec7fcdfefa4bf295da9e5..6b59912a3e48380f85daf01b7e79d62766af48fd 100644 (file)
@@ -30,6 +30,7 @@ public:
        TimelineSubtitleContentView (Timeline& tl, boost::shared_ptr<SubtitleContent> c);
 
 private:
+       bool active () const;
        wxColour background_colour () const;
        wxColour foreground_colour () const;
 
index 2667d9834a7ecd5497e8cb8330722e653b7e09e3..bbaf5fde2847422114088407f56d4ef684eb83fb 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2013-2015 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2013-2016 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
@@ -22,6 +22,8 @@
 #include <wx/wx.h>
 #include <wx/graphics.h>
 
+using std::list;
+
 TimelineTimeAxisView::TimelineTimeAxisView (Timeline& tl, int y)
        : TimelineView (tl)
        , _y (y)
@@ -43,7 +45,7 @@ TimelineTimeAxisView::set_y (int y)
 }
 
 void
-TimelineTimeAxisView::do_paint (wxGraphicsContext* gc)
+TimelineTimeAxisView::do_paint (wxGraphicsContext* gc, list<dcpomatic::Rect<int> >)
 {
        if (!_timeline.pixels_per_second()) {
                return;
index f72acd4a7fefe23ffa8266f626ea390b2edbbc7d..fbd7c5de9a81245dcc13da4a5a9b2bf269f2129c 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2013-2015 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2013-2016 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
@@ -28,7 +28,7 @@ public:
        void set_y (int y);
 
 private:
-       void do_paint (wxGraphicsContext* gc);
+       void do_paint (wxGraphicsContext* gc, std::list<dcpomatic::Rect<int> > overlaps);
 
 private:
        int _y;
index 795c23006114a95b82b1e72bc0724fde29b617a3..6397ccdb3968ce84704d40beec2a9f73ceea0332 100644 (file)
@@ -28,6 +28,9 @@ public:
        TimelineVideoContentView (Timeline& tl, boost::shared_ptr<Content> c);
 
 private:
+       bool active () const {
+               return true;
+       }
        wxColour background_colour () const;
        wxColour foreground_colour () const;
 };
index fee1921ed3019caca45574ea73fdfd1551d6f26d..d96b8998fd6cf1d14e4666f2654142528b680be4 100644 (file)
@@ -20,6 +20,8 @@
 #include "timeline_view.h"
 #include "timeline.h"
 
+using std::list;
+
 /** @class TimelineView
  *  @brief Parent class for components of the timeline (e.g. a piece of content or an axis).
  */
@@ -30,10 +32,10 @@ TimelineView::TimelineView (Timeline& t)
 }
 
 void
-TimelineView::paint (wxGraphicsContext* g)
+TimelineView::paint (wxGraphicsContext* g, list<dcpomatic::Rect<int> > overlaps)
 {
        _last_paint_bbox = bbox ();
-       do_paint (g);
+       do_paint (g, overlaps);
 }
 
 void
index 55fd64d51bfc453dc61545203a8439914347c6a4..01f1ca23d2c44bbe63e0b2ef5ba5677a446bc22b 100644 (file)
@@ -36,13 +36,13 @@ public:
        TimelineView (Timeline& t);
        virtual ~TimelineView () {}
 
-       void paint (wxGraphicsContext* g);
+       void paint (wxGraphicsContext* g, std::list<dcpomatic::Rect<int> > overlaps);
        void force_redraw ();
 
        virtual dcpomatic::Rect<int> bbox () const = 0;
 
 protected:
-       virtual void do_paint (wxGraphicsContext *) = 0;
+       virtual void do_paint (wxGraphicsContext *, std::list<dcpomatic::Rect<int> > overlaps) = 0;
 
        int time_x (DCPTime t) const;
 
diff --git a/test/rect_test.cc b/test/rect_test.cc
new file mode 100644 (file)
index 0000000..b2f70cf
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+    Copyright (C) 2016 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
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "lib/rect.h"
+#include <boost/test/unit_test.hpp>
+#include <iostream>
+
+using boost::optional;
+
+BOOST_AUTO_TEST_CASE (rect_test)
+{
+       dcpomatic::Rect<int> a (0, 0, 100, 100);
+       dcpomatic::Rect<int> b (200, 200, 100, 100);
+       optional<dcpomatic::Rect<int> > c = a.intersection (b);
+       BOOST_CHECK (!c);
+}
index 5d468f68c8a24658952fe1c195aaf91a17bba101..7efe6e61c9f692f594e631ab0ec97ca107ff6967 100644 (file)
@@ -71,6 +71,7 @@ def build(bld):
                  ratio_test.cc
                  repeat_frame_test.cc
                  recover_test.cc
+                 rect_test.cc
                  reels_test.cc
                  required_disk_space_test.cc
                  resampler_test.cc