X-Git-Url: https://main.carlh.net/gitweb/?p=dcpomatic.git;a=blobdiff_plain;f=src%2Fwx%2Ftimeline.cc;h=7b9758febd16a4b3a27e300ab0f259745a3c5c42;hp=206c13cf69e64fa15a00316dfff917de9d9304a0;hb=c04fec82d25127fafa73c3daff87bece9aa8c8e8;hpb=254b3044d72de6b033d7c584f5abd2b9aa70aad5 diff --git a/src/wx/timeline.cc b/src/wx/timeline.cc index 206c13cf6..7b9758feb 100644 --- a/src/wx/timeline.cc +++ b/src/wx/timeline.cc @@ -29,6 +29,7 @@ #include "timeline_atmos_content_view.h" #include "content_panel.h" #include "wx_util.h" +#include "film_viewer.h" #include "lib/film.h" #include "lib/playlist.h" #include "lib/image_content.h" @@ -54,17 +55,22 @@ using boost::weak_ptr; using boost::dynamic_pointer_cast; using boost::bind; using boost::optional; +using namespace dcpomatic; +#if BOOST_VERSION >= 106100 +using namespace boost::placeholders; +#endif /* 3 hours in 640 pixels */ double const Timeline::_minimum_pixels_per_second = 640.0 / (60 * 60 * 3); int const Timeline::_minimum_pixels_per_track = 16; -Timeline::Timeline (wxWindow* parent, ContentPanel* cp, shared_ptr film) +Timeline::Timeline (wxWindow* parent, ContentPanel* cp, shared_ptr film, weak_ptr viewer) : wxPanel (parent, wxID_ANY) , _labels_canvas (new wxScrolledCanvas (this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE)) , _main_canvas (new wxScrolledCanvas (this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE)) , _content_panel (cp) , _film (film) + , _viewer (viewer) , _time_axis_view (new TimelineTimeAxisView (*this, 64)) , _reels_view (new TimelineReelsView (*this, 32)) , _labels_view (new TimelineLabelsView (*this)) @@ -79,6 +85,7 @@ Timeline::Timeline (wxWindow* parent, ContentPanel* cp, shared_ptr film) , _y_scroll_rate (16) , _pixels_per_track (48) , _first_resize (true) + , _timer (this) { #ifndef __WXOSX__ _labels_canvas->SetDoubleBuffered (true); @@ -113,10 +120,19 @@ Timeline::Timeline (wxWindow* parent, ContentPanel* cp, shared_ptr film) _film_changed_connection = film->Change.connect (bind (&Timeline::film_change, this, _1, _2)); _film_content_change_connection = film->ContentChange.connect (bind (&Timeline::film_content_change, this, _1, _3, _4)); + Bind (wxEVT_TIMER, boost::bind(&Timeline::update_playhead, this)); + _timer.Start (200, wxTIMER_CONTINUOUS); + setup_scrollbars (); _labels_canvas->ShowScrollbars (wxSHOW_SB_NEVER, wxSHOW_SB_NEVER); } +void +Timeline::update_playhead () +{ + Refresh (); +} + void Timeline::set_pixels_per_second (double pps) { @@ -194,6 +210,18 @@ Timeline::paint_main () ); } + /* Playhead */ + + shared_ptr vp = _viewer.lock (); + DCPOMATIC_ASSERT (vp); + + gc->SetPen (*wxRED_PEN); + wxGraphicsPath path = gc->CreatePath (); + double const ph = vp->position().seconds() * pixels_per_second().get_value_or(0); + path.MoveToPoint (ph, 0); + path.AddLineToPoint (ph, pixels_per_track() * _tracks + 32); + gc->StrokePath (path); + delete gc; } @@ -237,8 +265,8 @@ Timeline::recreate_views () _views.push_back (shared_ptr (new TimelineTextContentView (*this, i, j))); } - if (dynamic_pointer_cast (i)) { - _views.push_back (shared_ptr (new TimelineAtmosContentView (*this, i))); + if (i->atmos) { + _views.push_back (shared_ptr(new TimelineAtmosContentView(*this, i))); } } @@ -256,7 +284,7 @@ Timeline::film_content_change (ChangeType type, int property, bool frequent) ensure_ui_thread (); - if (property == AudioContentProperty::STREAMS) { + if (property == AudioContentProperty::STREAMS || property == VideoContentProperty::FRAME_TYPE) { recreate_views (); } else if (property == ContentProperty::POSITION || property == ContentProperty::LENGTH) { _reels_view->force_redraw (); @@ -395,12 +423,9 @@ Timeline::assign_tracks () bool have_atmos = false; BOOST_FOREACH (shared_ptr i, _views) { - shared_ptr cv = dynamic_pointer_cast (i); - if (!cv) { - continue; - } - if (dynamic_pointer_cast (i)) { - cv->set_track (_tracks - 1); + shared_ptr cv = dynamic_pointer_cast(i); + if (cv) { + cv->set_track (_tracks); have_atmos = true; } } @@ -453,7 +478,11 @@ Timeline::event_to_view (wxMouseEvent& ev) { /* Search backwards through views so that we find the uppermost one first */ TimelineViewList::reverse_iterator i = _views.rbegin(); - Position const p (ev.GetX(), ev.GetY()); + + int vsx, vsy; + _main_canvas->GetViewStart (&vsx, &vsy); + Position const p (ev.GetX() + vsx * _x_scroll_rate, ev.GetY() + vsy * _y_scroll_rate); + while (i != _views.rend() && !(*i)->bbox().contains (p)) { shared_ptr cv = dynamic_pointer_cast (*i); ++i; @@ -531,7 +560,7 @@ Timeline::left_down_select (wxMouseEvent& ev) _start_snaps.push_back (cv->content()->end(film)); _end_snaps.push_back (cv->content()->end(film)); - BOOST_FOREACH (DCPTime i, cv->content()->reel_split_points()) { + BOOST_FOREACH (DCPTime i, cv->content()->reel_split_points(film)) { _start_snaps.push_back (i); } } @@ -568,7 +597,12 @@ Timeline::left_up_select (wxMouseEvent& ev) } _content_panel->set_selection (selected_content ()); - set_position_from_event (ev); + /* Since we may have just set change signals back to `not-frequent', we have to + make sure this position change is signalled, even if the position value has + not changed since the last time it was set (with frequent=true). This is + a bit of a hack. + */ + set_position_from_event (ev, true); /* Clear up up the stuff we don't do during drag */ assign_tracks (); @@ -704,7 +738,7 @@ Timeline::maybe_snap (DCPTime a, DCPTime b, optional& nearest_distance) } void -Timeline::set_position_from_event (wxMouseEvent& ev) +Timeline::set_position_from_event (wxMouseEvent& ev, bool force_emit) { if (!_pixels_per_second) { return; @@ -763,7 +797,7 @@ Timeline::set_position_from_event (wxMouseEvent& ev) new_position = DCPTime (); } - _down_view->content()->set_position (film, new_position); + _down_view->content()->set_position (film, new_position, force_emit); film->set_sequence (false); }