From ef65fd251023378699c3ef3842fc55e93a92d04a Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Thu, 17 May 2007 10:41:14 +0000 Subject: Add stacked lanes mode which displays regions on different layers at different positions in the view. git-svn-id: svn://localhost/ardour2/trunk@1855 d708f5d6-7413-0410-9779-e7cbd77b26cf --- gtk2_ardour/audio_region_view.cc | 72 ++++++++++++++++++++++------------ gtk2_ardour/audio_region_view.h | 8 +++- gtk2_ardour/audio_streamview.cc | 57 +++++++++++++++------------ gtk2_ardour/audio_streamview.h | 6 ++- gtk2_ardour/audio_time_axis.cc | 20 ++++++++++ gtk2_ardour/audio_time_axis.h | 1 + gtk2_ardour/automation_line.cc | 33 ++++++++++------ gtk2_ardour/automation_line.h | 4 +- gtk2_ardour/automation_time_axis.cc | 4 +- gtk2_ardour/crossfade_view.cc | 26 ++++++------ gtk2_ardour/crossfade_view.h | 4 +- gtk2_ardour/editor_mouse.cc | 19 +++++---- gtk2_ardour/enums.h | 5 +++ gtk2_ardour/marker_time_axis_view.cc | 10 ++--- gtk2_ardour/midi_region_view.cc | 2 +- gtk2_ardour/region_view.cc | 14 +------ gtk2_ardour/region_view.h | 2 - gtk2_ardour/streamview.cc | 76 ++++++++++++++++++++++++++++-------- gtk2_ardour/streamview.h | 12 +++++- gtk2_ardour/time_axis_view_item.cc | 27 +++++++------ gtk2_ardour/time_axis_view_item.h | 7 +--- 21 files changed, 260 insertions(+), 149 deletions(-) diff --git a/gtk2_ardour/audio_region_view.cc b/gtk2_ardour/audio_region_view.cc index 2e1c13b487..bc0e3671c3 100644 --- a/gtk2_ardour/audio_region_view.cc +++ b/gtk2_ardour/audio_region_view.cc @@ -157,20 +157,18 @@ AudioRegionView::init (Gdk::Color& basic_color, bool wfd) fade_in_handle = new ArdourCanvas::SimpleRect (*group); fade_in_handle->property_fill_color_rgba() = RGBA_TO_UINT(r,g,b,0); fade_in_handle->property_outline_pixels() = 0; - fade_in_handle->property_y1() = 2.0; - fade_in_handle->property_y2() = 7.0; fade_in_handle->set_data ("regionview", this); fade_out_handle = new ArdourCanvas::SimpleRect (*group); fade_out_handle->property_fill_color_rgba() = RGBA_TO_UINT(r,g,b,0); fade_out_handle->property_outline_pixels() = 0; - fade_out_handle->property_y1() = 2.0; - fade_out_handle->property_y2() = 7.0; fade_out_handle->set_data ("regionview", this); } + setup_fade_handle_positions (); + string foo = _region->name(); foo += ':'; foo += "gain"; @@ -185,7 +183,7 @@ AudioRegionView::init (Gdk::Color& basic_color, bool wfd) gain_line->reset (); - set_height (trackview.height); + set_y_position_and_height (0, trackview.height); region_muted (); region_sync_changed (); @@ -400,38 +398,41 @@ AudioRegionView::region_muted () } void -AudioRegionView::set_height (gdouble height) +AudioRegionView::set_y_position_and_height (double y, double h) { - RegionView::set_height(height); - - uint32_t wcnt = waves.size(); + RegionView::set_y_position_and_height(y, h - 2); + + _y_position = y; + _height = h; - for (uint32_t n=0; n < wcnt; ++n) { - gdouble ht; + uint32_t const wcnt = waves.size(); + for (uint32_t n = 0; n < wcnt; ++n) { + double ht; - if ((height) <= NAME_HIGHLIGHT_THRESH) { - ht = ((height-2*wcnt) / (double) wcnt); + if (h <= NAME_HIGHLIGHT_THRESH) { + ht = ((_height - 2 * wcnt) / (double) wcnt); } else { - ht = (((height-2*wcnt) - NAME_HIGHLIGHT_SIZE) / (double) wcnt); + ht = (((_height - 2 * wcnt) - NAME_HIGHLIGHT_SIZE) / (double) wcnt); } - gdouble yoff = n * (ht+1); + double const yoff = n * (ht + 1); waves[n]->property_height() = ht; - waves[n]->property_y() = yoff + 2; + waves[n]->property_y() = _y_position + yoff + 2; } if (gain_line) { - if ((height/wcnt) < NAME_HIGHLIGHT_SIZE) { + if ((_height / wcnt) < NAME_HIGHLIGHT_SIZE) { gain_line->hide (); } else { if (_flags & EnvelopeVisible) { gain_line->show (); } } - gain_line->set_height ((uint32_t) rint (height - NAME_HIGHLIGHT_SIZE)); + gain_line->set_y_position_and_height ((uint32_t) _y_position, (uint32_t) rint (_height - NAME_HIGHLIGHT_SIZE)); } + setup_fade_handle_positions (); manage_zero_line (); reset_fade_shapes (); @@ -440,6 +441,25 @@ AudioRegionView::set_height (gdouble height) } } +void +AudioRegionView::setup_fade_handle_positions() +{ + /* position of fade handle offset from the top of the region view */ + double const handle_pos = 2; + /* height of fade handles */ + double const handle_height = 5; + + if (fade_in_handle) { + fade_in_handle->property_y1() = _y_position + handle_pos; + fade_in_handle->property_y2() = _y_position + handle_pos + handle_height; + } + + if (fade_out_handle) { + fade_out_handle->property_y1() = _y_position + handle_pos; + fade_out_handle->property_y2() = _y_position + handle_pos + handle_height; + } +} + void AudioRegionView::manage_zero_line () { @@ -448,7 +468,7 @@ AudioRegionView::manage_zero_line () } if (_height >= 100) { - gdouble wave_midpoint = (_height - NAME_HIGHLIGHT_SIZE) / 2.0; + double const wave_midpoint = _y_position + (_height - NAME_HIGHLIGHT_SIZE) / 2.0; zero_line->property_y1() = wave_midpoint; zero_line->property_y2() = wave_midpoint; zero_line->show(); @@ -529,16 +549,16 @@ AudioRegionView::reset_fade_in_shape_width (nframes_t width) for (pi = 0, pc = 0; pc < npoints; ++pc) { (*points)[pi].set_x(1 + (pc * xdelta)); - (*points)[pi++].set_y(2 + (h - (curve[pc] * h))); + (*points)[pi++].set_y(_y_position + 2 + (h - (curve[pc] * h))); } /* fold back */ (*points)[pi].set_x(pwidth); - (*points)[pi++].set_y(2); + (*points)[pi++].set_y(_y_position + 2); (*points)[pi].set_x(1); - (*points)[pi++].set_y(2); + (*points)[pi++].set_y(_y_position + 2); /* connect the dots ... */ @@ -615,16 +635,16 @@ AudioRegionView::reset_fade_out_shape_width (nframes_t width) for (pi = 0, pc = 0; pc < npoints; ++pc) { (*points)[pi].set_x(_pixel_width - 1 - pwidth + (pc*xdelta)); - (*points)[pi++].set_y(2 + (h - (curve[pc] * h))); + (*points)[pi++].set_y(_y_position + 2 + (h - (curve[pc] * h))); } /* fold back */ (*points)[pi].set_x(_pixel_width); - (*points)[pi++].set_y(h); + (*points)[pi++].set_y(_y_position + h); (*points)[pi].set_x(_pixel_width); - (*points)[pi++].set_y(2); + (*points)[pi++].set_y(_y_position + 2); /* connect the dots ... */ @@ -912,7 +932,7 @@ AudioRegionView::add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev) /* compute vertical fractional position */ - y = 1.0 - (y / (trackview.height - NAME_HIGHLIGHT_SIZE)); + y = 1.0 - ((y - _y_position) / (_height - NAME_HIGHLIGHT_SIZE)); /* map using gain line */ diff --git a/gtk2_ardour/audio_region_view.h b/gtk2_ardour/audio_region_view.h index 233e1a7c9b..e581e01146 100644 --- a/gtk2_ardour/audio_region_view.h +++ b/gtk2_ardour/audio_region_view.h @@ -63,7 +63,7 @@ class AudioRegionView : public RegionView boost::shared_ptr audio_region() const; - void set_height (double); + void set_y_position_and_height (double, double); void set_samples_per_unit (double); void set_amplitude_above_axis (gdouble spp); @@ -132,6 +132,8 @@ class AudioRegionView : public RegionView AudioRegionGainLine * gain_line; double _amplitude_above_axis; + double _y_position; + double _height; uint32_t _flags; uint32_t fade_color; @@ -165,6 +167,10 @@ class AudioRegionView : public RegionView void color_handler (ColorID, uint32_t); vector wave_caches; + + private: + + void setup_fade_handle_positions (); }; #endif /* __gtk_ardour_audio_region_view_h__ */ diff --git a/gtk2_ardour/audio_streamview.cc b/gtk2_ardour/audio_streamview.cc index db7b07dfb2..4ca3ad38b9 100644 --- a/gtk2_ardour/audio_streamview.cc +++ b/gtk2_ardour/audio_streamview.cc @@ -79,23 +79,6 @@ AudioStreamView::~AudioStreamView () { } -int -AudioStreamView::set_height (gdouble h) -{ - /* limit the values to something sane-ish */ - if (h < 10.0 || h > 1000.0) { - return -1; - } - - StreamView::set_height(h); - - for (CrossfadeViewList::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) { - (*i)->set_height (h); - } - - return 0; -} - int AudioStreamView::set_samples_per_unit (gdouble spp) { @@ -263,11 +246,23 @@ AudioStreamView::undisplay_diskstream () } void -AudioStreamView::playlist_modified () +AudioStreamView::playlist_modified_weak (boost::weak_ptr ds) { - ENSURE_GUI_THREAD (mem_fun (*this, &AudioStreamView::playlist_modified)); + boost::shared_ptr sp (ds.lock()); + if (!sp) { + return; + } - StreamView::playlist_modified(); + playlist_modified (sp); +} + +void +AudioStreamView::playlist_modified (boost::shared_ptr ds) +{ + /* we do not allow shared_ptr to be bound to slots */ + ENSURE_GUI_THREAD (bind (mem_fun (*this, &AudioStreamView::playlist_modified_weak), ds)); + + StreamView::playlist_modified (ds); /* make sure xfades are on top and all the regionviews are stacked correctly. */ @@ -314,7 +309,7 @@ AudioStreamView::add_crossfade (boost::shared_ptr crossfade) for (list::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) { if ((*i)->crossfade == crossfade) { - if (!crossfades_visible) { + if (!crossfades_visible || layer_display == Stacked) { (*i)->hide(); } else { (*i)->show (); @@ -347,7 +342,7 @@ AudioStreamView::add_crossfade (boost::shared_ptr crossfade) crossfade->Invalidated.connect (mem_fun (*this, &AudioStreamView::remove_crossfade)); crossfade_views.push_back (cv); - if (!Config->get_xfades_visible() || !crossfades_visible) { + if (!Config->get_xfades_visible() || !crossfades_visible || layer_display == Stacked) { cv->hide (); } } @@ -378,7 +373,7 @@ AudioStreamView::redisplay_diskstream () for (xi = crossfade_views.begin(); xi != crossfade_views.end(); ++xi) { (*xi)->set_valid (false); - if ((*xi)->visible()) { + if ((*xi)->visible() && layer_display != Stacked) { (*xi)->show (); } } @@ -755,7 +750,7 @@ void AudioStreamView::reveal_xfades_involving (AudioRegionView& rv) { for (list::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) { - if ((*i)->crossfade->involves (rv.audio_region()) && (*i)->visible()) { + if ((*i)->crossfade->involves (rv.audio_region()) && (*i)->visible() && layer_display != Stacked) { (*i)->show (); } } @@ -784,3 +779,17 @@ AudioStreamView::color_handler (ColorID id, uint32_t val) } } +void +AudioStreamView::update_contents_y_position_and_height () +{ + StreamView::update_contents_y_position_and_height (); + + for (CrossfadeViewList::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) { + if (layer_display == Overlaid) { + (*i)->show (); + (*i)->set_y_position_and_height (0, height); + } else { + (*i)->hide (); + } + } +} diff --git a/gtk2_ardour/audio_streamview.h b/gtk2_ardour/audio_streamview.h index 9f3630c182..fc707e97e7 100644 --- a/gtk2_ardour/audio_streamview.h +++ b/gtk2_ardour/audio_streamview.h @@ -63,7 +63,6 @@ class AudioStreamView : public StreamView void set_waveform_scale (WaveformScale); WaveformScale get_waveform_scale () const { return _waveform_scale; } - int set_height (gdouble h); int set_samples_per_unit (gdouble spp); int set_amplitude_above_axis (gdouble app); @@ -90,7 +89,8 @@ class AudioStreamView : public StreamView void undisplay_diskstream (); void redisplay_diskstream (); - void playlist_modified (); + void playlist_modified_weak (boost::weak_ptr); + void playlist_modified (boost::shared_ptr); void playlist_changed (boost::shared_ptr); void add_crossfade (boost::shared_ptr); @@ -98,6 +98,8 @@ class AudioStreamView : public StreamView void remove_crossfade (boost::shared_ptr); void color_handler (ColorID id, uint32_t val); + + void update_contents_y_position_and_height (); double _amplitude_above_axis; diff --git a/gtk2_ardour/audio_time_axis.cc b/gtk2_ardour/audio_time_axis.cc index 414329f145..d37b164ed1 100644 --- a/gtk2_ardour/audio_time_axis.cc +++ b/gtk2_ardour/audio_time_axis.cc @@ -287,6 +287,18 @@ AudioTimeAxisView::append_extra_display_menu_items () } items.push_back (MenuElem (_("Waveform"), *waveform_menu)); + + + Menu *layers_menu = manage(new Menu); + MenuList &layers_items = layers_menu->items(); + layers_menu->set_name("ArdourContextMenu"); + + RadioMenuItem::Group layers_group; + + layers_items.push_back(RadioMenuElem (layers_group, _("Overlaid"), bind (mem_fun (*this, &AudioTimeAxisView::set_layer_display), Overlaid))); + layers_items.push_back(RadioMenuElem (layers_group, _("Stacked"), bind (mem_fun (*this, &AudioTimeAxisView::set_layer_display), Stacked))); + + items.push_back (MenuElem (_("Layers"), *layers_menu)); } void @@ -663,3 +675,11 @@ AudioTimeAxisView::get_child_xml_node (const string & childname) return RouteUI::get_child_xml_node (childname); } +void +AudioTimeAxisView::set_layer_display (LayerDisplay d) +{ + AudioStreamView* asv = audio_view (); + if (asv) { + asv->set_layer_display (d); + } +} diff --git a/gtk2_ardour/audio_time_axis.h b/gtk2_ardour/audio_time_axis.h index d8c3f07cc1..ab5ef955c7 100644 --- a/gtk2_ardour/audio_time_axis.h +++ b/gtk2_ardour/audio_time_axis.h @@ -77,6 +77,7 @@ class AudioTimeAxisView : public RouteTimeAxisView void hide_all_xfades (); void hide_dependent_views (TimeAxisViewItem&); void reveal_dependent_views (TimeAxisViewItem&); + void set_layer_display (LayerDisplay d); /* Overridden from parent to store display state */ guint32 show_at (double y, int& nth, Gtk::VBox *parent); diff --git a/gtk2_ardour/automation_line.cc b/gtk2_ardour/automation_line.cc index 67f91e1ed4..a729161911 100644 --- a/gtk2_ardour/automation_line.cc +++ b/gtk2_ardour/automation_line.cc @@ -232,6 +232,7 @@ AutomationLine::AutomationLine (const string & name, TimeAxisView& tv, ArdourCan no_draw = false; _visible = true; terminal_points_can_slide = true; + _y_position = 0; _height = 0; group = new ArdourCanvas::Group (parent); @@ -307,17 +308,27 @@ AutomationLine::control_point_box_size () } void -AutomationLine::set_height (guint32 h) +AutomationLine::set_y_position_and_height (guint32 y, guint32 h) { + bool changed = false; + + if (y != _y_position) { + _y_position = y; + changed = true; + } + if (h != _height) { _height = h; - double bsz = control_point_box_size(); + double const bsz = control_point_box_size(); for (vector::iterator i = control_points.begin(); i != control_points.end(); ++i) { (*i)->set_size (bsz); } + changed = true; + } + if (changed) { reset (); } } @@ -365,7 +376,7 @@ AutomationLine::modify_view_point (ControlPoint& cp, double x, double y, bool wi y = max (0.0, y); y = min (1.0, y); - y = _height - (y * _height); + y = _y_position + _height - (y * _height); if (cp.can_slide) { @@ -494,7 +505,7 @@ AutomationLine::model_representation (ControlPoint& cp, ModelRepresentation& mr) */ mr.xval = (nframes_t) floor (cp.get_x()); - mr.yval = 1.0 - (cp.get_y() / _height); + mr.yval = 1.0 - ( (cp.get_y() - _y_position) / _height); /* if xval has not changed, set it directly from the model to avoid rounding errors */ @@ -831,7 +842,7 @@ AutomationLine::point_drag (ControlPoint& cp, nframes_t x, float fraction, bool void AutomationLine::line_drag (uint32_t i1, uint32_t i2, float fraction, bool with_push) { - double ydelta = fraction - last_drag_fraction; + double const ydelta = fraction - last_drag_fraction; did_push = with_push; @@ -844,7 +855,7 @@ AutomationLine::line_drag (uint32_t i1, uint32_t i2, float fraction, bool with_p for (uint32_t i = i1 ; i <= i2; i++) { cp = nth (i); - modify_view_point (*cp, trackview.editor.unit_to_frame (cp->get_x()), ((_height - cp->get_y()) /_height) + ydelta, with_push); + modify_view_point (*cp, trackview.editor.unit_to_frame (cp->get_x()), ((_height - cp->get_y() + _y_position) /_height) + ydelta, with_push); } if (line_points.size() > 1) { @@ -1041,8 +1052,8 @@ AutomationLine::get_selectables (nframes_t& start, nframes_t& end, /* Curse X11 and its inverted coordinate system! */ - bot = (1.0 - topfrac) * _height; - top = (1.0 - botfrac) * _height; + bot = _y_position + (1.0 - topfrac) * _height; + top = _y_position + (1.0 - botfrac) * _height; nstart = max_frames; nend = 0; @@ -1108,8 +1119,8 @@ AutomationLine::set_selected_points (PointSelection& points) /* Curse X11 and its inverted coordinate system! */ - bot = (1.0 - (*r).high_fract) * _height; - top = (1.0 - (*r).low_fract) * _height; + bot = _y_position + (1.0 - (*r).high_fract) * _height; + top = _y_position + (1.0 - (*r).low_fract) * _height; for (vector::iterator i = control_points.begin(); i != control_points.end(); ++i) { @@ -1203,7 +1214,7 @@ AutomationLine::reset_callback (const AutomationList& events) model_to_view_y (translated_y); tmp_points.push_back (ALPoint (trackview.editor.frame_to_unit ((*ai)->when), - _height - (translated_y * _height))); + _y_position + _height - (translated_y * _height))); } determine_visible_control_points (tmp_points); diff --git a/gtk2_ardour/automation_line.h b/gtk2_ardour/automation_line.h index 76afff5097..2637a0c554 100644 --- a/gtk2_ardour/automation_line.h +++ b/gtk2_ardour/automation_line.h @@ -127,13 +127,14 @@ class AutomationLine : public sigc::trackable, public PBD::StatefulThingWithGoin string name() const { return _name; } bool visible() const { return _visible; } guint32 height() const { return _height; } + guint32 y_position() const { return _y_position; } void set_line_color (uint32_t); uint32_t get_line_color() const { return _line_color; } void show (); void hide (); - void set_height (guint32); + void set_y_position_and_height (uint32_t, uint32_t); void set_verbose_cursor_uses_gain_mapping (bool yn); TimeAxisView& trackview; @@ -164,6 +165,7 @@ class AutomationLine : public sigc::trackable, public PBD::StatefulThingWithGoin protected: string _name; + guint32 _y_position; guint32 _height; uint32_t _line_color; ARDOUR::AutomationList& alist; diff --git a/gtk2_ardour/automation_time_axis.cc b/gtk2_ardour/automation_time_axis.cc index 12998ee7d6..45103ec7f1 100644 --- a/gtk2_ardour/automation_time_axis.cc +++ b/gtk2_ardour/automation_time_axis.cc @@ -313,7 +313,7 @@ AutomationTimeAxisView::set_height (TrackHeight ht) base_rect->property_y2() = h; for (vector::iterator i = lines.begin(); i != lines.end(); ++i) { - (*i)->set_height (h); + (*i)->set_y_position_and_height (0, h); } for (list::iterator i = ghosts.begin(); i != ghosts.end(); ++i) { @@ -771,7 +771,7 @@ AutomationTimeAxisView::add_line (AutomationLine& line) } lines.push_back (&line); - line.set_height (height); + line.set_y_position_and_height (0, height); if (get) { /* pick up the current state */ diff --git a/gtk2_ardour/crossfade_view.cc b/gtk2_ardour/crossfade_view.cc index ef43ee9873..261b2b3ca4 100644 --- a/gtk2_ardour/crossfade_view.cc +++ b/gtk2_ardour/crossfade_view.cc @@ -68,7 +68,7 @@ CrossfadeView::CrossfadeView (ArdourCanvas::Group *parent, fade_out->property_fill_color_rgba() = color_map[cCrossfadeLine]; fade_out->property_width_pixels() = 1; - set_height (get_time_axis_view().height); + set_y_position_and_height (0, get_time_axis_view().height); /* no frame around the xfade or overlap rects */ @@ -105,13 +105,16 @@ CrossfadeView::reset_width_dependent_items (double pixel_width) } void -CrossfadeView::set_height (double height) +CrossfadeView::set_y_position_and_height (double y, double h) { - if (height == TimeAxisView::hSmaller || - height == TimeAxisView::hSmall) - TimeAxisViewItem::set_height (height - 3 ); - else - TimeAxisViewItem::set_height (height - NAME_HIGHLIGHT_SIZE - 3 ); + if (h == TimeAxisView::hSmaller || h == TimeAxisView::hSmall) { + TimeAxisViewItem::set_y_position_and_height (y, h - 3 ); + } else { + TimeAxisViewItem::set_y_position_and_height (y, h - NAME_HIGHLIGHT_SIZE - 3 ); + } + + _y_position = y; + _height = h; redraw_curves (); } @@ -158,9 +161,8 @@ CrossfadeView::redraw_curves () At "height - 3.0" the bottom of the crossfade touches the name highlight or the bottom of the track (if the track is either Small or Smaller. */ - double tav_height = get_time_axis_view().height; - if (tav_height == TimeAxisView::hSmaller || - tav_height == TimeAxisView::hSmall) { + double const tav_height = get_time_axis_view().height; + if (tav_height == TimeAxisView::hSmaller || tav_height == TimeAxisView::hSmall) { h = tav_height - 3.0; } else { h = tav_height - NAME_HIGHLIGHT_SIZE - 3.0; @@ -190,7 +192,7 @@ CrossfadeView::redraw_curves () for (int i = 0, pci = 0; i < npoints; ++i) { Art::Point &p = (*points)[pci++]; p.set_x(i); - p.set_y(2.0 + h - (h * vec[i])); + p.set_y(_y_position + 2.0 + h - (h * vec[i])); } fade_in->property_points() = *points; @@ -198,7 +200,7 @@ CrossfadeView::redraw_curves () for (int i = 0, pci = 0; i < npoints; ++i) { Art::Point &p = (*points)[pci++]; p.set_x(i); - p.set_y(2.0 + h - (h * vec[i])); + p.set_y(_y_position + 2.0 + h - (h * vec[i])); } fade_out->property_points() = *points; diff --git a/gtk2_ardour/crossfade_view.h b/gtk2_ardour/crossfade_view.h index 556d8c80c5..02f3cd0df2 100644 --- a/gtk2_ardour/crossfade_view.h +++ b/gtk2_ardour/crossfade_view.h @@ -46,7 +46,7 @@ struct CrossfadeView : public TimeAxisViewItem AudioRegionView& left_view; // and these too AudioRegionView& right_view; - void set_height (double); + void set_y_position_and_height (double, double); bool valid() const { return _valid; } bool visible() const { return _visible; } @@ -68,6 +68,8 @@ struct CrossfadeView : public TimeAxisViewItem bool _visible; double spu; + double _y_position; + double _height; ArdourCanvas::Item *overlap_rect; ArdourCanvas::Line *fade_in; diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc index 4f06562fb0..5247b596b6 100644 --- a/gtk2_ardour/editor_mouse.cc +++ b/gtk2_ardour/editor_mouse.cc @@ -1066,7 +1066,7 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_ at_x += 20.0; at_y += 20.0; - fraction = 1.0 - (cp->get_y() / cp->line.height()); + fraction = 1.0 - ((cp->get_y() - cp->line.y_position()) / cp->line.height()); set_verbose_canvas_cursor (cp->line.get_verbose_cursor_string (fraction), at_x, at_y); show_verbose_canvas_cursor (); @@ -2446,7 +2446,7 @@ void Editor::start_control_point_grab (ArdourCanvas::Item* item, GdkEvent* event) { ControlPoint* control_point; - + if ((control_point = reinterpret_cast (item->get_data ("control_point"))) == 0) { fatal << _("programming error: control point canvas item has no control point object pointer!") << endmsg; /*NOTREACHED*/ @@ -2461,7 +2461,7 @@ Editor::start_control_point_grab (ArdourCanvas::Item* item, GdkEvent* event) control_point->line.start_drag (control_point, drag_info.grab_frame, 0); - float fraction = 1.0 - (control_point->get_y() / control_point->line.height()); + float fraction = 1.0 - ((control_point->get_y() - control_point->line.y_position()) / control_point->line.height()); set_verbose_canvas_cursor (control_point->line.get_verbose_cursor_string (fraction), drag_info.current_pointer_x + 20, drag_info.current_pointer_y + 20); @@ -2490,7 +2490,7 @@ Editor::control_point_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* cx = max (0.0, cx); cy = max (0.0, cy); - cy = min ((double) cp->line.height(), cy); + cy = min ((double) (cp->line.y_position() + cp->line.height()), cy); //translate cx to frames nframes_t cx_frames = unit_to_frame (cx); @@ -2499,8 +2499,8 @@ Editor::control_point_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* snap_to (cx_frames); } - float fraction = 1.0 - (cy / cp->line.height()); - + float const fraction = 1.0 - ((cy - cp->line.y_position()) / cp->line.height()); + bool push; if (Keyboard::modifier_state_contains (event->button.state, Keyboard::Control)) { @@ -2590,7 +2590,7 @@ Editor::start_line_grab (AutomationLine* line, GdkEvent* event) start_grab (event, fader_cursor); - double fraction = 1.0 - (cy / line->height()); + double const fraction = 1.0 - ((cy - line->y_position()) / line->height()); line->start_drag (0, drag_info.grab_frame, fraction); @@ -2608,8 +2608,7 @@ Editor::line_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) line->parent_group().w2i (cx, cy); - double fraction; - fraction = 1.0 - (cy / line->height()); + double const fraction = 1.0 - ((cy - line->y_position()) / line->height()); bool push; @@ -3140,7 +3139,7 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) tvp2 = trackview_by_y_position (iy1 + y_delta); temp_rtv = dynamic_cast(tvp2); - rv->set_height (temp_rtv->height); + rv->set_y_position_and_height (0, temp_rtv->height); /* if you un-comment the following, the region colours will follow the track colours whilst dragging, personally, i think this can confuse things, but never mind. diff --git a/gtk2_ardour/enums.h b/gtk2_ardour/enums.h index d345b30bf8..fcb675fd46 100644 --- a/gtk2_ardour/enums.h +++ b/gtk2_ardour/enums.h @@ -44,6 +44,11 @@ namespace Gnome { } } +enum LayerDisplay { + Overlaid, + Stacked +}; + struct SelectionRect { Gnome::Canvas::SimpleRect *rect; Gnome::Canvas::SimpleRect *end_trim; diff --git a/gtk2_ardour/marker_time_axis_view.cc b/gtk2_ardour/marker_time_axis_view.cc index f33e0bbefc..34acf51fbf 100644 --- a/gtk2_ardour/marker_time_axis_view.cc +++ b/gtk2_ardour/marker_time_axis_view.cc @@ -115,16 +115,14 @@ MarkerTimeAxisView::~MarkerTimeAxisView() int MarkerTimeAxisView::set_height(gdouble h) { - if (h < 10.0 || h > 1000.0) - { - return -1 ; + if (h < 10.0 || h > 1000.0) { + return -1; } canvas_rect->property_y2() = h; - for (MarkerViewList::iterator i = marker_view_list.begin(); i != marker_view_list.end(); ++i) - { - (*i)->set_height(h) ; + for (MarkerViewList::iterator i = marker_view_list.begin(); i != marker_view_list.end(); ++i) { + (*i)->set_y_position_and_height(0, h); } return 0; diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc index c225295f13..cef1329ed5 100644 --- a/gtk2_ardour/midi_region_view.cc +++ b/gtk2_ardour/midi_region_view.cc @@ -75,7 +75,7 @@ MidiRegionView::init (Gdk::Color& basic_color, bool wfd) reset_width_dependent_items ((double) _region->length() / samples_per_unit); - set_height (trackview.height); + set_y_position_and_height (0, trackview.height); region_muted (); region_resized (BoundsChanged); diff --git a/gtk2_ardour/region_view.cc b/gtk2_ardour/region_view.cc index 859e2edfb4..3923f7e79a 100644 --- a/gtk2_ardour/region_view.cc +++ b/gtk2_ardour/region_view.cc @@ -72,7 +72,6 @@ RegionView::RegionView (ArdourCanvas::Group* parent, , current_visible_sync_position(0.0) , valid(false) , _pixel_width(1.0) - , _height(1.0) , in_destructor(false) , wait_for_data(false) { @@ -88,7 +87,6 @@ RegionView::RegionView (const RegionView& other) current_visible_sync_position = other.current_visible_sync_position; valid = false; _pixel_width = other._pixel_width; - _height = other._height; } RegionView::RegionView (ArdourCanvas::Group* parent, @@ -104,7 +102,6 @@ RegionView::RegionView (ArdourCanvas::Group* parent, , current_visible_sync_position(0.0) , valid(false) , _pixel_width(1.0) - , _height(1.0) , in_destructor(false) , wait_for_data(false) { @@ -115,7 +112,6 @@ RegionView::init (Gdk::Color& basic_color, bool wfd) { valid = true; in_destructor = false; - _height = 0; wait_for_data = wfd; compute_colors (basic_color); @@ -141,7 +137,7 @@ RegionView::init (Gdk::Color& basic_color, bool wfd) reset_width_dependent_items ((double) _region->length() / samples_per_unit); - set_height (trackview.height); + set_y_position_and_height (0, trackview.height); _region->StateChanged.connect (mem_fun(*this, &RegionView::region_changed)); @@ -254,14 +250,6 @@ RegionView::reset_width_dependent_items (double pixel_width) _pixel_width = pixel_width; } -void -RegionView::set_height (gdouble height) -{ - TimeAxisViewItem::set_height (height - 2); - - _height = height; -} - void RegionView::region_layered () { diff --git a/gtk2_ardour/region_view.h b/gtk2_ardour/region_view.h index 0f4d57ad04..d16d81e373 100644 --- a/gtk2_ardour/region_view.h +++ b/gtk2_ardour/region_view.h @@ -60,7 +60,6 @@ class RegionView : public TimeAxisViewItem void set_valid (bool yn) { valid = yn; } - virtual void set_height (double); virtual void set_samples_per_unit (double); virtual bool set_duration (nframes_t, void*); @@ -134,7 +133,6 @@ class RegionView : public TimeAxisViewItem bool valid; ///< see StreamView::redisplay_diskstream() double _pixel_width; - double _height; bool in_destructor; bool wait_for_data; diff --git a/gtk2_ardour/streamview.cc b/gtk2_ardour/streamview.cc index d6f2edeba9..2997661848 100644 --- a/gtk2_ardour/streamview.cc +++ b/gtk2_ardour/streamview.cc @@ -56,6 +56,7 @@ StreamView::StreamView (RouteTimeAxisView& tv) , use_rec_regions(tv.editor.show_waveforms_recording()) , region_color(_trackview.color()) , stream_base_color(0xFFFFFFFF) + , layers(1) , last_rec_data_frame(0) { /* set_position() will position the group */ @@ -96,7 +97,6 @@ StreamView::attach () int StreamView::set_position (gdouble x, gdouble y) - { canvas_group->property_x() = x; canvas_group->property_y() = y; @@ -104,10 +104,9 @@ StreamView::set_position (gdouble x, gdouble y) } int -StreamView::set_height (gdouble h) +StreamView::set_height (double h) { /* limit the values to something sane-ish */ - if (h < 10.0 || h > 1000.0) { return -1; } @@ -116,17 +115,8 @@ StreamView::set_height (gdouble h) return 0; } - canvas_rect->property_y2() = h; - - for (RegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) { - (*i)->set_height (h); - } - - for (vector::iterator i = rec_rects.begin(); i != rec_rects.end(); ++i) { - RecBoxInfo &recbox = (*i); - recbox.rectangle->property_y2() = h - 1.0; - } - + height = h; + update_contents_y_position_and_height (); return 0; } @@ -162,6 +152,7 @@ void StreamView::add_region_view (boost::shared_ptr r) { add_region_view_internal (r, true); + update_contents_y_position_and_height (); } void @@ -203,9 +194,25 @@ StreamView::display_diskstream (boost::shared_ptr ds) } void -StreamView::playlist_modified () +StreamView::playlist_modified_weak (boost::weak_ptr ds) { - ENSURE_GUI_THREAD (mem_fun (*this, &StreamView::playlist_modified)); + boost::shared_ptr sp (ds.lock()); + if (!sp) { + return; + } + + playlist_modified (sp); +} + +void +StreamView::playlist_modified (boost::shared_ptr ds) +{ + /* we do not allow shared_ptr to be bound to slots */ + ENSURE_GUI_THREAD (bind (mem_fun (*this, &StreamView::playlist_modified_weak), ds)); + + /* update layers count and the y positions and heights of our regions */ + layers = ds->playlist()->top_layer() + 1; + update_contents_y_position_and_height (); redisplay_diskstream (); } @@ -213,6 +220,7 @@ StreamView::playlist_modified () void StreamView::playlist_changed (boost::shared_ptr ds) { + /* XXX: binding to a shared_ptr, is this ok? */ ENSURE_GUI_THREAD (bind (mem_fun (*this, &StreamView::playlist_changed), ds)); /* disconnect from old playlist */ @@ -230,7 +238,11 @@ StreamView::playlist_changed (boost::shared_ptr ds) /* catch changes */ - playlist_connections.push_back (ds->playlist()->Modified.connect (mem_fun (*this, &StreamView::playlist_modified))); + playlist_connections.push_back (ds->playlist()->Modified.connect (bind (mem_fun (*this, &StreamView::playlist_modified_weak), ds))); + + /* update layers count and the y positions and heights of our regions */ + layers = ds->playlist()->top_layer() + 1; + update_contents_y_position_and_height (); } void @@ -390,3 +402,33 @@ StreamView::get_inverted_selectables (Selection& sel, list& results } } +void +StreamView::update_contents_y_position_and_height () +{ + canvas_rect->property_y2() = height; + + const double lh = height / layers; + + for (RegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) { + switch (layer_display) { + case Overlaid: + (*i)->set_y_position_and_height (0, height); + break; + case Stacked: + double const y = (*i)->region()->layer() * lh; + (*i)->set_y_position_and_height (y, lh); + break; + } + } + + for (vector::iterator i = rec_rects.begin(); i != rec_rects.end(); ++i) { + i->rectangle->property_y2() = height - 1.0; + } +} + +void +StreamView::set_layer_display (LayerDisplay d) +{ + layer_display = d; + update_contents_y_position_and_height (); +} diff --git a/gtk2_ardour/streamview.h b/gtk2_ardour/streamview.h index 39c04aea7f..365f2d4edf 100644 --- a/gtk2_ardour/streamview.h +++ b/gtk2_ardour/streamview.h @@ -68,11 +68,13 @@ public: void set_zoom_all(); int set_position (gdouble x, gdouble y); - virtual int set_height (gdouble); + virtual int set_height (double); virtual int set_samples_per_unit (gdouble spp); gdouble get_samples_per_unit () { return _samples_per_unit; } + void set_layer_display (LayerDisplay); + ArdourCanvas::Item* canvas_item() { return canvas_group; } enum ColorTarget { @@ -117,10 +119,12 @@ protected: void diskstream_changed (); virtual void playlist_changed (boost::shared_ptr); - virtual void playlist_modified (); + virtual void playlist_modified_weak (boost::weak_ptr); + virtual void playlist_modified (boost::shared_ptr); virtual void color_handler (ColorID, uint32_t) = 0; + virtual void update_contents_y_position_and_height (); RouteTimeAxisView& _trackview; ArdourCanvas::Group* canvas_group; @@ -143,6 +147,10 @@ protected: vector playlist_connections; sigc::connection playlist_change_connection; + + int layers; + double height; + LayerDisplay layer_display; list rec_data_ready_connections; jack_nframes_t last_rec_data_frame; diff --git a/gtk2_ardour/time_axis_view_item.cc b/gtk2_ardour/time_axis_view_item.cc index 7830e8f437..0e66ab2bae 100644 --- a/gtk2_ardour/time_axis_view_item.cc +++ b/gtk2_ardour/time_axis_view_item.cc @@ -567,15 +567,16 @@ TimeAxisViewItem::set_name_text(const ustring& new_name) } /** - * Set the height of this item + * Set the y position and height of this item. * + * @param y the new y position * @param h the new height */ void -TimeAxisViewItem::set_height (double height) +TimeAxisViewItem::set_y_position_and_height (double y, double h) { if (name_highlight) { - if (height < NAME_HIGHLIGHT_THRESH) { + if (h < NAME_HIGHLIGHT_THRESH) { name_highlight->hide(); if (name_text) { name_text->hide(); @@ -587,20 +588,20 @@ TimeAxisViewItem::set_height (double height) } } - if (height > NAME_HIGHLIGHT_SIZE) { - name_highlight->property_y1() = (double) height+1 - NAME_HIGHLIGHT_SIZE; - name_highlight->property_y2() = (double) height; + if (h > NAME_HIGHLIGHT_SIZE) { + name_highlight->property_y1() = (double) y + h + 1 - NAME_HIGHLIGHT_SIZE; + name_highlight->property_y2() = (double) y + h; } else { /* it gets hidden now anyway */ - name_highlight->property_y1() = (double) 1.0; - name_highlight->property_y2() = (double) height; + name_highlight->property_y1() = (double) y; + name_highlight->property_y2() = (double) y + h; } } if (name_text) { - name_text->property_y() = height+1 - NAME_Y_OFFSET; - if (height < NAME_HIGHLIGHT_THRESH) { + name_text->property_y() = y + h + 1 - NAME_Y_OFFSET; + if (h < NAME_HIGHLIGHT_THRESH) { name_text->property_fill_color_rgba() = fill_color; } else { @@ -609,10 +610,12 @@ TimeAxisViewItem::set_height (double height) } if (frame) { - frame->property_y2() = height+1; + frame->property_y1() = y; + frame->property_y2() = y + h + 1; } - vestigial_frame->property_y2() = height+1; + vestigial_frame->property_y1() = y; + vestigial_frame->property_y2() = y + h + 1; } /** diff --git a/gtk2_ardour/time_axis_view_item.h b/gtk2_ardour/time_axis_view_item.h index aeeebe1c79..118a042920 100644 --- a/gtk2_ardour/time_axis_view_item.h +++ b/gtk2_ardour/time_axis_view_item.h @@ -201,12 +201,7 @@ class TimeAxisViewItem : public Selectable */ void set_name_text(const Glib::ustring& new_name) ; - /** - * Set the height of this item - * - * @param h the new height - */ - virtual void set_height(double h) ; + virtual void set_y_position_and_height(double y, double h); /** * -- cgit v1.2.3