Add a PlaylistOrderChanged signal and emit it when the playlist
authorCarl Hetherington <cth@carlh.net>
Sat, 30 Jan 2016 20:39:12 +0000 (20:39 +0000)
committerCarl Hetherington <cth@carlh.net>
Sat, 30 Jan 2016 20:39:12 +0000 (20:39 +0000)
is sorted.  Do playlist sorting when content position / length etc.
changes.  Handle sorts better when comparing content at the same
position.

ChangeLog
src/lib/film.cc
src/lib/film.h
src/lib/playlist.cc
src/lib/playlist.h
src/wx/content_panel.cc
src/wx/timeline.cc

index c2d05c5eb0ba8bb71486a7019a60002e7574a5d1..3ae8fe78aeeab8915471767dc0ef743ffed378a6 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2016-01-30  Carl Hetherington  <cth@carlh.net>
+
+       * Fix a collection of strange problems with the content list when
+       dragging content around in the timeline.
+
 2016-01-24  Carl Hetherington  <cth@carlh.net>
 
        * Fix encodes getting stuck in some cases (#783).
 2016-01-24  Carl Hetherington  <cth@carlh.net>
 
        * Fix encodes getting stuck in some cases (#783).
index 006cf8dca9c0a814f990fd4269fb73bfa2ac4560..20b959dd04c526e215050cf5f8af4b45c0bdc0b6 100644 (file)
@@ -135,6 +135,7 @@ Film::Film (boost::filesystem::path dir, bool log)
        set_isdcf_date_today ();
 
        _playlist_changed_connection = _playlist->Changed.connect (bind (&Film::playlist_changed, this));
        set_isdcf_date_today ();
 
        _playlist_changed_connection = _playlist->Changed.connect (bind (&Film::playlist_changed, this));
+       _playlist_order_changed_connection = _playlist->OrderChanged.connect (bind (&Film::playlist_order_changed, this));
        _playlist_content_changed_connection = _playlist->ContentChanged.connect (bind (&Film::playlist_content_changed, this, _1, _2, _3));
 
        /* Make state.directory a complete path without ..s (where possible)
        _playlist_content_changed_connection = _playlist->ContentChanged.connect (bind (&Film::playlist_content_changed, this, _1, _2, _3));
 
        /* Make state.directory a complete path without ..s (where possible)
@@ -1092,6 +1093,12 @@ Film::playlist_changed ()
        signal_changed (NAME);
 }
 
        signal_changed (NAME);
 }
 
+void
+Film::playlist_order_changed ()
+{
+       signal_changed (CONTENT_ORDER);
+}
+
 int
 Film::audio_frame_rate () const
 {
 int
 Film::audio_frame_rate () const
 {
index 17bdd09ebc35aaeaf0b9670d75d89736535d7cfc..2fb3e810b88739190fd0f3f071d2a9dbc29f74f2 100644 (file)
@@ -163,6 +163,8 @@ public:
                USE_ISDCF_NAME,
                /** The playlist's content list has changed (i.e. content has been added or removed) */
                CONTENT,
                USE_ISDCF_NAME,
                /** The playlist's content list has changed (i.e. content has been added or removed) */
                CONTENT,
+               /** The order of content in the playlist has changed */
+               CONTENT_ORDER,
                DCP_CONTENT_TYPE,
                CONTAINER,
                RESOLUTION,
                DCP_CONTENT_TYPE,
                CONTAINER,
                RESOLUTION,
@@ -309,6 +311,7 @@ private:
        void signal_changed (Property);
        std::string video_identifier () const;
        void playlist_changed ();
        void signal_changed (Property);
        std::string video_identifier () const;
        void playlist_changed ();
+       void playlist_order_changed ();
        void playlist_content_changed (boost::weak_ptr<Content>, int, bool frequent);
        void maybe_add_content (boost::weak_ptr<Job>, boost::weak_ptr<Content>);
        void audio_analysis_finished ();
        void playlist_content_changed (boost::weak_ptr<Content>, int, bool frequent);
        void maybe_add_content (boost::weak_ptr<Job>, boost::weak_ptr<Content>);
        void audio_analysis_finished ();
@@ -362,6 +365,7 @@ private:
        mutable bool _dirty;
 
        boost::signals2::scoped_connection _playlist_changed_connection;
        mutable bool _dirty;
 
        boost::signals2::scoped_connection _playlist_changed_connection;
+       boost::signals2::scoped_connection _playlist_order_changed_connection;
        boost::signals2::scoped_connection _playlist_content_changed_connection;
        std::list<boost::signals2::connection> _job_connections;
        std::list<boost::signals2::connection> _audio_analysis_connections;
        boost::signals2::scoped_connection _playlist_content_changed_connection;
        std::list<boost::signals2::connection> _job_connections;
        std::list<boost::signals2::connection> _audio_analysis_connections;
index 1eaef3a51fffed13eab34d7c7ce12e7ee20c59a8..e3d0c8ebb7c98053d7981277732c203d35d647e4 100644 (file)
@@ -66,16 +66,28 @@ Playlist::~Playlist ()
 void
 Playlist::content_changed (weak_ptr<Content> content, int property, bool frequent)
 {
 void
 Playlist::content_changed (weak_ptr<Content> content, int property, bool frequent)
 {
-       /* Don't respond to position changes here, as:
-          - sequencing after earlier/later changes is handled by move_earlier/move_later
-          - any other position changes will be timeline drags which should not result in content
-          being sequenced.
-       */
-
        if (property == ContentProperty::LENGTH || property == VideoContentProperty::VIDEO_FRAME_TYPE) {
        if (property == ContentProperty::LENGTH || property == VideoContentProperty::VIDEO_FRAME_TYPE) {
+               /* Don't respond to position changes here, as:
+                  - sequencing after earlier/later changes is handled by move_earlier/move_later
+                  - any other position changes will be timeline drags which should not result in content
+                  being sequenced.
+               */
                maybe_sequence_video ();
        }
 
                maybe_sequence_video ();
        }
 
+       if (
+               property == ContentProperty::POSITION ||
+               property == ContentProperty::LENGTH ||
+               property == ContentProperty::TRIM_START ||
+               property == ContentProperty::TRIM_END) {
+
+               ContentList old = _content;
+               sort (_content.begin(), _content.end(), ContentSorter ());
+               if (_content != old) {
+                       OrderChanged ();
+               }
+       }
+
        ContentChanged (content, property, frequent);
 }
 
        ContentChanged (content, property, frequent);
 }
 
@@ -138,6 +150,7 @@ Playlist::set_from_xml (shared_ptr<const Film> film, cxml::ConstNodePtr node, in
                _content.push_back (content_factory (film, i, version, notes));
        }
 
                _content.push_back (content_factory (film, i, version, notes));
        }
 
+       /* This shouldn't be necessary but better safe than sorry (there could be old files) */
        sort (_content.begin(), _content.end(), ContentSorter ());
 
        reconnect ();
        sort (_content.begin(), _content.end(), ContentSorter ());
 
        reconnect ();
@@ -349,7 +362,19 @@ Playlist::set_sequence_video (bool s)
 bool
 ContentSorter::operator() (shared_ptr<Content> a, shared_ptr<Content> b)
 {
 bool
 ContentSorter::operator() (shared_ptr<Content> a, shared_ptr<Content> b)
 {
-       return a->position() < b->position();
+       if (a->position() != b->position()) {
+               return a->position() < b->position();
+       }
+
+       /* Put video before audio if they start at the same time */
+       if (dynamic_pointer_cast<VideoContent>(a) && !dynamic_pointer_cast<VideoContent>(b)) {
+               return true;
+       } else if (!dynamic_pointer_cast<VideoContent>(a) && dynamic_pointer_cast<VideoContent>(b)) {
+               return false;
+       }
+
+       /* Last resort */
+       return a->digest() < b->digest();
 }
 
 /** @return content in ascending order of position */
 }
 
 /** @return content in ascending order of position */
@@ -389,8 +414,6 @@ Playlist::repeat (ContentList c, int n)
 void
 Playlist::move_earlier (shared_ptr<Content> c)
 {
 void
 Playlist::move_earlier (shared_ptr<Content> c)
 {
-       sort (_content.begin(), _content.end(), ContentSorter ());
-
        ContentList::iterator previous = _content.end ();
        ContentList::iterator i = _content.begin();
        while (i != _content.end() && *i != c) {
        ContentList::iterator previous = _content.end ();
        ContentList::iterator i = _content.begin();
        while (i != _content.end() && *i != c) {
@@ -407,14 +430,11 @@ Playlist::move_earlier (shared_ptr<Content> c)
        DCPTime const p = (*previous)->position ();
        (*previous)->set_position (p + c->length_after_trim ());
        c->set_position (p);
        DCPTime const p = (*previous)->position ();
        (*previous)->set_position (p + c->length_after_trim ());
        c->set_position (p);
-       sort (_content.begin(), _content.end(), ContentSorter ());
 }
 
 void
 Playlist::move_later (shared_ptr<Content> c)
 {
 }
 
 void
 Playlist::move_later (shared_ptr<Content> c)
 {
-       sort (_content.begin(), _content.end(), ContentSorter ());
-
        ContentList::iterator i = _content.begin();
        while (i != _content.end() && *i != c) {
                ++i;
        ContentList::iterator i = _content.begin();
        while (i != _content.end() && *i != c) {
                ++i;
@@ -431,7 +451,6 @@ Playlist::move_later (shared_ptr<Content> c)
 
        (*next)->set_position (c->position ());
        c->set_position (c->position() + (*next)->length_after_trim ());
 
        (*next)->set_position (c->position ());
        c->set_position (c->position() + (*next)->length_after_trim ());
-       sort (_content.begin(), _content.end(), ContentSorter ());
 }
 
 int64_t
 }
 
 int64_t
index 0baf667fc119a6b78d295c7ae3649917ea046337..3af17bb6c4794cf3114016eedfba312dcab5576b 100644 (file)
@@ -70,8 +70,9 @@ public:
 
        void repeat (ContentList, int);
 
 
        void repeat (ContentList, int);
 
-       /** Emitted when content has been added to or removed from the playlist */
+       /** Emitted when content has been added to or removed from the playlist; implies OrderChanged */
        mutable boost::signals2::signal<void ()> Changed;
        mutable boost::signals2::signal<void ()> Changed;
+       mutable boost::signals2::signal<void ()> OrderChanged;
        /** Emitted when something about a piece of our content has changed;
         *  these emissions include when the position of the content changes.
         *  Third parameter is true if signals are currently being emitted frequently.
        /** Emitted when something about a piece of our content has changed;
         *  these emissions include when the position of the content changes.
         *  Third parameter is true if signals are currently being emitted frequently.
index 1f9352f06472aec8da5dad412b7407500d5dff2f..06c371348667e05dd471267fac7c54b478a24b81 100644 (file)
@@ -210,6 +210,7 @@ ContentPanel::film_changed (Film::Property p)
 {
        switch (p) {
        case Film::CONTENT:
 {
        switch (p) {
        case Film::CONTENT:
+       case Film::CONTENT_ORDER:
                setup ();
                break;
        default:
                setup ();
                break;
        default:
@@ -422,7 +423,7 @@ ContentPanel::set_selection (weak_ptr<Content> wc)
 void
 ContentPanel::film_content_changed (int property)
 {
 void
 ContentPanel::film_content_changed (int property)
 {
-       if (property == ContentProperty::PATH || property == ContentProperty::POSITION || property == DCPContentProperty::CAN_BE_PLAYED) {
+       if (property == ContentProperty::PATH || property == DCPContentProperty::CAN_BE_PLAYED) {
                setup ();
        }
 
                setup ();
        }
 
@@ -435,7 +436,6 @@ void
 ContentPanel::setup ()
 {
        ContentList content = _film->content ();
 ContentPanel::setup ()
 {
        ContentList content = _film->content ();
-       sort (content.begin(), content.end(), ContentSorter ());
 
        /* First, check to see if anything has changed and bail if not; this avoids
           flickering on OS X.
 
        /* First, check to see if anything has changed and bail if not; this avoids
           flickering on OS X.
index 952945884117cdb1dbdabb6e653a5f8a9f20484c..8a61eccb07e39b3736fa527f313079fd80b46018 100644 (file)
@@ -101,6 +101,13 @@ Timeline::film_changed (Film::Property p)
        if (p == Film::CONTENT || p == Film::REEL_TYPE || p == Film::REEL_LENGTH) {
                ensure_ui_thread ();
                recreate_views ();
        if (p == Film::CONTENT || p == Film::REEL_TYPE || p == Film::REEL_LENGTH) {
                ensure_ui_thread ();
                recreate_views ();
+       } else if (p == Film::CONTENT_ORDER) {
+               assign_tracks ();
+               if (!_left_down) {
+                       /* Only do this if we are not dragging, as it's confusing otherwise */
+                       setup_pixels_per_second ();
+               }
+               Refresh ();
        }
 }
 
        }
 }
 
@@ -142,14 +149,7 @@ Timeline::film_content_changed (int property)
 {
        ensure_ui_thread ();
 
 {
        ensure_ui_thread ();
 
-       if (property == ContentProperty::POSITION) {
-               assign_tracks ();
-               if (!_left_down) {
-                       /* Only do this if we are not dragging, as it's confusing otherwise */
-                       setup_pixels_per_second ();
-               }
-               Refresh ();
-       } else if (property == AudioContentProperty::AUDIO_STREAMS) {
+       if (property == AudioContentProperty::AUDIO_STREAMS) {
                recreate_views ();
        }
 }
                recreate_views ();
        }
 }