diff options
| author | Carl Hetherington <cth@carlh.net> | 2017-05-08 10:54:49 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2017-05-08 10:54:49 +0100 |
| commit | 58e851f428a035841acf0196348a0643230ed808 (patch) | |
| tree | 505c1401445581a39d428b43addefcbe93b324c0 /src | |
| parent | 0e9d03990993bd19a968ee356443a39336e9b8c5 (diff) | |
Show overlapping subs in multiple tracks on the timeline (#941).
Diffstat (limited to 'src')
| -rw-r--r-- | src/wx/timeline.cc | 157 | ||||
| -rw-r--r-- | src/wx/timeline_labels_view.cc | 10 | ||||
| -rw-r--r-- | src/wx/timeline_labels_view.h | 4 |
3 files changed, 95 insertions, 76 deletions
diff --git a/src/wx/timeline.cc b/src/wx/timeline.cc index 5cdd73b25..04db5c628 100644 --- a/src/wx/timeline.cc +++ b/src/wx/timeline.cc @@ -184,19 +184,75 @@ Timeline::film_content_changed (int property, bool frequent) } } +template <class T> +int +place (TimelineViewList& views, int& tracks) +{ + int const base = tracks; + + BOOST_FOREACH (shared_ptr<TimelineView> i, views) { + if (!dynamic_pointer_cast<T>(i)) { + continue; + } + + shared_ptr<TimelineContentView> cv = dynamic_pointer_cast<TimelineContentView> (i); + + int t = base; + + shared_ptr<Content> content = cv->content(); + DCPTimePeriod const content_period (content->position(), content->end()); + + while (true) { + TimelineViewList::iterator j = views.begin(); + while (j != views.end()) { + shared_ptr<T> test = dynamic_pointer_cast<T> (*j); + if (!test) { + ++j; + continue; + } + + shared_ptr<Content> test_content = test->content(); + if ( + test->track() && test->track().get() == t && + content_period.overlap(DCPTimePeriod(test_content->position(), test_content->end()))) { + /* we have an overlap on track `t' */ + ++t; + break; + } + + ++j; + } + + if (j == views.end ()) { + /* no overlap on `t' */ + break; + } + } + + cv->set_track (t); + tracks = max (tracks, t + 1); + } + + return tracks - base; +} + void Timeline::assign_tracks () { /* Tracks are: Video (mono or left-eye) Video (right-eye) - Subtitle + Subtitle 1 + Subtitle 2 + Subtitle N Atmos Audio 1 Audio 2 Audio N */ + _tracks = 0; + for (TimelineViewList::iterator i = _views.begin(); i != _views.end(); ++i) { shared_ptr<TimelineContentView> c = dynamic_pointer_cast<TimelineContentView> (*i); if (c) { @@ -204,93 +260,56 @@ Timeline::assign_tracks () } } - /* See if we have any subtitle / atmos / right-eye views */ + /* Video */ + bool have_3d = false; - bool have_subtitle = false; - bool have_atmos = false; BOOST_FOREACH (shared_ptr<TimelineView> i, _views) { - shared_ptr<TimelineContentView> cv = dynamic_pointer_cast<TimelineContentView> (i); + shared_ptr<TimelineVideoContentView> cv = dynamic_pointer_cast<TimelineVideoContentView> (i); if (!cv) { continue; } - if (dynamic_pointer_cast<TimelineVideoContentView> (i)) { - if (cv->content()->video->frame_type() == VIDEO_FRAME_TYPE_3D_RIGHT) { - have_3d = true; - } - } else if (dynamic_pointer_cast<TimelineSubtitleContentView> (i)) { - have_subtitle = true; - } else if (dynamic_pointer_cast<TimelineAtmosContentView> (i)) { - have_atmos = true; + /* Video on tracks 0 and maybe 1 (left and right eye) */ + if (cv->content()->video->frame_type() == VIDEO_FRAME_TYPE_3D_RIGHT) { + cv->set_track (1); + _tracks = max (_tracks, 2); + have_3d = true; + } else { + cv->set_track (0); } } - _labels_view->set_3d (have_3d); - _labels_view->set_subtitle (have_subtitle); - _labels_view->set_atmos (have_atmos); + _tracks = max (_tracks, 1); - /* Hence decide where to start subtitle, atmos and audio tracks */ - int const subtitle = have_3d ? 2 : 1; - int const atmos = have_subtitle ? subtitle + 1 : subtitle; - int const audio = have_atmos ? atmos + 1: atmos; + /* Subtitle */ - for (TimelineViewList::iterator i = _views.begin(); i != _views.end(); ++i) { - shared_ptr<TimelineContentView> cv = dynamic_pointer_cast<TimelineContentView> (*i); + int const subtitle_tracks = place<TimelineSubtitleContentView> (_views, _tracks); + + /* Atmos */ + + bool have_atmos = false; + BOOST_FOREACH (shared_ptr<TimelineView> i, _views) { + shared_ptr<TimelineVideoContentView> cv = dynamic_pointer_cast<TimelineVideoContentView> (i); if (!cv) { continue; } - - if (dynamic_pointer_cast<TimelineVideoContentView> (*i)) { - /* Video on tracks 0 and maybe 1 (left and right eye) */ - cv->set_track (cv->content()->video->frame_type() == VIDEO_FRAME_TYPE_3D_RIGHT ? 1 : 0); - _tracks = max (_tracks, have_3d ? 2 : 1); - continue; - } else if (dynamic_pointer_cast<TimelineSubtitleContentView> (*i)) { - cv->set_track (subtitle); - _tracks = max (_tracks, subtitle + 1); - continue; - } else if (dynamic_pointer_cast<TimelineAtmosContentView> (*i)) { - cv->set_track (atmos); - _tracks = max (_tracks, atmos + 1); - continue; + if (dynamic_pointer_cast<TimelineAtmosContentView> (i)) { + cv->set_track (_tracks - 1); + have_atmos = true; } + } - int t = audio; - - shared_ptr<Content> content = cv->content(); - DCPTimePeriod content_period (content->position(), content->end()); - - while (true) { - TimelineViewList::iterator j = _views.begin(); - while (j != _views.end()) { - shared_ptr<TimelineAudioContentView> test = dynamic_pointer_cast<TimelineAudioContentView> (*j); - if (!test) { - ++j; - continue; - } - - shared_ptr<Content> test_content = test->content(); + if (have_atmos) { + ++_tracks; + } - if (test && test->track() && test->track().get() == t) { - if (content_period.overlap (DCPTimePeriod(test_content->position(), test_content->end()))) { - /* we have an overlap on track `t' */ - ++t; - break; - } - } + /* Audio */ - ++j; - } + place<TimelineAudioContentView> (_views, _tracks); - if (j == _views.end ()) { - /* no overlap on `t' */ - break; - } - } - - cv->set_track (t); - _tracks = max (_tracks, t + 1); - } + _labels_view->set_3d (have_3d); + _labels_view->set_subtitle_tracks (subtitle_tracks); + _labels_view->set_atmos (have_atmos); _time_axis_view->set_y (tracks() * track_height() + 64); _reels_view->set_y (8); diff --git a/src/wx/timeline_labels_view.cc b/src/wx/timeline_labels_view.cc index 1a712f42d..ee1b19489 100644 --- a/src/wx/timeline_labels_view.cc +++ b/src/wx/timeline_labels_view.cc @@ -31,7 +31,7 @@ using std::max; TimelineLabelsView::TimelineLabelsView (Timeline& tl) : TimelineView (tl) , _threed (true) - , _subtitle (true) + , _subtitle_tracks (0) , _atmos (true) { wxString labels[] = { @@ -69,8 +69,8 @@ TimelineLabelsView::do_paint (wxGraphicsContext* gc, list<dcpomatic::Rect<int> > gc->DrawText (_("Video"), 0, _timeline.tracks_position().y + (ty + fy) / 2 - 8); fy = ty; - if (_subtitle) { - ty = fy + h; + if (_subtitle_tracks) { + ty = fy + _subtitle_tracks * h; gc->DrawText (_("Subtitles"), 0, _timeline.tracks_position().y + (ty + fy) / 2 - 8); fy = ty; } @@ -92,9 +92,9 @@ TimelineLabelsView::set_3d (bool s) } void -TimelineLabelsView::set_subtitle (bool s) +TimelineLabelsView::set_subtitle_tracks (int n) { - _subtitle = s; + _subtitle_tracks = n; } void diff --git a/src/wx/timeline_labels_view.h b/src/wx/timeline_labels_view.h index 3b7153344..87b3cc902 100644 --- a/src/wx/timeline_labels_view.h +++ b/src/wx/timeline_labels_view.h @@ -30,7 +30,7 @@ public: dcpomatic::Rect<int> bbox () const; void set_3d (bool s); - void set_subtitle (bool s); + void set_subtitle_tracks (int n); void set_atmos (bool s); private: @@ -38,6 +38,6 @@ private: int _width; bool _threed; - bool _subtitle; + int _subtitle_tracks; bool _atmos; }; |
