X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;ds=sidebyside;f=gtk2_ardour%2Fstreamview.cc;h=c0917d7e57119a905da4d4b8d0e39c44d2a6ffbd;hb=352c824fa3999244ef1ebf002d57d4b2dea5ae3c;hp=d77681b6d5c173d8ec32865c03dda0933ab3771f;hpb=d1d75380b9108af6c02d945958fd2deec1b533f6;p=ardour.git diff --git a/gtk2_ardour/streamview.cc b/gtk2_ardour/streamview.cc index d77681b6d5..c0917d7e57 100644 --- a/gtk2_ardour/streamview.cc +++ b/gtk2_ardour/streamview.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2001, 2006 Paul Davis + Copyright (C) 2001, 2006 Paul Davis 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 @@ -21,98 +21,91 @@ #include #include +#include -#include -#include -#include -#include -#include +#include "ardour/playlist.h" +#include "ardour/region.h" +#include "ardour/track.h" +#include "ardour/session.h" + +#include "pbd/compose.h" + +#include "canvas/rectangle.h" +#include "canvas/debug.h" #include "streamview.h" #include "region_view.h" #include "route_time_axis.h" -#include "canvas-waveview.h" -#include "canvas-simplerect.h" #include "region_selection.h" #include "selection.h" #include "public_editor.h" -#include "ardour_ui.h" +#include "timers.h" #include "rgb_macros.h" #include "gui_thread.h" +#include "ui_config.h" #include "utils.h" +#include "pbd/i18n.h" + +using namespace std; using namespace ARDOUR; +using namespace ARDOUR_UI_UTILS; using namespace PBD; using namespace Editing; -StreamView::StreamView (RouteTimeAxisView& tv, ArdourCanvas::Group* group) +StreamView::StreamView (RouteTimeAxisView& tv, ArdourCanvas::Container* canvas_group) : _trackview (tv) - , owns_canvas_group(group == 0) - , _background_group(new ArdourCanvas::Group(*_trackview.canvas_background)) - , canvas_group(group ? group : new ArdourCanvas::Group(*_trackview.canvas_display)) - , _samples_per_unit(_trackview.editor.get_current_zoom()) + , _canvas_group (canvas_group ? canvas_group : new ArdourCanvas::Container (_trackview.canvas_display())) + , _samples_per_pixel (_trackview.editor().get_current_zoom ()) , rec_updating(false) , rec_active(false) - , use_rec_regions(tv.editor.show_waveforms_recording()) - , region_color(_trackview.color()) , stream_base_color(0xFFFFFFFF) - , layers(1) - , height(tv.height) - , layer_display(Overlaid) - , last_rec_data_frame(0) + , _layers (1) + , _layer_display (Overlaid) + , height (tv.height) + , last_rec_data_sample(0) { - /* set_position() will position the group */ - - canvas_rect = new ArdourCanvas::SimpleRect (*_background_group); - canvas_rect->property_x1() = 0.0; - canvas_rect->property_y1() = 0.0; - canvas_rect->property_x2() = _trackview.editor.get_physical_screen_width(); - canvas_rect->property_y2() = (double) tv.current_height(); - canvas_rect->raise(1); // raise above tempo lines + CANVAS_DEBUG_NAME (_canvas_group, string_compose ("SV canvas group %1", _trackview.name())); - // DR-way - canvas_rect->property_outline_what() = (guint32) (0x2|0x8); // outline RHS and bottom - // 2.0 way - //canvas_rect->property_outline_what() = (guint32) (0x1|0x2|0x8); // outline ends and bottom - // (Fill/Outline colours set in derived classes) + /* set_position() will position the group */ - canvas_rect->signal_event().connect (bind (mem_fun (_trackview.editor, &PublicEditor::canvas_stream_view_event), canvas_rect, &_trackview)); + canvas_rect = new ArdourCanvas::Rectangle (_canvas_group); + CANVAS_DEBUG_NAME (canvas_rect, string_compose ("SV canvas rectangle %1", _trackview.name())); + canvas_rect->set (ArdourCanvas::Rect (0, 0, ArdourCanvas::COORD_MAX, tv.current_height ())); + canvas_rect->set_outline (false); + canvas_rect->set_fill (true); + canvas_rect->Event.connect (sigc::bind (sigc::mem_fun (_trackview.editor(), &PublicEditor::canvas_stream_view_event), canvas_rect, &_trackview)); if (_trackview.is_track()) { - _trackview.track()->DiskstreamChanged.connect (mem_fun (*this, &StreamView::diskstream_changed)); - _trackview.session().TransportStateChange.connect (mem_fun (*this, &StreamView::transport_changed)); - _trackview.session().TransportLooped.connect (mem_fun (*this, &StreamView::transport_looped)); - _trackview.get_diskstream()->RecordEnableChanged.connect (mem_fun (*this, &StreamView::rec_enable_changed)); - _trackview.session().RecordStateChanged.connect (mem_fun (*this, &StreamView::sess_rec_enable_changed)); - } + _trackview.track()->rec_enable_control()->Changed.connect (*this, invalidator (*this), boost::bind (&StreamView::rec_enable_changed, this), gui_context()); + + _trackview.session()->TransportStateChange.connect (*this, invalidator (*this), boost::bind (&StreamView::transport_changed, this), gui_context()); + _trackview.session()->TransportLooped.connect (*this, invalidator (*this), boost::bind (&StreamView::transport_looped, this), gui_context()); + _trackview.session()->RecordStateChanged.connect (*this, invalidator (*this), boost::bind (&StreamView::sess_rec_enable_changed, this), gui_context()); + } - ColorsChanged.connect (mem_fun (*this, &StreamView::color_handler)); + UIConfiguration::instance().ColorsChanged.connect (sigc::mem_fun (*this, &StreamView::color_handler)); } StreamView::~StreamView () { - undisplay_diskstream (); - + undisplay_track (); + delete canvas_rect; - - if (owns_canvas_group) { - delete canvas_group; - } } void StreamView::attach () { if (_trackview.is_track()) { - display_diskstream (_trackview.get_diskstream()); + display_track (_trackview.track ()); } } int StreamView::set_position (gdouble x, gdouble y) { - canvas_group->property_x() = x; - canvas_group->property_y() = y; + _canvas_group->set_position (ArdourCanvas::Duple (x, y)); return 0; } @@ -120,60 +113,75 @@ int StreamView::set_height (double h) { /* limit the values to something sane-ish */ + if (h < 10.0 || h > 1000.0) { return -1; } - if (canvas_rect->property_y2() == h) { + if (height == h) { return 0; } height = h; + canvas_rect->set_y1 (height); update_contents_height (); + return 0; } -int -StreamView::set_samples_per_unit (gdouble spp) +int +StreamView::set_samples_per_pixel (double fpp) { RegionViewList::iterator i; - if (spp < 1.0) { + if (fpp < 1.0) { return -1; } - _samples_per_unit = spp; + if (fpp == _samples_per_pixel) { + return 0; + } + + _samples_per_pixel = fpp; for (i = region_views.begin(); i != region_views.end(); ++i) { - (*i)->set_samples_per_unit (spp); + (*i)->set_samples_per_pixel (fpp); } for (vector::iterator xi = rec_rects.begin(); xi != rec_rects.end(); ++xi) { RecBoxInfo &recbox = (*xi); - - gdouble xstart = _trackview.editor.frame_to_pixel ( recbox.start ); - gdouble xend = _trackview.editor.frame_to_pixel ( recbox.start + recbox.length ); - recbox.rectangle->property_x1() = xstart; - recbox.rectangle->property_x2() = xend; + ArdourCanvas::Coord const xstart = _trackview.editor().sample_to_pixel (recbox.start); + ArdourCanvas::Coord const xend = _trackview.editor().sample_to_pixel (recbox.start + recbox.length); + + recbox.rectangle->set_x0 (xstart); + recbox.rectangle->set_x1 (xend); } + update_coverage_samples (); + return 0; } void -StreamView::add_region_view (boost::shared_ptr r) +StreamView::add_region_view (boost::weak_ptr wr) { - // ENSURE_GUI_THREAD (bind (mem_fun (*this, &AudioStreamView::add_region_view), r)); + boost::shared_ptr r (wr.lock()); + if (!r) { + return; + } add_region_view_internal (r, true); - update_contents_height (); + + if (_layer_display == Stacked || _layer_display == Expanded) { + update_contents_height (); + } } void StreamView::remove_region_view (boost::weak_ptr weak_r) { - ENSURE_GUI_THREAD (bind (mem_fun (*this, &StreamView::remove_region_view), weak_r)); + ENSURE_GUI_THREAD (*this, &StreamView::remove_region_view, weak_r) boost::shared_ptr r (weak_r.lock()); @@ -189,10 +197,12 @@ StreamView::remove_region_view (boost::weak_ptr weak_r) break; } } + + RegionViewRemoved (); /* EMIT SIGNAL */ } void -StreamView::undisplay_diskstream () +StreamView::undisplay_track () { for (RegionViewList::iterator i = region_views.begin(); i != region_views.end() ; ) { RegionViewList::iterator next = i; @@ -205,83 +215,146 @@ StreamView::undisplay_diskstream () } void -StreamView::display_diskstream (boost::shared_ptr ds) +StreamView::display_track (boost::shared_ptr tr) { - playlist_change_connection.disconnect(); - playlist_changed (ds); - playlist_change_connection = ds->PlaylistChanged.connect (bind (mem_fun (*this, &StreamView::playlist_changed), ds)); + playlist_switched_connection.disconnect(); + playlist_switched (tr); + tr->PlaylistChanged.connect (playlist_switched_connection, invalidator (*this), boost::bind (&StreamView::playlist_switched, this, boost::weak_ptr (tr)), gui_context()); } void -StreamView::playlist_modified_weak (boost::weak_ptr ds) +StreamView::layer_regions() { - boost::shared_ptr sp (ds.lock()); - if (!sp) { - return; + // In one traversal of the region view list: + // - Build a list of region views sorted by layer + // - Remove invalid views from the actual region view list + RegionViewList copy; + list::iterator i, tmp; + for (i = region_views.begin(); i != region_views.end(); ) { + tmp = i; + tmp++; + + if (!(*i)->is_valid()) { + delete *i; + region_views.erase (i); + i = tmp; + continue; + } else { + (*i)->enable_display(true); + } + + if (copy.size() == 0) { + copy.push_front((*i)); + i = tmp; + continue; + } + + RegionViewList::iterator k = copy.begin(); + RegionViewList::iterator l = copy.end(); + l--; + + if ((*i)->region()->layer() <= (*k)->region()->layer()) { + copy.push_front((*i)); + i = tmp; + continue; + } else if ((*i)->region()->layer() >= (*l)->region()->layer()) { + copy.push_back((*i)); + i = tmp; + continue; + } + + for (RegionViewList::iterator j = copy.begin(); j != copy.end(); ++j) { + if ((*j)->region()->layer() >= (*i)->region()->layer()) { + copy.insert(j, (*i)); + break; + } + } + + i = tmp; } - playlist_modified (sp); + // Fix canvas layering by raising each to the top in the sorted order. + for (RegionViewList::iterator i = copy.begin(); i != copy.end(); ++i) { + (*i)->get_canvas_group()->raise_to_top (); + } } void -StreamView::playlist_modified (boost::shared_ptr ds) +StreamView::playlist_layered (boost::weak_ptr wtr) { - /* we do not allow shared_ptr to be bound to slots */ - ENSURE_GUI_THREAD (bind (mem_fun (*this, &StreamView::playlist_modified_weak), ds)); + boost::shared_ptr tr (wtr.lock()); + + if (!tr) { + return; + } /* update layers count and the y positions and heights of our regions */ - if (ds->playlist()) { - layers = ds->playlist()->top_layer() + 1; + if (tr->playlist()) { + _layers = tr->playlist()->top_layer() + 1; + } + + if (_layer_display == Stacked) { update_contents_height (); - update_coverage_frames (); - redisplay_diskstream (); + /* tricky. playlist_changed() does this as well, and its really inefficient. */ + update_coverage_samples (); + } else { + /* layering has probably been modified. reflect this in the canvas. */ + layer_regions(); } } void -StreamView::playlist_changed (boost::shared_ptr ds) +StreamView::playlist_switched (boost::weak_ptr wtr) { - /* XXX: binding to a shared_ptr, is this ok? */ - ENSURE_GUI_THREAD (bind (mem_fun (*this, &StreamView::playlist_changed), ds)); + boost::shared_ptr tr (wtr.lock()); + + if (!tr) { + return; + } /* disconnect from old playlist */ - for (vector::iterator i = playlist_connections.begin(); i != playlist_connections.end(); ++i) { - (*i).disconnect(); - } - - playlist_connections.clear(); - undisplay_diskstream (); + playlist_connections.drop_connections (); + //undisplay_track (); + /* draw it */ + tr->playlist()->freeze(); + redisplay_track (); + tr->playlist()->thaw(); /* update layers count and the y positions and heights of our regions */ - layers = ds->playlist()->top_layer() + 1; + _layers = tr->playlist()->top_layer() + 1; update_contents_height (); - - update_coverage_frames (); - - /* draw it */ - redisplay_diskstream (); + update_coverage_samples (); /* catch changes */ - playlist_connections.push_back (ds->playlist()->Modified.connect (bind (mem_fun (*this, &StreamView::playlist_modified_weak), ds))); + tr->playlist()->LayeringChanged.connect (playlist_connections, invalidator (*this), boost::bind (&StreamView::playlist_layered, this, boost::weak_ptr (tr)), gui_context()); + tr->playlist()->RegionAdded.connect (playlist_connections, invalidator (*this), boost::bind (&StreamView::add_region_view, this, _1), gui_context()); + tr->playlist()->RegionRemoved.connect (playlist_connections, invalidator (*this), boost::bind (&StreamView::remove_region_view, this, _1), gui_context()); + tr->playlist()->ContentsChanged.connect (playlist_connections, invalidator (*this), boost::bind (&StreamView::update_coverage_samples, this), gui_context()); } + void StreamView::diskstream_changed () { boost::shared_ptr t; if ((t = _trackview.track()) != 0) { - Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun (*this, &StreamView::display_diskstream), t->diskstream())); + Gtkmm2ext::UI::instance()->call_slot (invalidator (*this), boost::bind (&StreamView::display_track, this, t)); } else { - Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &StreamView::undisplay_diskstream)); + Gtkmm2ext::UI::instance()->call_slot (invalidator (*this), boost::bind (&StreamView::undisplay_track, this)); } } void -StreamView::apply_color (Gdk::Color& color, ColorTarget target) +StreamView::apply_color (Gdk::Color const& c, ColorTarget target) +{ + return apply_color (gdk_color_to_rgba (c), target); +} +void +StreamView::apply_color (uint32_t color, ColorTarget target) { list::iterator i; @@ -292,11 +365,10 @@ StreamView::apply_color (Gdk::Color& color, ColorTarget target) (*i)->set_color (region_color); } break; - + case StreamBaseColor: - stream_base_color = RGBA_TO_UINT ( - color.get_red_p(), color.get_green_p(), color.get_blue_p(), 255); - canvas_rect->property_fill_color_rgba() = stream_base_color; + stream_base_color = color; + canvas_rect->set_fill_color (stream_base_color); break; } } @@ -313,19 +385,19 @@ StreamView::region_layered (RegionView* rv) void StreamView::rec_enable_changed () { - Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &StreamView::setup_rec_box)); + setup_rec_box (); } void StreamView::sess_rec_enable_changed () { - Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &StreamView::setup_rec_box)); + setup_rec_box (); } void StreamView::transport_changed() { - Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &StreamView::setup_rec_box)); + setup_rec_box (); } void @@ -333,7 +405,43 @@ StreamView::transport_looped() { // to force a new rec region rec_active = false; - Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &StreamView::setup_rec_box)); + Gtkmm2ext::UI::instance()->call_slot (invalidator (*this), boost::bind (&StreamView::setup_rec_box, this)); +} + +void +StreamView::create_rec_box(samplepos_t sample_pos, double width) +{ + const double xstart = _trackview.editor().sample_to_pixel(sample_pos); + const double xend = xstart + width; + const uint32_t fill_color = UIConfiguration::instance().color_mod("recording rect", "recording_rect"); + + ArdourCanvas::Rectangle* rec_rect = new ArdourCanvas::Rectangle(_canvas_group); + rec_rect->set_x0(xstart); + rec_rect->set_y0(0); + rec_rect->set_x1(xend); + rec_rect->set_y1(child_height ()); + rec_rect->set_outline_what(ArdourCanvas::Rectangle::What(0)); + rec_rect->set_outline_color(UIConfiguration::instance().color("recording rect")); + rec_rect->set_fill_color(fill_color); + rec_rect->lower_to_bottom(); + + RecBoxInfo recbox; + recbox.rectangle = rec_rect; + recbox.length = 0; + + if (rec_rects.empty()) { + recbox.start = _trackview.session()->record_location (); + } else { + recbox.start = _trackview.session()->transport_sample (); + } + + rec_rects.push_back (recbox); + + screen_update_connection.disconnect(); + screen_update_connection = Timers::rapid_connect (sigc::mem_fun(*this, &StreamView::update_rec_box)); + + rec_updating = true; + rec_active = true; } void @@ -342,29 +450,36 @@ StreamView::update_rec_box () if (rec_active && rec_rects.size() > 0) { /* only update the last box */ RecBoxInfo & rect = rec_rects.back(); - nframes_t at = _trackview.get_diskstream()->current_capture_end(); + samplepos_t const at = _trackview.track()->current_capture_end (); double xstart; double xend; - + switch (_trackview.track()->mode()) { + + case NonLayered: case Normal: rect.length = at - rect.start; - xstart = _trackview.editor.frame_to_pixel (rect.start); - xend = _trackview.editor.frame_to_pixel (at); + xstart = _trackview.editor().sample_to_pixel (rect.start); + xend = _trackview.editor().sample_to_pixel (at); break; - + case Destructive: rect.length = 2; - xstart = _trackview.editor.frame_to_pixel (_trackview.get_diskstream()->current_capture_start()); - xend = _trackview.editor.frame_to_pixel (at); + xstart = _trackview.editor().sample_to_pixel (_trackview.track()->current_capture_start()); + xend = _trackview.editor().sample_to_pixel (at); break; + + default: + fatal << string_compose (_("programming error: %1"), "illegal track mode") << endmsg; + abort(); /*NOTREACHED*/ + return; } - - rect.rectangle->property_x1() = xstart; - rect.rectangle->property_x2() = xend; + + rect.rectangle->set_x0 (xstart); + rect.rectangle->set_x1 (xend); } } - + RegionView* StreamView::find_view (boost::shared_ptr region) { @@ -376,7 +491,20 @@ StreamView::find_view (boost::shared_ptr region) } return 0; } - + +uint32_t +StreamView::num_selected_regionviews () const +{ + uint32_t cnt = 0; + + for (list::const_iterator i = region_views.begin(); i != region_views.end(); ++i) { + if ((*i)->selected()) { + ++cnt; + } + } + return cnt; +} + void StreamView::foreach_regionview (sigc::slot slot) { @@ -385,18 +513,29 @@ StreamView::foreach_regionview (sigc::slot slot) } } +void +StreamView::foreach_selected_regionview (sigc::slot slot) +{ + for (list::iterator i = region_views.begin(); i != region_views.end(); ++i) { + if ((*i)->selected()) { + slot (*i); + } + } +} + void StreamView::set_selected_regionviews (RegionSelection& regions) { bool selected; for (list::iterator i = region_views.begin(); i != region_views.end(); ++i) { - + selected = false; - + for (RegionSelection::iterator ii = regions.begin(); ii != regions.end(); ++ii) { if (*i == *ii) { selected = true; + break; } } @@ -404,13 +543,61 @@ StreamView::set_selected_regionviews (RegionSelection& regions) } } +/** Get selectable things within a given range. + * @param start Start time in session samples. + * @param end End time in session samples. + * @param top Top y range, in trackview coordinates (ie 0 is the top of the track view) + * @param bot Bottom y range, in trackview coordinates (ie 0 is the top of the track view) + * @param result Filled in with selectable things. + */ void -StreamView::get_selectables (nframes_t start, nframes_t end, list& results) +StreamView::get_selectables (samplepos_t start, samplepos_t end, double top, double bottom, list& results, bool within) { + if (_trackview.editor().internal_editing()) { + return; // Don't select regions with an internal tool + } + + layer_t min_layer = 0; + layer_t max_layer = 0; + + if (_layer_display == Stacked) { + double const c = child_height (); + + int const mi = _layers - ((bottom - _trackview.y_position()) / c); + if (mi < 0) { + min_layer = 0; + } else { + min_layer = mi; + } + + int const ma = _layers - ((top - _trackview.y_position()) / c); + if (ma > (int) _layers) { + max_layer = _layers - 1; + } else { + max_layer = ma; + } + + } + for (list::iterator i = region_views.begin(); i != region_views.end(); ++i) { - if ((*i)->region()->coverage(start, end) != OverlapNone) { - results.push_back (*i); + + bool layer_ok = true; + + if (_layer_display == Stacked) { + layer_t const l = (*i)->region()->layer (); + layer_ok = (min_layer <= l && l <= max_layer); } + + if (within) { + if ((*i)->region()->coverage (start, end) == Evoral::OverlapExternal && layer_ok) { + results.push_back (*i); + } + } else { + if ((*i)->region()->coverage (start, end) != Evoral::OverlapNone && layer_ok) { + results.push_back (*i); + } + } + } } @@ -428,50 +615,112 @@ StreamView::get_inverted_selectables (Selection& sel, list& results double StreamView::child_height () const { - if (layer_display == Stacked) { - return height / layers; + switch (_layer_display) { + case Overlaid: + return height; + case Stacked: + return height / _layers; + case Expanded: + return height / (_layers * 2 + 1); } - + + abort(); /* NOTREACHED */ return height; } void StreamView::update_contents_height () { - canvas_rect->property_y2() = height; - const double h = child_height (); for (RegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) { - switch (layer_display) { + switch (_layer_display) { case Overlaid: (*i)->set_y (0); break; case Stacked: (*i)->set_y (height - ((*i)->region()->layer() + 1) * h); break; + case Expanded: + (*i)->set_y (height - ((*i)->region()->layer() + 1) * 2 * h); + break; } (*i)->set_height (h); } for (vector::iterator i = rec_rects.begin(); i != rec_rects.end(); ++i) { - i->rectangle->property_y2() = height - 1.0; + switch (_layer_display) { + case Overlaid: + i->rectangle->set_y1 (height); + break; + case Stacked: + case Expanded: + /* In stacked displays, the recregion is always at the top */ + i->rectangle->set_y0 (0); + i->rectangle->set_y1 (h); + break; + } } + + ContentsHeightChanged (); /* EMIT SIGNAL */ } void StreamView::set_layer_display (LayerDisplay d) { - layer_display = d; + _layer_display = d; + + if (_layer_display == Overlaid) { + layer_regions (); + } + update_contents_height (); - update_coverage_frames (); + update_coverage_samples (); } void -StreamView::update_coverage_frames () +StreamView::update_coverage_samples () { for (RegionViewList::iterator i = region_views.begin (); i != region_views.end (); ++i) { - (*i)->update_coverage_frames (layer_display); + (*i)->update_coverage_samples (_layer_display); + } +} + +void +StreamView::check_record_layers (boost::shared_ptr region, samplepos_t to) +{ + if (_new_rec_layer_time < to) { + /* The region being recorded has overlapped the start of a top-layered region, so + `fake' a new visual layer for the recording. This is only a visual thing for now, + as the proper layering will get sorted out when the recorded region is added to + its playlist. + */ + + /* Stop this happening again */ + _new_rec_layer_time = max_samplepos; + + /* Make space in the view for the new layer */ + ++_layers; + + /* Set the temporary region to the correct layer so that it gets drawn correctly */ + region->set_layer (_layers - 1); + + /* and reset the view */ + update_contents_height (); + } +} + +void +StreamView::setup_new_rec_layer_time (boost::shared_ptr region) +{ + /* If we are in Stacked mode, we may need to (visually) create a new layer to put the + recorded region in. To work out where this needs to happen, find the start of the next + top-layered region after the start of the region we are recording and make a note of it. + */ + if (_layer_display == Stacked) { + _new_rec_layer_time = _trackview.track()->playlist()->find_next_top_layer_position (region->start()); + } else { + _new_rec_layer_time = max_samplepos; } }