diff options
author | David Robillard <d@drobilla.net> | 2006-07-30 03:25:38 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2006-07-30 03:25:38 +0000 |
commit | 9d5d82b4df5b3510177fd31557ac765f46778fe8 (patch) | |
tree | b0b786f4f8fcee4e76c7c3ab1a66f603c08de070 /gtk2_ardour | |
parent | 8277d134b9733aee344782891c99f07114384d9e (diff) |
Abstraction cleanups/polish, towards merging with trunk
git-svn-id: svn://localhost/ardour2/branches/midi@720 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'gtk2_ardour')
-rw-r--r-- | gtk2_ardour/audio_regionview.cc | 298 | ||||
-rw-r--r-- | gtk2_ardour/audio_regionview.h | 60 | ||||
-rw-r--r-- | gtk2_ardour/audio_streamview.cc | 33 | ||||
-rw-r--r-- | gtk2_ardour/audio_streamview.h | 9 | ||||
-rw-r--r-- | gtk2_ardour/audio_time_axis.cc | 487 | ||||
-rw-r--r-- | gtk2_ardour/audio_time_axis.h | 94 | ||||
-rw-r--r-- | gtk2_ardour/editor.cc | 12 | ||||
-rw-r--r-- | gtk2_ardour/plugin_selector.h | 1 | ||||
-rw-r--r-- | gtk2_ardour/regionview.cc | 87 | ||||
-rw-r--r-- | gtk2_ardour/regionview.h | 56 | ||||
-rw-r--r-- | gtk2_ardour/route_time_axis.cc | 506 | ||||
-rw-r--r-- | gtk2_ardour/route_time_axis.h | 164 | ||||
-rw-r--r-- | gtk2_ardour/streamview.cc | 1 | ||||
-rw-r--r-- | gtk2_ardour/streamview.h | 30 | ||||
-rw-r--r-- | gtk2_ardour/taperegionview.cc | 46 |
15 files changed, 749 insertions, 1135 deletions
diff --git a/gtk2_ardour/audio_regionview.cc b/gtk2_ardour/audio_regionview.cc index 125654c35c..f22028f33e 100644 --- a/gtk2_ardour/audio_regionview.cc +++ b/gtk2_ardour/audio_regionview.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2001 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 @@ -19,6 +19,7 @@ */ #include <cmath> +#include <cassert> #include <algorithm> #include <gtkmm.h> @@ -68,20 +69,18 @@ AudioRegionView::AudioRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView } void -AudioRegionView::init (Gdk::Color& basic_color, bool wfw) +AudioRegionView::init (Gdk::Color& basic_color, bool wfd) { - ArdourCanvas::Points shape; + // FIXME: Some redundancy here with RegionView::init. Need to figure out + // where order is important and where it isn't... + + RegionView::init(basic_color, wfd); + XMLNode *node; - editor = 0; - valid = true; - in_destructor = false; _amplitude_above_axis = 1.0; - zero_line = 0; - wait_for_waves = wfw; - _height = 0; - - _flags = 0; + zero_line = 0; + _flags = 0; if ((node = _region.extra_xml ("GUI")) != 0) { set_flags (node); @@ -98,23 +97,6 @@ AudioRegionView::init (Gdk::Color& basic_color, bool wfw) create_waves (); - name_highlight->set_data ("regionview", this); - name_text->set_data ("regionview", this); - - // shape = new ArdourCanvas::Points (); - - /* an equilateral triangle */ - - shape.push_back (Gnome::Art::Point (-((sync_mark_width-1)/2), 1)); - shape.push_back (Gnome::Art::Point ((sync_mark_width - 1)/2, 1)); - shape.push_back (Gnome::Art::Point (0, sync_mark_width - 1)); - shape.push_back (Gnome::Art::Point (-((sync_mark_width-1)/2), 1)); - - sync_mark = new ArdourCanvas::Polygon (*group); - sync_mark->property_points() = shape; - sync_mark->property_fill_color_rgba() = fill_color; - sync_mark->hide(); - fade_in_shape = new ArdourCanvas::Polygon (*group); fade_in_shape->property_fill_color_rgba() = fade_color; fade_in_shape->set_data ("regionview", this); @@ -175,8 +157,6 @@ AudioRegionView::init (Gdk::Color& basic_color, bool wfw) _region.StateChanged.connect (mem_fun(*this, &AudioRegionView::region_changed)); - group->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_region_view_event), group, this)); - name_highlight->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_region_view_name_highlight_event), name_highlight, this)); fade_in_shape->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_fade_in_event), fade_in_shape, this)); fade_in_handle->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_fade_in_handle_event), fade_in_handle, this)); fade_out_shape->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_fade_out_event), fade_out_shape, this)); @@ -184,8 +164,6 @@ AudioRegionView::init (Gdk::Color& basic_color, bool wfw) set_colors (); - ColorChanged.connect (mem_fun (*this, &AudioRegionView::color_handler)); - /* XXX sync mark drag? */ } @@ -201,14 +179,6 @@ AudioRegionView::~AudioRegionView () /* all waveviews etc will be destroyed when the group is destroyed */ - for (vector<GhostRegion*>::iterator g = ghosts.begin(); g != ghosts.end(); ++g) { - delete *g; - } - - if (editor) { - delete editor; - } - if (gain_line) { delete gain_line; } @@ -217,58 +187,17 @@ AudioRegionView::~AudioRegionView () ARDOUR::AudioRegion& AudioRegionView::audio_region() const { - // Guaranteed to succeed + // "Guaranteed" to succeed... return dynamic_cast<AudioRegion&>(_region); } - -gint -AudioRegionView::_lock_toggle (ArdourCanvas::Item* item, GdkEvent* ev, void* arg) -{ - switch (ev->type) { - case GDK_BUTTON_RELEASE: - static_cast<AudioRegionView*>(arg)->lock_toggle (); - return TRUE; - break; - default: - break; - } - return FALSE; -} - -void -AudioRegionView::lock_toggle () -{ - _region.set_locked (!_region.locked()); -} - void AudioRegionView::region_changed (Change what_changed) { ENSURE_GUI_THREAD (bind (mem_fun(*this, &AudioRegionView::region_changed), what_changed)); - if (what_changed & BoundsChanged) { - region_resized (what_changed); - region_sync_changed (); - } - if (what_changed & Region::MuteChanged) { - region_muted (); - } - if (what_changed & Region::OpacityChanged) { - region_opacity (); - } - if (what_changed & ARDOUR::NameChanged) { - region_renamed (); - } - if (what_changed & Region::SyncOffsetChanged) { - region_sync_changed (); - } - if (what_changed & Region::LayerChanged) { - region_layered (); - } - if (what_changed & Region::LockChanged) { - region_locked (); - } + RegionView::region_changed(what_changed); + if (what_changed & AudioRegion::ScaleAmplitudeChanged) { region_scale_amplitude_changed (); } @@ -366,37 +295,18 @@ AudioRegionView::region_scale_amplitude_changed () } void -AudioRegionView::region_locked () -{ - /* name will show locked status */ - region_renamed (); -} - -void AudioRegionView::region_resized (Change what_changed) { - double unit_length; - - if (what_changed & ARDOUR::PositionChanged) { - set_position (_region.position(), 0); - } + RegionView::region_resized(what_changed); if (what_changed & Change (StartChanged|LengthChanged)) { - set_duration (_region.length(), 0); - - unit_length = _region.length() / samples_per_unit; - - reset_width_dependent_items (unit_length); - for (uint32_t n = 0; n < waves.size(); ++n) { waves[n]->property_region_start() = _region.start(); - } + } for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) { - (*i)->set_duration (unit_length); - for (vector<WaveView*>::iterator w = (*i)->waves.begin(); w != (*i)->waves.end(); ++w) { (*w)->property_region_start() = _region.start(); } @@ -407,8 +317,8 @@ AudioRegionView::region_resized (Change what_changed) void AudioRegionView::reset_width_dependent_items (double pixel_width) { - TimeAxisViewItem::reset_width_dependent_items (pixel_width); - _pixel_width = pixel_width; + RegionView::reset_width_dependent_items(pixel_width); + assert(_pixel_width == pixel_width); if (zero_line) { zero_line->property_x2() = pixel_width - 1.0; @@ -433,17 +343,9 @@ AudioRegionView::reset_width_dependent_items (double pixel_width) } void -AudioRegionView::region_layered () -{ - RouteTimeAxisView *atv = dynamic_cast<RouteTimeAxisView*> (&get_time_axis_view()); - atv->view()->region_layered (this); -} - -void AudioRegionView::region_muted () { - set_frame_color (); - region_renamed (); + RegionView::region_muted(); for (uint32_t n=0; n < waves.size(); ++n) { if (_region.muted()) { @@ -460,6 +362,7 @@ AudioRegionView::set_height (gdouble height) { uint32_t wcnt = waves.size(); + // FIXME: ick TimeAxisViewItem::set_height (height - 2); _height = height; @@ -695,36 +598,16 @@ AudioRegionView::reset_fade_out_shape_width (jack_nframes_t width) void AudioRegionView::set_samples_per_unit (gdouble spu) { - TimeAxisViewItem::set_samples_per_unit (spu); + RegionView::set_samples_per_unit (spu); for (uint32_t n=0; n < waves.size(); ++n) { waves[n]->property_samples_per_unit() = spu; } - for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) { - (*i)->set_samples_per_unit (spu); - (*i)->set_duration (_region.length() / samples_per_unit); - } - if (gain_line) { gain_line->reset (); } reset_fade_shapes (); - region_sync_changed (); -} - -bool -AudioRegionView::set_duration (jack_nframes_t frames, void *src) -{ - if (!TimeAxisViewItem::set_duration (frames, src)) { - return false; - } - - for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) { - (*i)->set_duration (_region.length() / samples_per_unit); - } - - return true; } void @@ -738,7 +621,8 @@ AudioRegionView::set_amplitude_above_axis (gdouble spp) void AudioRegionView::compute_colors (Gdk::Color& basic_color) { - TimeAxisViewItem::compute_colors (basic_color); + RegionView::compute_colors(basic_color); + uint32_t r, g, b, a; /* gain color computed in envelope_active_changed() */ @@ -750,16 +634,12 @@ AudioRegionView::compute_colors (Gdk::Color& basic_color) void AudioRegionView::set_colors () { - TimeAxisViewItem::set_colors (); + RegionView::set_colors(); if (gain_line) { gain_line->set_line_color (audio_region().envelope_active() ? color_map[cGainLine] : color_map[cGainLineInactive]); } - if (sync_mark) { - sync_mark->property_fill_color_rgba() = fill_color; - } - for (uint32_t n=0; n < waves.size(); ++n) { if (_region.muted()) { waves[n]->property_wave_color() = color_map[cMutedWaveForm]; @@ -770,18 +650,6 @@ AudioRegionView::set_colors () } void -AudioRegionView::set_frame_color () -{ - if (_region.opaque()) { - fill_opacity = 180; - } else { - fill_opacity = 100; - } - - TimeAxisViewItem::set_frame_color (); -} - -void AudioRegionView::show_region_editor () { if (editor == 0) { @@ -796,89 +664,6 @@ AudioRegionView::show_region_editor () } void -AudioRegionView::hide_region_editor() -{ - if (editor) { - editor->hide_all (); - } -} - -void -AudioRegionView::region_renamed () -{ - string str; - - if (_region.locked()) { - str += '>'; - str += _region.name(); - str += '<'; - } else { - str = _region.name(); - } - - if (audio_region().speed_mismatch (trackview.session().frame_rate())) { - str = string ("*") + str; - } - - if (_region.muted()) { - str = string ("!") + str; - } - - set_item_name (str, this); - set_name_text (str); -} - -void -AudioRegionView::region_sync_changed () -{ - if (sync_mark == 0) { - return; - } - - int sync_dir; - jack_nframes_t sync_offset; - - sync_offset = _region.sync_offset (sync_dir); - - /* this has to handle both a genuine change of position, a change of samples_per_unit, - and a change in the bounds of the _region. - */ - - if (sync_offset == 0) { - - /* no sync mark - its the start of the region */ - - sync_mark->hide(); - - } else { - - if ((sync_dir < 0) || ((sync_dir > 0) && (sync_offset > _region.length()))) { - - /* no sync mark - its out of the bounds of the region */ - - sync_mark->hide(); - - } else { - - /* lets do it */ - - Points points; - - //points = sync_mark->property_points().get_value(); - - double offset = sync_offset / samples_per_unit; - points.push_back (Gnome::Art::Point (offset - ((sync_mark_width-1)/2), 1)); - points.push_back (Gnome::Art::Point (offset + ((sync_mark_width-1)/2), 1)); - points.push_back (Gnome::Art::Point (offset, sync_mark_width - 1)); - points.push_back (Gnome::Art::Point (offset - ((sync_mark_width-1)/2), 1)); - sync_mark->property_points().set_value (points); - sync_mark->show(); - - } - } -} - -void AudioRegionView::set_waveform_visible (bool yn) { if (((_flags & WaveformVisible) != yn)) { @@ -954,8 +739,8 @@ AudioRegionView::create_waves () wave_caches.push_back (WaveView::create_cache ()); - if (wait_for_waves) { - if (audio_region().source(n).peaks_ready (bind (mem_fun(*this, &AudioRegionView::peaks_ready_handler), n), peaks_ready_connection)) { + if (wait_for_data) { + if (audio_region().source(n).peaks_ready (bind (mem_fun(*this, &AudioRegionView::peaks_ready_handler), n), data_ready_connection)) { create_one_wave (n, true); } else { create_zero_line = false; @@ -1056,7 +841,7 @@ AudioRegionView::peaks_ready_handler (uint32_t which) if (!waves.empty()) { /* all waves created, don't hook into peaks ready anymore */ - peaks_ready_connection.disconnect (); + data_ready_connection.disconnect (); } } @@ -1184,22 +969,6 @@ AudioRegionView::set_waveform_shape (WaveformShape shape) } } -void -AudioRegionView::move (double x_delta, double y_delta) -{ - if (_region.locked() || (x_delta == 0 && y_delta == 0)) { - return; - } - - get_canvas_group()->move (x_delta, y_delta); - - /* note: ghosts never leave their tracks so y_delta for them is always zero */ - - for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) { - (*i)->group->move (x_delta, 0.0); - } -} - GhostRegion* AudioRegionView::add_ghost (AutomationTimeAxisView& atv) { @@ -1244,21 +1013,6 @@ AudioRegionView::add_ghost (AutomationTimeAxisView& atv) } void -AudioRegionView::remove_ghost (GhostRegion* ghost) -{ - if (in_destructor) { - return; - } - - for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) { - if (*i == ghost) { - ghosts.erase (i); - break; - } - } -} - -void AudioRegionView::entered () { if (gain_line && _flags & EnvelopeVisible) { diff --git a/gtk2_ardour/audio_regionview.h b/gtk2_ardour/audio_regionview.h index 7889f0c8b5..b59f5f4791 100644 --- a/gtk2_ardour/audio_regionview.h +++ b/gtk2_ardour/audio_regionview.h @@ -57,21 +57,15 @@ class AudioRegionView : public RegionView ~AudioRegionView (); - virtual void init (Gdk::Color& base_color, bool wait_for_waves); + virtual void init (Gdk::Color& base_color, bool wait_for_data = false); ARDOUR::AudioRegion& audio_region() const; - bool is_valid() const { return valid; } - void set_valid (bool yn) { valid = yn; } - void set_height (double); void set_samples_per_unit (double); - bool set_duration (jack_nframes_t, void*); void set_amplitude_above_axis (gdouble spp); - void move (double xdelta, double ydelta); - void temporarily_hide_envelope (); ///< Dangerous! void unhide_envelope (); ///< Dangerous! @@ -80,11 +74,10 @@ class AudioRegionView : public RegionView void set_waveform_shape (WaveformShape); bool waveform_rectified() const { return _flags & WaveformRectified; } - bool waveform_visible() const { return _flags & WaveformVisible; } - bool envelope_visible() const { return _flags & EnvelopeVisible; } + bool waveform_visible() const { return _flags & WaveformVisible; } + bool envelope_visible() const { return _flags & EnvelopeVisible; } void show_region_editor (); - void hide_region_editor(); void add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *event); void remove_gain_point_event (ArdourCanvas::Item *item, GdkEvent *event); @@ -95,7 +88,6 @@ class AudioRegionView : public RegionView void envelope_active_changed (); GhostRegion* add_ghost (AutomationTimeAxisView&); - void remove_ghost (GhostRegion*); void reset_fade_in_shape_width (jack_nframes_t); void reset_fade_out_shape_width (jack_nframes_t); @@ -113,11 +105,11 @@ class AudioRegionView : public RegionView */ AudioRegionView (ArdourCanvas::Group *, - RouteTimeAxisView&, - ARDOUR::AudioRegion&, - double initial_samples_per_unit, - Gdk::Color& basic_color, - TimeAxisViewItem::Visibility); + RouteTimeAxisView&, + ARDOUR::AudioRegion&, + double samples_per_unit, + Gdk::Color& basic_color, + TimeAxisViewItem::Visibility); enum Flags { EnvelopeVisible = 0x1, @@ -125,32 +117,22 @@ class AudioRegionView : public RegionView WaveformRectified = 0x8 }; - vector<ArdourCanvas::WaveView *> waves; ///< waveviews + vector<ArdourCanvas::WaveView *> waves; vector<ArdourCanvas::WaveView *> tmp_waves; ///< see ::create_waves() - ArdourCanvas::Polygon* sync_mark; ///< polgyon for sync position - ArdourCanvas::Text* no_wave_msg; ///< text - ArdourCanvas::SimpleLine* zero_line; ///< simpleline - ArdourCanvas::Polygon* fade_in_shape; ///< polygon - ArdourCanvas::Polygon* fade_out_shape; ///< polygon - ArdourCanvas::SimpleRect* fade_in_handle; ///< simplerect - ArdourCanvas::SimpleRect* fade_out_handle; ///< simplerect + ArdourCanvas::Polygon* sync_mark; ///< polgyon for sync position + ArdourCanvas::SimpleLine* zero_line; + ArdourCanvas::Polygon* fade_in_shape; + ArdourCanvas::Polygon* fade_out_shape; + ArdourCanvas::SimpleRect* fade_in_handle; + ArdourCanvas::SimpleRect* fade_out_handle; AudioRegionGainLine * gain_line; - AudioRegionEditor * editor; - vector<ControlPoint *> control_points; double _amplitude_above_axis; - double current_visible_sync_position; uint32_t _flags; uint32_t fade_color; - bool valid; /* see StreamView::redisplay_diskstream() */ - double _pixel_width; - double _height; - bool in_destructor; - bool wait_for_waves; - sigc::connection peaks_ready_connection; - + void reset_fade_shapes (); void reset_fade_in_shape (); void reset_fade_out_shape (); @@ -162,31 +144,21 @@ class AudioRegionView : public RegionView void region_resized (ARDOUR::Change); void region_moved (void *); void region_muted (); - void region_locked (); - void region_layered (); - void region_renamed (); - void region_sync_changed (); void region_scale_amplitude_changed (); - static gint _lock_toggle (ArdourCanvas::Item*, GdkEvent*, void*); - void lock_toggle (); - void create_waves (); void create_one_wave (uint32_t, bool); void manage_zero_line (); void peaks_ready_handler (uint32_t); - void reset_name (gdouble width); void set_flags (XMLNode *); void store_flags (); void set_colors (); void compute_colors (Gdk::Color&); - virtual void set_frame_color (); void reset_width_dependent_items (double pixel_width); void set_waveview_data_src(); vector<GnomeCanvasWaveViewCache*> wave_caches; - vector<GhostRegion*> ghosts; void color_handler (ColorID, uint32_t); }; diff --git a/gtk2_ardour/audio_streamview.cc b/gtk2_ardour/audio_streamview.cc index 1e43f1dac1..0d0cd7889c 100644 --- a/gtk2_ardour/audio_streamview.cc +++ b/gtk2_ardour/audio_streamview.cc @@ -54,7 +54,6 @@ using namespace Editing; AudioStreamView::AudioStreamView (AudioTimeAxisView& tv) : StreamView (tv) { - region_color = _trackview.color(); crossfades_visible = true; if (tv.is_audio_track()) @@ -62,43 +61,16 @@ AudioStreamView::AudioStreamView (AudioTimeAxisView& tv) else stream_base_color = color_map[cAudioBusBase]; - /* set_position() will position the group */ - - canvas_group = new ArdourCanvas::Group(*_trackview.canvas_display); - - canvas_rect = new ArdourCanvas::SimpleRect (*canvas_group); - canvas_rect->property_x1() = 0.0; - canvas_rect->property_y1() = 0.0; - canvas_rect->property_x2() = 1000000.0; - canvas_rect->property_y2() = (double) tv.height; canvas_rect->property_outline_color_rgba() = color_map[cAudioTrackOutline]; - canvas_rect->property_outline_what() = (guint32) (0x1|0x2|0x8); // outline ends and bottom - canvas_rect->property_fill_color_rgba() = stream_base_color; - - canvas_rect->signal_event().connect (bind (mem_fun (_trackview.editor, &PublicEditor::canvas_stream_view_event), canvas_rect, &_trackview)); - _samples_per_unit = _trackview.editor.get_current_zoom(); _amplitude_above_axis = 1.0; - if (_trackview.is_audio_track()) { - _trackview.audio_track()->DiskstreamChanged.connect (mem_fun (*this, &AudioStreamView::diskstream_changed)); - _trackview.session().TransportStateChange.connect (mem_fun (*this, &AudioStreamView::transport_changed)); - _trackview.get_diskstream()->RecordEnableChanged.connect (mem_fun (*this, &AudioStreamView::rec_enable_changed)); - _trackview.session().RecordStateChanged.connect (mem_fun (*this, &AudioStreamView::sess_rec_enable_changed)); - } - - rec_updating = false; - rec_active = false; use_rec_regions = tv.editor.show_waveforms_recording (); last_rec_peak_frame = 0; - - ColorChanged.connect (mem_fun (*this, &AudioStreamView::color_handler)); } AudioStreamView::~AudioStreamView () { - undisplay_diskstream (); - delete canvas_group; } int @@ -132,7 +104,6 @@ AudioStreamView::set_samples_per_unit (gdouble spp) int AudioStreamView::set_amplitude_above_axis (gdouble app) - { RegionViewList::iterator i; @@ -206,8 +177,6 @@ AudioStreamView::remove_region_view (Region *r) { ENSURE_GUI_THREAD (bind (mem_fun (*this, &AudioStreamView::remove_region_view), r)); - StreamView::remove_region_view(r); - for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end();) { list<CrossfadeView*>::iterator tmp; @@ -222,6 +191,8 @@ AudioStreamView::remove_region_view (Region *r) i = tmp; } + + StreamView::remove_region_view(r); } void diff --git a/gtk2_ardour/audio_streamview.h b/gtk2_ardour/audio_streamview.h index d05ecd9307..05ce8125f6 100644 --- a/gtk2_ardour/audio_streamview.h +++ b/gtk2_ardour/audio_streamview.h @@ -59,10 +59,9 @@ class AudioStreamView : public StreamView void set_waveform_shape (WaveformShape); int set_height (gdouble h); - int set_samples_per_unit (gdouble spp); - int set_amplitude_above_axis (gdouble app); + int set_amplitude_above_axis (gdouble app); gdouble get_amplitude_above_axis () { return _amplitude_above_axis; } void set_show_waveforms (bool yn); @@ -90,17 +89,17 @@ class AudioStreamView : public StreamView void playlist_modified (); void playlist_changed (ARDOUR::Diskstream *ds); - bool crossfades_visible; void add_crossfade (ARDOUR::Crossfade*); void remove_crossfade (ARDOUR::Crossfade*); void color_handler (ColorID id, uint32_t val); + double _amplitude_above_axis; + typedef list<CrossfadeView*> CrossfadeViewList; CrossfadeViewList crossfade_views; - - double _amplitude_above_axis; + bool crossfades_visible; list<sigc::connection> peak_ready_connections; jack_nframes_t last_rec_peak_frame; diff --git a/gtk2_ardour/audio_time_axis.cc b/gtk2_ardour/audio_time_axis.cc index ea822b97c5..13383fa6a4 100644 --- a/gtk2_ardour/audio_time_axis.cc +++ b/gtk2_ardour/audio_time_axis.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2000 Paul Davis + Copyright (C) 2000-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 @@ -41,7 +41,6 @@ #include <ardour/audioplaylist.h> #include <ardour/audio_diskstream.h> #include <ardour/insert.h> -#include <ardour/ladspa_plugin.h> #include <ardour/location.h> #include <ardour/panner.h> #include <ardour/playlist.h> @@ -53,25 +52,18 @@ #include "audio_time_axis.h" #include "automation_gain_line.h" #include "automation_pan_line.h" -#include "automation_time_axis.h" #include "canvas_impl.h" #include "crossfade_view.h" #include "enums.h" #include "gain_automation_time_axis.h" -#include "gui_thread.h" #include "keyboard.h" #include "pan_automation_time_axis.h" #include "playlist_selector.h" #include "plugin_selector.h" #include "plugin_ui.h" -#include "point_selection.h" #include "prompter.h" #include "public_editor.h" -#include "redirect_automation_line.h" -#include "redirect_automation_time_axis.h" #include "audio_regionview.h" -#include "rgb_macros.h" -#include "selection.h" #include "simplerect.h" #include "audio_streamview.h" #include "utils.h" @@ -87,9 +79,12 @@ using namespace Editing; AudioTimeAxisView::AudioTimeAxisView (PublicEditor& ed, Session& sess, boost::shared_ptr<Route> rt, Canvas& canvas) - : AxisView(sess), // FIXME: won't compile without this, why?? - RouteTimeAxisView(ed, sess, rt, canvas) + : AxisView(sess) + , RouteTimeAxisView(ed, sess, rt, canvas) { + // Make sure things are sane... + assert(!is_track() || is_audio_track()); + subplugin_menu.set_name ("ArdourContextMenu"); gain_track = 0; pan_track = 0; @@ -143,11 +138,6 @@ AudioTimeAxisView::AudioTimeAxisView (PublicEditor& ed, Session& sess, boost::sh AudioTimeAxisView::~AudioTimeAxisView () { - vector_delete (&redirect_automation_curves); - - for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) { - delete *i; - } } AudioStreamView* @@ -227,56 +217,14 @@ AudioTimeAxisView::set_state (const XMLNode& node) } void -AudioTimeAxisView::reset_redirect_automation_curves () -{ - for (vector<RedirectAutomationLine*>::iterator i = redirect_automation_curves.begin(); i != redirect_automation_curves.end(); ++i) { - (*i)->reset(); - } -} - -void -AudioTimeAxisView::build_display_menu () +AudioTimeAxisView::build_automation_action_menu () { using namespace Menu_Helpers; - /* get the size menu ready */ - - build_size_menu (); - - /* prepare it */ - - TimeAxisView::build_display_menu (); - - /* now fill it with our stuff */ - - MenuList& items = display_menu->items(); - display_menu->set_name ("ArdourContextMenu"); - - items.push_back (MenuElem (_("Height"), *size_menu)); - items.push_back (MenuElem (_("Color"), mem_fun(*this, &AudioTimeAxisView::select_track_color))); - - - items.push_back (SeparatorElem()); - items.push_back (MenuElem (_("Hide all crossfades"), mem_fun(*this, &AudioTimeAxisView::hide_all_xfades))); - items.push_back (MenuElem (_("Show all crossfades"), mem_fun(*this, &AudioTimeAxisView::show_all_xfades))); - items.push_back (SeparatorElem()); - - build_remote_control_menu (); - items.push_back (MenuElem (_("Remote Control ID"), *remote_control_menu)); + RouteTimeAxisView::build_automation_action_menu (); - automation_action_menu = manage (new Menu); MenuList& automation_items = automation_action_menu->items(); - automation_action_menu->set_name ("ArdourContextMenu"); - automation_items.push_back (MenuElem (_("Show all automation"), - mem_fun(*this, &AudioTimeAxisView::show_all_automation))); - - automation_items.push_back (MenuElem (_("Show existing automation"), - mem_fun(*this, &AudioTimeAxisView::show_existing_automation))); - - automation_items.push_back (MenuElem (_("Hide all automation"), - mem_fun(*this, &AudioTimeAxisView::hide_all_automation))); - automation_items.push_back (SeparatorElem()); automation_items.push_back (CheckMenuElem (_("Fader"), @@ -288,11 +236,21 @@ AudioTimeAxisView::build_display_menu () mem_fun(*this, &AudioTimeAxisView::toggle_pan_track))); pan_automation_item = static_cast<CheckMenuItem*> (&automation_items.back()); pan_automation_item->set_active(show_pan_automation); + +} - automation_items.push_back (MenuElem (_("Plugins"), subplugin_menu)); +void +AudioTimeAxisView::append_extra_display_menu_items () +{ + using namespace Menu_Helpers; - items.push_back (MenuElem (_("Automation"), *automation_action_menu)); + MenuList& items = display_menu->items(); + // crossfade stuff + items.push_back (MenuElem (_("Hide all crossfades"), mem_fun(*this, &AudioTimeAxisView::hide_all_xfades))); + items.push_back (MenuElem (_("Show all crossfades"), mem_fun(*this, &AudioTimeAxisView::show_all_xfades))); + + // waveform menu Menu *waveform_menu = manage(new Menu); MenuList& waveform_items = waveform_menu->items(); waveform_menu->set_name ("ArdourContextMenu"); @@ -312,39 +270,6 @@ AudioTimeAxisView::build_display_menu () rectified_item = static_cast<RadioMenuItem *> (&waveform_items.back()); items.push_back (MenuElem (_("Waveform"), *waveform_menu)); - - if (is_audio_track()) { - - Menu* alignment_menu = manage (new Menu); - MenuList& alignment_items = alignment_menu->items(); - alignment_menu->set_name ("ArdourContextMenu"); - - RadioMenuItem::Group align_group; - - alignment_items.push_back (RadioMenuElem (align_group, _("Align with existing material"), bind (mem_fun(*this, &AudioTimeAxisView::set_align_style), ExistingMaterial))); - align_existing_item = dynamic_cast<RadioMenuItem*>(&alignment_items.back()); - if (get_diskstream()->alignment_style() == ExistingMaterial) { - align_existing_item->set_active(); - } - alignment_items.push_back (RadioMenuElem (align_group, _("Align with capture time"), bind (mem_fun(*this, &AudioTimeAxisView::set_align_style), CaptureTime))); - align_capture_item = dynamic_cast<RadioMenuItem*>(&alignment_items.back()); - if (get_diskstream()->alignment_style() == CaptureTime) { - align_capture_item->set_active(); - } - - items.push_back (MenuElem (_("Alignment"), *alignment_menu)); - - get_diskstream()->AlignmentStyleChanged.connect (mem_fun(*this, &AudioTimeAxisView::align_style_changed)); - } - - items.push_back (SeparatorElem()); - items.push_back (CheckMenuElem (_("Active"), mem_fun(*this, &RouteUI::toggle_route_active))); - route_active_menu_item = dynamic_cast<CheckMenuItem *> (&items.back()); - route_active_menu_item->set_active (_route->active()); - - items.push_back (SeparatorElem()); - items.push_back (MenuElem (_("Remove"), mem_fun(*this, &RouteUI::remove_this_route))); - } void @@ -394,16 +319,6 @@ AudioTimeAxisView::set_waveform_shape (WaveformShape shape) } void -AudioTimeAxisView::set_selected_regionviews (RegionSelection& regions) -{ - AudioStreamView* asv = audio_view(); - - if (asv) { - asv->set_selected_regionviews (regions); - } -} - -void AudioTimeAxisView::add_gain_automation_child () { XMLProperty* prop; @@ -587,322 +502,6 @@ AudioTimeAxisView::pan_hidden () _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */ } -AudioTimeAxisView::RedirectAutomationInfo::~RedirectAutomationInfo () -{ - for (vector<RedirectAutomationNode*>::iterator i = lines.begin(); i != lines.end(); ++i) { - delete *i; - } -} - - -AudioTimeAxisView::RedirectAutomationNode::~RedirectAutomationNode () -{ - parent.remove_ran (this); - - if (view) { - delete view; - } -} - -void -AudioTimeAxisView::remove_ran (RedirectAutomationNode* ran) -{ - if (ran->view) { - remove_child (ran->view); - } -} - -AudioTimeAxisView::RedirectAutomationNode* -AudioTimeAxisView::find_redirect_automation_node (boost::shared_ptr<Redirect> redirect, uint32_t what) -{ - for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) { - - if ((*i)->redirect == redirect) { - - for (vector<RedirectAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) { - if ((*ii)->what == what) { - return *ii; - } - } - } - } - - return 0; -} - -// FIXME: duplicated in midi_time_axis.cc -static string -legalize_for_xml_node (string str) -{ - string::size_type pos; - string legal_chars = "abcdefghijklmnopqrtsuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_+=:"; - string legal; - - legal = str; - pos = 0; - - while ((pos = legal.find_first_not_of (legal_chars, pos)) != string::npos) { - legal.replace (pos, 1, "_"); - pos += 1; - } - - return legal; -} - - -void -AudioTimeAxisView::add_redirect_automation_curve (boost::shared_ptr<Redirect> redirect, uint32_t what) -{ - RedirectAutomationLine* ral; - string name; - RedirectAutomationNode* ran; - - if ((ran = find_redirect_automation_node (redirect, what)) == 0) { - fatal << _("programming error: ") - << string_compose (X_("redirect automation curve for %1:%2 not registered with audio track!"), - redirect->name(), what) - << endmsg; - /*NOTREACHED*/ - return; - } - - if (ran->view) { - return; - } - - name = redirect->describe_parameter (what); - - /* create a string that is a legal XML node name that can be used to refer to this redirect+port combination */ - - char state_name[256]; - snprintf (state_name, sizeof (state_name), "Redirect-%s-%" PRIu32, legalize_for_xml_node (redirect->name()).c_str(), what); - - ran->view = new RedirectAutomationTimeAxisView (_session, _route, editor, *this, parent_canvas, name, what, *redirect, state_name); - - ral = new RedirectAutomationLine (name, - *redirect, what, _session, *ran->view, - *ran->view->canvas_display, redirect->automation_list (what)); - - ral->set_line_color (color_map[cRedirectAutomationLine]); - ral->queue_reset (); - - ran->view->add_line (*ral); - - ran->view->Hiding.connect (bind (mem_fun(*this, &AudioTimeAxisView::redirect_automation_track_hidden), ran, redirect)); - - if (!ran->view->marked_for_display()) { - ran->view->hide (); - } else { - ran->menu_item->set_active (true); - } - - add_child (ran->view); - - audio_view()->foreach_regionview (bind (mem_fun(*this, &AudioTimeAxisView::add_ghost_to_redirect), ran->view)); - - redirect->mark_automation_visible (what, true); -} - -void -AudioTimeAxisView::redirect_automation_track_hidden (AudioTimeAxisView::RedirectAutomationNode* ran, boost::shared_ptr<Redirect> r) -{ - if (!_hidden) { - ran->menu_item->set_active (false); - } - - r->mark_automation_visible (ran->what, false); - - _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */ -} - -void -AudioTimeAxisView::add_existing_redirect_automation_curves (boost::shared_ptr<Redirect> redirect) -{ - set<uint32_t> s; - RedirectAutomationLine *ral; - - redirect->what_has_visible_automation (s); - - for (set<uint32_t>::iterator i = s.begin(); i != s.end(); ++i) { - - if ((ral = find_redirect_automation_curve (redirect, *i)) != 0) { - ral->queue_reset (); - } else { - add_redirect_automation_curve (redirect, (*i)); - } - } -} - -void -AudioTimeAxisView::add_redirect_to_subplugin_menu (boost::shared_ptr<Redirect> r) -{ - using namespace Menu_Helpers; - RedirectAutomationInfo *rai; - list<RedirectAutomationInfo*>::iterator x; - - const std::set<uint32_t>& automatable = r->what_can_be_automated (); - std::set<uint32_t> has_visible_automation; - - r->what_has_visible_automation(has_visible_automation); - - if (automatable.empty()) { - return; - } - - for (x = redirect_automation.begin(); x != redirect_automation.end(); ++x) { - if ((*x)->redirect == r) { - break; - } - } - - if (x == redirect_automation.end()) { - - rai = new RedirectAutomationInfo (r); - redirect_automation.push_back (rai); - - } else { - - rai = *x; - - } - - /* any older menu was deleted at the top of redirects_changed() - when we cleared the subplugin menu. - */ - - rai->menu = manage (new Menu); - MenuList& items = rai->menu->items(); - rai->menu->set_name ("ArdourContextMenu"); - - items.clear (); - - for (std::set<uint32_t>::const_iterator i = automatable.begin(); i != automatable.end(); ++i) { - - RedirectAutomationNode* ran; - CheckMenuItem* mitem; - - string name = r->describe_parameter (*i); - - items.push_back (CheckMenuElem (name)); - mitem = dynamic_cast<CheckMenuItem*> (&items.back()); - - if (has_visible_automation.find((*i)) != has_visible_automation.end()) { - mitem->set_active(true); - } - - if ((ran = find_redirect_automation_node (r, *i)) == 0) { - - /* new item */ - - ran = new RedirectAutomationNode (*i, mitem, *this); - - rai->lines.push_back (ran); - - } else { - - ran->menu_item = mitem; - - } - - mitem->signal_toggled().connect (bind (mem_fun(*this, &AudioTimeAxisView::redirect_menu_item_toggled), rai, ran)); - } - - /* add the menu for this redirect, because the subplugin - menu is always cleared at the top of redirects_changed(). - this is the result of some poor design in gtkmm and/or - GTK+. - */ - - subplugin_menu.items().push_back (MenuElem (r->name(), *rai->menu)); - rai->valid = true; -} - -void -AudioTimeAxisView::redirect_menu_item_toggled (AudioTimeAxisView::RedirectAutomationInfo* rai, - AudioTimeAxisView::RedirectAutomationNode* ran) -{ - bool showit = ran->menu_item->get_active(); - bool redraw = false; - - if (ran->view == 0 && showit) { - add_redirect_automation_curve (rai->redirect, ran->what); - redraw = true; - } - - if (showit != ran->view->marked_for_display()) { - - if (showit) { - ran->view->set_marked_for_display (true); - ran->view->canvas_display->show(); - } else { - rai->redirect->mark_automation_visible (ran->what, true); - ran->view->set_marked_for_display (false); - ran->view->hide (); - } - - redraw = true; - - } - - if (redraw && !no_redraw) { - - /* now trigger a redisplay */ - - _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */ - - } -} - -void -AudioTimeAxisView::redirects_changed (void *src) -{ - using namespace Menu_Helpers; - - for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) { - (*i)->valid = false; - } - - subplugin_menu.items().clear (); - - _route->foreach_redirect (this, &AudioTimeAxisView::add_redirect_to_subplugin_menu); - _route->foreach_redirect (this, &AudioTimeAxisView::add_existing_redirect_automation_curves); - - for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ) { - - list<RedirectAutomationInfo*>::iterator tmp; - - tmp = i; - ++tmp; - - if (!(*i)->valid) { - - delete *i; - redirect_automation.erase (i); - - } - - i = tmp; - } - - /* change in visibility was possible */ - - _route->gui_changed ("track_height", this); -} - -RedirectAutomationLine * -AudioTimeAxisView::find_redirect_automation_curve (boost::shared_ptr<Redirect> redirect, uint32_t what) -{ - RedirectAutomationNode* ran; - - if ((ran = find_redirect_automation_node (redirect, what)) != 0) { - if (ran->view) { - return dynamic_cast<RedirectAutomationLine*> (ran->view->lines.front()); - } - } - - return 0; -} - void AudioTimeAxisView::show_all_automation () { @@ -911,15 +510,7 @@ AudioTimeAxisView::show_all_automation () pan_automation_item->set_active (true); gain_automation_item->set_active (true); - for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) { - for (vector<RedirectAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) { - if ((*ii)->view == 0) { - add_redirect_automation_curve ((*i)->redirect, (*ii)->what); - } - - (*ii)->menu_item->set_active (true); - } - } + RouteTimeAxisView::show_all_automation (); no_redraw = false; @@ -934,13 +525,7 @@ AudioTimeAxisView::show_existing_automation () pan_automation_item->set_active (true); gain_automation_item->set_active (true); - for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) { - for (vector<RedirectAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) { - if ((*ii)->view != 0) { - (*ii)->menu_item->set_active (true); - } - } - } + RouteTimeAxisView::show_existing_automation (); no_redraw = false; @@ -955,37 +540,13 @@ AudioTimeAxisView::hide_all_automation () pan_automation_item->set_active (false); gain_automation_item->set_active (false); - for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) { - for (vector<RedirectAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) { - (*ii)->menu_item->set_active (false); - } - } + RouteTimeAxisView::hide_all_automation(); no_redraw = false; _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */ } void -AudioTimeAxisView::region_view_added (RegionView* rv) -{ - assert(dynamic_cast<AudioRegionView*>(rv)); - - for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) { - AutomationTimeAxisView* atv; - - if ((atv = dynamic_cast<AutomationTimeAxisView*> (*i)) != 0) { - rv->add_ghost (*atv); - } - } -} - -void -AudioTimeAxisView::add_ghost_to_redirect (RegionView* rv, AutomationTimeAxisView* atv) -{ - rv->add_ghost (*atv); -} - -void AudioTimeAxisView::show_all_xfades () { AudioStreamView* asv = audio_view(); @@ -1030,7 +591,7 @@ AudioTimeAxisView::reveal_dependent_views (TimeAxisViewItem& tavi) void AudioTimeAxisView::route_active_changed () { - RouteUI::route_active_changed (); + RouteTimeAxisView::route_active_changed (); if (is_audio_track()) { if (_route->active()) { diff --git a/gtk2_ardour/audio_time_axis.h b/gtk2_ardour/audio_time_axis.h index 2a6aa1c4d6..2162771285 100644 --- a/gtk2_ardour/audio_time_axis.h +++ b/gtk2_ardour/audio_time_axis.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2000 Paul Davis + Copyright (C) 2000-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 @@ -33,7 +33,6 @@ #include <list> #include <ardour/types.h> -#include <ardour/region.h> #include "ardour_dialog.h" #include "route_ui.h" @@ -62,7 +61,6 @@ class AudioRegionView; class AutomationLine; class AutomationGainLine; class AutomationPanLine; -class RedirectAutomationLine; class TimeSelection; class AutomationTimeAxisView; @@ -78,11 +76,10 @@ class AudioTimeAxisView : public RouteTimeAxisView void set_show_waveforms_recording (bool yn); void show_all_xfades (); void hide_all_xfades (); - void set_selected_regionviews (RegionSelection&); void hide_dependent_views (TimeAxisViewItem&); void reveal_dependent_views (TimeAxisViewItem&); - /* overridden from parent to store display state */ + /* Overridden from parent to store display state */ guint32 show_at (double y, int& nth, Gtk::VBox *parent); void hide (); @@ -95,83 +92,16 @@ class AudioTimeAxisView : public RouteTimeAxisView void route_active_changed (); - AutomationTimeAxisView *gain_track; - AutomationTimeAxisView *pan_track; - - void update_automation_view (ARDOUR::AutomationType); - void reset_redirect_automation_curves (); - - // variables to get the context menu - // automation buttons correctly initialized - bool show_gain_automation; - bool show_pan_automation; - - // FIXME? - void redirects_changed (void *); - - void build_display_menu (); - - Gtk::CheckMenuItem* waveform_item; - Gtk::RadioMenuItem* traditional_item; - Gtk::RadioMenuItem* rectified_item; + void build_automation_action_menu (); + void append_extra_display_menu_items (); void toggle_show_waveforms (); - void set_waveform_shape (WaveformShape); void toggle_waveforms (); - /* automation stuff */ - - Gtk::Menu* automation_action_menu; - Gtk::CheckMenuItem* gain_automation_item; - Gtk::CheckMenuItem* pan_automation_item; - - void automation_click (); - void clear_automation (); - void hide_all_automation (); void show_all_automation (); void show_existing_automation (); - - struct RedirectAutomationNode { - uint32_t what; - Gtk::CheckMenuItem* menu_item; - AutomationTimeAxisView* view; - AudioTimeAxisView& parent; - - RedirectAutomationNode (uint32_t w, Gtk::CheckMenuItem* mitem, AudioTimeAxisView& p) - : what (w), menu_item (mitem), view (0), parent (p) {} - - ~RedirectAutomationNode (); - }; - - struct RedirectAutomationInfo { - boost::shared_ptr<ARDOUR::Redirect> redirect; - bool valid; - Gtk::Menu* menu; - vector<RedirectAutomationNode*> lines; - - RedirectAutomationInfo (boost::shared_ptr<ARDOUR::Redirect> r) - : redirect (r), valid (true) {} - - ~RedirectAutomationInfo (); - }; - - list<RedirectAutomationInfo*> redirect_automation; - RedirectAutomationNode* find_redirect_automation_node (boost::shared_ptr<ARDOUR::Redirect> redirect, uint32_t what); - - Gtk::Menu subplugin_menu; - void add_redirect_to_subplugin_menu (boost::shared_ptr<ARDOUR::Redirect>); - - void remove_ran (RedirectAutomationNode* ran); - - void redirect_menu_item_toggled (AudioTimeAxisView::RedirectAutomationInfo*, - AudioTimeAxisView::RedirectAutomationNode*); - void redirect_automation_track_hidden (RedirectAutomationNode*, boost::shared_ptr<ARDOUR::Redirect>); - - vector<RedirectAutomationLine*> redirect_automation_curves; - RedirectAutomationLine *find_redirect_automation_curve (boost::shared_ptr<ARDOUR::Redirect>,uint32_t); - void add_redirect_automation_curve (boost::shared_ptr<ARDOUR::Redirect>, uint32_t); - void add_existing_redirect_automation_curves (boost::shared_ptr<ARDOUR::Redirect>); + void hide_all_automation (); void add_gain_automation_child (); void add_pan_automation_child (); @@ -185,8 +115,18 @@ class AudioTimeAxisView : public RouteTimeAxisView void update_pans (); - void region_view_added (RegionView*); - void add_ghost_to_redirect (RegionView*, AutomationTimeAxisView*); + AutomationTimeAxisView* gain_track; + AutomationTimeAxisView* pan_track; + + // Set from XML so context menu automation buttons can be correctly initialized + bool show_gain_automation; + bool show_pan_automation; + + Gtk::CheckMenuItem* waveform_item; + Gtk::RadioMenuItem* traditional_item; + Gtk::RadioMenuItem* rectified_item; + Gtk::CheckMenuItem* gain_automation_item; + Gtk::CheckMenuItem* pan_automation_item; }; #endif /* __ardour_audio_time_axis_h__ */ diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index 6edc738c41..fcd17cdb4c 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -209,15 +209,6 @@ Editor::Editor (AudioEngine& eng) toolbar_selection_clock_table (2,3), - //mouse_mode_button_table (2, 3), - - /*mouse_select_button (_("range")), - mouse_move_button (_("object")), - mouse_gain_button (_("gain")), - mouse_zoom_button (_("zoom")), - mouse_timefx_button (_("timefx")), - mouse_audition_button (_("listen")),*/ - automation_mode_button (_("mode")), global_automation_button (_("automation")), @@ -2588,9 +2579,8 @@ Editor::setup_toolbar () mouse_mode_button_box.pack_start(mouse_audition_button, true, true); mouse_mode_button_box.set_homogeneous(true); - // This one needs a little more "FUDGE" on my machine at least.. edit_mode_selector.set_name ("EditModeSelector"); - Gtkmm2ext::set_size_request_to_display_given_text (edit_mode_selector, "Splice Edit", 3+FUDGE, 10); + Gtkmm2ext::set_size_request_to_display_given_text (edit_mode_selector, "Splice Edit", 2+FUDGE, 10); set_popdown_strings (edit_mode_selector, internationalize (edit_mode_strings)); edit_mode_selector.signal_changed().connect (mem_fun(*this, &Editor::edit_mode_selection_done)); diff --git a/gtk2_ardour/plugin_selector.h b/gtk2_ardour/plugin_selector.h index 220de74871..bbaf359aa4 100644 --- a/gtk2_ardour/plugin_selector.h +++ b/gtk2_ardour/plugin_selector.h @@ -29,6 +29,7 @@ namespace ARDOUR { class Session; class PluginManager; class Plugin; + class PluginInfo; } class PluginSelector : public ArdourDialog diff --git a/gtk2_ardour/regionview.cc b/gtk2_ardour/regionview.cc index d47b09853c..411117b1af 100644 --- a/gtk2_ardour/regionview.cc +++ b/gtk2_ardour/regionview.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2001 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 @@ -82,35 +82,21 @@ RegionView::RegionView (ArdourCanvas::Group* parent, } void -RegionView::init (Gdk::Color& basic_color, bool wfw) +RegionView::init (Gdk::Color& basic_color, bool wfd) { - ArdourCanvas::Points shape; - //XMLNode *node; - - editor = 0; - valid = true; + editor = 0; + valid = true; in_destructor = false; - _height = 0; - - _flags = 0; - - /* - if ((node = _region.extra_xml ("GUI")) != 0) { - set_flags (node); - } else { - //_flags = WaveformVisible; - store_flags (); - }*/ + _height = 0; + wait_for_data = wfd; compute_colors (basic_color); name_highlight->set_data ("regionview", this); name_text->set_data ("regionview", this); - // shape = new ArdourCanvas::Points (); - /* an equilateral triangle */ - + ArdourCanvas::Points shape; shape.push_back (Gnome::Art::Point (-((sync_mark_width-1)/2), 1)); shape.push_back (Gnome::Art::Point ((sync_mark_width - 1)/2, 1)); shape.push_back (Gnome::Art::Point (0, sync_mark_width - 1)); @@ -234,9 +220,6 @@ RegionView::region_resized (Change what_changed) (*i)->set_duration (unit_length); - /*for (vector<WaveView*>::iterator w = (*i)->waves.begin(); w != (*i)->waves.end(); ++w) { - (*w)->property_region_start() = _region.start(); - }*/ } } } @@ -246,27 +229,6 @@ RegionView::reset_width_dependent_items (double pixel_width) { TimeAxisViewItem::reset_width_dependent_items (pixel_width); _pixel_width = pixel_width; -/* - if (zero_line) { - zero_line->property_x2() = pixel_width - 1.0; - } - - if (fade_in_handle) { - if (pixel_width <= 6.0) { - fade_in_handle->hide(); - fade_out_handle->hide(); - } else { - if (_height < 5.0) { - fade_in_handle->hide(); - fade_out_handle->hide(); - } else { - fade_in_handle->show(); - fade_out_handle->show(); - } - } - } - - reset_fade_shapes ();*/ } void @@ -282,14 +244,6 @@ RegionView::region_muted () { set_frame_color (); region_renamed (); - - /*for (uint32_t n=0; n < waves.size(); ++n) { - if (_region.muted()) { - waves[n]->property_wave_color() = color_map[cMutedWaveForm]; - } else { - waves[n]->property_wave_color() = color_map[cWaveForm]; - } - }*/ } void @@ -350,19 +304,11 @@ RegionView::set_samples_per_unit (gdouble spu) { TimeAxisViewItem::set_samples_per_unit (spu); - /*for (uint32_t n=0; n < waves.size(); ++n) { - waves[n]->property_samples_per_unit() = spu; - }*/ - for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) { (*i)->set_samples_per_unit (spu); (*i)->set_duration (_region.length() / samples_per_unit); } - /*if (gain_line) { - gain_line->reset (); - }*/ - //reset_fade_shapes (); region_sync_changed (); } @@ -384,10 +330,6 @@ void RegionView::compute_colors (Gdk::Color& basic_color) { TimeAxisViewItem::compute_colors (basic_color); - uint32_t r, g, b, a; - - UINT_TO_RGBA (fill_color, &r, &g, &b, &a); - fade_color = RGBA_TO_UINT(r,g,b,120); } void @@ -395,21 +337,9 @@ RegionView::set_colors () { TimeAxisViewItem::set_colors (); - /*if (gain_line) { - gain_line->set_line_color (_region.envelope_active() ? color_map[cGainLine] : color_map[cGainLineInactive]); - }*/ - if (sync_mark) { sync_mark->property_fill_color_rgba() = fill_color; } - - /*for (uint32_t n=0; n < waves.size(); ++n) { - if (_region.muted()) { - waves[n]->property_wave_color() = color_map[cMutedWaveForm]; - } else { - waves[n]->property_wave_color() = color_map[cWaveForm]; - } - }*/ } void @@ -445,10 +375,9 @@ RegionView::region_renamed () str = _region.name(); } - /* FIXME if (_region.speed_mismatch (trackview.session().frame_rate())) { str = string ("*") + str; - }*/ + } if (_region.muted()) { str = string ("!") + str; diff --git a/gtk2_ardour/regionview.h b/gtk2_ardour/regionview.h index 29c5817a25..d2d2c22760 100644 --- a/gtk2_ardour/regionview.h +++ b/gtk2_ardour/regionview.h @@ -49,7 +49,7 @@ class RegionView : public TimeAxisViewItem ~RegionView (); - virtual void init (Gdk::Color& base_color, bool wait_for_waves); + virtual void init (Gdk::Color& base_color, bool wait_for_data); ARDOUR::Region& region() const { return _region; } @@ -57,8 +57,8 @@ class RegionView : public TimeAxisViewItem void set_valid (bool yn) { valid = yn; } virtual void set_height (double) = 0; - void set_samples_per_unit (double); - bool set_duration (jack_nframes_t, void*); + virtual void set_samples_per_unit (double); + virtual bool set_duration (jack_nframes_t, void*); void move (double xdelta, double ydelta); @@ -70,9 +70,9 @@ class RegionView : public TimeAxisViewItem bool set_position(jack_nframes_t pos, void* src, double* delta = 0); virtual void show_region_editor () = 0; - void hide_region_editor(); + virtual void hide_region_editor(); - void region_changed (ARDOUR::Change); + virtual void region_changed (ARDOUR::Change); virtual GhostRegion* add_ghost (AutomationTimeAxisView&) = 0; void remove_ghost (GhostRegion*); @@ -93,56 +93,44 @@ class RegionView : public TimeAxisViewItem RegionView (ArdourCanvas::Group *, TimeAxisView&, ARDOUR::Region&, - double initial_samples_per_unit, + double samples_per_unit, Gdk::Color& basic_color, TimeAxisViewItem::Visibility); ARDOUR::Region& _region; - enum Flags { - EnvelopeVisible = 0x1, - WaveformVisible = 0x4, - WaveformRectified = 0x8 - }; - ArdourCanvas::Polygon* sync_mark; ///< polgyon for sync position - ArdourCanvas::Text* no_wave_msg; ///< text + ArdourCanvas::Text* no_wave_msg; RegionEditor *editor; vector<ControlPoint *> control_points; double current_visible_sync_position; - uint32_t _flags; - uint32_t fade_color; bool valid; ///< see StreamView::redisplay_diskstream() double _pixel_width; double _height; bool in_destructor; - bool wait_for_waves; - - sigc::connection peaks_ready_connection; - - void region_resized (ARDOUR::Change); - void region_moved (void *); - void region_muted (); - void region_locked (); - void region_opacity (); - void region_layered (); - void region_renamed (); - void region_sync_changed (); - void region_scale_amplitude_changed (); + + bool wait_for_data; + sigc::connection data_ready_connection; + + virtual void region_resized (ARDOUR::Change); + void region_moved (void *); + virtual void region_muted (); + void region_locked (); + void region_opacity (); + void region_layered (); + void region_renamed (); + void region_sync_changed (); static gint _lock_toggle (ArdourCanvas::Item*, GdkEvent*, void*); void lock_toggle (); - void peaks_ready_handler (uint32_t); - void reset_name (gdouble width); - - void set_colors (); - void compute_colors (Gdk::Color&); + virtual void set_colors (); + virtual void compute_colors (Gdk::Color&); virtual void set_frame_color (); - void reset_width_dependent_items (double pixel_width); + virtual void reset_width_dependent_items (double pixel_width); vector<GhostRegion*> ghosts; diff --git a/gtk2_ardour/route_time_axis.cc b/gtk2_ardour/route_time_axis.cc index b4f250b5ef..1eba885b44 100644 --- a/gtk2_ardour/route_time_axis.cc +++ b/gtk2_ardour/route_time_axis.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2000 Paul Davis + Copyright (C) 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 @@ -30,6 +30,8 @@ #include <pbd/stl_delete.h> #include <pbd/whitespace.h> +#include <gtkmm/menu.h> +#include <gtkmm/menuitem.h> #include <gtkmm2ext/gtk_ui.h> #include <gtkmm2ext/selector.h> #include <gtkmm2ext/stop_signal.h> @@ -49,6 +51,9 @@ #include "ardour_ui.h" #include "route_time_axis.h" +#include "automation_time_axis.h" +#include "redirect_automation_time_axis.h" +#include "redirect_automation_line.h" #include "canvas_impl.h" #include "crossfade_view.h" #include "enums.h" @@ -217,6 +222,12 @@ RouteTimeAxisView::~RouteTimeAxisView () { GoingAway (); /* EMIT_SIGNAL */ + vector_delete (&redirect_automation_curves); + + for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) { + delete *i; + } + if (playlist_menu) { delete playlist_menu; playlist_menu = 0; @@ -374,6 +385,97 @@ RouteTimeAxisView::automation_click () } void +RouteTimeAxisView::build_automation_action_menu () +{ + using namespace Menu_Helpers; + + automation_action_menu = manage (new Menu); + MenuList& automation_items = automation_action_menu->items(); + automation_action_menu->set_name ("ArdourContextMenu"); + + automation_items.push_back (MenuElem (_("Show all automation"), + mem_fun(*this, &RouteTimeAxisView::show_all_automation))); + + automation_items.push_back (MenuElem (_("Show existing automation"), + mem_fun(*this, &RouteTimeAxisView::show_existing_automation))); + + automation_items.push_back (MenuElem (_("Hide all automation"), + mem_fun(*this, &RouteTimeAxisView::hide_all_automation))); + + automation_items.push_back (MenuElem (_("Plugins"), subplugin_menu)); +} + +void +RouteTimeAxisView::build_display_menu () +{ + using namespace Menu_Helpers; + + /* get the size menu ready */ + + build_size_menu (); + + /* prepare it */ + + TimeAxisView::build_display_menu (); + + /* now fill it with our stuff */ + + MenuList& items = display_menu->items(); + display_menu->set_name ("ArdourContextMenu"); + + items.push_back (MenuElem (_("Height"), *size_menu)); + items.push_back (MenuElem (_("Color"), mem_fun(*this, &RouteTimeAxisView::select_track_color))); + + items.push_back (SeparatorElem()); + + build_remote_control_menu (); + items.push_back (MenuElem (_("Remote Control ID"), *remote_control_menu)); + + build_automation_action_menu (); + items.push_back (MenuElem (_("Automation"), *automation_action_menu)); + + // Hook for derived classes to add type specific stuff + items.push_back (SeparatorElem()); + append_extra_display_menu_items (); + items.push_back (SeparatorElem()); + + if (is_track()) { + + Menu* alignment_menu = manage (new Menu); + MenuList& alignment_items = alignment_menu->items(); + alignment_menu->set_name ("ArdourContextMenu"); + + RadioMenuItem::Group align_group; + + alignment_items.push_back (RadioMenuElem (align_group, _("Align with existing material"), + bind (mem_fun(*this, &RouteTimeAxisView::set_align_style), ExistingMaterial))); + align_existing_item = dynamic_cast<RadioMenuItem*>(&alignment_items.back()); + if (get_diskstream()->alignment_style() == ExistingMaterial) + align_existing_item->set_active(); + + alignment_items.push_back (RadioMenuElem (align_group, _("Align with capture time"), + bind (mem_fun(*this, &RouteTimeAxisView::set_align_style), CaptureTime))); + align_capture_item = dynamic_cast<RadioMenuItem*>(&alignment_items.back()); + if (get_diskstream()->alignment_style() == CaptureTime) + align_capture_item->set_active(); + + items.push_back (MenuElem (_("Alignment"), *alignment_menu)); + + get_diskstream()->AlignmentStyleChanged.connect ( + mem_fun(*this, &RouteTimeAxisView::align_style_changed)); + } + + items.push_back (SeparatorElem()); + items.push_back (CheckMenuElem (_("Active"), mem_fun(*this, &RouteUI::toggle_route_active))); + route_active_menu_item = dynamic_cast<CheckMenuItem *> (&items.back()); + route_active_menu_item->set_active (_route->active()); + + items.push_back (SeparatorElem()); + items.push_back (MenuElem (_("Remove"), mem_fun(*this, &RouteUI::remove_this_route))); +} + + +void RouteTimeAxisView::show_timestretch (jack_nframes_t start, jack_nframes_t end) { double x1; @@ -760,6 +862,12 @@ RouteTimeAxisView::set_selected_points (PointSelection& points) } void +RouteTimeAxisView::set_selected_regionviews (RegionSelection& regions) +{ + _view->set_selected_regionviews (regions); +} + +void RouteTimeAxisView::get_selectables (jack_nframes_t start, jack_nframes_t end, double top, double bot, list<Selectable*>& results) { double speed = 1.0; @@ -1053,3 +1161,399 @@ RouteTimeAxisView::select_me (GdkEventButton* ev) return false; } +void +RouteTimeAxisView::show_all_automation () +{ + no_redraw = true; + + for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) { + for (vector<RedirectAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) { + if ((*ii)->view == 0) { + add_redirect_automation_curve ((*i)->redirect, (*ii)->what); + } + + (*ii)->menu_item->set_active (true); + } + } + + no_redraw = false; + + _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */ +} + +void +RouteTimeAxisView::show_existing_automation () +{ + no_redraw = true; + + for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) { + for (vector<RedirectAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) { + if ((*ii)->view != 0) { + (*ii)->menu_item->set_active (true); + } + } + } + + no_redraw = false; + + _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */ +} + +void +RouteTimeAxisView::hide_all_automation () +{ + no_redraw = true; + + for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) { + for (vector<RedirectAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) { + (*ii)->menu_item->set_active (false); + } + } + + no_redraw = false; + _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */ +} + + +void +RouteTimeAxisView::region_view_added (RegionView* rv) +{ + for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) { + AutomationTimeAxisView* atv; + + if ((atv = dynamic_cast<AutomationTimeAxisView*> (*i)) != 0) { + rv->add_ghost (*atv); + } + } +} + +void +RouteTimeAxisView::add_ghost_to_redirect (RegionView* rv, AutomationTimeAxisView* atv) +{ + rv->add_ghost (*atv); +} + +RouteTimeAxisView::RedirectAutomationInfo::~RedirectAutomationInfo () +{ + for (vector<RedirectAutomationNode*>::iterator i = lines.begin(); i != lines.end(); ++i) { + delete *i; + } +} + + +RouteTimeAxisView::RedirectAutomationNode::~RedirectAutomationNode () +{ + parent.remove_ran (this); + + if (view) { + delete view; + } +} + +void +RouteTimeAxisView::remove_ran (RedirectAutomationNode* ran) +{ + if (ran->view) { + remove_child (ran->view); + } +} + +RouteTimeAxisView::RedirectAutomationNode* +RouteTimeAxisView::find_redirect_automation_node (boost::shared_ptr<Redirect> redirect, uint32_t what) +{ + for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) { + + if ((*i)->redirect == redirect) { + + for (vector<RedirectAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) { + if ((*ii)->what == what) { + return *ii; + } + } + } + } + + return 0; +} + +// FIXME: duplicated in midi_time_axis.cc +static string +legalize_for_xml_node (string str) +{ + string::size_type pos; + string legal_chars = "abcdefghijklmnopqrtsuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_+=:"; + string legal; + + legal = str; + pos = 0; + + while ((pos = legal.find_first_not_of (legal_chars, pos)) != string::npos) { + legal.replace (pos, 1, "_"); + pos += 1; + } + + return legal; +} + + +void +RouteTimeAxisView::add_redirect_automation_curve (boost::shared_ptr<Redirect> redirect, uint32_t what) +{ + RedirectAutomationLine* ral; + string name; + RedirectAutomationNode* ran; + + if ((ran = find_redirect_automation_node (redirect, what)) == 0) { + fatal << _("programming error: ") + << string_compose (X_("redirect automation curve for %1:%2 not registered with audio track!"), + redirect->name(), what) + << endmsg; + /*NOTREACHED*/ + return; + } + + if (ran->view) { + return; + } + + name = redirect->describe_parameter (what); + + /* create a string that is a legal XML node name that can be used to refer to this redirect+port combination */ + + char state_name[256]; + snprintf (state_name, sizeof (state_name), "Redirect-%s-%" PRIu32, legalize_for_xml_node (redirect->name()).c_str(), what); + + ran->view = new RedirectAutomationTimeAxisView (_session, _route, editor, *this, parent_canvas, name, what, *redirect, state_name); + + ral = new RedirectAutomationLine (name, + *redirect, what, _session, *ran->view, + *ran->view->canvas_display, redirect->automation_list (what)); + + ral->set_line_color (color_map[cRedirectAutomationLine]); + ral->queue_reset (); + + ran->view->add_line (*ral); + + ran->view->Hiding.connect (bind (mem_fun(*this, &RouteTimeAxisView::redirect_automation_track_hidden), ran, redirect)); + + if (!ran->view->marked_for_display()) { + ran->view->hide (); + } else { + ran->menu_item->set_active (true); + } + + add_child (ran->view); + + _view->foreach_regionview (bind (mem_fun(*this, &RouteTimeAxisView::add_ghost_to_redirect), ran->view)); + + redirect->mark_automation_visible (what, true); +} + +void +RouteTimeAxisView::redirect_automation_track_hidden (RouteTimeAxisView::RedirectAutomationNode* ran, boost::shared_ptr<Redirect> r) +{ + if (!_hidden) { + ran->menu_item->set_active (false); + } + + r->mark_automation_visible (ran->what, false); + + _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */ +} + +void +RouteTimeAxisView::add_existing_redirect_automation_curves (boost::shared_ptr<Redirect> redirect) +{ + set<uint32_t> s; + RedirectAutomationLine *ral; + + redirect->what_has_visible_automation (s); + + for (set<uint32_t>::iterator i = s.begin(); i != s.end(); ++i) { + + if ((ral = find_redirect_automation_curve (redirect, *i)) != 0) { + ral->queue_reset (); + } else { + add_redirect_automation_curve (redirect, (*i)); + } + } +} + +void +RouteTimeAxisView::add_redirect_to_subplugin_menu (boost::shared_ptr<Redirect> r) +{ + using namespace Menu_Helpers; + RedirectAutomationInfo *rai; + list<RedirectAutomationInfo*>::iterator x; + + const std::set<uint32_t>& automatable = r->what_can_be_automated (); + std::set<uint32_t> has_visible_automation; + + r->what_has_visible_automation(has_visible_automation); + + if (automatable.empty()) { + return; + } + + for (x = redirect_automation.begin(); x != redirect_automation.end(); ++x) { + if ((*x)->redirect == r) { + break; + } + } + + if (x == redirect_automation.end()) { + + rai = new RedirectAutomationInfo (r); + redirect_automation.push_back (rai); + + } else { + + rai = *x; + + } + + /* any older menu was deleted at the top of redirects_changed() + when we cleared the subplugin menu. + */ + + rai->menu = manage (new Menu); + MenuList& items = rai->menu->items(); + rai->menu->set_name ("ArdourContextMenu"); + + items.clear (); + + for (std::set<uint32_t>::const_iterator i = automatable.begin(); i != automatable.end(); ++i) { + + RedirectAutomationNode* ran; + CheckMenuItem* mitem; + + string name = r->describe_parameter (*i); + + items.push_back (CheckMenuElem (name)); + mitem = dynamic_cast<CheckMenuItem*> (&items.back()); + + if (has_visible_automation.find((*i)) != has_visible_automation.end()) { + mitem->set_active(true); + } + + if ((ran = find_redirect_automation_node (r, *i)) == 0) { + + /* new item */ + + ran = new RedirectAutomationNode (*i, mitem, *this); + + rai->lines.push_back (ran); + + } else { + + ran->menu_item = mitem; + + } + + mitem->signal_toggled().connect (bind (mem_fun(*this, &RouteTimeAxisView::redirect_menu_item_toggled), rai, ran)); + } + + /* add the menu for this redirect, because the subplugin + menu is always cleared at the top of redirects_changed(). + this is the result of some poor design in gtkmm and/or + GTK+. + */ + + subplugin_menu.items().push_back (MenuElem (r->name(), *rai->menu)); + rai->valid = true; +} + +void +RouteTimeAxisView::redirect_menu_item_toggled (RouteTimeAxisView::RedirectAutomationInfo* rai, + RouteTimeAxisView::RedirectAutomationNode* ran) +{ + bool showit = ran->menu_item->get_active(); + bool redraw = false; + + if (ran->view == 0 && showit) { + add_redirect_automation_curve (rai->redirect, ran->what); + redraw = true; + } + + if (showit != ran->view->marked_for_display()) { + + if (showit) { + ran->view->set_marked_for_display (true); + ran->view->canvas_display->show(); + } else { + rai->redirect->mark_automation_visible (ran->what, true); + ran->view->set_marked_for_display (false); + ran->view->hide (); + } + + redraw = true; + + } + + if (redraw && !no_redraw) { + + /* now trigger a redisplay */ + + _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */ + + } +} + +void +RouteTimeAxisView::redirects_changed (void *src) +{ + using namespace Menu_Helpers; + + for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) { + (*i)->valid = false; + } + + subplugin_menu.items().clear (); + + _route->foreach_redirect (this, &RouteTimeAxisView::add_redirect_to_subplugin_menu); + _route->foreach_redirect (this, &RouteTimeAxisView::add_existing_redirect_automation_curves); + + for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ) { + + list<RedirectAutomationInfo*>::iterator tmp; + + tmp = i; + ++tmp; + + if (!(*i)->valid) { + + delete *i; + redirect_automation.erase (i); + + } + + i = tmp; + } + + /* change in visibility was possible */ + + _route->gui_changed ("track_height", this); +} + +RedirectAutomationLine * +RouteTimeAxisView::find_redirect_automation_curve (boost::shared_ptr<Redirect> redirect, uint32_t what) +{ + RedirectAutomationNode* ran; + + if ((ran = find_redirect_automation_node (redirect, what)) != 0) { + if (ran->view) { + return dynamic_cast<RedirectAutomationLine*> (ran->view->lines.front()); + } + } + + return 0; +} + +void +RouteTimeAxisView::reset_redirect_automation_curves () +{ + for (vector<RedirectAutomationLine*>::iterator i = redirect_automation_curves.begin(); i != redirect_automation_curves.end(); ++i) { + (*i)->reset(); + } +} + diff --git a/gtk2_ardour/route_time_axis.h b/gtk2_ardour/route_time_axis.h index a75851b8a8..476a135c39 100644 --- a/gtk2_ardour/route_time_axis.h +++ b/gtk2_ardour/route_time_axis.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2000 Paul Davis + Copyright (C) 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 @@ -33,7 +33,6 @@ #include <list> #include <ardour/types.h> -#include <ardour/region.h> #include "ardour_dialog.h" #include "route_ui.h" @@ -44,6 +43,7 @@ namespace ARDOUR { class Session; + class Region; class Diskstream; class RouteGroup; class Redirect; @@ -57,12 +57,14 @@ class RegionView; class StreamView; class Selection; class Selectable; +class AutomationTimeAxisView; class AutomationLine; +class RedirectAutomationLine; class TimeSelection; class RouteTimeAxisView : public RouteUI, public TimeAxisView { - public: +public: RouteTimeAxisView (PublicEditor&, ARDOUR::Session&, boost::shared_ptr<ARDOUR::Route>, ArdourCanvas::Canvas& canvas); virtual ~RouteTimeAxisView (); @@ -74,51 +76,57 @@ class RouteTimeAxisView : public RouteUI, public TimeAxisView void hide_timestretch (); void selection_click (GdkEventButton*); void set_selected_points (PointSelection&); + void set_selected_regionviews (RegionSelection&); void get_selectables (jack_nframes_t start, jack_nframes_t end, double top, double bot, list<Selectable *>&); void get_inverted_selectables (Selection&, list<Selectable*>&); ARDOUR::Region* find_next_region (jack_nframes_t pos, ARDOUR::RegionPoint, int32_t dir); - string name() const; - - ARDOUR::RouteGroup* edit_group() const; - - void build_playlist_menu (Gtk::Menu *); - ARDOUR::Playlist* playlist() const; - - StreamView* view() { return _view; } - - /* editing operations */ - + /* Editing operations */ bool cut_copy_clear (Selection&, Editing::CutCopyOp); bool paste (jack_nframes_t, float times, Selection&, size_t nth); list<TimeAxisView*> get_child_list(); - /* the editor calls these when mapping an operation across multiple tracks */ - + /* The editor calls these when mapping an operation across multiple tracks */ void use_new_playlist (bool prompt); void use_copy_playlist (bool prompt); void clear_playlist (); + + void build_playlist_menu (Gtk::Menu *); + + string name() const; + StreamView* view() const { return _view; } + ARDOUR::RouteGroup* edit_group() const; + ARDOUR::Playlist* playlist() const; - //private: (FIXME) +protected: friend class StreamView; - StreamView *_view; + struct RedirectAutomationNode { + uint32_t what; + Gtk::CheckMenuItem* menu_item; + AutomationTimeAxisView* view; + RouteTimeAxisView& parent; - ArdourCanvas::Canvas& parent_canvas; + RedirectAutomationNode (uint32_t w, Gtk::CheckMenuItem* mitem, RouteTimeAxisView& p) + : what (w), menu_item (mitem), view (0), parent (p) {} - bool no_redraw; - - Gtk::HBox other_button_hbox; - Gtk::Table button_table; - Gtk::Button redirect_button; - Gtk::Button edit_group_button; - Gtk::Button playlist_button; - Gtk::Button size_button; - Gtk::Button automation_button; - Gtk::Button hide_button; - Gtk::Button visual_button; + ~RedirectAutomationNode (); + }; + + struct RedirectAutomationInfo { + boost::shared_ptr<ARDOUR::Redirect> redirect; + bool valid; + Gtk::Menu* menu; + vector<RedirectAutomationNode*> lines; + + RedirectAutomationInfo (boost::shared_ptr<ARDOUR::Redirect> r) + : redirect (r), valid (true), menu (0) {} + + ~RedirectAutomationInfo (); + }; + void diskstream_changed (void *src); void update_diskstream_display (); @@ -133,11 +141,30 @@ class RouteTimeAxisView : public RouteUI, public TimeAxisView void redirect_relist (); void redirect_row_selected (gint row, gint col, GdkEvent *ev); void add_to_redirect_display (ARDOUR::Redirect *); - //void redirects_changed (void *); + void redirects_changed (void *); + + void add_redirect_to_subplugin_menu (boost::shared_ptr<ARDOUR::Redirect>); + void remove_ran (RedirectAutomationNode* ran); - sigc::connection modified_connection; - sigc::connection state_changed_connection; + void redirect_menu_item_toggled (RouteTimeAxisView::RedirectAutomationInfo*, + RouteTimeAxisView::RedirectAutomationNode*); + + void redirect_automation_track_hidden (RedirectAutomationNode*, + boost::shared_ptr<ARDOUR::Redirect>); + + RedirectAutomationNode* + find_redirect_automation_node (boost::shared_ptr<ARDOUR::Redirect> r, uint32_t); + + RedirectAutomationLine* + find_redirect_automation_curve (boost::shared_ptr<ARDOUR::Redirect> r, uint32_t); + void add_redirect_automation_curve (boost::shared_ptr<ARDOUR::Redirect> r, uint32_t); + void add_existing_redirect_automation_curves (boost::shared_ptr<ARDOUR::Redirect>); + + void reset_redirect_automation_curves (); + + void update_automation_view (ARDOUR::AutomationType); + void take_name_changed (void *); void route_name_changed (void *); void name_entry_changed (); @@ -145,9 +172,7 @@ class RouteTimeAxisView : public RouteUI, public TimeAxisView void on_area_realize (); virtual void label_view (); - - Gtk::Menu edit_group_menu; - + void add_edit_group_menu_item (ARDOUR::RouteGroup *, Gtk::RadioMenuItem::Group*); void set_edit_group_from_menu (ARDOUR::RouteGroup *); @@ -155,35 +180,27 @@ class RouteTimeAxisView : public RouteUI, public TimeAxisView void select_track_color(); - virtual void build_display_menu () = 0; - - Gtk::RadioMenuItem* align_existing_item; - Gtk::RadioMenuItem* align_capture_item; + virtual void build_automation_action_menu (); + virtual void append_extra_display_menu_items () {} + void build_display_menu (); void align_style_changed (); void set_align_style (ARDOUR::AlignStyle); - - Gtk::Menu *playlist_menu; - Gtk::Menu *playlist_action_menu; - Gtk::MenuItem *playlist_item; - /* playlist */ - virtual void set_playlist (ARDOUR::Playlist *); - void playlist_click (); - void show_playlist_selector (); - - void playlist_changed (); - void playlist_state_changed (ARDOUR::Change); - void playlist_modified (); + void playlist_click (); + void show_playlist_selector (); + void playlist_changed (); + void playlist_state_changed (ARDOUR::Change); + void playlist_modified (); void add_playlist_to_playlist_menu (ARDOUR::Playlist*); void rename_current_playlist (); - Gtk::Menu* automation_action_menu; - void automation_click (); - - ArdourCanvas::SimpleRect *timestretch_rect; + void automation_click (); + virtual void show_all_automation (); + virtual void show_existing_automation (); + virtual void hide_all_automation (); void timestretch (jack_nframes_t start, jack_nframes_t end); @@ -198,7 +215,40 @@ class RouteTimeAxisView : public RouteUI, public TimeAxisView void color_handler (ColorID, uint32_t); bool select_me (GdkEventButton*); - virtual void region_view_added (RegionView*) = 0; + void region_view_added (RegionView*); + void add_ghost_to_redirect (RegionView*, AutomationTimeAxisView*); + + + StreamView* _view; + ArdourCanvas::Canvas& parent_canvas; + bool no_redraw; + + Gtk::HBox other_button_hbox; + Gtk::Table button_table; + Gtk::Button redirect_button; + Gtk::Button edit_group_button; + Gtk::Button playlist_button; + Gtk::Button size_button; + Gtk::Button automation_button; + Gtk::Button hide_button; + Gtk::Button visual_button; + + Gtk::Menu subplugin_menu; + Gtk::Menu* automation_action_menu; + Gtk::Menu edit_group_menu; + Gtk::RadioMenuItem* align_existing_item; + Gtk::RadioMenuItem* align_capture_item; + Gtk::Menu* playlist_menu; + Gtk::Menu* playlist_action_menu; + Gtk::MenuItem* playlist_item; + + ArdourCanvas::SimpleRect* timestretch_rect; + + list<RedirectAutomationInfo*> redirect_automation; + vector<RedirectAutomationLine*> redirect_automation_curves; + + sigc::connection modified_connection; + sigc::connection state_changed_connection; }; #endif /* __ardour_route_time_axis_h__ */ diff --git a/gtk2_ardour/streamview.cc b/gtk2_ardour/streamview.cc index 93d25b6a97..c94184272e 100644 --- a/gtk2_ardour/streamview.cc +++ b/gtk2_ardour/streamview.cc @@ -60,7 +60,6 @@ StreamView::StreamView (RouteTimeAxisView& tv) canvas_rect->property_y1() = 0.0; canvas_rect->property_x2() = 1000000.0; canvas_rect->property_y2() = (double) tv.height; - canvas_rect->property_outline_color_rgba() = color_map[cAudioTrackOutline]; // FIXME canvas_rect->property_outline_what() = (guint32) (0x1|0x2|0x8); // outline ends and bottom canvas_rect->property_fill_color_rgba() = stream_base_color; diff --git a/gtk2_ardour/streamview.h b/gtk2_ardour/streamview.h index f2906d40c4..baa779ba67 100644 --- a/gtk2_ardour/streamview.h +++ b/gtk2_ardour/streamview.h @@ -98,35 +98,37 @@ public: protected: StreamView (RouteTimeAxisView&); -//private: - void update_rec_box (); - void transport_changed(); - void rec_enable_changed(void* src = 0); - void sess_rec_enable_changed(); +//private: (FIXME?) + + void transport_changed(); + void rec_enable_changed(void* src = 0); + void sess_rec_enable_changed(); virtual void setup_rec_box () = 0; - void rec_peak_range_ready (jack_nframes_t start, jack_nframes_t cnt, ARDOUR::Source* src); + void update_rec_box (); virtual void update_rec_regions () = 0; virtual void add_region_view_internal (ARDOUR::Region*, bool wait_for_waves) = 0; virtual void remove_region_view (ARDOUR::Region* ); - void remove_rec_region (ARDOUR::Region*); + void remove_rec_region (ARDOUR::Region*); - void display_diskstream (ARDOUR::Diskstream* ); + void display_diskstream (ARDOUR::Diskstream* ); virtual void undisplay_diskstream (); virtual void redisplay_diskstream () = 0; - void diskstream_changed (void* ); - void playlist_state_changed (ARDOUR::Change); + void diskstream_changed (void* ); + + void playlist_state_changed (ARDOUR::Change); virtual void playlist_changed (ARDOUR::Diskstream* ); virtual void playlist_modified (); + + virtual void color_handler (ColorID, uint32_t) = 0; - RouteTimeAxisView& _trackview; - + RouteTimeAxisView& _trackview; ArdourCanvas::Group* canvas_group; ArdourCanvas::SimpleRect* canvas_rect; /* frame around the whole thing */ typedef list<RegionView* > RegionViewList; - RegionViewList region_views; + RegionViewList region_views; double _samples_per_unit; @@ -141,8 +143,6 @@ protected: Gdk::Color region_color; uint32_t stream_base_color; - virtual void color_handler (ColorID, uint32_t) = 0; - vector<sigc::connection> playlist_connections; sigc::connection playlist_change_connection; }; diff --git a/gtk2_ardour/taperegionview.cc b/gtk2_ardour/taperegionview.cc index 76fd91337e..19e6ba3ad3 100644 --- a/gtk2_ardour/taperegionview.cc +++ b/gtk2_ardour/taperegionview.cc @@ -63,53 +63,9 @@ TapeAudioRegionView::TapeAudioRegionView (ArdourCanvas::Group *parent, RouteTime void TapeAudioRegionView::init (Gdk::Color& basic_color, bool wfw) { - XMLNode *node; - - editor = 0; - valid = true; - in_destructor = false; - _amplitude_above_axis = 1.0; - zero_line = 0; - wait_for_waves = wfw; - _height = 0; - - _flags = 0; - - if ((node = _region.extra_xml ("GUI")) != 0) { - set_flags (node); - } else { - _flags = WaveformVisible; - store_flags (); - } - - fade_in_handle = 0; - fade_out_handle = 0; - gain_line = 0; - sync_mark = 0; - - compute_colors (basic_color); - - create_waves (); - - name_highlight->set_data ("regionview", this); - - reset_width_dependent_items ((double) _region.length() / samples_per_unit); - - set_height (trackview.height); - - region_muted (); - region_resized (BoundsChanged); - set_waveview_data_src(); - region_locked (); - - /* no events, no state changes */ - - set_colors (); - - // ColorChanged.connect (mem_fun (*this, &AudioRegionView::color_handler)); + AudioRegionView::init(basic_color, wfw); /* every time the wave data changes and peaks are ready, redraw */ - for (uint32_t n = 0; n < audio_region().n_channels(); ++n) { audio_region().source(n).PeaksReady.connect (bind (mem_fun(*this, &TapeAudioRegionView::update), n)); |