diff options
Diffstat (limited to 'gtk2_ardour')
38 files changed, 753 insertions, 401 deletions
diff --git a/gtk2_ardour/SConscript b/gtk2_ardour/SConscript index c5e8f10856..cb5cc41ae2 100644 --- a/gtk2_ardour/SConscript +++ b/gtk2_ardour/SConscript @@ -96,6 +96,7 @@ audio_clock.cc audio_time_axis.cc audio_region_editor.cc automation_gain_line.cc +automation_midi_cc_line.cc automation_line.cc automation_pan_line.cc automation_time_axis.cc @@ -142,6 +143,7 @@ export_session_dialog.cc export_region_dialog.cc export_range_markers_dialog.cc gain_automation_time_axis.cc +midi_controller_time_axis.cc gain_meter.cc ghostregion.cc gtk-custom-hruler.c diff --git a/gtk2_ardour/audio_region_view.cc b/gtk2_ardour/audio_region_view.cc index 991f15075a..058295949f 100644 --- a/gtk2_ardour/audio_region_view.cc +++ b/gtk2_ardour/audio_region_view.cc @@ -534,7 +534,7 @@ AudioRegionView::reset_fade_in_shape_width (nframes_t width) fade_in_shape->show(); float curve[npoints]; - audio_region()->fade_in().get_vector (0, audio_region()->fade_in().back()->when, curve, npoints); + audio_region()->fade_in().curve().get_vector (0, audio_region()->fade_in().back()->when, curve, npoints); points = get_canvas_points ("fade in shape", npoints+3); @@ -620,7 +620,7 @@ AudioRegionView::reset_fade_out_shape_width (nframes_t width) fade_out_shape->show(); float curve[npoints]; - audio_region()->fade_out().get_vector (0, audio_region()->fade_out().back()->when, curve, npoints); + audio_region()->fade_out().curve().get_vector (0, audio_region()->fade_out().back()->when, curve, npoints); if (_height > NAME_HIGHLIGHT_THRESH) { h = _height - NAME_HIGHLIGHT_SIZE; @@ -953,7 +953,7 @@ AudioRegionView::add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev) audio_region()->envelope().add (fx, y); XMLNode &after = audio_region()->envelope().get_state(); - trackview.session().add_command (new MementoCommand<Curve>(audio_region()->envelope(), &before, &after)); + trackview.session().add_command (new MementoCommand<AutomationList>(audio_region()->envelope(), &before, &after)); trackview.session().commit_reversible_command (); } diff --git a/gtk2_ardour/audio_time_axis.cc b/gtk2_ardour/audio_time_axis.cc index f1160e26ec..b259d8723d 100644 --- a/gtk2_ardour/audio_time_axis.cc +++ b/gtk2_ardour/audio_time_axis.cc @@ -83,16 +83,12 @@ AudioTimeAxisView::AudioTimeAxisView (PublicEditor& ed, Session& sess, boost::sh assert(!is_track() || is_audio_track()); subplugin_menu.set_name ("ArdourContextMenu"); - gain_track = 0; - pan_track = 0; waveform_item = 0; - pan_automation_item = 0; - gain_automation_item = 0; _view = new AudioStreamView (*this); - add_gain_automation_child (); - add_pan_automation_child (); + create_automation_child (GainAutomation); + create_automation_child (PanAutomation); ignore_toggle = false; @@ -156,81 +152,6 @@ AudioTimeAxisView::hide () } void -AudioTimeAxisView::set_state (const XMLNode& node) -{ - const XMLProperty *prop; - - TimeAxisView::set_state (node); - - if ((prop = node.property ("shown_editor")) != 0) { - if (prop->value() == "no") { - _marked_for_display = false; - } else { - _marked_for_display = true; - } - } else { - _marked_for_display = true; - } - - XMLNodeList nlist = node.children(); - XMLNodeConstIterator niter; - XMLNode *child_node; - - - show_gain_automation = false; - show_pan_automation = false; - - for (niter = nlist.begin(); niter != nlist.end(); ++niter) { - child_node = *niter; - - if (child_node->name() == "gain") { - XMLProperty *prop=child_node->property ("shown"); - - if (prop != 0) { - if (prop->value() == "yes") { - show_gain_automation = true; - } - } - continue; - } - - if (child_node->name() == "pan") { - XMLProperty *prop=child_node->property ("shown"); - - if (prop != 0) { - if (prop->value() == "yes") { - show_pan_automation = true; - } - } - continue; - } - } -} - -void -AudioTimeAxisView::build_automation_action_menu () -{ - using namespace Menu_Helpers; - - RouteTimeAxisView::build_automation_action_menu (); - - MenuList& automation_items = automation_action_menu->items(); - - automation_items.push_back (SeparatorElem()); - - automation_items.push_back (CheckMenuElem (_("Fader"), - mem_fun(*this, &AudioTimeAxisView::toggle_gain_track))); - gain_automation_item = static_cast<CheckMenuItem*> (&automation_items.back()); - gain_automation_item->set_active(show_gain_automation); - - automation_items.push_back (CheckMenuElem (_("Pan"), - mem_fun(*this, &AudioTimeAxisView::toggle_pan_track))); - pan_automation_item = static_cast<CheckMenuItem*> (&automation_items.back()); - pan_automation_item->set_active(show_pan_automation); - -} - -void AudioTimeAxisView::append_extra_display_menu_items () { using namespace Menu_Helpers; @@ -360,79 +281,45 @@ AudioTimeAxisView::set_waveform_scale (WaveformScale scale) } void -AudioTimeAxisView::add_gain_automation_child () +AudioTimeAxisView::create_automation_child (ParamID param) { - XMLProperty* prop; - AutomationLine* line; - - gain_track = new GainAutomationTimeAxisView (_session, - _route, - editor, - *this, - parent_canvas, - _("gain"), - _route->gain_automation_curve()); - - line = new AutomationGainLine ("automation gain", - _session, - *gain_track, - *gain_track->canvas_display, - _route->gain_automation_curve()); + if (param.type() == GainAutomation) { + GainAutomationTimeAxisView* gain_track = new GainAutomationTimeAxisView (_session, + _route, + editor, + *this, + parent_canvas, + _route->describe_parameter(param), + _route->gain_automation()); - line->set_line_color (Config->canvasvar_AutomationLine.get()); - + AutomationLine* line = new AutomationGainLine ("automation gain", + *gain_track, + *gain_track->canvas_display, + _route->gain_automation()); - gain_track->add_line (*line); + line->set_line_color (Config->canvasvar_AutomationLine.get()); - add_child (gain_track); + gain_track->add_line (*line); - gain_track->Hiding.connect (mem_fun(*this, &AudioTimeAxisView::gain_hidden)); + add_automation_child(ParamID(GainAutomation), gain_track); - bool hideit = true; - - XMLNode* node; - - if ((node = gain_track->get_state_node()) != 0) { - if ((prop = node->property ("shown")) != 0) { - if (prop->value() == "yes") { - hideit = false; - } - } - } + } else if (param.type() == PanAutomation) { - if (hideit) { - gain_track->hide (); - } -} + PanAutomationTimeAxisView* pan_track = new PanAutomationTimeAxisView (_session, + _route, + editor, + *this, + parent_canvas, + _route->describe_parameter(param)); -void -AudioTimeAxisView::add_pan_automation_child () -{ - XMLProperty* prop; - - pan_track = new PanAutomationTimeAxisView (_session, _route, editor, *this, parent_canvas, _("pan")); - - update_pans (); - - add_child (pan_track); - - pan_track->Hiding.connect (mem_fun(*this, &AudioTimeAxisView::pan_hidden)); + ensure_xml_node (); - ensure_xml_node (); - bool hideit = true; - - XMLNode* node; - - if ((node = pan_track->get_state_node()) != 0) { - if ((prop = node->property ("shown")) != 0) { - if (prop->value() == "yes") { - hideit = false; - } - } - } + add_automation_child(ParamID(PanAutomation), pan_track); + + update_pans (); - if (hideit) { - pan_track->hide (); + } else { + error << "AudioTimeAxisView: unknown automation child " << param.to_string() << endmsg; } } @@ -441,6 +328,14 @@ AudioTimeAxisView::update_pans () { Panner::iterator p; + RouteAutomationNode* ran = automation_track(PanAutomation); + if (!ran) { + warning << _route << " has no pan automation track" << endmsg; + return; + } + + AutomationTimeAxisView* pan_track = ran->track; + pan_track->clear_lines (); /* we don't draw lines for "greater than stereo" panning. @@ -454,7 +349,7 @@ AudioTimeAxisView::update_pans () AutomationLine* line; - line = new AutomationPanLine ("automation pan", _session, *pan_track, + line = new AutomationPanLine ("automation pan", *pan_track, *pan_track->canvas_display, (*p)->automation()); @@ -471,79 +366,6 @@ AudioTimeAxisView::update_pans () } void -AudioTimeAxisView::toggle_gain_track () -{ - - bool showit = gain_automation_item->get_active(); - - if (showit != gain_track->marked_for_display()) { - if (showit) { - gain_track->set_marked_for_display (true); - gain_track->canvas_display->show(); - gain_track->get_state_node()->add_property ("shown", X_("yes")); - } else { - gain_track->set_marked_for_display (false); - gain_track->hide (); - gain_track->get_state_node()->add_property ("shown", X_("no")); - } - - /* now trigger a redisplay */ - - if (!no_redraw) { - _route->gui_changed (X_("track_height"), (void *) 0); /* EMIT_SIGNAL */ - } - } -} - -void -AudioTimeAxisView::gain_hidden () -{ - gain_track->get_state_node()->add_property (X_("shown"), X_("no")); - - if (gain_automation_item && !_hidden) { - gain_automation_item->set_active (false); - } - - _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */ -} - -void -AudioTimeAxisView::toggle_pan_track () -{ - bool showit = pan_automation_item->get_active(); - - if (showit != pan_track->marked_for_display()) { - if (showit) { - pan_track->set_marked_for_display (true); - pan_track->canvas_display->show(); - pan_track->get_state_node()->add_property ("shown", X_("yes")); - } else { - pan_track->set_marked_for_display (false); - pan_track->hide (); - pan_track->get_state_node()->add_property ("shown", X_("no")); - } - - /* now trigger a redisplay */ - - if (!no_redraw) { - _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */ - } - } -} - -void -AudioTimeAxisView::pan_hidden () -{ - pan_track->get_state_node()->add_property ("shown", "no"); - - if (pan_automation_item && !_hidden) { - pan_automation_item->set_active (false); - } - - _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */ -} - -void AudioTimeAxisView::show_all_automation () { no_redraw = true; @@ -669,12 +491,6 @@ AudioTimeAxisView::update_control_names () } } -XMLNode* -AudioTimeAxisView::get_child_xml_node (const string & childname) -{ - return RouteUI::get_child_xml_node (childname); -} - void AudioTimeAxisView::set_layer_display (LayerDisplay d) { diff --git a/gtk2_ardour/audio_time_axis.h b/gtk2_ardour/audio_time_axis.h index ab5ef955c7..a2f331cf6a 100644 --- a/gtk2_ardour/audio_time_axis.h +++ b/gtk2_ardour/audio_time_axis.h @@ -83,16 +83,14 @@ class AudioTimeAxisView : public RouteTimeAxisView guint32 show_at (double y, int& nth, Gtk::VBox *parent); void hide (); - void set_state (const XMLNode&); - XMLNode* get_child_xml_node (const string & childname); - + void create_automation_child (ARDOUR::ParamID param); + private: friend class AudioStreamView; friend class AudioRegionView; void route_active_changed (); - void build_automation_action_menu (); void append_extra_display_menu_items (); void toggle_show_waveforms (); @@ -104,26 +102,12 @@ class AudioTimeAxisView : public RouteTimeAxisView void show_existing_automation (); void hide_all_automation (); - void add_gain_automation_child (); - void add_pan_automation_child (); - void add_parameter_automation_child (); - - void toggle_gain_track (); - void toggle_pan_track (); - void gain_hidden (); void pan_hidden (); void update_pans (); void update_control_names (); - 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; diff --git a/gtk2_ardour/automation_gain_line.cc b/gtk2_ardour/automation_gain_line.cc index 006543df18..84488dc2b5 100644 --- a/gtk2_ardour/automation_gain_line.cc +++ b/gtk2_ardour/automation_gain_line.cc @@ -26,16 +26,13 @@ #include "automation_gain_line.h" #include "utils.h" -#include <ardour/session.h> - using namespace std; using namespace ARDOUR; using namespace PBD; -AutomationGainLine::AutomationGainLine (const string & name, Session& s, TimeAxisView& tv, ArdourCanvas::Group& parent, Curve& c) +AutomationGainLine::AutomationGainLine (const string & name, TimeAxisView& tv, ArdourCanvas::Group& parent, AutomationList& l) - : AutomationLine (name, tv, parent, c), - session (s) + : AutomationLine (name, tv, parent, l) { set_verbose_cursor_uses_gain_mapping (true); } diff --git a/gtk2_ardour/automation_gain_line.h b/gtk2_ardour/automation_gain_line.h index ca90216c8f..fe8c9274f2 100644 --- a/gtk2_ardour/automation_gain_line.h +++ b/gtk2_ardour/automation_gain_line.h @@ -25,23 +25,15 @@ #include "canvas.h" #include "automation_line.h" -namespace ARDOUR { - class Session; -} - class TimeAxisView; class AutomationGainLine : public AutomationLine { public: - AutomationGainLine (const string & name, ARDOUR::Session&, TimeAxisView&, ArdourCanvas::Group& parent, ARDOUR::Curve&); + AutomationGainLine (const string & name, TimeAxisView&, ArdourCanvas::Group& parent, ARDOUR::AutomationList&); void view_to_model_y (double&); void model_to_view_y (double&); - - private: - ARDOUR::Session& session; - }; diff --git a/gtk2_ardour/automation_line.h b/gtk2_ardour/automation_line.h index 2637a0c554..41034dbf6e 100644 --- a/gtk2_ardour/automation_line.h +++ b/gtk2_ardour/automation_line.h @@ -56,7 +56,7 @@ namespace Gnome { class ControlPoint { public: - ControlPoint (AutomationLine& al); + ControlPoint (AutomationLine& al); ControlPoint (const ControlPoint&, bool dummy_arg_to_force_special_copy_constructor); virtual ~ControlPoint (); @@ -98,7 +98,7 @@ class ControlPoint class AutomationLine : public sigc::trackable, public PBD::StatefulThingWithGoingAway { public: - AutomationLine (const string & name, TimeAxisView&, ArdourCanvas::Group&, ARDOUR::AutomationList&); + AutomationLine (const string & name, TimeAxisView&, ArdourCanvas::Group&, ARDOUR::AutomationList&); virtual ~AutomationLine (); void queue_reset (); diff --git a/gtk2_ardour/automation_midi_cc_line.cc b/gtk2_ardour/automation_midi_cc_line.cc new file mode 100644 index 0000000000..4a074ddbe9 --- /dev/null +++ b/gtk2_ardour/automation_midi_cc_line.cc @@ -0,0 +1,76 @@ +/* + Copyright (C) 2000-2007 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include <sigc++/signal.h> + +#include <ardour/curve.h> + +#include "automation_midi_cc_line.h" + +using namespace std; +using namespace ARDOUR; +using namespace PBD; + +AutomationMidiCCLine::AutomationMidiCCLine (const string & name, TimeAxisView& tv, ArdourCanvas::Group& parent, AutomationList& l) + + : AutomationLine (name, tv, parent, l) +{ + set_verbose_cursor_uses_gain_mapping (true); +} + +void +AutomationMidiCCLine::view_to_model_y (double& y) +{ + assert(y >= 0); + assert(y <= 1); + + y = (int)(y * 127.0); + + assert(y >= 0); + assert(y <= 127); +} + +void +AutomationMidiCCLine::model_to_view_y (double& y) +{ + assert(y >= 0); + assert(y <= 127); + + y = y / 127.0; + + assert(y >= 0); + assert(y <= 1); +} + +string +AutomationMidiCCLine::get_verbose_cursor_string (float fraction) +{ + static const size_t MAX_VAL_LEN = 4; // 4 for "127\0" + char buf[MAX_VAL_LEN]; + + double cc_val = fraction; + view_to_model_y(cc_val); // 0..127 + + snprintf (buf, MAX_VAL_LEN, "%u", (unsigned)cc_val); + + return buf; +} + + + diff --git a/gtk2_ardour/automation_midi_cc_line.h b/gtk2_ardour/automation_midi_cc_line.h new file mode 100644 index 0000000000..6ac078a911 --- /dev/null +++ b/gtk2_ardour/automation_midi_cc_line.h @@ -0,0 +1,44 @@ +/* + Copyright (C) 2000-2007 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef __ardour_gtk_automation_midi_cc_line_h__ +#define __ardour_gtk_automation_midi_cc_line_h__ + +#include <ardour/ardour.h> + +#include "canvas.h" +#include "automation_line.h" + +class TimeAxisView; + +class AutomationMidiCCLine : public AutomationLine +{ + public: + AutomationMidiCCLine (const string & name, TimeAxisView&, ArdourCanvas::Group& parent, ARDOUR::AutomationList&); + + void view_to_model_y (double&); + void model_to_view_y (double&); + + string get_verbose_cursor_string (float); +}; + + +#endif /* __ardour_gtk_automation_midi_cc_line_h__ */ + + diff --git a/gtk2_ardour/automation_pan_line.cc b/gtk2_ardour/automation_pan_line.cc index 04cfb0a311..0e36f4ef88 100644 --- a/gtk2_ardour/automation_pan_line.cc +++ b/gtk2_ardour/automation_pan_line.cc @@ -27,15 +27,12 @@ #include "utils.h" #include <cmath> -#include <ardour/session.h> - using namespace ARDOUR; using namespace PBD; -AutomationPanLine::AutomationPanLine (const string & name, Session& s, TimeAxisView& tv, ArdourCanvas::Group& parent, Curve& c) +AutomationPanLine::AutomationPanLine (const string & name, TimeAxisView& tv, ArdourCanvas::Group& parent, AutomationList& l) - : AutomationLine (name, tv, parent, c), - session (s) + : AutomationLine (name, tv, parent, l) { } diff --git a/gtk2_ardour/automation_pan_line.h b/gtk2_ardour/automation_pan_line.h index c6b32cbc92..6374c535e0 100644 --- a/gtk2_ardour/automation_pan_line.h +++ b/gtk2_ardour/automation_pan_line.h @@ -25,22 +25,17 @@ #include "canvas.h" #include "automation_line.h" -namespace ARDOUR { - class Session; -} - class TimeAxisView; class AutomationPanLine : public AutomationLine { public: - AutomationPanLine (const string & name, ARDOUR::Session&, TimeAxisView&, ArdourCanvas::Group& parent, ARDOUR::Curve&); + AutomationPanLine (const string & name, TimeAxisView&, ArdourCanvas::Group& parent, ARDOUR::AutomationList&); void view_to_model_y (double&); void model_to_view_y (double&); private: - ARDOUR::Session& session; vector<ArdourCanvas::Item*> lines; }; diff --git a/gtk2_ardour/crossfade_edit.cc b/gtk2_ardour/crossfade_edit.cc index 349297f8cd..fd677ac4a6 100644 --- a/gtk2_ardour/crossfade_edit.cc +++ b/gtk2_ardour/crossfade_edit.cc @@ -66,8 +66,8 @@ CrossfadeEditor::Presets* CrossfadeEditor::fade_out_presets = 0; CrossfadeEditor::Half::Half () : line (0), - normative_curve (0.0, 1.0, 1.0, true), - gain_curve (0.0, 2.0, 1.0, true) + normative_curve (ParamID(GainAutomation), 0.0, 1.0, 1.0), // FIXME: GainAutomation? + gain_curve (ParamID(GainAutomation), 0.0, 2.0, 1.0) { } @@ -327,10 +327,10 @@ CrossfadeEditor::audition_state_changed (bool yn) } void -CrossfadeEditor::set (const ARDOUR::Curve& curve, WhichFade which) +CrossfadeEditor::set (const ARDOUR::AutomationList& curve, WhichFade which) { double firstx, endx; - ARDOUR::Curve::const_iterator the_end; + ARDOUR::AutomationList::const_iterator the_end; for (list<Point*>::iterator i = fade[which].points.begin(); i != fade[which].points.end(); ++i) { delete *i; @@ -350,7 +350,7 @@ CrossfadeEditor::set (const ARDOUR::Curve& curve, WhichFade which) firstx = (*curve.const_begin())->when; endx = (*the_end)->when; - for (ARDOUR::Curve::const_iterator i = curve.const_begin(); i != curve.const_end(); ++i) { + for (ARDOUR::AutomationList::const_iterator i = curve.const_begin(); i != curve.const_end(); ++i) { double xfract = ((*i)->when - firstx) / (endx - firstx); double yfract = ((*i)->value - miny) / (maxy - miny); @@ -644,7 +644,7 @@ CrossfadeEditor::redraw () size_t npoints = (size_t) effective_width(); float vec[npoints]; - fade[current].normative_curve.get_vector (0, 1.0, vec, npoints); + fade[current].normative_curve.curve().get_vector (0, 1.0, vec, npoints); ArdourCanvas::Points pts; ArdourCanvas::Points spts; @@ -760,13 +760,13 @@ CrossfadeEditor::apply () void CrossfadeEditor::_apply_to (boost::shared_ptr<Crossfade> xf) { - ARDOUR::Curve& in (xf->fade_in()); - ARDOUR::Curve& out (xf->fade_out()); + ARDOUR::AutomationList& in (xf->fade_in()); + ARDOUR::AutomationList& out (xf->fade_out()); /* IN */ - ARDOUR::Curve::const_iterator the_end = in.const_end(); + ARDOUR::AutomationList::const_iterator the_end = in.const_end(); --the_end; double firstx = (*in.begin())->when; @@ -813,8 +813,8 @@ CrossfadeEditor::setup (boost::shared_ptr<Crossfade> xfade) { _apply_to (xfade); xfade->set_active (true); - xfade->fade_in().solve (); - xfade->fade_out().solve (); + xfade->fade_in().curve().solve (); + xfade->fade_out().curve().solve (); } void diff --git a/gtk2_ardour/crossfade_edit.h b/gtk2_ardour/crossfade_edit.h index 715aa1a360..e9f2dcf762 100644 --- a/gtk2_ardour/crossfade_edit.h +++ b/gtk2_ardour/crossfade_edit.h @@ -33,7 +33,7 @@ namespace ARDOUR { class Session; - class Curve; + class AutomationList; class Crossfade; } @@ -105,8 +105,8 @@ class CrossfadeEditor : public ArdourDialog ArdourCanvas::Line* line; ArdourCanvas::Polygon* shading; list<Point*> points; - ARDOUR::Curve normative_curve; /* 0 - 1.0, linear */ - ARDOUR::Curve gain_curve; /* 0 - 2.0, gain mapping */ + ARDOUR::AutomationList normative_curve; /* 0 - 1.0, linear */ + ARDOUR::AutomationList gain_curve; /* 0 - 2.0, gain mapping */ vector<ArdourCanvas::WaveView*> waves; Half(); @@ -176,7 +176,7 @@ class CrossfadeEditor : public ArdourDialog double x_coordinate (double& xfract) const; double y_coordinate (double& yfract) const; - void set (const ARDOUR::Curve& alist, WhichFade); + void set (const ARDOUR::AutomationList& alist, WhichFade); sigc::connection peaks_ready_connection; diff --git a/gtk2_ardour/crossfade_view.cc b/gtk2_ardour/crossfade_view.cc index d2fdd94e03..cf19137d98 100644 --- a/gtk2_ardour/crossfade_view.cc +++ b/gtk2_ardour/crossfade_view.cc @@ -189,7 +189,7 @@ CrossfadeView::redraw_curves () points = get_canvas_points ("xfade edit redraw", npoints); vec = new float[npoints]; - crossfade->fade_in().get_vector (0, crossfade->length(), vec, npoints); + crossfade->fade_in().curve().get_vector (0, crossfade->length(), vec, npoints); for (int i = 0, pci = 0; i < npoints; ++i) { Art::Point &p = (*points)[pci++]; p.set_x(i); @@ -197,7 +197,7 @@ CrossfadeView::redraw_curves () } fade_in->property_points() = *points; - crossfade->fade_out().get_vector (0, crossfade->length(), vec, npoints); + crossfade->fade_out().curve().get_vector (0, crossfade->length(), vec, npoints); for (int i = 0, pci = 0; i < npoints; ++i) { Art::Point &p = (*points)[pci++]; p.set_x(i); diff --git a/gtk2_ardour/curvetest.cc b/gtk2_ardour/curvetest.cc index 63804bd1b4..71f0600f32 100644 --- a/gtk2_ardour/curvetest.cc +++ b/gtk2_ardour/curvetest.cc @@ -33,7 +33,7 @@ curvetest (string filename) { ifstream in (filename.c_str()); stringstream line; - Curve c (-1.0, +1.0, 0, true); + AutomationList al (ParamID(), -1.0, +1.0, 0); double minx = DBL_MAX; double maxx = DBL_MIN; @@ -55,13 +55,13 @@ curvetest (string filename) maxx = x; } - c.add (x, y); + al.add (x, y); } float foo[1024]; - c.get_vector (minx, maxx, foo, 1024); + al.curve().get_vector (minx, maxx, foo, 1024); for (int i = 0; i < 1024; ++i) { cout << minx + (((double) i / 1024.0) * (maxx - minx)) << ' ' << foo[i] << endl; diff --git a/gtk2_ardour/editor_canvas_events.cc b/gtk2_ardour/editor_canvas_events.cc index 40bef304c5..e1ed2d2fa1 100644 --- a/gtk2_ardour/editor_canvas_events.cc +++ b/gtk2_ardour/editor_canvas_events.cc @@ -35,6 +35,7 @@ #include "region_gain_line.h" #include "automation_gain_line.h" #include "automation_pan_line.h" +#include "automation_midi_cc_line.h" #include "automation_time_axis.h" #include "redirect_automation_line.h" #include "canvas_impl.h" @@ -592,6 +593,8 @@ Editor::canvas_control_point_event (GdkEvent *event, ArdourCanvas::Item* item, C type = PanAutomationControlPointItem; } else if (dynamic_cast<RedirectAutomationLine*> (&cp->line) != 0) { type = RedirectAutomationControlPointItem; + } else if (dynamic_cast<AutomationMidiCCLine*> (&cp->line) != 0) { + type = MidiCCAutomationControlPointItem; } else { return false; } @@ -612,6 +615,8 @@ Editor::canvas_line_event (GdkEvent *event, ArdourCanvas::Item* item, Automation type = PanAutomationLineItem; } else if (dynamic_cast<RedirectAutomationLine*> (al) != 0) { type = RedirectAutomationLineItem; + } else if (dynamic_cast<AutomationMidiCCLine*> (al) != 0) { + type = MidiCCAutomationLineItem; } else { return false; } diff --git a/gtk2_ardour/editor_items.h b/gtk2_ardour/editor_items.h index ad1d63b5bf..ddba43350a 100644 --- a/gtk2_ardour/editor_items.h +++ b/gtk2_ardour/editor_items.h @@ -38,6 +38,8 @@ enum ItemType { PanAutomationLineItem, RedirectAutomationControlPointItem, RedirectAutomationLineItem, + MidiCCAutomationControlPointItem, + MidiCCAutomationLineItem, MeterMarkerItem, TempoMarkerItem, MeterBarItem, diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc index 2f671c77eb..773c26f67d 100644 --- a/gtk2_ardour/editor_mouse.cc +++ b/gtk2_ardour/editor_mouse.cc @@ -350,6 +350,7 @@ Editor::button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType it case GainAutomationControlPointItem: case PanAutomationControlPointItem: case RedirectAutomationControlPointItem: + case MidiCCAutomationControlPointItem: commit = set_selected_track_from_click (press, op, true); if (mouse_mode != MouseRange) { commit |= set_selected_control_point_from_click (op, false); @@ -539,6 +540,7 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp case GainAutomationControlPointItem: case PanAutomationControlPointItem: case RedirectAutomationControlPointItem: + case MidiCCAutomationControlPointItem: start_control_point_grab (item, event); return true; break; @@ -546,6 +548,7 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp case GainAutomationLineItem: case PanAutomationLineItem: case RedirectAutomationLineItem: + case MidiCCAutomationLineItem: start_line_grab_from_line (item, event); return true; break; @@ -608,6 +611,7 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp case GainAutomationControlPointItem: case PanAutomationControlPointItem: case RedirectAutomationControlPointItem: + case MidiCCAutomationControlPointItem: start_control_point_grab (item, event); return true; break; @@ -622,12 +626,14 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp case GainAutomationControlPointItem: case PanAutomationControlPointItem: case RedirectAutomationControlPointItem: + case MidiCCAutomationControlPointItem: start_control_point_grab (item, event); break; case GainAutomationLineItem: case PanAutomationLineItem: case RedirectAutomationLineItem: + case MidiCCAutomationLineItem: start_line_grab_from_line (item, event); break; @@ -682,6 +688,7 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp case GainAutomationControlPointItem: case PanAutomationControlPointItem: case RedirectAutomationControlPointItem: + case MidiCCAutomationControlPointItem: start_control_point_grab (item, event); return true; break; @@ -896,6 +903,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT case GainAutomationControlPointItem: case PanAutomationControlPointItem: case RedirectAutomationControlPointItem: + case MidiCCAutomationControlPointItem: remove_control_point (item, event); break; @@ -917,6 +925,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT case GainAutomationLineItem: case PanAutomationLineItem: case RedirectAutomationLineItem: + case MidiCCAutomationLineItem: case StartSelectionTrimItem: case EndSelectionTrimItem: return true; @@ -1061,6 +1070,7 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_ case GainAutomationControlPointItem: case PanAutomationControlPointItem: case RedirectAutomationControlPointItem: + case MidiCCAutomationControlPointItem: if (mouse_mode == MouseGain || mouse_mode == MouseObject) { cp = static_cast<ControlPoint*>(item->get_data ("control_point")); cp->set_visible (true); @@ -1096,6 +1106,7 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_ case GainAutomationLineItem: case RedirectAutomationLineItem: + case MidiCCAutomationLineItem: case PanAutomationLineItem: if (mouse_mode == MouseGain || mouse_mode == MouseObject) { { @@ -1218,11 +1229,13 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_ case GainLineItem: case GainAutomationLineItem: case RedirectAutomationLineItem: + case MidiCCAutomationLineItem: case PanAutomationLineItem: case GainControlPointItem: case GainAutomationControlPointItem: case PanAutomationControlPointItem: case RedirectAutomationControlPointItem: + case MidiCCAutomationControlPointItem: /* these do not affect the current entered track state */ clear_entered_track = false; break; @@ -1254,6 +1267,7 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_ case GainAutomationControlPointItem: case PanAutomationControlPointItem: case RedirectAutomationControlPointItem: + case MidiCCAutomationControlPointItem: cp = reinterpret_cast<ControlPoint*>(item->get_data ("control_point")); if (cp->line.npoints() > 1) { if (!cp->selected) { @@ -1289,6 +1303,7 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_ case GainLineItem: case GainAutomationLineItem: case RedirectAutomationLineItem: + case MidiCCAutomationLineItem: case PanAutomationLineItem: al = reinterpret_cast<AutomationLine*> (item->get_data ("line")); { @@ -1432,6 +1447,7 @@ Editor::motion_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item case MarkerItem: case GainControlPointItem: case RedirectAutomationControlPointItem: + case MidiCCAutomationControlPointItem: case GainAutomationControlPointItem: case PanAutomationControlPointItem: case TempoMarkerItem: @@ -1442,6 +1458,7 @@ Editor::motion_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item case SelectionItem: case GainLineItem: case RedirectAutomationLineItem: + case MidiCCAutomationLineItem: case GainAutomationLineItem: case PanAutomationLineItem: case FadeInHandleItem: diff --git a/gtk2_ardour/gain_automation_time_axis.cc b/gtk2_ardour/gain_automation_time_axis.cc index 9890854d4b..509c941555 100644 --- a/gtk2_ardour/gain_automation_time_axis.cc +++ b/gtk2_ardour/gain_automation_time_axis.cc @@ -17,7 +17,7 @@ */ -#include <ardour/curve.h> +#include <ardour/automation_event.h> #include <ardour/route.h> #include <pbd/memento_command.h> @@ -33,11 +33,11 @@ using namespace Gtk; GainAutomationTimeAxisView::GainAutomationTimeAxisView (Session& s, boost::shared_ptr<Route> r, PublicEditor& e, TimeAxisView& parent, - ArdourCanvas::Canvas& canvas, const string & n, ARDOUR::Curve& c) + ArdourCanvas::Canvas& canvas, const string & n, ARDOUR::AutomationList& l) : AxisView (s), AutomationTimeAxisView (s, r, e, parent, canvas, n, X_("gain"), ""), - curve (c) + list (l) { } @@ -62,10 +62,10 @@ GainAutomationTimeAxisView::add_automation_event (ArdourCanvas::Item* item, GdkE lines.front()->view_to_model_y (y); _session.begin_reversible_command (_("add gain automation event")); - XMLNode& before = curve.get_state(); - curve.add (when, y); - XMLNode& after = curve.get_state(); - _session.commit_reversible_command (new MementoCommand<ARDOUR::Curve>(curve, &before, &after)); + XMLNode& before = list.get_state(); + list.add (when, y); + XMLNode& after = list.get_state(); + _session.commit_reversible_command (new MementoCommand<ARDOUR::AutomationList>(list, &before, &after)); _session.set_dirty (); } @@ -73,6 +73,6 @@ void GainAutomationTimeAxisView::set_automation_state (AutoState state) { if (!ignore_state_request) { - route->set_gain_automation_state (state); + route->set_parameter_automation_state (ParamID(GainAutomation), state); } } diff --git a/gtk2_ardour/gain_automation_time_axis.h b/gtk2_ardour/gain_automation_time_axis.h index 25a97a1a97..3f07be4ace 100644 --- a/gtk2_ardour/gain_automation_time_axis.h +++ b/gtk2_ardour/gain_automation_time_axis.h @@ -24,8 +24,7 @@ #include "automation_time_axis.h" namespace ARDOUR { - class Redirect; - class Curve; + class AutomationList; } class GainAutomationTimeAxisView : public AutomationTimeAxisView @@ -37,16 +36,16 @@ class GainAutomationTimeAxisView : public AutomationTimeAxisView TimeAxisView& parent_axis, ArdourCanvas::Canvas& canvas, const string & name, - ARDOUR::Curve&); + ARDOUR::AutomationList&); ~GainAutomationTimeAxisView(); void add_automation_event (ArdourCanvas::Item *item, GdkEvent *event, nframes_t, double); private: - ARDOUR::Curve& curve; + ARDOUR::AutomationList& list; - void automation_changed (); + void automation_changed (); void set_automation_state (ARDOUR::AutoState); }; diff --git a/gtk2_ardour/gain_meter.cc b/gtk2_ardour/gain_meter.cc index f67682019e..a4eea61bfa 100644 --- a/gtk2_ardour/gain_meter.cc +++ b/gtk2_ardour/gain_meter.cc @@ -166,13 +166,17 @@ GainMeter::GainMeter (boost::shared_ptr<IO> io, Session& s) using namespace Menu_Helpers; gain_astate_menu.items().push_back (MenuElem (_("Manual"), - bind (mem_fun (*_io, &IO::set_gain_automation_state), (AutoState) Off))); + bind (mem_fun (*_io, &IO::set_parameter_automation_state), + ParamID(GainAutomation), (AutoState) Off))); gain_astate_menu.items().push_back (MenuElem (_("Play"), - bind (mem_fun (*_io, &IO::set_gain_automation_state), (AutoState) Play))); + bind (mem_fun (*_io, &IO::set_parameter_automation_state), + ParamID(GainAutomation), (AutoState) Play))); gain_astate_menu.items().push_back (MenuElem (_("Write"), - bind (mem_fun (*_io, &IO::set_gain_automation_state), (AutoState) Write))); + bind (mem_fun (*_io, &IO::set_parameter_automation_state), + ParamID(GainAutomation), (AutoState) Write))); gain_astate_menu.items().push_back (MenuElem (_("Touch"), - bind (mem_fun (*_io, &IO::set_gain_automation_state), (AutoState) Touch))); + bind (mem_fun (*_io, &IO::set_parameter_automation_state), + ParamID(GainAutomation), (AutoState) Touch))); gain_astyle_menu.items().push_back (MenuElem (_("Trim"))); gain_astyle_menu.items().push_back (MenuElem (_("Abs"))); @@ -183,8 +187,8 @@ GainMeter::GainMeter (boost::shared_ptr<IO> io, Session& s) gain_automation_style_button.signal_button_press_event().connect (mem_fun(*this, &GainMeter::gain_automation_style_button_event), false); gain_automation_state_button.signal_button_press_event().connect (mem_fun(*this, &GainMeter::gain_automation_state_button_event), false); - r->gain_automation_curve().automation_state_changed.connect (mem_fun(*this, &GainMeter::gain_automation_state_changed)); - r->gain_automation_curve().automation_style_changed.connect (mem_fun(*this, &GainMeter::gain_automation_style_changed)); + r->gain_automation().automation_state_changed.connect (mem_fun(*this, &GainMeter::gain_automation_state_changed)); + r->gain_automation().automation_style_changed.connect (mem_fun(*this, &GainMeter::gain_automation_style_changed)); fader_vbox->pack_start (gain_automation_state_button, false, false, 0); gain_automation_state_changed (); @@ -668,7 +672,7 @@ GainMeter::set_fader_name (const char * name) void GainMeter::update_gain_sensitive () { - static_cast<Gtkmm2ext::SliderController*>(gain_slider)->set_sensitive (!(_io->gain_automation_state() & Play)); + static_cast<Gtkmm2ext::SliderController*>(gain_slider)->set_sensitive (!(_io->gain_automation().automation_state() & Play)); } @@ -811,14 +815,14 @@ GainMeter::meter_point_clicked () gint GainMeter::start_gain_touch (GdkEventButton* ev) { - _io->start_gain_touch (); + _io->gain_automation().start_touch (); return FALSE; } gint GainMeter::end_gain_touch (GdkEventButton* ev) { - _io->end_gain_touch (); + _io->gain_automation().stop_touch (); return FALSE; } @@ -922,10 +926,10 @@ GainMeter::gain_automation_style_changed () // Route* _route = dynamic_cast<Route*>(&_io); switch (_width) { case Wide: - gain_automation_style_button.set_label (astyle_string(_io->gain_automation_curve().automation_style())); + gain_automation_style_button.set_label (astyle_string(_io->gain_automation().automation_style())); break; case Narrow: - gain_automation_style_button.set_label (short_astyle_string(_io->gain_automation_curve().automation_style())); + gain_automation_style_button.set_label (short_astyle_string(_io->gain_automation().automation_style())); break; } } @@ -940,14 +944,14 @@ GainMeter::gain_automation_state_changed () switch (_width) { case Wide: - gain_automation_state_button.set_label (astate_string(_io->gain_automation_curve().automation_state())); + gain_automation_state_button.set_label (astate_string(_io->gain_automation().automation_state())); break; case Narrow: - gain_automation_state_button.set_label (short_astate_string(_io->gain_automation_curve().automation_state())); + gain_automation_state_button.set_label (short_astate_string(_io->gain_automation().automation_state())); break; } - x = (_io->gain_automation_state() != Off); + x = (_io->gain_automation().automation_state() != Off); if (gain_automation_state_button.get_active() != x) { ignore_toggle = true; diff --git a/gtk2_ardour/ladspa_pluginui.cc b/gtk2_ardour/ladspa_pluginui.cc index cd585d073a..25c497a377 100644 --- a/gtk2_ardour/ladspa_pluginui.cc +++ b/gtk2_ardour/ladspa_pluginui.cc @@ -177,7 +177,7 @@ LadspaPluginUI::build () /* Don't show latency control ports */ - if (plugin->describe_parameter (i) == X_("latency")) { + if (plugin->describe_parameter (ParamID(PluginAutomation, i)) == X_("latency")) { continue; } @@ -324,7 +324,8 @@ LadspaPluginUI::automation_state_changed (ControlUI* cui) { /* update button label */ - switch (insert->get_port_automation_state (cui->port_index) & (Off|Play|Touch|Write)) { + switch (insert->get_parameter_automation_state (ParamID(PluginAutomation, cui->port_index)) + & (Off|Play|Touch|Write)) { case Off: cui->automate_button.set_label (_("Manual")); break; @@ -491,7 +492,7 @@ LadspaPluginUI::build_control_ui (guint32 port_index, PBD::Controllable* mcontro automation_state_changed (control_ui); plugin->ParameterChanged.connect (bind (mem_fun(*this, &LadspaPluginUI::parameter_changed), control_ui)); - insert->automation_list (port_index).automation_state_changed.connect + insert->automation_list (ParamID(PluginAutomation, port_index))->automation_state_changed.connect (bind (mem_fun(*this, &LadspaPluginUI::automation_state_changed), control_ui)); } else if (plugin->parameter_is_output (port_index)) { @@ -548,13 +549,13 @@ LadspaPluginUI::build_control_ui (guint32 port_index, PBD::Controllable* mcontro void LadspaPluginUI::start_touch (LadspaPluginUI::ControlUI* cui) { - insert->automation_list (cui->port_index).start_touch (); + insert->automation_list (ParamID(PluginAutomation, cui->port_index))->start_touch (); } void LadspaPluginUI::stop_touch (LadspaPluginUI::ControlUI* cui) { - insert->automation_list (cui->port_index).stop_touch (); + insert->automation_list (ParamID(PluginAutomation, cui->port_index))->stop_touch (); } void @@ -585,7 +586,7 @@ LadspaPluginUI::astate_clicked (ControlUI* cui, uint32_t port) void LadspaPluginUI::set_automation_state (AutoState state, ControlUI* cui) { - insert->set_port_automation_state (cui->port_index, state); + insert->set_parameter_automation_state (ParamID(PluginAutomation, cui->port_index), state); } void @@ -601,7 +602,7 @@ LadspaPluginUI::control_adjustment_changed (ControlUI* cui) value = exp(value); } - insert->set_parameter (cui->port_index, (float) value); + insert->set_parameter (ParamID(PluginAutomation, cui->port_index), (float) value); } void @@ -656,7 +657,7 @@ void LadspaPluginUI::control_port_toggled (ControlUI* cui) { if (!cui->ignore_change) { - insert->set_parameter (cui->port_index, cui->button->get_active()); + insert->set_parameter (ParamID(PluginAutomation, cui->port_index), cui->button->get_active()); } } @@ -666,7 +667,7 @@ LadspaPluginUI::control_combo_changed (ControlUI* cui) if (!cui->ignore_change) { string value = cui->combo->get_active_text(); std::map<string,float> mapping = *cui->combo_map; - insert->set_parameter (cui->port_index, mapping[value]); + insert->set_parameter (ParamID(PluginAutomation, cui->port_index), mapping[value]); } } diff --git a/gtk2_ardour/midi_controller_time_axis.cc b/gtk2_ardour/midi_controller_time_axis.cc new file mode 100644 index 0000000000..a3dcb0f508 --- /dev/null +++ b/gtk2_ardour/midi_controller_time_axis.cc @@ -0,0 +1,81 @@ +/* + Copyright (C) 2003 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include <ardour/automation_event.h> +#include <ardour/route.h> +#include <pbd/memento_command.h> + +#include "midi_controller_time_axis.h" +#include "automation_line.h" +#include "canvas.h" + +#include "i18n.h" + +using namespace ARDOUR; +using namespace PBD; +using namespace Gtk; + +MidiControllerTimeAxisView::MidiControllerTimeAxisView (Session& s, boost::shared_ptr<Route> r, + PublicEditor& e, TimeAxisView& parent, + ArdourCanvas::Canvas& canvas, const string & n, + ParamID param, ARDOUR::AutomationList& l) + + : AxisView (s), + AutomationTimeAxisView (s, r, e, parent, canvas, n, param.to_string(), ""), + _list (l), + _param (param) +{ +} + +MidiControllerTimeAxisView::~MidiControllerTimeAxisView () +{ +} + +void +MidiControllerTimeAxisView::add_automation_event (ArdourCanvas::Item* item, GdkEvent* event, nframes_t when, double y) +{ + double x = 0; + + canvas_display->w2i (x, y); + + /* compute vertical fractional position */ + + y = 1.0 - (y / height); + + /* map using line */ + + lines.front()->view_to_model_y (y); + + _session.begin_reversible_command (_("add midi controller automation event")); + XMLNode& before = _list.get_state(); + _list.add (when, y); + XMLNode& after = _list.get_state(); + _session.commit_reversible_command (new MementoCommand<ARDOUR::AutomationList>(_list, &before, &after)); + _session.set_dirty (); +} + +void +MidiControllerTimeAxisView::set_automation_state (AutoState state) +{ + if (!ignore_state_request) { + cerr << "FIXME: set midi controller automation state" << endl; + //route->set_midi_controller_state (state); + } +} + diff --git a/gtk2_ardour/midi_controller_time_axis.h b/gtk2_ardour/midi_controller_time_axis.h new file mode 100644 index 0000000000..78f3c12c1a --- /dev/null +++ b/gtk2_ardour/midi_controller_time_axis.h @@ -0,0 +1,54 @@ +/* + Copyright (C) 2000-2007 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef __ardour_gtk_midi_controller_time_axis_h__ +#define __ardour_gtk_midi_controller_time_axis_h__ + +#include "canvas.h" +#include "automation_time_axis.h" + +namespace ARDOUR { + class AutomationList; +} + +class MidiControllerTimeAxisView : public AutomationTimeAxisView +{ + public: + MidiControllerTimeAxisView (ARDOUR::Session&, + boost::shared_ptr<ARDOUR::Route>, + PublicEditor&, + TimeAxisView& parent_axis, + ArdourCanvas::Canvas& canvas, + const string & name, + ARDOUR::ParamID param, + ARDOUR::AutomationList&); + + ~MidiControllerTimeAxisView(); + + void add_automation_event (ArdourCanvas::Item *item, GdkEvent *event, nframes_t, double); + + private: + ARDOUR::AutomationList& _list; + ARDOUR::ParamID _param; + + void automation_changed (); + void set_automation_state (ARDOUR::AutoState); +}; + +#endif /* __ardour_gtk_midi_controller_time_axis_h__ */ diff --git a/gtk2_ardour/midi_time_axis.cc b/gtk2_ardour/midi_time_axis.cc index dd008bd9c5..960ca36af9 100644 --- a/gtk2_ardour/midi_time_axis.cc +++ b/gtk2_ardour/midi_time_axis.cc @@ -48,6 +48,7 @@ #include "ardour_ui.h" #include "midi_time_axis.h" #include "automation_time_axis.h" +#include "automation_midi_cc_line.h" #include "canvas_impl.h" #include "crossfade_view.h" #include "enums.h" @@ -61,6 +62,7 @@ #include "public_editor.h" #include "redirect_automation_line.h" #include "redirect_automation_time_axis.h" +#include "midi_controller_time_axis.h" #include "region_view.h" #include "rgb_macros.h" #include "selection.h" @@ -147,30 +149,67 @@ MidiTimeAxisView::hide () } void -MidiTimeAxisView::set_state (const XMLNode& node) +MidiTimeAxisView::build_automation_action_menu () { - const XMLProperty *prop; + using namespace Menu_Helpers; + + RouteTimeAxisView::build_automation_action_menu (); + + MenuList& automation_items = automation_action_menu->items(); - TimeAxisView::set_state (node); + automation_items.push_back (SeparatorElem()); + + automation_items.push_back (MenuElem (_("Controller..."), + mem_fun(*this, &MidiTimeAxisView::add_controller_track))); +} + +/** Prompt for a controller with a dialog and add an automation track for it + */ +void +MidiTimeAxisView::add_controller_track() +{ + /* TODO: fancy controller selection dialog here... */ + + ParamID param(MidiCCAutomation, 7); + create_automation_child(param); +} + +void +MidiTimeAxisView::create_automation_child (ParamID param) +{ + if (param.type() == MidiCCAutomation) { - if ((prop = node.property ("shown_editor")) != 0) { - if (prop->value() == "no") { - _marked_for_display = false; - } else { - _marked_for_display = true; - } + /* FIXME: this all probably leaks */ + + ARDOUR::AutomationList* al = _route->automation_list(param); + + if (!al) + al = new ARDOUR::AutomationList(param, 0, 127, 64); + + _route->add_automation_parameter(al); + + MidiControllerTimeAxisView* track = new MidiControllerTimeAxisView (_session, + _route, + editor, + *this, + parent_canvas, + _route->describe_parameter(param), + param, + *al); + + AutomationMidiCCLine* line = new AutomationMidiCCLine (param.to_string(), + *track, + *track->canvas_display, + *al); + + line->set_line_color (Config->canvasvar_AutomationLine.get()); + + track->add_line(*line); + + add_automation_child(param, track); + } else { - _marked_for_display = true; - } - - XMLNodeList nlist = node.children(); - XMLNodeConstIterator niter; - XMLNode *child_node; - - for (niter = nlist.begin(); niter != nlist.end(); ++niter) { - child_node = *niter; - - // uh... do stuff.. + error << "MidiTimeAxisView: unknown automation child " << param.to_string() << endmsg; } } @@ -205,9 +244,3 @@ MidiTimeAxisView::route_active_changed () } } -XMLNode* -MidiTimeAxisView::get_child_xml_node (const string & childname) -{ - return RouteUI::get_child_xml_node (childname); -} - diff --git a/gtk2_ardour/midi_time_axis.h b/gtk2_ardour/midi_time_axis.h index 17b3d72794..3b06411418 100644 --- a/gtk2_ardour/midi_time_axis.h +++ b/gtk2_ardour/midi_time_axis.h @@ -61,11 +61,14 @@ class MidiTimeAxisView : public RouteTimeAxisView /* overridden from parent to store display state */ guint32 show_at (double y, int& nth, Gtk::VBox *parent); void hide (); - - void set_state (const XMLNode&); - XMLNode* get_child_xml_node (const string & childname); + + void add_controller_track (); + void create_automation_child (ARDOUR::ParamID param); private: + + void build_automation_action_menu (); + void route_active_changed (); void add_insert_to_subplugin_menu (ARDOUR::Insert *); diff --git a/gtk2_ardour/mixer_strip.cc b/gtk2_ardour/mixer_strip.cc index 0c99dc7401..cb27ef4e88 100644 --- a/gtk2_ardour/mixer_strip.cc +++ b/gtk2_ardour/mixer_strip.cc @@ -435,8 +435,8 @@ MixerStrip::set_width (Width w, void* owner) ((Gtk::Label*)comment_button.get_child())->set_text (_("*comments*")); } - ((Gtk::Label*)gpm.gain_automation_style_button.get_child())->set_text (gpm.astyle_string(_route->gain_automation_curve().automation_style())); - ((Gtk::Label*)gpm.gain_automation_state_button.get_child())->set_text (gpm.astate_string(_route->gain_automation_curve().automation_state())); + ((Gtk::Label*)gpm.gain_automation_style_button.get_child())->set_text (gpm.astyle_string(_route->gain_automation().automation_style())); + ((Gtk::Label*)gpm.gain_automation_state_button.get_child())->set_text (gpm.astate_string(_route->gain_automation().automation_state())); ((Gtk::Label*)panners.pan_automation_style_button.get_child())->set_text (panners.astyle_string(_route->panner().automation_style())); ((Gtk::Label*)panners.pan_automation_state_button.get_child())->set_text (panners.astate_string(_route->panner().automation_state())); Gtkmm2ext::set_size_request_to_display_given_text (name_button, "long", 2, 2); @@ -457,8 +457,8 @@ MixerStrip::set_width (Width w, void* owner) ((Gtk::Label*)comment_button.get_child())->set_text (_("*Cmt*")); } - ((Gtk::Label*)gpm.gain_automation_style_button.get_child())->set_text (gpm.short_astyle_string(_route->gain_automation_curve().automation_style())); - ((Gtk::Label*)gpm.gain_automation_state_button.get_child())->set_text (gpm.short_astate_string(_route->gain_automation_curve().automation_state())); + ((Gtk::Label*)gpm.gain_automation_style_button.get_child())->set_text (gpm.short_astyle_string(_route->gain_automation().automation_style())); + ((Gtk::Label*)gpm.gain_automation_state_button.get_child())->set_text (gpm.short_astate_string(_route->gain_automation().automation_state())); ((Gtk::Label*)panners.pan_automation_style_button.get_child())->set_text (panners.short_astyle_string(_route->panner().automation_style())); ((Gtk::Label*)panners.pan_automation_state_button.get_child())->set_text (panners.short_astate_string(_route->panner().automation_state())); Gtkmm2ext::set_size_request_to_display_given_text (name_button, "longest label", 2, 2); diff --git a/gtk2_ardour/pan_automation_time_axis.cc b/gtk2_ardour/pan_automation_time_axis.cc index c008a10ff0..1199982b5d 100644 --- a/gtk2_ardour/pan_automation_time_axis.cc +++ b/gtk2_ardour/pan_automation_time_axis.cc @@ -55,6 +55,11 @@ PanAutomationTimeAxisView::add_automation_event (ArdourCanvas::Item* item, GdkEv { if (lines.empty()) { /* no data, possibly caused by no outputs/inputs */ + Gtkmm2ext::PopUp* msg = new Gtkmm2ext::PopUp (Gtk::WIN_POS_MOUSE, 5000, true); + + msg->set_text (_("Pan automation track has no lines, unable to add point\n(is track pannable?)")); + msg->touch (); + return; } diff --git a/gtk2_ardour/plugin_ui.h b/gtk2_ardour/plugin_ui.h index a505f80576..e583f11dce 100644 --- a/gtk2_ardour/plugin_ui.h +++ b/gtk2_ardour/plugin_ui.h @@ -136,6 +136,10 @@ class LadspaPluginUI : public PlugUIBase, public Gtk::VBox static const int32_t initial_output_rows = 1; static const int32_t initial_output_cols = 4; + /* TODO: pull this out of PluginUI and make it generic. + * Sticking this in the track controls of an automation track would + * make a handy touch controller for anything. + */ struct ControlUI : public Gtk::HBox { uint32_t port_index; diff --git a/gtk2_ardour/redirect_automation_line.cc b/gtk2_ardour/redirect_automation_line.cc index 89b6fb4f2a..5680a8b98f 100644 --- a/gtk2_ardour/redirect_automation_line.cc +++ b/gtk2_ardour/redirect_automation_line.cc @@ -33,7 +33,7 @@ using namespace std; using namespace ARDOUR; using namespace PBD; -RedirectAutomationLine::RedirectAutomationLine (const string & name, Insert& i, uint32_t port, Session& s, +RedirectAutomationLine::RedirectAutomationLine (const string & name, Insert& i, ParamID param, Session& s, TimeAxisView& tv, ArdourCanvas::Group& parent, @@ -42,7 +42,7 @@ RedirectAutomationLine::RedirectAutomationLine (const string & name, Insert& i, : AutomationLine (name, tv, parent, l), session (s), _insert (i), - _port (port) + _param (param) { set_verbose_cursor_uses_gain_mapping (false); @@ -54,7 +54,7 @@ RedirectAutomationLine::RedirectAutomationLine (const string & name, Insert& i, /*NOTREACHED*/ } - pi->plugin()->get_parameter_descriptor (_port, desc); + pi->plugin()->get_parameter_descriptor (_param, desc); upper = desc.upper; lower = desc.lower; diff --git a/gtk2_ardour/redirect_automation_line.h b/gtk2_ardour/redirect_automation_line.h index 33d411e48e..d0e3aa8897 100644 --- a/gtk2_ardour/redirect_automation_line.h +++ b/gtk2_ardour/redirect_automation_line.h @@ -34,10 +34,10 @@ class TimeAxisView; class RedirectAutomationLine : public AutomationLine { public: - RedirectAutomationLine (const string & name, ARDOUR::Insert&, uint32_t port, ARDOUR::Session&, TimeAxisView&, + RedirectAutomationLine (const string & name, ARDOUR::Insert&, ARDOUR::ParamID param, ARDOUR::Session&, TimeAxisView&, ArdourCanvas::Group& parent, ARDOUR::AutomationList&); - uint32_t port() const { return _port; } + ARDOUR::ParamID param() const { return _param; } ARDOUR::Insert& insert() const { return _insert; } string get_verbose_cursor_string (float); @@ -45,7 +45,7 @@ class RedirectAutomationLine : public AutomationLine private: ARDOUR::Session& session; ARDOUR::Insert& _insert; - uint32_t _port; + ARDOUR::ParamID _param; float upper; float lower; float range; diff --git a/gtk2_ardour/redirect_automation_time_axis.cc b/gtk2_ardour/redirect_automation_time_axis.cc index 9df0bb9e0c..bb7937cdf7 100644 --- a/gtk2_ardour/redirect_automation_time_axis.cc +++ b/gtk2_ardour/redirect_automation_time_axis.cc @@ -34,12 +34,12 @@ using namespace Gtk; RedirectAutomationTimeAxisView::RedirectAutomationTimeAxisView (Session& s, boost::shared_ptr<Route> r, PublicEditor& e, TimeAxisView& parent, Canvas& canvas, std::string n, - uint32_t prt, Insert& i, string state_name) + ParamID p, Insert& i, string state_name) : AxisView (s), AutomationTimeAxisView (s, r, e, parent, canvas, n, state_name, i.name()), insert (i), - port (prt) + param (p) { char buf[32]; @@ -53,7 +53,7 @@ RedirectAutomationTimeAxisView::RedirectAutomationTimeAxisView (Session& s, boos kids = xml_node->children (); - snprintf (buf, sizeof(buf), "Port_%" PRIu32, port); + snprintf (buf, sizeof(buf), "Port_%" PRIu32, param.id()); for (iter = kids.begin(); iter != kids.end(); ++iter) { if ((*iter)->name() == buf) { @@ -91,17 +91,17 @@ RedirectAutomationTimeAxisView::add_automation_event (ArdourCanvas::Item* item, /* map to model space */ if (!lines.empty()) { - AutomationList& alist (insert.automation_list(port)); + AutomationList* alist (insert.automation_list(param, true)); string description = _("add automation event to "); - description += insert.describe_parameter (port); + description += insert.describe_parameter (param); lines.front()->view_to_model_y (y); _session.begin_reversible_command (description); - XMLNode &before = alist.get_state(); - alist.add (when, y); - XMLNode &after = alist.get_state(); - _session.add_command(new MementoCommand<AutomationList>(alist, &before, &after)); + XMLNode &before = alist->get_state(); + alist->add (when, y); + XMLNode &after = alist->get_state(); + _session.add_command(new MementoCommand<AutomationList>(*alist, &before, &after)); _session.commit_reversible_command (); _session.set_dirty (); } @@ -146,7 +146,7 @@ RedirectAutomationTimeAxisView::update_extra_xml_shown (bool editor_shown) XMLNodeConstIterator i; XMLNode * port_node = 0; - snprintf (buf, sizeof(buf), "Port_%" PRIu32, port); + snprintf (buf, sizeof(buf), "Port_%" PRIu32, param.id()); for (i = nlist.begin(); i != nlist.end(); ++i) { if ((*i)->name() == buf) { @@ -168,6 +168,6 @@ void RedirectAutomationTimeAxisView::set_automation_state (AutoState state) { if (!ignore_state_request) { - insert.automation_list (port).set_automation_state (state); + insert.automation_list (param, true)->set_automation_state (state); } } diff --git a/gtk2_ardour/redirect_automation_time_axis.h b/gtk2_ardour/redirect_automation_time_axis.h index eceed7446a..d87e4faca5 100644 --- a/gtk2_ardour/redirect_automation_time_axis.h +++ b/gtk2_ardour/redirect_automation_time_axis.h @@ -24,6 +24,7 @@ #include "canvas.h" #include "automation_time_axis.h" +#include <ardour/param_id.h> namespace ARDOUR { class Redirect; @@ -38,7 +39,7 @@ class RedirectAutomationTimeAxisView : public AutomationTimeAxisView TimeAxisView& parent, ArdourCanvas::Canvas& canvas, std::string name, - uint32_t port, + ARDOUR::ParamID param, ARDOUR::Insert& i, std::string state_name); @@ -52,7 +53,7 @@ class RedirectAutomationTimeAxisView : public AutomationTimeAxisView private: ARDOUR::Insert& insert; - uint32_t port; + ARDOUR::ParamID param; XMLNode *xml_node; void ensure_xml_node(); diff --git a/gtk2_ardour/redirect_box.cc b/gtk2_ardour/redirect_box.cc index 8749ab12db..0402b0e1f6 100644 --- a/gtk2_ardour/redirect_box.cc +++ b/gtk2_ardour/redirect_box.cc @@ -1050,7 +1050,7 @@ RedirectBox::edit_insert (boost::shared_ptr<Insert> insert) } } - if ((send = boost::dynamic_pointer_cast<Send> (send)) == 0) { + if ((send = boost::dynamic_pointer_cast<Send> (send)) != 0) { if (!_session.engine().connected()) { return; diff --git a/gtk2_ardour/region_gain_line.cc b/gtk2_ardour/region_gain_line.cc index e935d3adc2..25ba903ca8 100644 --- a/gtk2_ardour/region_gain_line.cc +++ b/gtk2_ardour/region_gain_line.cc @@ -38,8 +38,8 @@ using namespace std; using namespace ARDOUR; using namespace PBD; -AudioRegionGainLine::AudioRegionGainLine (const string & name, Session& s, AudioRegionView& r, ArdourCanvas::Group& parent, Curve& c) - : AutomationLine (name, r.get_time_axis_view(), parent, c), +AudioRegionGainLine::AudioRegionGainLine (const string & name, Session& s, AudioRegionView& r, ArdourCanvas::Group& parent, AutomationList& l) + : AutomationLine (name, r.get_time_axis_view(), parent, l), session (s), rv (r) { diff --git a/gtk2_ardour/region_gain_line.h b/gtk2_ardour/region_gain_line.h index 801fe09bad..259615aa39 100644 --- a/gtk2_ardour/region_gain_line.h +++ b/gtk2_ardour/region_gain_line.h @@ -35,7 +35,7 @@ class AudioRegionView; class AudioRegionGainLine : public AutomationLine { public: - AudioRegionGainLine (const string & name, ARDOUR::Session&, AudioRegionView&, ArdourCanvas::Group& parent, ARDOUR::Curve&); + AudioRegionGainLine (const string & name, ARDOUR::Session&, AudioRegionView&, ArdourCanvas::Group& parent, ARDOUR::AutomationList&); void view_to_model_y (double&); void model_to_view_y (double&); diff --git a/gtk2_ardour/route_time_axis.cc b/gtk2_ardour/route_time_axis.cc index 900064a763..f113724cf5 100644 --- a/gtk2_ardour/route_time_axis.cc +++ b/gtk2_ardour/route_time_axis.cc @@ -23,6 +23,7 @@ #include <algorithm> #include <string> #include <vector> +#include <utility> #include <sigc++/bind.h> @@ -50,6 +51,7 @@ #include <ardour/session.h> #include <ardour/session_playlist.h> #include <ardour/utils.h> +#include <ardour/param_id.h> #include "ardour_ui.h" #include "route_time_axis.h" @@ -80,6 +82,7 @@ using namespace ARDOUR; using namespace PBD; using namespace Gtk; using namespace Editing; +using namespace sigc; RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session& sess, boost::shared_ptr<Route> rt, Canvas& canvas) @@ -252,6 +255,58 @@ RouteTimeAxisView::playlist_modified () { } +void +RouteTimeAxisView::set_state (const XMLNode& node) +{ + const XMLProperty *prop; + + TimeAxisView::set_state (node); + + if ((prop = node.property ("shown_editor")) != 0) { + if (prop->value() == "no") { + _marked_for_display = false; + } else { + _marked_for_display = true; + } + } else { + _marked_for_display = true; + } + + XMLNodeList nlist = node.children(); + XMLNodeConstIterator niter; + XMLNode *child_node; + + _show_automation.clear(); + + for (niter = nlist.begin(); niter != nlist.end(); ++niter) { + child_node = *niter; + + ParamID param(child_node->name()); + + if (param) { + + cerr << "RTAV::set_state parameter: " << param.to_string() << endl; + + XMLProperty* prop = child_node->property ("shown"); + + if (_automation_tracks.find(param) == _automation_tracks.end()) + create_automation_child(param); + + if (prop != 0 && prop->value() == "yes") + _show_automation.insert(ParamID(GainAutomation)); + + } else { + cerr << "RTAV: no parameter " << child_node->name() << endl; + } + } +} + +XMLNode* +RouteTimeAxisView::get_child_xml_node (const string & childname) +{ + return RouteUI::get_child_xml_node (childname); +} + gint RouteTimeAxisView::edit_click (GdkEventButton *ev) { @@ -386,6 +441,24 @@ RouteTimeAxisView::build_automation_action_menu () mem_fun(*this, &RouteTimeAxisView::hide_all_automation))); automation_items.push_back (MenuElem (_("Plugins"), subplugin_menu)); + + map<ARDOUR::ParamID, RouteAutomationNode*>::iterator i; + for (i = _automation_tracks.begin(); i != _automation_tracks.end(); ++i) { + + automation_items.push_back (SeparatorElem()); + + if ( ! i->second->menu_item) { + automation_items.push_back(CheckMenuElem (_route->describe_parameter(i->second->param), + bind (mem_fun(*this, &RouteTimeAxisView::toggle_automation_track), i->second->param))); + + i->second->menu_item = static_cast<Gtk::CheckMenuItem*>(&automation_items.back()); + + } else { + automation_items.push_back (*i->second->menu_item); + } + + i->second->menu_item->set_active(show_automation(i->second->param)); + } } void @@ -1092,6 +1165,33 @@ RouteTimeAxisView::get_inverted_selectables (Selection& sel, list<Selectable*>& return; } +bool +RouteTimeAxisView::show_automation(ParamID param) +{ + return (_show_automation.find(param) != _show_automation.end()); +} + +/** Retuns NULL if track for \a param doesn't exist. + */ +RouteTimeAxisView::RouteAutomationNode* +RouteTimeAxisView::automation_track(ParamID param) +{ + map<ARDOUR::ParamID, RouteAutomationNode*>::iterator i = _automation_tracks.find(param); + + if (i != _automation_tracks.end()) + return i->second; + else + return NULL; +} + +/** Shorthand for GainAutomation, etc. + */ +RouteTimeAxisView::RouteAutomationNode* +RouteTimeAxisView::automation_track(AutomationType type) +{ + return automation_track(ParamID(type)); +} + RouteGroup* RouteTimeAxisView::edit_group() const { @@ -1380,9 +1480,69 @@ RouteTimeAxisView::color_handler () } void +RouteTimeAxisView::toggle_automation_track (ParamID param) +{ + RouteAutomationNode* node = automation_track(param); + + if (!node) + return; + + bool showit = node->menu_item->get_active(); + + if (showit != node->track->marked_for_display()) { + if (showit) { + node->track->set_marked_for_display (true); + node->track->canvas_display->show(); + node->track->get_state_node()->add_property ("shown", X_("yes")); + } else { + node->track->set_marked_for_display (false); + node->track->hide (); + node->track->get_state_node()->add_property ("shown", X_("no")); + } + + /* now trigger a redisplay */ + + if (!no_redraw) { + _route->gui_changed (X_("track_height"), (void *) 0); /* EMIT_SIGNAL */ + } + } +} + +void +RouteTimeAxisView::automation_track_hidden (ParamID param) +{ + RouteAutomationNode* ran = automation_track(param); + if (!ran) + return; + + _show_automation.erase(param); + ran->track->get_state_node()->add_property (X_("shown"), X_("no")); + + if (ran->menu_item && !_hidden) { + ran->menu_item->set_active (false); + } + + _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */ +} + + +void RouteTimeAxisView::show_all_automation () { no_redraw = true; + + /* Show our automation */ + + map<ARDOUR::ParamID, RouteAutomationNode*>::iterator i; + for (i = _automation_tracks.begin(); i != _automation_tracks.end(); ++i) { + i->second->track->set_marked_for_display (true); + i->second->track->canvas_display->show(); + i->second->track->get_state_node()->add_property ("shown", X_("yes")); + i->second->menu_item->set_active(true); + } + + + /* Show insert automation */ for (list<InsertAutomationInfo*>::iterator i = insert_automation.begin(); i != insert_automation.end(); ++i) { for (vector<InsertAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) { @@ -1396,6 +1556,9 @@ RouteTimeAxisView::show_all_automation () no_redraw = false; + + /* Redraw */ + _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */ } @@ -1403,6 +1566,22 @@ void RouteTimeAxisView::show_existing_automation () { no_redraw = true; + + /* Show our automation */ + + map<ARDOUR::ParamID, RouteAutomationNode*>::iterator i; + for (i = _automation_tracks.begin(); i != _automation_tracks.end(); ++i) { + // FIXME: only shown if /first/ line has points + if (!i->second->track->lines.empty() && i->second->track->lines[0]->npoints() > 0) { + i->second->track->set_marked_for_display (true); + i->second->track->canvas_display->show(); + i->second->track->get_state_node()->add_property ("shown", X_("yes")); + i->second->menu_item->set_active(true); + } + } + + + /* Show insert automation */ for (list<InsertAutomationInfo*>::iterator i = insert_automation.begin(); i != insert_automation.end(); ++i) { for (vector<InsertAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) { @@ -1477,7 +1656,7 @@ RouteTimeAxisView::remove_ran (InsertAutomationNode* ran) } RouteTimeAxisView::InsertAutomationNode* -RouteTimeAxisView::find_insert_automation_node (boost::shared_ptr<Insert> insert, uint32_t what) +RouteTimeAxisView::find_insert_automation_node (boost::shared_ptr<Insert> insert, ParamID what) { for (list<InsertAutomationInfo*>::iterator i = insert_automation.begin(); i != insert_automation.end(); ++i) { @@ -1514,7 +1693,7 @@ legalize_for_xml_node (string str) void -RouteTimeAxisView::add_insert_automation_curve (boost::shared_ptr<Insert> insert, uint32_t what) +RouteTimeAxisView::add_insert_automation_curve (boost::shared_ptr<Insert> insert, ParamID what) { RedirectAutomationLine* ral; string name; @@ -1538,13 +1717,13 @@ RouteTimeAxisView::add_insert_automation_curve (boost::shared_ptr<Insert> insert /* 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 (insert->name()).c_str(), what); + snprintf (state_name, sizeof (state_name), "Redirect-%s-%" PRIu32, legalize_for_xml_node (insert->name()).c_str(), what.id()); ran->view = new RedirectAutomationTimeAxisView (_session, _route, editor, *this, parent_canvas, name, what, *insert, state_name); ral = new RedirectAutomationLine (name, *insert, what, _session, *ran->view, - *ran->view->canvas_display, insert->automation_list (what)); + *ran->view->canvas_display, *insert->automation_list (what, true)); ral->set_line_color (Config->canvasvar_RedirectAutomationLine.get()); ral->queue_reset (); @@ -1583,12 +1762,12 @@ RouteTimeAxisView::insert_automation_track_hidden (RouteTimeAxisView::InsertAuto void RouteTimeAxisView::add_existing_insert_automation_curves (boost::shared_ptr<Insert> insert) { - set<uint32_t> s; + set<ParamID> s; RedirectAutomationLine *ral; insert->what_has_visible_automation (s); - for (set<uint32_t>::iterator i = s.begin(); i != s.end(); ++i) { + for (set<ParamID>::iterator i = s.begin(); i != s.end(); ++i) { if ((ral = find_insert_automation_curve (insert, *i)) != 0) { ral->queue_reset (); @@ -1599,14 +1778,47 @@ RouteTimeAxisView::add_existing_insert_automation_curves (boost::shared_ptr<Inse } void +RouteTimeAxisView::add_automation_child(ParamID param, AutomationTimeAxisView* track) +{ + using namespace Menu_Helpers; + + XMLProperty* prop; + + add_child (track); + + track->Hiding.connect (bind (mem_fun (*this, &RouteTimeAxisView::automation_track_hidden), param)); + + bool hideit = true; + + XMLNode* node; + + if ((node = track->get_state_node()) != 0) { + if ((prop = node->property ("shown")) != 0) { + if (prop->value() == "yes") { + hideit = false; + } + } + } + + if (hideit) { + track->hide (); + } else { + _show_automation.insert(param); + } + + _automation_tracks.insert(std::make_pair(param, new RouteAutomationNode(param, NULL, track))); +} + + +void RouteTimeAxisView::add_insert_to_subplugin_menu (boost::shared_ptr<Insert> insert) { using namespace Menu_Helpers; InsertAutomationInfo *rai; list<InsertAutomationInfo*>::iterator x; - const std::set<uint32_t>& automatable = insert->what_can_be_automated (); - std::set<uint32_t> has_visible_automation; + const std::set<ParamID>& automatable = insert->what_can_be_automated (); + std::set<ParamID> has_visible_automation; insert->what_has_visible_automation(has_visible_automation); @@ -1641,7 +1853,7 @@ RouteTimeAxisView::add_insert_to_subplugin_menu (boost::shared_ptr<Insert> inser items.clear (); - for (std::set<uint32_t>::const_iterator i = automatable.begin(); i != automatable.end(); ++i) { + for (std::set<ParamID>::const_iterator i = automatable.begin(); i != automatable.end(); ++i) { InsertAutomationNode* ran; CheckMenuItem* mitem; @@ -1755,7 +1967,7 @@ RouteTimeAxisView::inserts_changed () } RedirectAutomationLine * -RouteTimeAxisView::find_insert_automation_curve (boost::shared_ptr<Insert> insert, uint32_t what) +RouteTimeAxisView::find_insert_automation_curve (boost::shared_ptr<Insert> insert, ParamID what) { InsertAutomationNode* ran; diff --git a/gtk2_ardour/route_time_axis.h b/gtk2_ardour/route_time_axis.h index e14d682c83..42c889e16f 100644 --- a/gtk2_ardour/route_time_axis.h +++ b/gtk2_ardour/route_time_axis.h @@ -79,6 +79,7 @@ public: void set_selected_regionviews (RegionSelection&); void get_selectables (nframes_t start, nframes_t end, double top, double bot, list<Selectable *>&); void get_inverted_selectables (Selection&, list<Selectable*>&); + bool show_automation(ARDOUR::ParamID param); boost::shared_ptr<ARDOUR::Region> find_next_region (nframes_t pos, ARDOUR::RegionPoint, int32_t dir); @@ -94,6 +95,8 @@ public: void clear_playlist (); void build_playlist_menu (Gtk::Menu *); + + virtual void create_automation_child (ARDOUR::ParamID param) = 0; string name() const; StreamView* view() const { return _view; } @@ -103,13 +106,22 @@ public: protected: friend class StreamView; + struct RouteAutomationNode { + ARDOUR::ParamID param; + Gtk::CheckMenuItem* menu_item; + AutomationTimeAxisView* track; + + RouteAutomationNode (ARDOUR::ParamID par, Gtk::CheckMenuItem* mi, AutomationTimeAxisView* tr) + : param (par), menu_item (mi), track (tr) {} + }; + struct InsertAutomationNode { - uint32_t what; + ARDOUR::ParamID what; Gtk::CheckMenuItem* menu_item; AutomationTimeAxisView* view; RouteTimeAxisView& parent; - InsertAutomationNode (uint32_t w, Gtk::CheckMenuItem* mitem, RouteTimeAxisView& p) + InsertAutomationNode (ARDOUR::ParamID w, Gtk::CheckMenuItem* mitem, RouteTimeAxisView& p) : what (w), menu_item (mitem), view (0), parent (p) {} ~InsertAutomationNode (); @@ -143,15 +155,22 @@ protected: void insert_automation_track_hidden (InsertAutomationNode*, boost::shared_ptr<ARDOUR::Insert>); + + void automation_track_hidden (ARDOUR::ParamID param); + + RouteAutomationNode* automation_track(ARDOUR::ParamID param); + RouteAutomationNode* automation_track(ARDOUR::AutomationType type); InsertAutomationNode* - find_insert_automation_node (boost::shared_ptr<ARDOUR::Insert> i, uint32_t); + find_insert_automation_node (boost::shared_ptr<ARDOUR::Insert> i, ARDOUR::ParamID); RedirectAutomationLine* - find_insert_automation_curve (boost::shared_ptr<ARDOUR::Insert> i, uint32_t); + find_insert_automation_curve (boost::shared_ptr<ARDOUR::Insert> i, ARDOUR::ParamID); - void add_insert_automation_curve (boost::shared_ptr<ARDOUR::Insert> r, uint32_t); + void add_insert_automation_curve (boost::shared_ptr<ARDOUR::Insert> r, ARDOUR::ParamID); void add_existing_insert_automation_curves (boost::shared_ptr<ARDOUR::Insert>); + + void add_automation_child(ARDOUR::ParamID param, AutomationTimeAxisView* track); void reset_insert_automation_curves (); @@ -186,6 +205,7 @@ protected: void rename_current_playlist (); void automation_click (); + void toggle_automation_track (ARDOUR::ParamID param); virtual void show_all_automation (); virtual void show_existing_automation (); virtual void hide_all_automation (); @@ -204,7 +224,6 @@ protected: void region_view_added (RegionView*); void add_ghost_to_insert (RegionView*, AutomationTimeAxisView*); - StreamView* _view; ArdourCanvas::Canvas& parent_canvas; bool no_redraw; @@ -238,12 +257,21 @@ protected: void _set_track_mode (ARDOUR::Track* track, ARDOUR::TrackMode mode, Gtk::RadioMenuItem* reset_item); void track_mode_changed (); - list<InsertAutomationInfo*> insert_automation; + list<InsertAutomationInfo*> insert_automation; vector<RedirectAutomationLine*> insert_automation_curves; + + // Set from XML so context menu automation buttons can be correctly initialized + set<ARDOUR::ParamID> _show_automation; + + map<ARDOUR::ParamID, RouteAutomationNode*> _automation_tracks; sigc::connection modified_connection; void post_construct (); + + void set_state (const XMLNode&); + + XMLNode* get_child_xml_node (const string & childname); }; #endif /* __ardour_route_time_axis_h__ */ |