is sorted. Do playlist sorting when content position / length etc.
changes. Handle sorts better when comparing content at the same
position.
+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).
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)
signal_changed (NAME);
}
+void
+Film::playlist_order_changed ()
+{
+ signal_changed (CONTENT_ORDER);
+}
+
int
Film::audio_frame_rate () const
{
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,
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 ();
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;
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) {
+ /* 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 ();
}
+ 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);
}
_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 ();
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 */
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) {
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)
{
- sort (_content.begin(), _content.end(), ContentSorter ());
-
ContentList::iterator i = _content.begin();
while (i != _content.end() && *i != c) {
++i;
(*next)->set_position (c->position ());
c->set_position (c->position() + (*next)->length_after_trim ());
- sort (_content.begin(), _content.end(), ContentSorter ());
}
int64_t
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 ()> 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.
{
switch (p) {
case Film::CONTENT:
+ case Film::CONTENT_ORDER:
setup ();
break;
default:
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 ();
}
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.
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 ();
}
}
{
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 ();
}
}