From 24ccaac67e9d416b3f3c564a441934313f3e9a21 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Fri, 29 Jun 2007 04:02:58 +0000 Subject: [PATCH] Further automation refactoring - bring in the concept of Controllable, work towards making automation + GUI + play/write/touch generic and easily reusable. Added bar controller to automation track controls (mostly relevant for MIDI CC, but added for gain and pan too Just Because). Fixed glaring "redirect" list errors. Fix plugin controls/automation loading. git-svn-id: svn://localhost/ardour2/trunk@2080 d708f5d6-7413-0410-9779-e7cbd77b26cf --- gtk2_ardour/SConscript | 1 + gtk2_ardour/ardour.bindings.in | 30 +- gtk2_ardour/ardour.menus | 2 +- gtk2_ardour/audio_region_view.cc | 26 +- gtk2_ardour/audio_time_axis.cc | 13 +- gtk2_ardour/automation_controller.cc | 110 +++++++ gtk2_ardour/automation_controller.h | 62 ++++ gtk2_ardour/automation_gain_line.cc | 2 +- gtk2_ardour/automation_gain_line.h | 2 +- gtk2_ardour/automation_line.cc | 48 +-- gtk2_ardour/automation_line.h | 6 +- gtk2_ardour/automation_midi_cc_line.cc | 2 +- gtk2_ardour/automation_midi_cc_line.h | 2 +- gtk2_ardour/automation_pan_line.cc | 2 +- gtk2_ardour/automation_pan_line.h | 2 +- gtk2_ardour/automation_time_axis.cc | 162 +++++----- gtk2_ardour/automation_time_axis.h | 10 +- gtk2_ardour/editor.cc | 2 +- gtk2_ardour/editor_mouse.cc | 20 +- gtk2_ardour/editor_ops.cc | 22 +- gtk2_ardour/editor_route_list.cc | 2 +- gtk2_ardour/export_dialog.cc | 2 +- gtk2_ardour/gain_automation_time_axis.cc | 23 +- gtk2_ardour/gain_automation_time_axis.h | 6 +- gtk2_ardour/gain_meter.cc | 36 +-- gtk2_ardour/gain_meter.h | 2 +- gtk2_ardour/ladspa_pluginui.cc | 6 +- gtk2_ardour/midi_controller_time_axis.cc | 28 +- gtk2_ardour/midi_controller_time_axis.h | 7 +- gtk2_ardour/midi_time_axis.cc | 16 +- gtk2_ardour/mixer_strip.cc | 16 +- gtk2_ardour/mixer_ui.cc | 14 +- gtk2_ardour/pan_automation_time_axis.cc | 20 +- gtk2_ardour/pan_automation_time_axis.h | 1 - gtk2_ardour/panner.cc | 4 +- gtk2_ardour/panner.h | 3 +- gtk2_ardour/panner_ui.cc | 6 +- gtk2_ardour/processor_automation_line.cc | 9 +- gtk2_ardour/processor_automation_line.h | 6 +- gtk2_ardour/processor_automation_time_axis.cc | 32 +- gtk2_ardour/processor_automation_time_axis.h | 1 + gtk2_ardour/processor_box.cc | 4 +- gtk2_ardour/region_gain_line.cc | 18 +- gtk2_ardour/region_gain_line.h | 2 +- gtk2_ardour/route_params_ui.cc | 2 +- gtk2_ardour/route_time_axis.cc | 10 +- gtk2_ardour/route_ui.cc | 6 +- gtk2_ardour/utils.cc | 1 - libs/ardour/SConscript | 1 + libs/ardour/ardour/audioregion.h | 22 +- libs/ardour/ardour/automatable.h | 28 +- libs/ardour/ardour/automation_control.h | 59 ++++ libs/ardour/ardour/io.h | 54 ++-- libs/ardour/ardour/panner.h | 14 +- libs/ardour/ardour/plugin_insert.h | 1 - libs/ardour/ardour/processor.h | 2 +- libs/ardour/ardour/route.h | 14 +- libs/ardour/ardour/session.h | 20 +- libs/ardour/ardour/track.h | 5 +- libs/ardour/audio_track.cc | 14 +- libs/ardour/audioregion.cc | 286 +++++++++--------- libs/ardour/automatable.cc | 164 +++++----- libs/ardour/automation_control.cc | 85 ++++++ libs/ardour/automation_event.cc | 14 +- libs/ardour/io.cc | 114 +++---- libs/ardour/midi_diskstream.cc | 5 +- libs/ardour/midi_track.cc | 15 +- libs/ardour/panner.cc | 60 ++-- libs/ardour/plugin_insert.cc | 89 +++--- libs/ardour/processor.cc | 6 +- libs/ardour/route.cc | 47 ++- libs/ardour/session.cc | 22 +- libs/ardour/session_process.cc | 8 +- libs/ardour/session_state.cc | 17 +- libs/ardour/session_transport.cc | 4 +- libs/ardour/track.cc | 6 +- libs/gtkmm2ext/barcontroller.cc | 3 +- libs/gtkmm2ext/gtkmm2ext/barcontroller.h | 8 +- .../mackie/mackie_control_protocol.cc | 8 +- libs/surfaces/mackie/route_signal.cc | 9 +- 80 files changed, 1202 insertions(+), 811 deletions(-) create mode 100644 gtk2_ardour/automation_controller.cc create mode 100644 gtk2_ardour/automation_controller.h create mode 100644 libs/ardour/ardour/automation_control.h create mode 100644 libs/ardour/automation_control.cc diff --git a/gtk2_ardour/SConscript b/gtk2_ardour/SConscript index 384e312e62..91245a5584 100644 --- a/gtk2_ardour/SConscript +++ b/gtk2_ardour/SConscript @@ -101,6 +101,7 @@ automation_midi_cc_line.cc automation_line.cc automation_pan_line.cc automation_time_axis.cc +automation_controller.cc midi_time_axis.cc midi_streamview.cc axis_view.cc diff --git a/gtk2_ardour/ardour.bindings.in b/gtk2_ardour/ardour.bindings.in index 2bdbe71883..bbe72c0578 100644 --- a/gtk2_ardour/ardour.bindings.in +++ b/gtk2_ardour/ardour.bindings.in @@ -10,14 +10,14 @@ ; (gtk_accel_path "/Editor/Autoconnect" "") ; (gtk_accel_path "/Editor/Edit" "") (gtk_accel_path "/Editor/playhead-to-previous-region-end" "comma") -; (gtk_accel_path "/redirectmenu/copy" "") +; (gtk_accel_path "/processormenu/copy" "") ; (gtk_accel_path "/options/MeterFalloffFaster" "") (gtk_accel_path "/Transport/ToggleRollForgetCapture" "space") (gtk_accel_path "/Transport/Record" "r") ; (gtk_accel_path "/RegionList/SortByRegionLength" "") ; (gtk_accel_path "/options/MeterFalloffSlowest" "") ; (gtk_accel_path "/Editor/playhead-to-previous-region-sync" "") -; (gtk_accel_path "/redirectmenu/deactivate_all" "") +; (gtk_accel_path "/processormenu/deactivate_all" "") ; (gtk_accel_path "/RegionList/SortByRegionPosition" "") ; (gtk_accel_path "/Editor/ZoomFocus" "") ; (gtk_accel_path "/options/MeterFalloffSlow" "") @@ -28,7 +28,7 @@ ; (gtk_accel_path "/Zoom/zoom-focus-playhead" "") ; (gtk_accel_path "/Editor/center-edit-cursor" "") ; (gtk_accel_path "/Editor/Monitoring" "") -; (gtk_accel_path "/redirectmenu/deactivate" "") +; (gtk_accel_path "/processormenu/deactivate" "") ; (gtk_accel_path "/options/LatchedRecordEnable" "") ; (gtk_accel_path "/Transport/TogglePunchIn" "") ; (gtk_accel_path "/ShuttleActions/SetShuttleUnitsPercentage" "") @@ -96,9 +96,9 @@ ; (gtk_accel_path "/Zoom/zoom-focus-edit" "") (gtk_accel_path "/Editor/playhead-to-previous-region-start" "comma") ; (gtk_accel_path "/Editor/EditCursorMovementOptions" "") -; (gtk_accel_path "/redirectmenu/activate_all" "") +; (gtk_accel_path "/processormenu/activate_all" "") ; (gtk_accel_path "/Editor/addExternalAudioAsTapeTrack" "") -; (gtk_accel_path "/redirectmenu/paste" "") +; (gtk_accel_path "/processormenu/paste" "") ; (gtk_accel_path "/Editor/Smpte25" "") ; (gtk_accel_path "/options/RegionEquivalentsOverlap" "") ; (gtk_accel_path "/Main/MeteringFallOffRate" "") @@ -123,7 +123,7 @@ (gtk_accel_path "/Editor/align-regions-sync-relative" "a") ; (gtk_accel_path "/Editor/EditSelectRegionOptions" "") (gtk_accel_path "/Editor/crop" "c") -; (gtk_accel_path "/redirectmenu/newsend" "") +; (gtk_accel_path "/processormenu/newsend" "") ; (gtk_accel_path "/Editor/ToggleGeneric MIDISurfaceSubMenu" "") ; (gtk_accel_path "/Editor/MeterFalloff" "") ; (gtk_accel_path "/RegionList/rlRemove" "") @@ -136,7 +136,7 @@ (gtk_accel_path "/Editor/align-regions-sync" "a") ; (gtk_accel_path "/Main/Windows" "") ; (gtk_accel_path "/Main/CleanupUnused" "") -; (gtk_accel_path "/redirectmenu/deselectall" "") +; (gtk_accel_path "/processormenu/deselectall" "") ; (gtk_accel_path "/options/SoloViaBus" "") (gtk_accel_path "/MouseMode/set-mouse-mode-zoom" "z") ; (gtk_accel_path "/RegionList/rlAudition" "") @@ -202,7 +202,7 @@ (gtk_accel_path "/Editor/temporal-zoom-in" "minus") ; (gtk_accel_path "/JACK/Latency" "") (gtk_accel_path "/Editor/edit-cursor-to-range-end" "F2") -; (gtk_accel_path "/redirectmenu/rename" "") +; (gtk_accel_path "/processormenu/rename" "") ; (gtk_accel_path "/RegionList/rlShowAuto" "") (gtk_accel_path "/Editor/select-all-before-playhead" "p") ; (gtk_accel_path "/Editor/addExistingAudioFiles" "") @@ -231,7 +231,7 @@ (gtk_accel_path "/Common/goto-mixer" "m") ; (gtk_accel_path "/Editor/addExternalAudioToTrack" "") ; (gtk_accel_path "/RegionList/SortBySourceFileCreationDate" "") -; (gtk_accel_path "/redirectmenu/activate" "") +; (gtk_accel_path "/processormenu/activate" "") (gtk_accel_path "/Editor/extend-range-to-start-of-region" "leftanglebracket") ; (gtk_accel_path "/Editor/PullupMinus1" "") ; (gtk_accel_path "/Editor/snap-normal" "") @@ -239,7 +239,7 @@ (gtk_accel_path "/Common/ToggleBigClock" "b") ; (gtk_accel_path "/Snap/snap-to-asixteenthbeat" "") (gtk_accel_path "/Editor/select-all-in-punch-range" "d") -; (gtk_accel_path "/redirectmenu/edit" "") +; (gtk_accel_path "/processormenu/edit" "") (gtk_accel_path "/Editor/duplicate-region" "d") ; (gtk_accel_path "/JACK/JACKLatency2048" "") ; (gtk_accel_path "/Editor/ToggleWaveformsWhileRecording" "") @@ -248,8 +248,8 @@ ; (gtk_accel_path "/options/FileHeaderFormatWAVE" "") (gtk_accel_path "/Transport/GotoZero" "KP_Insert") (gtk_accel_path "/Transport/GotoEnd" "End") -; (gtk_accel_path "/redirectmenu/cut" "") -; (gtk_accel_path "/redirectmenu/newinsert" "") +; (gtk_accel_path "/processormenu/cut" "") +; (gtk_accel_path "/processormenu/newinsert" "") ; (gtk_accel_path "/options/UseMMC" "") ; (gtk_accel_path "/options/MeterFalloffOff" "") (gtk_accel_path "/MouseMode/set-mouse-mode-object" "o") @@ -296,7 +296,7 @@ ; (gtk_accel_path "/Editor/toggle-xfades-active" "") ; (gtk_accel_path "/Snap/snap-to-bar" "") ; (gtk_accel_path "/Editor/LayerLaterHigher" "") -; (gtk_accel_path "/redirectmenu/selectall" "") +; (gtk_accel_path "/processormenu/selectall" "") (gtk_accel_path "/Editor/editor-copy" "c") ; (gtk_accel_path "/Snap/snap-to-quarters" "") (gtk_accel_path "/Editor/temporal-zoom-out" "equal") @@ -306,13 +306,13 @@ ; (gtk_accel_path "/options/OutputAutoConnectManual" "") ; (gtk_accel_path "/Snap/snap-to-region-sync" "") (gtk_accel_path "/Editor/edit-cursor-to-previous-region-sync" "apostrophe") -; (gtk_accel_path "/redirectmenu/clear" "") +; (gtk_accel_path "/processormenu/clear" "") ; (gtk_accel_path "/Editor/ToggleGeneric MIDISurfaceFeedback" "") ; (gtk_accel_path "/Editor/PullupPlus4Minus1" "") ; (gtk_accel_path "/JACK/JACKLatency512" "") (gtk_accel_path "/Editor/edit-cursor-to-next-region-end" "bracketright") ; (gtk_accel_path "/Main/Recent" "") -; (gtk_accel_path "/redirectmenu/newplugin" "") +; (gtk_accel_path "/processormenu/newplugin" "") ; (gtk_accel_path "/options/InputAutoConnectManual" "") ; (gtk_accel_path "/options/MeterHoldLong" "") ; (gtk_accel_path "/Snap/snap-to-seconds" "") diff --git a/gtk2_ardour/ardour.menus b/gtk2_ardour/ardour.menus index 13b8cbf738..27dea430d8 100644 --- a/gtk2_ardour/ardour.menus +++ b/gtk2_ardour/ardour.menus @@ -374,7 +374,7 @@ - + diff --git a/gtk2_ardour/audio_region_view.cc b/gtk2_ardour/audio_region_view.cc index 058295949f..40349877a1 100644 --- a/gtk2_ardour/audio_region_view.cc +++ b/gtk2_ardour/audio_region_view.cc @@ -171,11 +171,11 @@ AudioRegionView::init (Gdk::Color& basic_color, bool wfd) setup_fade_handle_positions (); - string foo = _region->name(); - foo += ':'; - foo += "gain"; + string line_name = _region->name(); + line_name += ':'; + line_name += "gain"; - gain_line = new AudioRegionGainLine (foo, trackview.session(), *this, *group, audio_region()->envelope()); + gain_line = new AudioRegionGainLine (line_name, trackview.session(), *this, *group, audio_region()->envelope()); if (!(_flags & EnvelopeVisible)) { gain_line->hide (); @@ -489,7 +489,7 @@ AudioRegionView::reset_fade_shapes () void AudioRegionView::reset_fade_in_shape () { - reset_fade_in_shape_width ((nframes_t) audio_region()->fade_in().back()->when); + reset_fade_in_shape_width ((nframes_t) audio_region()->fade_in()->back()->when); } void @@ -534,7 +534,7 @@ AudioRegionView::reset_fade_in_shape_width (nframes_t width) fade_in_shape->show(); float curve[npoints]; - audio_region()->fade_in().curve().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); @@ -573,7 +573,7 @@ AudioRegionView::reset_fade_in_shape_width (nframes_t width) void AudioRegionView::reset_fade_out_shape () { - reset_fade_out_shape_width ((nframes_t) audio_region()->fade_out().back()->when); + reset_fade_out_shape_width ((nframes_t) audio_region()->fade_out()->back()->when); } void @@ -620,7 +620,7 @@ AudioRegionView::reset_fade_out_shape_width (nframes_t width) fade_out_shape->show(); float curve[npoints]; - audio_region()->fade_out().curve().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; @@ -941,7 +941,7 @@ AudioRegionView::add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev) gain_line->view_to_model_y (y); trackview.session().begin_reversible_command (_("add gain control point")); - XMLNode &before = audio_region()->envelope().get_state(); + XMLNode &before = audio_region()->envelope()->get_state(); if (!audio_region()->envelope_active()) { XMLNode ®ion_before = audio_region()->get_state(); @@ -950,10 +950,10 @@ AudioRegionView::add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev) trackview.session().add_command (new MementoCommand(*(audio_region().get()), ®ion_before, ®ion_after)); } - audio_region()->envelope().add (fx, y); + audio_region()->envelope()->add (fx, y); - XMLNode &after = audio_region()->envelope().get_state(); - trackview.session().add_command (new MementoCommand(audio_region()->envelope(), &before, &after)); + XMLNode &after = audio_region()->envelope()->get_state(); + trackview.session().add_command (new MementoCommand(*audio_region()->envelope().get(), &before, &after)); trackview.session().commit_reversible_command (); } @@ -961,7 +961,7 @@ void AudioRegionView::remove_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev) { ControlPoint *cp = reinterpret_cast (item->get_data ("control_point")); - audio_region()->envelope().erase (cp->model); + audio_region()->envelope()->erase (cp->model); } void diff --git a/gtk2_ardour/audio_time_axis.cc b/gtk2_ardour/audio_time_axis.cc index 416a86c1a5..3d62915171 100644 --- a/gtk2_ardour/audio_time_axis.cc +++ b/gtk2_ardour/audio_time_axis.cc @@ -284,18 +284,25 @@ void AudioTimeAxisView::create_automation_child (ParamID param) { if (param.type() == GainAutomation) { + + boost::shared_ptr c = _route->gain_control(); + if (!c) { + error << "Route has no gain automation, unable to add automation track view." << endmsg; + return; + } + GainAutomationTimeAxisView* gain_track = new GainAutomationTimeAxisView (_session, _route, editor, *this, parent_canvas, _route->describe_parameter(param), - _route->gain_automation()); + c); AutomationLine* line = new AutomationGainLine ("automation gain", *gain_track, *gain_track->canvas_display, - _route->gain_automation()); + c->list()); line->set_line_color (Config->canvasvar_AutomationLine.get()); @@ -304,7 +311,7 @@ AudioTimeAxisView::create_automation_child (ParamID param) add_automation_child(ParamID(GainAutomation), gain_track); } else if (param.type() == PanAutomation) { - + PanAutomationTimeAxisView* pan_track = new PanAutomationTimeAxisView (_session, _route, editor, diff --git a/gtk2_ardour/automation_controller.cc b/gtk2_ardour/automation_controller.cc new file mode 100644 index 0000000000..a72aa0ba7d --- /dev/null +++ b/gtk2_ardour/automation_controller.cc @@ -0,0 +1,110 @@ +/* + Copyright (C) 2007 Paul Davis + Author: Dave Robillard + + 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 +#include "automation_controller.h" +#include "ardour/automation_event.h" +#include "ardour/automation_control.h" +#include "ardour_ui.h" +#include "utils.h" + +#include "i18n.h" + +using namespace ARDOUR; +using namespace Gtk; + + +AutomationController::AutomationController(boost::shared_ptr ac, Adjustment* adj) + : BarController(*adj, *ac) + , _ignore_change(false) + , _controllable(ac) + , _adjustment(adj) +{ + set_name (X_("PluginSlider")); // FIXME: get yer own name! + set_style (BarController::LeftToRight); + set_use_parent (true); + + label_callback = sigc::mem_fun(this, &AutomationController::update_label); + + StartGesture.connect (mem_fun(*this, &AutomationController::start_touch)); + StopGesture.connect (mem_fun(*this, &AutomationController::end_touch)); + + _adjustment->signal_value_changed().connect ( + mem_fun(*this, &AutomationController::value_adjusted)); + + _screen_update_connection = ARDOUR_UI::RapidScreenUpdate.connect ( + mem_fun (*this, &AutomationController::display_effective_value)); +} + +AutomationController::~AutomationController() +{ +} + +boost::shared_ptr +AutomationController::create(Session& s, boost::shared_ptr al, boost::shared_ptr ac) +{ + Gtk::Adjustment* adjustment = manage(new Gtk::Adjustment(al->default_value(), al->get_min_y(), al->get_max_y())); + if (!ac) { + PBD::warning << "Creating AutomationController for " << al->param_id().to_string() << endmsg; + ac = boost::shared_ptr(new AutomationControl(s, al)); + } + return boost::shared_ptr(new AutomationController(ac, adjustment)); +} + +void +AutomationController::update_label(char* label, int label_len) +{ + //cerr << "Controller label: " << label << endl; +} + +void +AutomationController::display_effective_value() +{ + if ( ! _controllable->list()->automation_playback()) + return; + + float value = _controllable->get_value(); + + if (_adjustment->get_value() != value) { + _ignore_change = true; + _adjustment->set_value (value); + _ignore_change = false; + } +} + +void +AutomationController::value_adjusted() +{ + if (!_ignore_change) { + _controllable->set_value(_adjustment->get_value()); + } +} + +void +AutomationController::start_touch() +{ + _controllable->list()->start_touch(); +} + +void +AutomationController::end_touch() +{ + _controllable->list()->stop_touch(); +} diff --git a/gtk2_ardour/automation_controller.h b/gtk2_ardour/automation_controller.h new file mode 100644 index 0000000000..042f4a3b96 --- /dev/null +++ b/gtk2_ardour/automation_controller.h @@ -0,0 +1,62 @@ +/* + Copyright (C) 2007 Paul Davis + Author: Dave Robillard + + 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_controller_h__ +#define __ardour_gtk_automation_controller_h__ + +#include +#include +#include + +namespace ARDOUR { + class Session; + class AutomationList; + class AutomationControl; +} + + +class AutomationController : public Gtkmm2ext::BarController { +public: + static boost::shared_ptr create( + ARDOUR::Session& s, + boost::shared_ptr al, + boost::shared_ptr ac); + + ~AutomationController(); + + boost::shared_ptr controllable() { return _controllable; } + + void update_label(char* label, int label_len); + void display_effective_value(); + void value_adjusted(); + +private: + AutomationController(boost::shared_ptr ac, Gtk::Adjustment* adj); + void start_touch(); + void end_touch(); + + bool _ignore_change; + boost::shared_ptr _controllable; + Gtk::Adjustment* _adjustment; + sigc::connection _screen_update_connection; +}; + + +#endif /* __ardour_gtk_automation_controller_h__ */ diff --git a/gtk2_ardour/automation_gain_line.cc b/gtk2_ardour/automation_gain_line.cc index 84488dc2b5..0480016ca2 100644 --- a/gtk2_ardour/automation_gain_line.cc +++ b/gtk2_ardour/automation_gain_line.cc @@ -30,7 +30,7 @@ using namespace std; using namespace ARDOUR; using namespace PBD; -AutomationGainLine::AutomationGainLine (const string & name, TimeAxisView& tv, ArdourCanvas::Group& parent, AutomationList& l) +AutomationGainLine::AutomationGainLine (const string & name, TimeAxisView& tv, ArdourCanvas::Group& parent, boost::shared_ptr l) : AutomationLine (name, tv, parent, l) { diff --git a/gtk2_ardour/automation_gain_line.h b/gtk2_ardour/automation_gain_line.h index fe8c9274f2..a5ddafdd57 100644 --- a/gtk2_ardour/automation_gain_line.h +++ b/gtk2_ardour/automation_gain_line.h @@ -30,7 +30,7 @@ class TimeAxisView; class AutomationGainLine : public AutomationLine { public: - AutomationGainLine (const string & name, TimeAxisView&, ArdourCanvas::Group& parent, ARDOUR::AutomationList&); + AutomationGainLine (const string & name, TimeAxisView&, ArdourCanvas::Group& parent, boost::shared_ptr); void view_to_model_y (double&); void model_to_view_y (double&); diff --git a/gtk2_ardour/automation_line.cc b/gtk2_ardour/automation_line.cc index 683a767935..f6b54cd128 100644 --- a/gtk2_ardour/automation_line.cc +++ b/gtk2_ardour/automation_line.cc @@ -57,7 +57,7 @@ using namespace Gnome; // for Canvas ControlPoint::ControlPoint (AutomationLine& al) : line (al) { - model = al.the_list().end(); + model = al.the_list()->end(); view_index = 0; can_slide = true; _x = 0; @@ -220,7 +220,7 @@ ControlPoint::move_to (double x, double y, ShapeType shape) /*****/ -AutomationLine::AutomationLine (const string & name, TimeAxisView& tv, ArdourCanvas::Group& parent, AutomationList& al) +AutomationLine::AutomationLine (const string & name, TimeAxisView& tv, ArdourCanvas::Group& parent, boost::shared_ptr al) : trackview (tv), _name (name), alist (al), @@ -245,10 +245,9 @@ AutomationLine::AutomationLine (const string & name, TimeAxisView& tv, ArdourCan line->signal_event().connect (mem_fun (*this, &AutomationLine::event_handler)); - alist.StateChanged.connect (mem_fun(*this, &AutomationLine::list_changed)); - - trackview.session().register_with_memento_command_factory(alist.id(), this); + alist->StateChanged.connect (mem_fun(*this, &AutomationLine::list_changed)); + trackview.session().register_with_memento_command_factory(alist->id(), this); } AutomationLine::~AutomationLine () @@ -612,7 +611,7 @@ AutomationLine::determine_visible_control_points (ALPoints& points) view_index = 0; - for (model = alist.begin(), pi = 0; pi < npoints; ++model, ++pi) { + for (model = alist->begin(), pi = 0; pi < npoints; ++model, ++pi) { double tx = points[pi].x; double ty = points[pi].y; @@ -808,7 +807,7 @@ AutomationLine::start_drag (ControlPoint* cp, nframes_t x, float fraction) } trackview.editor.current_session()->begin_reversible_command (str); - trackview.editor.current_session()->add_command (new MementoCommand(alist, &get_state(), 0)); + trackview.editor.current_session()->add_command (new MementoCommand(*alist.get(), &get_state(), 0)); drag_x = x; drag_distance = 0; @@ -872,7 +871,7 @@ AutomationLine::end_drag (ControlPoint* cp) return; } - alist.freeze (); + alist->freeze (); if (cp) { sync_model_with_view_point (*cp, did_push, drag_distance); @@ -880,11 +879,11 @@ AutomationLine::end_drag (ControlPoint* cp) sync_model_with_view_line (line_drag_cp1, line_drag_cp2); } - alist.thaw (); + alist->thaw (); update_pending = false; - trackview.editor.current_session()->add_command (new MementoCommand(alist, 0, &alist.get_state())); + trackview.editor.current_session()->add_command (new MementoCommand(*alist.get(), 0, &alist->get_state())); trackview.editor.current_session()->commit_reversible_command (); trackview.editor.current_session()->set_dirty (); } @@ -919,14 +918,14 @@ AutomationLine::sync_model_with_view_point (ControlPoint& cp, bool did_push, int /* interpolate */ if (y_delta || x_delta) { - alist.modify (i, (*i)->when + x_delta, mr.ymin + y_delta); + alist->modify (i, (*i)->when + x_delta, mr.ymin + y_delta); } } /* change the primary point */ update_pending = true; - alist.modify (cp.model, mr.xval, mr.yval); + alist->modify (cp.model, mr.xval, mr.yval); /* change later points */ @@ -942,7 +941,7 @@ AutomationLine::sync_model_with_view_point (ControlPoint& cp, bool did_push, int /* all later points move by the same distance along the x-axis as the main point */ if (delta) { - alist.modify (i, (*i)->when + distance, (*i)->value + delta); + alist->modify (i, (*i)->when + distance, (*i)->value + delta); } ++i; @@ -954,7 +953,7 @@ AutomationLine::sync_model_with_view_point (ControlPoint& cp, bool did_push, int as the main point moved. */ - alist.slide (mr.end, drag_distance); + alist->slide (mr.end, drag_distance); } } @@ -998,7 +997,7 @@ AutomationLine::is_last_point (ControlPoint& cp) // If the list is not empty, and the point is the last point in the list - if (!alist.empty() && mr.end == alist.end()) { + if (!alist->empty() && mr.end == alist->end()) { return true; } @@ -1014,7 +1013,7 @@ AutomationLine::is_first_point (ControlPoint& cp) // If the list is not empty, and the point is the first point in the list - if (!alist.empty() && mr.start == alist.begin()) { + if (!alist->empty() && mr.start == alist->begin()) { return true; } @@ -1030,11 +1029,12 @@ AutomationLine::remove_point (ControlPoint& cp) model_representation (cp, mr); trackview.editor.current_session()->begin_reversible_command (_("remove control point")); - XMLNode &before = alist.get_state(); + XMLNode &before = alist->get_state(); - alist.erase (mr.start, mr.end); + alist->erase (mr.start, mr.end); - trackview.editor.current_session()->add_command(new MementoCommand(alist, &before, &alist.get_state())); + trackview.editor.current_session()->add_command(new MementoCommand( + *alist.get(), &before, &alist->get_state())); trackview.editor.current_session()->commit_reversible_command (); trackview.editor.current_session()->set_dirty (); } @@ -1229,7 +1229,7 @@ AutomationLine::reset () return; } - alist.apply_to_points (*this, &AutomationLine::reset_callback); + alist->apply_to_points (*this, &AutomationLine::reset_callback); } void @@ -1237,7 +1237,7 @@ AutomationLine::clear () { /* parent must create command */ XMLNode &before = get_state(); - alist.clear(); + alist->clear(); trackview.editor.current_session()->add_command (new MementoCommand(*this, &before, &get_state())); trackview.editor.current_session()->commit_reversible_command (); trackview.editor.current_session()->set_dirty (); @@ -1251,7 +1251,7 @@ AutomationLine::change_model (AutomationList::iterator i, double x, double y) void AutomationLine::change_model_range (AutomationList::iterator start, AutomationList::iterator end, double xdelta, float ydelta) { - alist.move_range (start, end, xdelta, ydelta); + alist->move_range (start, end, xdelta, ydelta); } void @@ -1281,12 +1281,12 @@ XMLNode & AutomationLine::get_state (void) { /* function as a proxy for the model */ - return alist.get_state(); + return alist->get_state(); } int AutomationLine::set_state (const XMLNode &node) { /* function as a proxy for the model */ - return alist.set_state (node); + return alist->set_state (node); } diff --git a/gtk2_ardour/automation_line.h b/gtk2_ardour/automation_line.h index 41034dbf6e..a915966d97 100644 --- a/gtk2_ardour/automation_line.h +++ b/gtk2_ardour/automation_line.h @@ -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&, boost::shared_ptr); virtual ~AutomationLine (); void queue_reset (); @@ -150,7 +150,7 @@ class AutomationLine : public sigc::trackable, public PBD::StatefulThingWithGoin virtual void view_to_model_y (double&) = 0; virtual void model_to_view_y (double&) = 0; - ARDOUR::AutomationList& the_list() const { return alist; } + boost::shared_ptr the_list() const { return alist; } void show_all_control_points (); void hide_all_but_selected_control_points (); @@ -168,7 +168,7 @@ class AutomationLine : public sigc::trackable, public PBD::StatefulThingWithGoin guint32 _y_position; guint32 _height; uint32_t _line_color; - ARDOUR::AutomationList& alist; + boost::shared_ptr alist; bool _visible : 1; bool _vc_uses_gain_mapping : 1; diff --git a/gtk2_ardour/automation_midi_cc_line.cc b/gtk2_ardour/automation_midi_cc_line.cc index 4a074ddbe9..9bfef278e1 100644 --- a/gtk2_ardour/automation_midi_cc_line.cc +++ b/gtk2_ardour/automation_midi_cc_line.cc @@ -27,7 +27,7 @@ using namespace std; using namespace ARDOUR; using namespace PBD; -AutomationMidiCCLine::AutomationMidiCCLine (const string & name, TimeAxisView& tv, ArdourCanvas::Group& parent, AutomationList& l) +AutomationMidiCCLine::AutomationMidiCCLine (const string & name, TimeAxisView& tv, ArdourCanvas::Group& parent, boost::shared_ptr l) : AutomationLine (name, tv, parent, l) { diff --git a/gtk2_ardour/automation_midi_cc_line.h b/gtk2_ardour/automation_midi_cc_line.h index 6ac078a911..82a5e0f816 100644 --- a/gtk2_ardour/automation_midi_cc_line.h +++ b/gtk2_ardour/automation_midi_cc_line.h @@ -30,7 +30,7 @@ class TimeAxisView; class AutomationMidiCCLine : public AutomationLine { public: - AutomationMidiCCLine (const string & name, TimeAxisView&, ArdourCanvas::Group& parent, ARDOUR::AutomationList&); + AutomationMidiCCLine (const string & name, TimeAxisView&, ArdourCanvas::Group& parent, boost::shared_ptr); void view_to_model_y (double&); void model_to_view_y (double&); diff --git a/gtk2_ardour/automation_pan_line.cc b/gtk2_ardour/automation_pan_line.cc index 0e36f4ef88..02c9fe2c49 100644 --- a/gtk2_ardour/automation_pan_line.cc +++ b/gtk2_ardour/automation_pan_line.cc @@ -30,7 +30,7 @@ using namespace ARDOUR; using namespace PBD; -AutomationPanLine::AutomationPanLine (const string & name, TimeAxisView& tv, ArdourCanvas::Group& parent, AutomationList& l) +AutomationPanLine::AutomationPanLine (const string & name, TimeAxisView& tv, ArdourCanvas::Group& parent, boost::shared_ptr l) : AutomationLine (name, tv, parent, l) { diff --git a/gtk2_ardour/automation_pan_line.h b/gtk2_ardour/automation_pan_line.h index 6374c535e0..d77efdd8e3 100644 --- a/gtk2_ardour/automation_pan_line.h +++ b/gtk2_ardour/automation_pan_line.h @@ -30,7 +30,7 @@ class TimeAxisView; class AutomationPanLine : public AutomationLine { public: - AutomationPanLine (const string & name, TimeAxisView&, ArdourCanvas::Group& parent, ARDOUR::AutomationList&); + AutomationPanLine (const string & name, TimeAxisView&, ArdourCanvas::Group& parent, boost::shared_ptr); void view_to_model_y (double&); void model_to_view_y (double&); diff --git a/gtk2_ardour/automation_time_axis.cc b/gtk2_ardour/automation_time_axis.cc index 04ac1ee076..ffb66e2270 100644 --- a/gtk2_ardour/automation_time_axis.cc +++ b/gtk2_ardour/automation_time_axis.cc @@ -17,8 +17,11 @@ */ +#include #include +#include #include +#include #include "ardour_ui.h" #include "automation_time_axis.h" @@ -38,6 +41,7 @@ using namespace ARDOUR; using namespace PBD; using namespace Gtk; +using namespace Gtkmm2ext; using namespace Editing; Pango::FontDescription AutomationTimeAxisView::name_font; @@ -69,7 +73,7 @@ AutomationTimeAxisView::AutomationTimeAxisView (Session& s, boost::shared_ptrproperty_x1() = 0.0; base_rect->property_y1() = 0.0; @@ -217,6 +221,17 @@ AutomationTimeAxisView::auto_clicked () automation_menu->popup (1, gtk_get_current_event_time()); } +void +AutomationTimeAxisView::set_automation_state (AutoState state) +{ + if (!ignore_state_request) { + for (Lines::iterator i = lines.begin(); i != lines.end(); ++i) { + route->set_parameter_automation_state ( + i->second->controllable()->list()->param_id(), + state); + } + } +} void AutomationTimeAxisView::automation_state_changed () @@ -228,7 +243,7 @@ AutomationTimeAxisView::automation_state_changed () if (lines.empty()) { state = Off; } else { - state = lines.front()->the_list().automation_state (); + state = lines.front().first->the_list()->automation_state (); } switch (state & (Off|Play|Touch|Write)) { @@ -292,8 +307,8 @@ void AutomationTimeAxisView::clear_clicked () { _session.begin_reversible_command (_("clear automation")); - for (vector::iterator i = lines.begin(); i != lines.end(); ++i) { - (*i)->clear (); + for (Lines::iterator i = lines.begin(); i != lines.end(); ++i) { + i->first->clear (); } _session.commit_reversible_command (); } @@ -304,7 +319,7 @@ AutomationTimeAxisView::set_height (TrackHeight ht) uint32_t h = height_to_pixels (ht); bool changed = (height != (uint32_t) h); - bool changed_between_small_and_normal = ( (ht == Small || ht == Smaller) ^ (height_style == Small || height_style == Smaller) ); + //bool changed_between_small_and_normal = ( (ht == Small || ht == Smaller) ^ (height_style == Small || height_style == Smaller) ); TimeAxisView* state_parent = get_parent_with_state (); XMLNode* xml_node = state_parent->get_child_xml_node (_state_name); @@ -312,8 +327,8 @@ AutomationTimeAxisView::set_height (TrackHeight ht) TimeAxisView::set_height (ht); base_rect->property_y2() = h; - for (vector::iterator i = lines.begin(); i != lines.end(); ++i) { - (*i)->set_y_position_and_height (0, h); + for (Lines::iterator i = lines.begin(); i != lines.end(); ++i) { + i->first->set_y_position_and_height (0, h); } for (list::iterator i = ghosts.begin(); i != ghosts.end(); ++i) { @@ -347,12 +362,20 @@ AutomationTimeAxisView::set_height (TrackHeight ht) break; } - if (changed_between_small_and_normal || first_call_to_set_height) { + //if (changed_between_small_and_normal || first_call_to_set_height) { first_call_to_set_height = false; + unsigned control_cnt = 0; switch (ht) { case Largest: case Large: case Larger: + + for (Lines::iterator i = lines.begin(); i != lines.end(); ++i) { + i->second->show (); + controls_table.attach (*i->second.get(), 0, 8, 2 + control_cnt, 3 + control_cnt, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND); + ++control_cnt; + } + case Normal: controls_table.remove (name_hbox); @@ -400,7 +423,7 @@ AutomationTimeAxisView::set_height (TrackHeight ht) hide_button.hide(); break; } - } + //} if (changed) { /* only emit the signal if the height really changed */ @@ -413,8 +436,8 @@ AutomationTimeAxisView::set_samples_per_unit (double spu) { TimeAxisView::set_samples_per_unit (editor.get_current_zoom()); - for (vector::iterator i = lines.begin(); i != lines.end(); ++i) { - (*i)->reset (); + for (Lines::iterator i = lines.begin(); i != lines.end(); ++i) { + i->first->reset (); } } @@ -486,8 +509,8 @@ AutomationTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op) { bool ret = false; - for (vector::iterator i = lines.begin(); i != lines.end(); ++i) { - ret = cut_copy_clear_one ((**i), selection, op); + for (Lines::iterator i = lines.begin(); i != lines.end(); ++i) { + ret = cut_copy_clear_one (*i->first, selection, op); } return ret; @@ -497,28 +520,28 @@ bool AutomationTimeAxisView::cut_copy_clear_one (AutomationLine& line, Selection& selection, CutCopyOp op) { AutomationList* what_we_got = 0; - AutomationList& alist (line.the_list()); + boost::shared_ptr alist (line.the_list()); bool ret = false; - XMLNode &before = alist.get_state(); + XMLNode &before = alist->get_state(); switch (op) { case Cut: - if ((what_we_got = alist.cut (selection.time.front().start, selection.time.front().end)) != 0) { + if ((what_we_got = alist->cut (selection.time.front().start, selection.time.front().end)) != 0) { editor.get_cut_buffer().add (what_we_got); - _session.add_command(new MementoCommand(alist, &before, &alist.get_state())); + _session.add_command(new MementoCommand(*alist.get(), &before, &alist->get_state())); ret = true; } break; case Copy: - if ((what_we_got = alist.copy (selection.time.front().start, selection.time.front().end)) != 0) { + if ((what_we_got = alist->copy (selection.time.front().start, selection.time.front().end)) != 0) { editor.get_cut_buffer().add (what_we_got); } break; case Clear: - if ((what_we_got = alist.cut (selection.time.front().start, selection.time.front().end)) != 0) { - _session.add_command(new MementoCommand(alist, &before, &alist.get_state())); + if ((what_we_got = alist->cut (selection.time.front().start, selection.time.front().end)) != 0) { + _session.add_command(new MementoCommand(*alist.get(), &before, &alist->get_state())); delete what_we_got; what_we_got = 0; ret = true; @@ -540,17 +563,17 @@ AutomationTimeAxisView::cut_copy_clear_one (AutomationLine& line, Selection& sel void AutomationTimeAxisView::reset_objects (PointSelection& selection) { - for (vector::iterator i = lines.begin(); i != lines.end(); ++i) { - reset_objects_one ((**i), selection); + for (Lines::iterator i = lines.begin(); i != lines.end(); ++i) { + reset_objects_one (*i->first, selection); } } void AutomationTimeAxisView::reset_objects_one (AutomationLine& line, PointSelection& selection) { - AutomationList& alist (line.the_list()); + boost::shared_ptr alist(line.the_list()); - _session.add_command (new MementoCommand(alist, &alist.get_state(), 0)); + _session.add_command (new MementoCommand(*alist.get(), &alist->get_state(), 0)); for (PointSelection::iterator i = selection.begin(); i != selection.end(); ++i) { @@ -558,7 +581,7 @@ AutomationTimeAxisView::reset_objects_one (AutomationLine& line, PointSelection& continue; } - alist.reset_range ((*i).start, (*i).end); + alist->reset_range ((*i).start, (*i).end); } } @@ -567,8 +590,8 @@ AutomationTimeAxisView::cut_copy_clear_objects (PointSelection& selection, CutCo { bool ret = false; - for (vector::iterator i = lines.begin(); i != lines.end(); ++i) { - ret = cut_copy_clear_objects_one ((**i), selection, op); + for (Lines::iterator i = lines.begin(); i != lines.end(); ++i) { + ret = cut_copy_clear_objects_one (*i->first, selection, op); } return ret; @@ -578,10 +601,10 @@ bool AutomationTimeAxisView::cut_copy_clear_objects_one (AutomationLine& line, PointSelection& selection, CutCopyOp op) { AutomationList* what_we_got = 0; - AutomationList& alist (line.the_list()); + boost::shared_ptr alist(line.the_list()); bool ret = false; - XMLNode &before = alist.get_state(); + XMLNode &before = alist->get_state(); for (PointSelection::iterator i = selection.begin(); i != selection.end(); ++i) { @@ -591,21 +614,21 @@ AutomationTimeAxisView::cut_copy_clear_objects_one (AutomationLine& line, PointS switch (op) { case Cut: - if ((what_we_got = alist.cut ((*i).start, (*i).end)) != 0) { + if ((what_we_got = alist->cut ((*i).start, (*i).end)) != 0) { editor.get_cut_buffer().add (what_we_got); - _session.add_command (new MementoCommand(alist, new XMLNode (before), &alist.get_state())); + _session.add_command (new MementoCommand(*alist.get(), new XMLNode (before), &alist->get_state())); ret = true; } break; case Copy: - if ((what_we_got = alist.copy ((*i).start, (*i).end)) != 0) { + if ((what_we_got = alist->copy ((*i).start, (*i).end)) != 0) { editor.get_cut_buffer().add (what_we_got); } break; case Clear: - if ((what_we_got = alist.cut ((*i).start, (*i).end)) != 0) { - _session.add_command (new MementoCommand(alist, new XMLNode (before), &alist.get_state())); + if ((what_we_got = alist->cut ((*i).start, (*i).end)) != 0) { + _session.add_command (new MementoCommand(*alist.get(), new XMLNode (before), &alist->get_state())); delete what_we_got; what_we_got = 0; ret = true; @@ -632,8 +655,8 @@ AutomationTimeAxisView::paste (nframes_t pos, float times, Selection& selection, { bool ret = true; - for (vector::iterator i = lines.begin(); i != lines.end(); ++i) { - ret = paste_one (**i, pos, times, selection, nth); + for (Lines::iterator i = lines.begin(); i != lines.end(); ++i) { + ret = paste_one (*i->first, pos, times, selection, nth); } return ret; @@ -643,7 +666,7 @@ bool AutomationTimeAxisView::paste_one (AutomationLine& line, nframes_t pos, float times, Selection& selection, size_t nth) { AutomationSelection::iterator p; - AutomationList& alist (line.the_list()); + boost::shared_ptr alist(line.the_list()); for (p = selection.lines.begin(); p != selection.lines.end() && nth; ++p, --nth); @@ -664,9 +687,9 @@ AutomationTimeAxisView::paste_one (AutomationLine& line, nframes_t pos, float ti (*x)->value = foo; } - XMLNode &before = alist.get_state(); - alist.paste (copy, pos, times); - _session.add_command (new MementoCommand(alist, &before, &alist.get_state())); + XMLNode &before = alist->get_state(); + alist->paste (copy, pos, times); + _session.add_command (new MementoCommand(*alist.get(), &before, &alist->get_state())); return true; } @@ -725,8 +748,8 @@ AutomationTimeAxisView::get_selectables (nframes_t start, nframes_t end, double botfrac = 1.0 - ((bot - y_position) / height); } - for (vector::iterator i = lines.begin(); i != lines.end(); ++i) { - (*i)->get_selectables (start, end, botfrac, topfrac, results); + for (Lines::iterator i = lines.begin(); i != lines.end(); ++i) { + i->first->get_selectables (start, end, botfrac, topfrac, results); } } } @@ -734,25 +757,24 @@ AutomationTimeAxisView::get_selectables (nframes_t start, nframes_t end, double void AutomationTimeAxisView::get_inverted_selectables (Selection& sel, list& result) { - for (vector::iterator i = lines.begin(); i != lines.end(); ++i) { - (*i)->get_inverted_selectables (sel, result); + for (Lines::iterator i = lines.begin(); i != lines.end(); ++i) { + i->first->get_inverted_selectables (sel, result); } } void AutomationTimeAxisView::set_selected_points (PointSelection& points) { - for (vector::iterator i = lines.begin(); i != lines.end(); ++i) { - (*i)->set_selected_points (points); + for (Lines::iterator i = lines.begin(); i != lines.end(); ++i) { + i->first->set_selected_points (points); } } void AutomationTimeAxisView::clear_lines () { - for (vector::iterator i = lines.begin(); i != lines.end(); ++i) { - delete *i; - } + for (Lines::iterator i = lines.begin(); i != lines.end(); ++i) + delete i->first; lines.clear (); automation_connection.disconnect (); @@ -765,33 +787,38 @@ AutomationTimeAxisView::add_line (AutomationLine& line) if (lines.empty()) { /* first line is the Model for automation state */ - automation_connection = line.the_list().automation_state_changed.connect + automation_connection = line.the_list()->automation_state_changed.connect (mem_fun(*this, &AutomationTimeAxisView::automation_state_changed)); get = true; } - lines.push_back (&line); + lines.push_back (std::make_pair(&line, + AutomationController::create(_session, line.the_list(), + route->control(line.the_list()->param_id())))); + line.set_y_position_and_height (0, height); if (get) { /* pick up the current state */ automation_state_changed (); } + + line.show(); } void AutomationTimeAxisView::show_all_control_points () { - for (vector::iterator i = lines.begin(); i != lines.end(); ++i) { - (*i)->show_all_control_points (); + for (Lines::iterator i = lines.begin(); i != lines.end(); ++i) { + i->first->show_all_control_points (); } } void AutomationTimeAxisView::hide_all_but_selected_control_points () { - for (vector::iterator i = lines.begin(); i != lines.end(); ++i) { - (*i)->hide_all_but_selected_control_points (); + for (Lines::iterator i = lines.begin(); i != lines.end(); ++i) { + i->first->hide_all_but_selected_control_points (); } } @@ -808,36 +835,23 @@ AutomationTimeAxisView::exited () } void -AutomationTimeAxisView::set_colors () { - - for( list::iterator i=ghosts.begin(); i != ghosts.end(); i++ ) { - (*i)->set_colors(); +AutomationTimeAxisView::set_colors () +{ + for (list::iterator i=ghosts.begin(); i != ghosts.end(); i++ ) { + (*i)->set_colors(); } - for( vector::iterator i=lines.begin(); i != lines.end(); i++ ) { - (*i)->set_colors(); + for (Lines::iterator i=lines.begin(); i != lines.end(); i++ ) { + i->first->set_colors(); } - } void AutomationTimeAxisView::color_handler () { - - //case cGhostTrackWave: - //case cGhostTrackWaveClip: - //case cGhostTrackZeroLine: - - //case cControlPoint: - //case cControlPointFill: - //case cControlPointOutline: - //case cAutomationLine: set_colors (); - } - - void AutomationTimeAxisView::set_state (const XMLNode& node) { diff --git a/gtk2_ardour/automation_time_axis.h b/gtk2_ardour/automation_time_axis.h index e302e14ebb..b88c21d68d 100644 --- a/gtk2_ardour/automation_time_axis.h +++ b/gtk2_ardour/automation_time_axis.h @@ -23,6 +23,7 @@ #include #include #include +#include #include @@ -31,6 +32,7 @@ #include "canvas.h" #include "time_axis_view.h" #include "simplerect.h" +#include "automation_controller.h" using std::vector; using std::list; @@ -50,6 +52,8 @@ class GhostRegion; class Selection; class Selectable; +/** TODO: All the derived types of this can probably be merged into this cleanly. + */ class AutomationTimeAxisView : public TimeAxisView { public: AutomationTimeAxisView (ARDOUR::Session&, @@ -72,7 +76,8 @@ class AutomationTimeAxisView : public TimeAxisView { virtual void clear_lines (); virtual void add_line (AutomationLine&); - vector lines; + typedef vector > > Lines; + Lines lines; void set_selected_points (PointSelection&); void get_selectables (nframes_t start, nframes_t end, double top, double bot, list&); @@ -102,6 +107,7 @@ class AutomationTimeAxisView : public TimeAxisView { string _name; string _state_name; bool in_destructor; + bool ignore_toggle; bool first_call_to_set_height; @@ -132,7 +138,7 @@ class AutomationTimeAxisView : public TimeAxisView { bool paste_one (AutomationLine&, nframes_t, float times, Selection&, size_t nth); void reset_objects_one (AutomationLine&, PointSelection&); - virtual void set_automation_state (ARDOUR::AutoState) = 0; + void set_automation_state (ARDOUR::AutoState); bool ignore_state_request; void automation_state_changed (); diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index 61250c1289..520db57eb4 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -1163,7 +1163,7 @@ Editor::connect_to_session (Session *t) RouteTimeAxisView *rtv; if ((rtv = dynamic_cast(tv)) != 0) { - if (rtv->route()->master()) { + if (rtv->route()->is_master()) { route_list_display.get_selection()->unselect (i); } } diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc index f6f4d3bf0b..bcbb806b79 100644 --- a/gtk2_ardour/editor_mouse.cc +++ b/gtk2_ardour/editor_mouse.cc @@ -1676,7 +1676,7 @@ Editor::start_fade_in_grab (ArdourCanvas::Item* item, GdkEvent* event) AudioRegionView* arv = static_cast(drag_info.data); - drag_info.pointer_frame_offset = drag_info.grab_frame - ((nframes_t) arv->audio_region()->fade_in().back()->when + arv->region()->position()); + drag_info.pointer_frame_offset = drag_info.grab_frame - ((nframes_t) arv->audio_region()->fade_in()->back()->when + arv->region()->position()); } void @@ -1755,13 +1755,13 @@ Editor::fade_in_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* even continue; } - AutomationList& alist = tmp->audio_region()->fade_in(); - XMLNode &before = alist.get_state(); + boost::shared_ptr alist = tmp->audio_region()->fade_in(); + XMLNode &before = alist->get_state(); tmp->audio_region()->set_fade_in_length (fade_length); - XMLNode &after = alist.get_state(); - session->add_command(new MementoCommand(alist, &before, &after)); + XMLNode &after = alist->get_state(); + session->add_command(new MementoCommand(*alist.get(), &before, &after)); } commit_reversible_command (); @@ -1783,7 +1783,7 @@ Editor::start_fade_out_grab (ArdourCanvas::Item* item, GdkEvent* event) AudioRegionView* arv = static_cast(drag_info.data); - drag_info.pointer_frame_offset = drag_info.grab_frame - (arv->region()->length() - (nframes_t) arv->audio_region()->fade_out().back()->when + arv->region()->position()); + drag_info.pointer_frame_offset = drag_info.grab_frame - (arv->region()->length() - (nframes_t) arv->audio_region()->fade_out()->back()->when + arv->region()->position()); } void @@ -1871,13 +1871,13 @@ Editor::fade_out_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* eve continue; } - AutomationList& alist = tmp->audio_region()->fade_out(); - XMLNode &before = alist.get_state(); + boost::shared_ptr alist = tmp->audio_region()->fade_out(); + XMLNode &before = alist->get_state(); tmp->audio_region()->set_fade_out_length (fade_length); - XMLNode &after = alist.get_state(); - session->add_command(new MementoCommand(alist, &before, &after)); + XMLNode &after = alist->get_state(); + session->add_command(new MementoCommand(*alist.get(), &before, &after)); } commit_reversible_command (); diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc index 843e0e3add..ccfcdbd6c5 100644 --- a/gtk2_ardour/editor_ops.cc +++ b/gtk2_ardour/editor_ops.cc @@ -3392,11 +3392,11 @@ Editor::reset_region_gain_envelopes () for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) { AudioRegionView* const arv = dynamic_cast(*i); if (arv) { - AutomationList& alist (arv->audio_region()->envelope()); - XMLNode& before (alist.get_state()); + boost::shared_ptr alist (arv->audio_region()->envelope()); + XMLNode& before (alist->get_state()); arv->audio_region()->set_default_envelope (); - session->add_command (new MementoCommand(arv->audio_region()->envelope(), &before, &alist.get_state())); + session->add_command (new MementoCommand(*arv->audio_region()->envelope().get(), &before, &alist->get_state())); } } @@ -3485,13 +3485,13 @@ Editor::set_fade_in_shape (AudioRegion::FadeShape shape) return; } - AutomationList& alist = tmp->audio_region()->fade_in(); - XMLNode &before = alist.get_state(); + boost::shared_ptr alist = tmp->audio_region()->fade_in(); + XMLNode &before = alist->get_state(); tmp->audio_region()->set_fade_in_shape (shape); - XMLNode &after = alist.get_state(); - session->add_command(new MementoCommand(alist, &before, &after)); + XMLNode &after = alist->get_state(); + session->add_command(new MementoCommand(*alist.get(), &before, &after)); } commit_reversible_command (); @@ -3509,13 +3509,13 @@ Editor::set_fade_out_shape (AudioRegion::FadeShape shape) return; } - AutomationList& alist = tmp->audio_region()->fade_out(); - XMLNode &before = alist.get_state(); + boost::shared_ptr alist = tmp->audio_region()->fade_out(); + XMLNode &before = alist->get_state(); tmp->audio_region()->set_fade_out_shape (shape); - XMLNode &after = alist.get_state(); - session->add_command(new MementoCommand(alist, &before, &after)); + XMLNode &after = alist->get_state(); + session->add_command(new MementoCommand(*alist.get(), &before, &after)); } commit_reversible_command (); diff --git a/gtk2_ardour/editor_route_list.cc b/gtk2_ardour/editor_route_list.cc index 04ef8b46b0..e11738f65b 100644 --- a/gtk2_ardour/editor_route_list.cc +++ b/gtk2_ardour/editor_route_list.cc @@ -56,7 +56,7 @@ Editor::handle_new_route (Session::RouteList& routes) for (Session::RouteList::iterator x = routes.begin(); x != routes.end(); ++x) { boost::shared_ptr route = (*x); - if (route->hidden()) { + if (route->is_hidden()) { continue; } diff --git a/gtk2_ardour/export_dialog.cc b/gtk2_ardour/export_dialog.cc index 2d73887d3a..2cf96fe02a 100644 --- a/gtk2_ardour/export_dialog.cc +++ b/gtk2_ardour/export_dialog.cc @@ -1089,7 +1089,7 @@ ExportDialog::fill_lists () boost::shared_ptr route = (*ri); - if (route->hidden()) { + if (route->is_hidden()) { continue; } diff --git a/gtk2_ardour/gain_automation_time_axis.cc b/gtk2_ardour/gain_automation_time_axis.cc index 509c941555..0daec3b250 100644 --- a/gtk2_ardour/gain_automation_time_axis.cc +++ b/gtk2_ardour/gain_automation_time_axis.cc @@ -33,12 +33,12 @@ using namespace Gtk; GainAutomationTimeAxisView::GainAutomationTimeAxisView (Session& s, boost::shared_ptr r, PublicEditor& e, TimeAxisView& parent, - ArdourCanvas::Canvas& canvas, const string & n, ARDOUR::AutomationList& l) + ArdourCanvas::Canvas& canvas, const string & n, + boost::shared_ptr c) : AxisView (s), AutomationTimeAxisView (s, r, e, parent, canvas, n, X_("gain"), ""), - list (l) - + _control (c) { } @@ -59,20 +59,13 @@ GainAutomationTimeAxisView::add_automation_event (ArdourCanvas::Item* item, GdkE /* map using line */ - lines.front()->view_to_model_y (y); + lines.front().first->view_to_model_y (y); _session.begin_reversible_command (_("add gain automation event")); - XMLNode& before = list.get_state(); - list.add (when, y); - XMLNode& after = list.get_state(); - _session.commit_reversible_command (new MementoCommand(list, &before, &after)); + XMLNode& before = _control->list()->get_state(); + _control->list()->add (when, y); + XMLNode& after = _control->list()->get_state(); + _session.commit_reversible_command (new MementoCommand(*_control->list(), &before, &after)); _session.set_dirty (); } -void -GainAutomationTimeAxisView::set_automation_state (AutoState state) -{ - if (!ignore_state_request) { - 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 3f07be4ace..f4132acb20 100644 --- a/gtk2_ardour/gain_automation_time_axis.h +++ b/gtk2_ardour/gain_automation_time_axis.h @@ -25,6 +25,7 @@ namespace ARDOUR { class AutomationList; + class AutomationControl; } class GainAutomationTimeAxisView : public AutomationTimeAxisView @@ -36,17 +37,16 @@ class GainAutomationTimeAxisView : public AutomationTimeAxisView TimeAxisView& parent_axis, ArdourCanvas::Canvas& canvas, const string & name, - ARDOUR::AutomationList&); + boost::shared_ptr control); ~GainAutomationTimeAxisView(); void add_automation_event (ArdourCanvas::Item *item, GdkEvent *event, nframes_t, double); private: - ARDOUR::AutomationList& list; + boost::shared_ptr _control; void automation_changed (); - void set_automation_state (ARDOUR::AutoState); }; #endif /* __ardour_gtk_gain_automation_time_axis_h__ */ diff --git a/gtk2_ardour/gain_meter.cc b/gtk2_ardour/gain_meter.cc index a4eea61bfa..d365066774 100644 --- a/gtk2_ardour/gain_meter.cc +++ b/gtk2_ardour/gain_meter.cc @@ -91,7 +91,7 @@ GainMeter::GainMeter (boost::shared_ptr io, Session& s) gain_slider = manage (new VSliderController (slider, &gain_adjustment, - _io->gain_control(), + *_io->gain_control().get(), false)); gain_slider->signal_button_press_event().connect (mem_fun(*this, &GainMeter::start_gain_touch)); @@ -154,12 +154,12 @@ GainMeter::GainMeter (boost::shared_ptr io, Session& s) if ((r = dynamic_cast (_io.get())) != 0) { - /* + /* if we have a route (ie. we're not the click), pack some route-dependent stuff. */ - gain_display_box.pack_end (peak_display, true, true); + gain_display_box.pack_end (peak_display, true, true); hbox.pack_end (meter_packer, true, true); @@ -187,8 +187,8 @@ GainMeter::GainMeter (boost::shared_ptr 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().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)); + r->gain_control()->list()->automation_state_changed.connect (mem_fun(*this, &GainMeter::gain_automation_state_changed)); + r->gain_control()->list()->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 (); @@ -199,7 +199,7 @@ GainMeter::GainMeter (boost::shared_ptr io, Session& s) pack_start (gain_display_box, Gtk::PACK_SHRINK); pack_start (hbox, Gtk::PACK_SHRINK); - _io->gain_changed.connect (mem_fun(*this, &GainMeter::gain_changed)); + _io->gain_control()->Changed.connect (mem_fun(*this, &GainMeter::gain_changed)); meter_metric_area.signal_expose_event().connect (mem_fun(*this, &GainMeter::meter_metrics_expose)); gain_adjustment.signal_value_changed().connect (mem_fun(*this, &GainMeter::gain_adjusted)); @@ -208,7 +208,7 @@ GainMeter::GainMeter (boost::shared_ptr io, Session& s) Config->ParameterChanged.connect (mem_fun (*this, &GainMeter::parameter_changed)); - gain_changed (0); + gain_changed (); show_gain (); update_gain_sensitive (); @@ -606,7 +606,7 @@ GainMeter::gain_activated () f = min (f, 6.0f); - _io->set_gain (dB_to_coefficient(f), this); + _io->gain_control()->set_value (dB_to_coefficient(f)); if (gain_display.has_focus()) { PublicEditor::instance().reset_focus(); @@ -634,7 +634,7 @@ void GainMeter::gain_adjusted () { if (!ignore_toggle) { - _io->set_gain (slider_position_to_gain (gain_adjustment.get_value()), this); + _io->gain_control()->set_value (slider_position_to_gain (gain_adjustment.get_value())); } show_gain (); } @@ -652,7 +652,7 @@ GainMeter::effective_gain_display () } void -GainMeter::gain_changed (void *src) +GainMeter::gain_changed () { Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &GainMeter::effective_gain_display)); } @@ -672,7 +672,7 @@ GainMeter::set_fader_name (const char * name) void GainMeter::update_gain_sensitive () { - static_cast(gain_slider)->set_sensitive (!(_io->gain_automation().automation_state() & Play)); + static_cast(gain_slider)->set_sensitive (!(_io->gain_control()->list()->automation_state() & Play)); } @@ -815,14 +815,14 @@ GainMeter::meter_point_clicked () gint GainMeter::start_gain_touch (GdkEventButton* ev) { - _io->gain_automation().start_touch (); + _io->gain_control()->list()->start_touch (); return FALSE; } gint GainMeter::end_gain_touch (GdkEventButton* ev) { - _io->gain_automation().stop_touch (); + _io->gain_control()->list()->stop_touch (); return FALSE; } @@ -926,10 +926,10 @@ GainMeter::gain_automation_style_changed () // Route* _route = dynamic_cast(&_io); switch (_width) { case Wide: - gain_automation_style_button.set_label (astyle_string(_io->gain_automation().automation_style())); + gain_automation_style_button.set_label (astyle_string(_io->gain_control()->list()->automation_style())); break; case Narrow: - gain_automation_style_button.set_label (short_astyle_string(_io->gain_automation().automation_style())); + gain_automation_style_button.set_label (short_astyle_string(_io->gain_control()->list()->automation_style())); break; } } @@ -944,14 +944,14 @@ GainMeter::gain_automation_state_changed () switch (_width) { case Wide: - gain_automation_state_button.set_label (astate_string(_io->gain_automation().automation_state())); + gain_automation_state_button.set_label (astate_string(_io->gain_control()->list()->automation_state())); break; case Narrow: - gain_automation_state_button.set_label (short_astate_string(_io->gain_automation().automation_state())); + gain_automation_state_button.set_label (short_astate_string(_io->gain_control()->list()->automation_state())); break; } - x = (_io->gain_automation().automation_state() != Off); + x = (_io->gain_control()->list()->automation_state() != Off); if (gain_automation_state_button.get_active() != x) { ignore_toggle = true; diff --git a/gtk2_ardour/gain_meter.h b/gtk2_ardour/gain_meter.h index 447271ed55..3839221e73 100644 --- a/gtk2_ardour/gain_meter.h +++ b/gtk2_ardour/gain_meter.h @@ -149,7 +149,7 @@ class GainMeter : public Gtk::VBox Gtk::HBox meter_packer; void gain_adjusted (); - void gain_changed (void *); + void gain_changed (); void meter_point_clicked (); void gain_unit_changed (); diff --git a/gtk2_ardour/ladspa_pluginui.cc b/gtk2_ardour/ladspa_pluginui.cc index 721e50753a..eacc8f024b 100644 --- a/gtk2_ardour/ladspa_pluginui.cc +++ b/gtk2_ardour/ladspa_pluginui.cc @@ -496,7 +496,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 (ParamID(PluginAutomation, port_index))->automation_state_changed.connect + insert->control (ParamID(PluginAutomation, port_index))->list()->automation_state_changed.connect (bind (mem_fun(*this, &LadspaPluginUI::automation_state_changed), control_ui)); } else if (plugin->parameter_is_output (port_index)) { @@ -553,13 +553,13 @@ LadspaPluginUI::build_control_ui (guint32 port_index, PBD::Controllable* mcontro void LadspaPluginUI::start_touch (LadspaPluginUI::ControlUI* cui) { - insert->automation_list (ParamID(PluginAutomation, cui->port_index))->start_touch (); + insert->control (ParamID(PluginAutomation, cui->port_index))->list()->start_touch (); } void LadspaPluginUI::stop_touch (LadspaPluginUI::ControlUI* cui) { - insert->automation_list (ParamID(PluginAutomation, cui->port_index))->stop_touch (); + insert->control (ParamID(PluginAutomation, cui->port_index))->list()->stop_touch (); } void diff --git a/gtk2_ardour/midi_controller_time_axis.cc b/gtk2_ardour/midi_controller_time_axis.cc index a3dcb0f508..d25b5e398a 100644 --- a/gtk2_ardour/midi_controller_time_axis.cc +++ b/gtk2_ardour/midi_controller_time_axis.cc @@ -20,6 +20,7 @@ #include #include #include +#include #include "midi_controller_time_axis.h" #include "automation_line.h" @@ -34,12 +35,10 @@ using namespace Gtk; MidiControllerTimeAxisView::MidiControllerTimeAxisView (Session& s, boost::shared_ptr r, PublicEditor& e, TimeAxisView& parent, ArdourCanvas::Canvas& canvas, const string & n, - ParamID param, ARDOUR::AutomationList& l) - + boost::shared_ptr c) : AxisView (s), - AutomationTimeAxisView (s, r, e, parent, canvas, n, param.to_string(), ""), - _list (l), - _param (param) + AutomationTimeAxisView (s, r, e, parent, canvas, n, c->list()->param_id().to_string(), ""), + _control (c) { } @@ -60,22 +59,13 @@ MidiControllerTimeAxisView::add_automation_event (ArdourCanvas::Item* item, GdkE /* map using line */ - lines.front()->view_to_model_y (y); + lines.front().first->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(_list, &before, &after)); + XMLNode& before = _control->list()->get_state(); + _control->list()->add (when, y); + XMLNode& after = _control->list()->get_state(); + _session.commit_reversible_command (new MementoCommand(*_control->list().get(), &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 index 78f3c12c1a..db14a77ca9 100644 --- a/gtk2_ardour/midi_controller_time_axis.h +++ b/gtk2_ardour/midi_controller_time_axis.h @@ -36,19 +36,16 @@ class MidiControllerTimeAxisView : public AutomationTimeAxisView TimeAxisView& parent_axis, ArdourCanvas::Canvas& canvas, const string & name, - ARDOUR::ParamID param, - ARDOUR::AutomationList&); + boost::shared_ptr c); ~MidiControllerTimeAxisView(); void add_automation_event (ArdourCanvas::Item *item, GdkEvent *event, nframes_t, double); private: - ARDOUR::AutomationList& _list; - ARDOUR::ParamID _param; + boost::shared_ptr _control; 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 52c9a29f12..8fe5823c78 100644 --- a/gtk2_ardour/midi_time_axis.cc +++ b/gtk2_ardour/midi_time_axis.cc @@ -185,12 +185,13 @@ MidiTimeAxisView::create_automation_child (ParamID param) /* FIXME: this all probably leaks */ - ARDOUR::AutomationList* al = _route->automation_list(param); + boost::shared_ptr c =_route->control(param); - if (!al) - al = new ARDOUR::AutomationList(param, 0, 127, 64); - - _route->add_automation_parameter(al); + if (!c) { + boost::shared_ptr al(new ARDOUR::AutomationList(param, 0, 127, 64)); + c = boost::shared_ptr(new AutomationControl(_session, al)); + _route->add_control(c); + } MidiControllerTimeAxisView* track = new MidiControllerTimeAxisView (_session, _route, @@ -198,13 +199,12 @@ MidiTimeAxisView::create_automation_child (ParamID param) *this, parent_canvas, _route->describe_parameter(param), - param, - *al); + c); AutomationMidiCCLine* line = new AutomationMidiCCLine (param.to_string(), *track, *track->canvas_display, - *al); + c->list()); line->set_line_color (Config->canvasvar_AutomationLine.get()); diff --git a/gtk2_ardour/mixer_strip.cc b/gtk2_ardour/mixer_strip.cc index 40571d3e91..54c3965993 100644 --- a/gtk2_ardour/mixer_strip.cc +++ b/gtk2_ardour/mixer_strip.cc @@ -261,7 +261,7 @@ MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, boost::shared_ptr rt global_vpacker.pack_start (output_button, Gtk::PACK_SHRINK); global_vpacker.pack_start (comment_button, Gtk::PACK_SHRINK); - if (route()->master() || route()->control()) { + if (route()->is_master() || route()->is_control()) { if (scrollbar_height == 0) { HScrollbar scrollbar; @@ -403,6 +403,8 @@ MixerStrip::set_width (Width w, void* owner) pre_processor_box.set_width (w); post_processor_box.set_width (w); + boost::shared_ptr gain_automation = _route->gain_control()->list(); + _width_owner = owner; if (_width == w) { @@ -435,8 +437,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().automation_style())); - ((Gtk::Label*)gpm.gain_automation_state_button.get_child())->set_text (gpm.astate_string(_route->gain_automation().automation_state())); + ((Gtk::Label*)gpm.gain_automation_style_button.get_child())->set_text (gpm.astyle_string(gain_automation->automation_style())); + ((Gtk::Label*)gpm.gain_automation_state_button.get_child())->set_text (gpm.astate_string(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 +459,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().automation_style())); - ((Gtk::Label*)gpm.gain_automation_state_button.get_child())->set_text (gpm.short_astate_string(_route->gain_automation().automation_state())); + ((Gtk::Label*)gpm.gain_automation_style_button.get_child())->set_text (gpm.short_astyle_string(gain_automation->automation_style())); + ((Gtk::Label*)gpm.gain_automation_state_button.get_child())->set_text (gpm.short_astate_string(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); @@ -699,8 +701,8 @@ MixerStrip::connect_to_pan () if (!_route->panner().empty()) { StreamPanner* sp = _route->panner().front(); - panstate_connection = sp->automation().automation_state_changed.connect (mem_fun(panners, &PannerUI::pan_automation_state_changed)); - panstyle_connection = sp->automation().automation_style_changed.connect (mem_fun(panners, &PannerUI::pan_automation_style_changed)); + panstate_connection = sp->automation()->automation_state_changed.connect (mem_fun(panners, &PannerUI::pan_automation_state_changed)); + panstyle_connection = sp->automation()->automation_style_changed.connect (mem_fun(panners, &PannerUI::pan_automation_style_changed)); } panners.pan_changed (this); diff --git a/gtk2_ardour/mixer_ui.cc b/gtk2_ardour/mixer_ui.cc index 665420fdbd..11f9b6357d 100644 --- a/gtk2_ardour/mixer_ui.cc +++ b/gtk2_ardour/mixer_ui.cc @@ -267,7 +267,7 @@ Mixer_UI::add_strip (Session::RouteList& routes) for (Session::RouteList::iterator x = routes.begin(); x != routes.end(); ++x) { boost::shared_ptr route = (*x); - if (route->hidden()) { + if (route->is_hidden()) { return; } @@ -473,7 +473,7 @@ Mixer_UI::set_all_strips_visibility (bool yn) continue; } - if (strip->route()->master() || strip->route()->control()) { + if (strip->route()->is_master() || strip->route()->is_control()) { continue; } @@ -501,7 +501,7 @@ Mixer_UI::set_all_audio_visibility (int tracks, bool yn) continue; } - if (strip->route()->master() || strip->route()->control()) { + if (strip->route()->is_master() || strip->route()->is_control()) { continue; } @@ -605,7 +605,7 @@ Mixer_UI::redisplay_track_list () if (strip->packed()) { - if (strip->route()->master() || strip->route()->control()) { + if (strip->route()->is_master() || strip->route()->is_control()) { out_packer.reorder_child (*strip, -1); } else { strip_packer.reorder_child (*strip, -1); /* put at end */ @@ -613,7 +613,7 @@ Mixer_UI::redisplay_track_list () } else { - if (strip->route()->master() || strip->route()->control()) { + if (strip->route()->is_master() || strip->route()->is_control()) { out_packer.pack_start (*strip, false, false); } else { strip_packer.pack_start (*strip, false, false); @@ -624,7 +624,7 @@ Mixer_UI::redisplay_track_list () } else { - if (strip->route()->master() || strip->route()->control()) { + if (strip->route()->is_master() || strip->route()->is_control()) { /* do nothing, these cannot be hidden */ } else { if (strip->packed()) { @@ -702,7 +702,7 @@ Mixer_UI::track_display_button_press (GdkEventButton* ev) MixerStrip* strip = (*iter)[track_columns.strip]; if (strip) { - if (!strip->route()->master() && !strip->route()->control()) { + if (!strip->route()->is_master() && !strip->route()->is_control()) { bool visible = (*iter)[track_columns.visible]; (*iter)[track_columns.visible] = !visible; } diff --git a/gtk2_ardour/pan_automation_time_axis.cc b/gtk2_ardour/pan_automation_time_axis.cc index 1199982b5d..49eed5d221 100644 --- a/gtk2_ardour/pan_automation_time_axis.cc +++ b/gtk2_ardour/pan_automation_time_axis.cc @@ -88,15 +88,15 @@ PanAutomationTimeAxisView::add_automation_event (ArdourCanvas::Item* item, GdkEv /* map using line */ - lines.front()->view_to_model_y (y); + lines.front().first->view_to_model_y (y); - AutomationList& alist (lines[line_index]->the_list()); + boost::shared_ptr alist (lines[line_index].first->the_list()); _session.begin_reversible_command (_("add pan automation event")); - XMLNode &before = alist.get_state(); - alist.add (when, y); - XMLNode &after = alist.get_state(); - _session.add_command(new MementoCommand(alist, &before, &after)); + XMLNode &before = alist->get_state(); + alist->add (when, y); + XMLNode &after = alist->get_state(); + _session.add_command(new MementoCommand(*alist.get(), &before, &after)); _session.commit_reversible_command (); _session.set_dirty (); } @@ -147,11 +147,3 @@ PanAutomationTimeAxisView::set_height (TimeAxisView::TrackHeight th) multiline_selector.hide(); } } - -void -PanAutomationTimeAxisView::set_automation_state (AutoState state) -{ - if (!ignore_state_request) { - route->panner().set_automation_state (state); - } -} diff --git a/gtk2_ardour/pan_automation_time_axis.h b/gtk2_ardour/pan_automation_time_axis.h index d4a22ebc29..fdffa875ca 100644 --- a/gtk2_ardour/pan_automation_time_axis.h +++ b/gtk2_ardour/pan_automation_time_axis.h @@ -52,7 +52,6 @@ class PanAutomationTimeAxisView : public AutomationTimeAxisView private: void automation_changed (); - void set_automation_state (ARDOUR::AutoState); }; #endif /* __ardour_gtk_pan_automation_time_axis_h__ */ diff --git a/gtk2_ardour/panner.cc b/gtk2_ardour/panner.cc index 23fae953a1..2607cdf2b8 100644 --- a/gtk2_ardour/panner.cc +++ b/gtk2_ardour/panner.cc @@ -34,8 +34,8 @@ null_label_callback (char* buf, unsigned int bufsize) } -PannerBar::PannerBar (Gtk::Adjustment& adj, PBD::Controllable& c) - : BarController (adj, c, sigc::ptr_fun (null_label_callback)) +PannerBar::PannerBar (Gtk::Adjustment& adj, boost::shared_ptr c) + : BarController (adj, *c.get(), sigc::ptr_fun (null_label_callback)) { set_style (BarController::Line); } diff --git a/gtk2_ardour/panner.h b/gtk2_ardour/panner.h index 6813f3d032..21f984aa7c 100644 --- a/gtk2_ardour/panner.h +++ b/gtk2_ardour/panner.h @@ -21,11 +21,12 @@ #define __gtk_ardour_panner_h__ #include +#include class PannerBar : public Gtkmm2ext::BarController { public: - PannerBar (Gtk::Adjustment& adj, PBD::Controllable&); + PannerBar (Gtk::Adjustment& adj, boost::shared_ptr); ~PannerBar (); protected: diff --git a/gtk2_ardour/panner_ui.cc b/gtk2_ardour/panner_ui.cc index 42ccba992e..0e12a418e7 100644 --- a/gtk2_ardour/panner_ui.cc +++ b/gtk2_ardour/panner_ui.cc @@ -573,9 +573,9 @@ PannerUI::update_pan_bars (bool only_if_aplay) float xpos, val; if (only_if_aplay) { - AutomationList& alist (_io->panner()[n]->automation()); + boost::shared_ptr alist (_io->panner()[n]->automation()); - if (!alist.automation_playback()) { + if (!alist->automation_playback()) { continue; } } @@ -707,7 +707,7 @@ PannerUI::pan_automation_state_changed () return; } - x = (_io->panner().front()->automation().automation_state() != Off); + x = (_io->panner().front()->automation()->automation_state() != Off); if (pan_automation_state_button.get_active() != x) { ignore_toggle = true; diff --git a/gtk2_ardour/processor_automation_line.cc b/gtk2_ardour/processor_automation_line.cc index 8b83b736f0..86eb7c7a7d 100644 --- a/gtk2_ardour/processor_automation_line.cc +++ b/gtk2_ardour/processor_automation_line.cc @@ -32,12 +32,11 @@ using namespace std; using namespace ARDOUR; using namespace PBD; -ProcessorAutomationLine::ProcessorAutomationLine (const string & name, Processor& proc, ParamID param, - TimeAxisView& tv, ArdourCanvas::Group& parent, AutomationList& l) +ProcessorAutomationLine::ProcessorAutomationLine (const string & name, Processor& proc, + TimeAxisView& tv, ArdourCanvas::Group& parent, boost::shared_ptr l) : AutomationLine (name, tv, parent, l), - _processor(proc), - _param(param) + _processor(proc) { set_verbose_cursor_uses_gain_mapping (false); @@ -49,7 +48,7 @@ ProcessorAutomationLine::ProcessorAutomationLine (const string & name, Processor /*NOTREACHED*/ } - pi->plugin()->get_parameter_descriptor (_param, desc); + pi->plugin()->get_parameter_descriptor (l->param_id(), desc); _upper = desc.upper; _lower = desc.lower; diff --git a/gtk2_ardour/processor_automation_line.h b/gtk2_ardour/processor_automation_line.h index 3a0a95786b..422f2b7f6f 100644 --- a/gtk2_ardour/processor_automation_line.h +++ b/gtk2_ardour/processor_automation_line.h @@ -33,17 +33,15 @@ class TimeAxisView; class ProcessorAutomationLine : public AutomationLine { public: - ProcessorAutomationLine (const string & name, ARDOUR::Processor&, ARDOUR::ParamID param, - TimeAxisView&, ArdourCanvas::Group& parent, ARDOUR::AutomationList&); + ProcessorAutomationLine (const string & name, ARDOUR::Processor&, + TimeAxisView&, ArdourCanvas::Group& parent, boost::shared_ptr); - ARDOUR::ParamID param() const { return _param; } ARDOUR::Processor& processor() const { return _processor; } string get_verbose_cursor_string (float); private: ARDOUR::Processor& _processor; - ARDOUR::ParamID _param; float _upper; float _lower; diff --git a/gtk2_ardour/processor_automation_time_axis.cc b/gtk2_ardour/processor_automation_time_axis.cc index 37c996d17e..4940f1fc10 100644 --- a/gtk2_ardour/processor_automation_time_axis.cc +++ b/gtk2_ardour/processor_automation_time_axis.cc @@ -91,11 +91,11 @@ ProcessorAutomationTimeAxisView::add_automation_event (ArdourCanvas::Item* item, /* map to model space */ if (!lines.empty()) { - AutomationList* alist (_processor.automation_list(_param, true)); + boost::shared_ptr alist (_processor.control(_param, true)->list()); string description = _("add automation event to "); description += _processor.describe_parameter (_param); - lines.front()->view_to_model_y (y); + lines.front().first->view_to_model_y (y); _session.begin_reversible_command (description); XMLNode &before = alist->get_state(); @@ -168,7 +168,33 @@ void ProcessorAutomationTimeAxisView::set_automation_state (AutoState state) { if (!ignore_state_request) { - _processor.automation_list (_param, true)->set_automation_state (state); + _processor.control (_param, true)->list()->set_automation_state (state); } } +void +ProcessorAutomationTimeAxisView::add_line (AutomationLine& line) +{ + bool get = false; + + if (lines.empty()) { + /* first line is the Model for automation state */ + automation_connection = line.the_list()->automation_state_changed.connect + (mem_fun(*this, &ProcessorAutomationTimeAxisView::automation_state_changed)); + get = true; + } + + lines.push_back (std::make_pair(&line, + AutomationController::create(_session, line.the_list(), + _processor.control(line.the_list()->param_id())))); + + line.set_y_position_and_height (0, height); + + if (get) { + /* pick up the current state */ + automation_state_changed (); + } + + line.show(); +} + diff --git a/gtk2_ardour/processor_automation_time_axis.h b/gtk2_ardour/processor_automation_time_axis.h index ec8caaf98f..980acdc441 100644 --- a/gtk2_ardour/processor_automation_time_axis.h +++ b/gtk2_ardour/processor_automation_time_axis.h @@ -46,6 +46,7 @@ class ProcessorAutomationTimeAxisView : public AutomationTimeAxisView ~ProcessorAutomationTimeAxisView(); void add_automation_event (ArdourCanvas::Item *item, GdkEvent *event, nframes_t, double); + void add_line (AutomationLine&); guint32 show_at (double y, int& nth, Gtk::VBox *parent); void hide (); diff --git a/gtk2_ardour/processor_box.cc b/gtk2_ardour/processor_box.cc index 51257e18c0..756067e1e2 100644 --- a/gtk2_ardour/processor_box.cc +++ b/gtk2_ardour/processor_box.cc @@ -347,7 +347,7 @@ ProcessorBox::processor_button_release_event (GdkEventButton *ev) Menu * ProcessorBox::build_processor_menu () { - processor_menu = dynamic_cast(ActionManager::get_widget("/redirectmenu") ); + processor_menu = dynamic_cast(ActionManager::get_widget("/processormenu") ); processor_menu->set_name ("ArdourContextMenu"); show_all_children(); @@ -1184,7 +1184,7 @@ ProcessorBox::enter_box (GdkEventCrossing *ev, ProcessorBox* rb) void ProcessorBox::register_actions () { - Glib::RefPtr popup_act_grp = Gtk::ActionGroup::create(X_("redirectmenu")); + Glib::RefPtr popup_act_grp = Gtk::ActionGroup::create(X_("processormenu")); Glib::RefPtr act; /* new stuff */ diff --git a/gtk2_ardour/region_gain_line.cc b/gtk2_ardour/region_gain_line.cc index 25ba903ca8..6299813121 100644 --- a/gtk2_ardour/region_gain_line.cc +++ b/gtk2_ardour/region_gain_line.cc @@ -38,7 +38,7 @@ using namespace std; using namespace ARDOUR; using namespace PBD; -AudioRegionGainLine::AudioRegionGainLine (const string & name, Session& s, AudioRegionView& r, ArdourCanvas::Group& parent, AutomationList& l) +AudioRegionGainLine::AudioRegionGainLine (const string & name, Session& s, AudioRegionView& r, ArdourCanvas::Group& parent, boost::shared_ptr l) : AutomationLine (name, r.get_time_axis_view(), parent, l), session (s), rv (r) @@ -67,8 +67,8 @@ AudioRegionGainLine::start_drag (ControlPoint* cp, nframes_t x, float fraction) { AutomationLine::start_drag (cp, x, fraction); if (!rv.audio_region()->envelope_active()) { - trackview.session().add_command(new MementoCommand(*(rv.audio_region().get()), &rv.audio_region()->get_state(), 0)); - rv.audio_region()->set_envelope_active(false); + trackview.session().add_command(new MementoCommand(*(rv.audio_region().get()), &rv.audio_region()->get_state(), 0)); + rv.audio_region()->set_envelope_active(false); } } @@ -81,18 +81,18 @@ AudioRegionGainLine::remove_point (ControlPoint& cp) model_representation (cp, mr); trackview.editor.current_session()->begin_reversible_command (_("remove control point")); - XMLNode &before = alist.get_state(); + XMLNode &before = alist->get_state(); if (!rv.audio_region()->envelope_active()) { - XMLNode ®ion_before = rv.audio_region()->get_state(); + XMLNode ®ion_before = rv.audio_region()->get_state(); rv.audio_region()->set_envelope_active(true); - XMLNode ®ion_after = rv.audio_region()->get_state(); - trackview.session().add_command(new MementoCommand(*(rv.audio_region().get()), ®ion_before, ®ion_after)); + XMLNode ®ion_after = rv.audio_region()->get_state(); + trackview.session().add_command(new MementoCommand(*(rv.audio_region().get()), ®ion_before, ®ion_after)); } - alist.erase (mr.start, mr.end); + alist->erase (mr.start, mr.end); - trackview.editor.current_session()->add_command (new MementoCommand(alist, &before, &alist.get_state())); + trackview.editor.current_session()->add_command (new MementoCommand(*alist.get(), &before, &alist->get_state())); trackview.editor.current_session()->commit_reversible_command (); trackview.editor.current_session()->set_dirty (); } diff --git a/gtk2_ardour/region_gain_line.h b/gtk2_ardour/region_gain_line.h index 259615aa39..fe03c0f76f 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::AutomationList&); + AudioRegionGainLine (const string & name, ARDOUR::Session&, AudioRegionView&, ArdourCanvas::Group& parent, boost::shared_ptr); void view_to_model_y (double&); void model_to_view_y (double&); diff --git a/gtk2_ardour/route_params_ui.cc b/gtk2_ardour/route_params_ui.cc index fb63ae8bd6..cbddd098bb 100644 --- a/gtk2_ardour/route_params_ui.cc +++ b/gtk2_ardour/route_params_ui.cc @@ -178,7 +178,7 @@ RouteParams_UI::add_routes (Session::RouteList& routes) for (Session::RouteList::iterator x = routes.begin(); x != routes.end(); ++x) { boost::shared_ptr route = (*x); - if (route->hidden()) { + if (route->is_hidden()) { return; } diff --git a/gtk2_ardour/route_time_axis.cc b/gtk2_ardour/route_time_axis.cc index 3b89517fce..dff6630213 100644 --- a/gtk2_ardour/route_time_axis.cc +++ b/gtk2_ardour/route_time_axis.cc @@ -1570,7 +1570,7 @@ RouteTimeAxisView::show_existing_automation () map::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) { + if (!i->second->track->lines.empty() && i->second->track->lines[0].first->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")); @@ -1714,14 +1714,16 @@ RouteTimeAxisView::add_processor_automation_curve (boost::shared_ptr /* create a string that is a legal XML node name that can be used to refer to this redirect+port combination */ + /* FIXME: ew */ + char state_name[256]; snprintf (state_name, sizeof (state_name), "Redirect-%s-%" PRIu32, legalize_for_xml_node (processor->name()).c_str(), what.id()); ran->view = new ProcessorAutomationTimeAxisView (_session, _route, editor, *this, parent_canvas, name, what, *processor, state_name); ral = new ProcessorAutomationLine (name, - *processor, what, *ran->view, - *ran->view->canvas_display, *processor->automation_list (what, true)); + *processor, *ran->view, *ran->view->canvas_display, + processor->control (what, true)->list()); ral->set_line_color (Config->canvasvar_ProcessorAutomationLine.get()); ral->queue_reset (); @@ -1974,7 +1976,7 @@ RouteTimeAxisView::find_processor_automation_curve (boost::shared_ptr if ((ran = find_processor_automation_node (processor, what)) != 0) { if (ran->view) { - return dynamic_cast (ran->view->lines.front()); + return dynamic_cast (ran->view->lines.front().first); } } diff --git a/gtk2_ardour/route_ui.cc b/gtk2_ardour/route_ui.cc index 95042af6ea..76c4b7b5b3 100644 --- a/gtk2_ardour/route_ui.cc +++ b/gtk2_ardour/route_ui.cc @@ -80,10 +80,10 @@ RouteUI::RouteUI (boost::shared_ptr rt, ARDOUR::Session& sess, co _route->active_changed.connect (mem_fun (*this, &RouteUI::route_active_changed)); - mute_button = manage (new BindableToggleButton (_route->mute_control(), m_name )); + mute_button = manage (new BindableToggleButton (*_route->mute_control().get(), m_name )); mute_button->set_self_managed (true); - solo_button = manage (new BindableToggleButton (_route->solo_control(), s_name )); + solo_button = manage (new BindableToggleButton (*_route->solo_control().get(), s_name )); solo_button->set_self_managed (true); mute_button->set_name ("MuteButton"); @@ -104,7 +104,7 @@ RouteUI::RouteUI (boost::shared_ptr rt, ARDOUR::Session& sess, co _session.RecordStateChanged.connect (mem_fun (*this, &RouteUI::session_rec_enable_changed)); - rec_enable_button = manage (new BindableToggleButton (t->rec_enable_control(), r_name )); + rec_enable_button = manage (new BindableToggleButton (*t->rec_enable_control().get(), r_name )); rec_enable_button->set_name ("RecordEnableButton"); rec_enable_button->set_self_managed (true); diff --git a/gtk2_ardour/utils.cc b/gtk2_ardour/utils.cc index e47be6a54b..c20b56f6f4 100644 --- a/gtk2_ardour/utils.cc +++ b/gtk2_ardour/utils.cc @@ -31,7 +31,6 @@ #include #include -//#include #include diff --git a/libs/ardour/SConscript b/libs/ardour/SConscript index dd76aadcba..f93c19649f 100644 --- a/libs/ardour/SConscript +++ b/libs/ardour/SConscript @@ -77,6 +77,7 @@ gdither.cc globals.cc import.cc automatable.cc +automation_control.cc processor.cc io_processor.cc plugin_insert.cc diff --git a/libs/ardour/ardour/audioregion.h b/libs/ardour/ardour/audioregion.h index db763876b0..52a07679af 100644 --- a/libs/ardour/ardour/audioregion.h +++ b/libs/ardour/ardour/audioregion.h @@ -67,9 +67,9 @@ class AudioRegion : public Region bool fade_in_active () const { return _flags & Region::FadeIn; } bool fade_out_active () const { return _flags & Region::FadeOut; } - AutomationList& fade_in() { return _fade_in; } - AutomationList& fade_out() { return _fade_out; } - AutomationList& envelope() { return _envelope; } + boost::shared_ptr fade_in() { return _fade_in; } + boost::shared_ptr fade_out() { return _fade_out; } + boost::shared_ptr envelope() { return _envelope; } virtual nframes_t read_peaks (PeakData *buf, nframes_t npeaks, nframes_t offset, nframes_t cnt, @@ -162,14 +162,14 @@ class AudioRegion : public Region void source_offset_changed (); void listen_to_my_curves (); - mutable AutomationList _fade_in; - FadeShape _fade_in_shape; - mutable AutomationList _fade_out; - FadeShape _fade_out_shape; - mutable AutomationList _envelope; - gain_t _scale_amplitude; - uint32_t _fade_in_disabled; - uint32_t _fade_out_disabled; + boost::shared_ptr _fade_in; + FadeShape _fade_in_shape; + boost::shared_ptr _fade_out; + FadeShape _fade_out_shape; + boost::shared_ptr _envelope; + gain_t _scale_amplitude; + uint32_t _fade_in_disabled; + uint32_t _fade_out_disabled; protected: /* default constructor for derived (compound) types */ diff --git a/libs/ardour/ardour/automatable.h b/libs/ardour/ardour/automatable.h index f6d6d86ed0..a1161db80d 100644 --- a/libs/ardour/ardour/automatable.h +++ b/libs/ardour/ardour/automatable.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2000,2007 Paul Davis + 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 @@ -22,13 +22,16 @@ #include #include +#include #include #include +#include #include namespace ARDOUR { class Session; +class AutomationControl; class Automatable : public SessionObject { @@ -38,16 +41,17 @@ public: virtual ~Automatable() {} // shorthand for gain, pan, etc - inline AutomationList* automation_list(AutomationType type, bool create_if_missing=false) { - return automation_list(ParamID(type), create_if_missing); + inline boost::shared_ptr + control(AutomationType type, bool create_if_missing=false) { + return control(ParamID(type), create_if_missing); } - virtual AutomationList* automation_list(ParamID id, bool create_if_missing=false); - virtual const AutomationList* automation_list(ParamID id) const; + virtual boost::shared_ptr control(ParamID id, bool create_if_missing=false); + virtual boost::shared_ptr control(ParamID id) const; - virtual void add_automation_parameter(AutomationList* al); + virtual void add_control(boost::shared_ptr); - virtual void automation_snapshot(nframes_t now) {}; + virtual void automation_snapshot(nframes_t now); virtual bool find_next_event(nframes_t start, nframes_t end, ControlEvent& ev) const; @@ -74,7 +78,7 @@ protected: void can_automate(ParamID); - virtual void automation_list_creation_callback(ParamID, AutomationList&) {} + virtual void auto_state_changed (ParamID which) {} int set_automation_state(const XMLNode&, ParamID default_param); XMLNode& get_automation_state(); @@ -83,9 +87,11 @@ protected: int old_set_automation_state(const XMLNode&); mutable Glib::Mutex _automation_lock; - - std::map _parameter_automation; - std::set _visible_parameter_automation; + + typedef std::map > Controls; + + Controls _controls; + std::set _visible_controls; std::set _can_automate_list; nframes_t _last_automation_snapshot; diff --git a/libs/ardour/ardour/automation_control.h b/libs/ardour/ardour/automation_control.h new file mode 100644 index 0000000000..d9e7a232af --- /dev/null +++ b/libs/ardour/ardour/automation_control.h @@ -0,0 +1,59 @@ +/* + Copyright (C) 2007 Paul Davis + Author: Dave Robillard + + 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_automation_control_h__ +#define __ardour_automation_control_h__ + +#include +#include + +namespace ARDOUR { + +class AutomationList; +class Session; + + +/** A PBD:Controllable with associated automation data (AutomationList) + */ +class AutomationControl : public PBD::Controllable +{ +public: + AutomationControl(ARDOUR::Session&, boost::shared_ptr, + std::string name="unnamed controllable"); + + void set_value(float val); + float get_value() const; + float user_value() const; + + void set_list(boost::shared_ptr); + + boost::shared_ptr list() { return _list; } + boost::shared_ptr list() const { return _list; } + +protected: + ARDOUR::Session& _session; + boost::shared_ptr _list; + float _user_value; +}; + + +} // namespace ARDOUR + +#endif /* __ardour_automation_control_h__ */ diff --git a/libs/ardour/ardour/io.h b/libs/ardour/ardour/io.h index fc49f0699f..60e1fc25f1 100644 --- a/libs/ardour/ardour/io.h +++ b/libs/ardour/ardour/io.h @@ -42,6 +42,7 @@ #include #include #include +#include using std::string; using std::vector; @@ -60,6 +61,7 @@ class AudioPort; class MidiPort; class BufferSet; + /** A collection of input and output ports with connections. * * An IO can contain ports of varying types, making routes/inserts/etc with @@ -103,8 +105,6 @@ class IO : public Automatable, public Latent void just_meter_input (nframes_t start_frame, nframes_t end_frame, nframes_t nframes, nframes_t offset); - virtual void set_gain (gain_t g, void *src); - void inc_gain (gain_t delta, void *src); gain_t gain () const { return _desired_gain; } virtual gain_t effective_gain () const; @@ -182,8 +182,6 @@ class IO : public Automatable, public Latent sigc::signal input_changed; sigc::signal output_changed; - sigc::signal gain_changed; - virtual XMLNode& state (bool full); XMLNode& get_state (void); int set_state (const XMLNode&); @@ -206,10 +204,6 @@ class IO : public Automatable, public Latent static sigc::signal MoreChannels; static sigc::signal PortsCreated; - PBD::Controllable& gain_control() { - return _gain_control; - } - static void update_meters(); private: @@ -221,13 +215,24 @@ class IO : public Automatable, public Latent public: /* automation */ + + struct GainControl : public AutomationControl { + GainControl (std::string name, IO& i, boost::shared_ptr al) + : AutomationControl (i._session, al, name) + , _io (i) + {} + + void set_value (float val); + float get_value (void) const; + + IO& _io; + }; - static void set_automation_interval (nframes_t frames) { - _automation_interval = frames; + boost::shared_ptr gain_control() { + return _gain_control; } - - static nframes_t automation_interval() { - return _automation_interval; + boost::shared_ptr gain_control() const { + return _gain_control; } void clear_automation (); @@ -237,10 +242,6 @@ class IO : public Automatable, public Latent virtual void transport_stopped (nframes_t now); // interface: matches Insert void automation_snapshot (nframes_t now); // interface: matches Automatable - // FIXME: these will probably become unsafe in the near future - ARDOUR::AutomationList& gain_automation() { return *automation_list(GainAutomation); } - const ARDOUR::AutomationList& gain_automation() const { return *automation_list(GainAutomation); } - void start_pan_touch (uint32_t which); void end_pan_touch (uint32_t which); @@ -282,25 +283,12 @@ class IO : public Automatable, public Latent virtual uint32_t pans_required() const { return _inputs.count().n_audio(); } - struct GainControllable : public PBD::Controllable { - GainControllable (std::string name, IO& i) : Controllable (name), io (i) {} - - void set_value (float val); - float get_value (void) const; - - IO& io; - }; + boost::shared_ptr _gain_control; - GainControllable _gain_control; - - nframes_t last_automation_snapshot; - static nframes_t _automation_interval; - - /*AutoState _gain_automation_state; - AutoStyle _gain_automation_style;*/ + virtual void set_gain (gain_t g, void *src); + void inc_gain (gain_t delta, void *src); bool apply_gain_automation; - //Curve _gain_automation_curve; virtual int load_automation (std::string path); diff --git a/libs/ardour/ardour/panner.h b/libs/ardour/ardour/panner.h index af3cda94e2..89f56e03c5 100644 --- a/libs/ardour/ardour/panner.h +++ b/libs/ardour/ardour/panner.h @@ -76,14 +76,14 @@ class StreamPanner : public sigc::trackable, public PBD::Stateful virtual void set_automation_state (AutoState) = 0; virtual void set_automation_style (AutoStyle) = 0; - PBD::Controllable& control() { return _control; } + boost::shared_ptr control() { return _control; } /* XXX this is wrong. for multi-dimensional panners, there must surely be more than 1 automation curve. */ /* TODO: Panner is-a Automation solves this */ - virtual AutomationList& automation() = 0; + virtual boost::shared_ptr automation() = 0; sigc::signal Changed; /* for position */ sigc::signal StateChanged; /* for mute */ @@ -125,7 +125,7 @@ class StreamPanner : public sigc::trackable, public PBD::Stateful bool can_send_feedback() const; }; - PanControllable _control; + boost::shared_ptr _control; void add_state (XMLNode&); virtual void update () = 0; @@ -151,7 +151,7 @@ class BaseStereoPanner : public StreamPanner void set_automation_style (AutoStyle); /* TODO: StreamPanner is-a Automatable? */ - AutomationList& automation() { return _automation; } + boost::shared_ptr automation() { return _automation; } /* old school automation loading */ @@ -165,7 +165,7 @@ class BaseStereoPanner : public StreamPanner float left_interp; float right_interp; - AutomationList _automation; + boost::shared_ptr _automation; }; class EqualPowerStereoPanner : public BaseStereoPanner @@ -208,7 +208,7 @@ class Multi2dPanner : public StreamPanner /* TODO: StreamPanner is-a Automatable? */ - AutomationList& automation() { return _automation; } + boost::shared_ptr automation() { return _automation; } void distribute (AudioBuffer& src, BufferSet& obufs, gain_t gain_coeff, nframes_t nframes); void distribute_automated (AudioBuffer& src, BufferSet& obufs, @@ -226,7 +226,7 @@ class Multi2dPanner : public StreamPanner int load (istream&, string path, uint32_t&); private: - AutomationList _automation; + boost::shared_ptr _automation; void update (); }; diff --git a/libs/ardour/ardour/plugin_insert.h b/libs/ardour/ardour/plugin_insert.h index e3b1b62b19..90c83057df 100644 --- a/libs/ardour/ardour/plugin_insert.h +++ b/libs/ardour/ardour/plugin_insert.h @@ -109,7 +109,6 @@ class PluginInsert : public Processor void init (); void set_automatable (); void auto_state_changed (ParamID which); - void automation_list_creation_callback (ParamID, AutomationList&); int32_t count_for_configuration (ChanCount in, ChanCount out) const; diff --git a/libs/ardour/ardour/processor.h b/libs/ardour/ardour/processor.h index 3985306d01..371572610a 100644 --- a/libs/ardour/ardour/processor.h +++ b/libs/ardour/ardour/processor.h @@ -80,7 +80,7 @@ class Processor : public Automatable, public Latent virtual bool configure_io (ChanCount in, ChanCount out) { _configured_input = in; return (_configured = true); } - /* Act as a pass through, if not overridden */ + /* Derived classes should override these, or processor appears as a pass-through */ virtual bool can_support_input_configuration (ChanCount in) const { return true; } virtual ChanCount output_for_input_configuration (ChanCount in) const { return in; } virtual ChanCount output_streams() const { return _configured_input; } diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h index b8c9431e42..1fd6eff0f8 100644 --- a/libs/ardour/ardour/route.h +++ b/libs/ardour/ardour/route.h @@ -81,9 +81,9 @@ class Route : public IO long order_key (const char* name) const; void set_order_key (const char* name, long n); - bool hidden() const { return _flags & Hidden; } - bool master() const { return _flags & MasterOut; } - bool control() const { return _flags & ControlOut; } + bool is_hidden() const { return _flags & Hidden; } + bool is_master() const { return _flags & MasterOut; } + bool is_control() const { return _flags & ControlOut; } /* these are the core of the API of a Route. see the protected sections as well */ @@ -243,11 +243,11 @@ class Route : public IO ToggleType type; }; - PBD::Controllable& solo_control() { + boost::shared_ptr solo_control() { return _solo_control; } - PBD::Controllable& mute_control() { + boost::shared_ptr mute_control() { return _mute_control; } @@ -306,8 +306,8 @@ class Route : public IO std::string _comment; bool _have_internal_generator; - ToggleControllable _solo_control; - ToggleControllable _mute_control; + boost::shared_ptr _solo_control; + boost::shared_ptr _mute_control; nframes_t check_initial_delay (nframes_t, nframes_t&, nframes_t&); diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 3a4a21cb8a..2c4c60a911 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -649,9 +649,11 @@ class Session : public PBD::StatefulDestructible sigc::signal NamedSelectionAdded; sigc::signal NamedSelectionRemoved; - /* Curves and AutomationLists (TODO when they go away) */ - void add_curve(Curve*); - void add_automation_list(AutomationList*); + /* Curves and AutomationLists (TODO when they go away) */ + void add_curve(Curve*); + void add_automation_list(AutomationList*); + + nframes_t automation_interval () const { return _automation_interval; } /* fade curves */ @@ -780,9 +782,9 @@ class Session : public PBD::StatefulDestructible std::map registry; - // these commands are implemented in libs/ardour/session_command.cc + // these commands are implemented in libs/ardour/session_command.cc Command* memento_command_factory(XMLNode* n); - void register_with_memento_command_factory(PBD::ID, PBD::StatefulThingWithGoingAway*); + void register_with_memento_command_factory(PBD::ID, PBD::StatefulThingWithGoingAway*); Command* global_state_command_factory (const XMLNode& n); @@ -917,9 +919,9 @@ class Session : public PBD::StatefulDestructible /* Controllables */ - PBD::Controllable* controllable_by_id (const PBD::ID&); + boost::shared_ptr controllable_by_id (const PBD::ID&); - void add_controllable (PBD::Controllable*); + void add_controllable (boost::shared_ptr); void remove_controllable (PBD::Controllable*); protected: @@ -1648,6 +1650,8 @@ class Session : public PBD::StatefulDestructible void allocate_pan_automation_buffers (nframes_t nframes, uint32_t howmany, bool force); uint32_t _npan_buffers; + nframes_t _automation_interval; + /* VST support */ long _vst_callback (VSTPlugin*, @@ -1672,7 +1676,7 @@ class Session : public PBD::StatefulDestructible LayerModel layer_model; CrossfadeModel xfade_model; - typedef std::set Controllables; + typedef std::set > Controllables; Glib::Mutex controllables_lock; Controllables controllables; diff --git a/libs/ardour/ardour/track.h b/libs/ardour/ardour/track.h index 06ce398896..4d5545c0dc 100644 --- a/libs/ardour/ardour/track.h +++ b/libs/ardour/ardour/track.h @@ -83,7 +83,7 @@ class Track : public Route XMLNode& get_template(); virtual int set_state(const XMLNode& node) = 0; - PBD::Controllable& rec_enable_control() { return _rec_enable_control; } + boost::shared_ptr rec_enable_control() { return _rec_enable_control; } bool record_enabled() const; void set_record_enable (bool yn, void *src); @@ -141,8 +141,9 @@ class Track : public Route XMLNode* pending_state; sigc::connection recenable_connection; sigc::connection ic_connection; - RecEnableControllable _rec_enable_control; bool _destructive; + + boost::shared_ptr _rec_enable_control; }; }; /* namespace ARDOUR*/ diff --git a/libs/ardour/audio_track.cc b/libs/ardour/audio_track.cc index 9f13aee465..4df8ffea49 100644 --- a/libs/ardour/audio_track.cc +++ b/libs/ardour/audio_track.cc @@ -278,8 +278,8 @@ AudioTrack::_set_state (const XMLNode& node, bool call_base) child = *niter; if (child->name() == X_("recenable")) { - _rec_enable_control.set_state (*child); - _session.add_controllable (&_rec_enable_control); + _rec_enable_control->set_state (*child); + _session.add_controllable (_rec_enable_control); } } @@ -334,7 +334,7 @@ AudioTrack::state(bool full_state) _diskstream->id().print (buf, sizeof (buf)); root.add_property ("diskstream-id", buf); - root.add_child_nocopy (_rec_enable_control.get_state()); + root.add_child_nocopy (_rec_enable_control->get_state()); return root; } @@ -601,8 +601,8 @@ AudioTrack::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, if (!diskstream->record_enabled() && _session.transport_rolling()) { Glib::Mutex::Lock am (_automation_lock, Glib::TRY_LOCK); - if (am.locked() && gain_automation().automation_playback()) { - apply_gain_automation = gain_automation().curve().rt_safe_get_vector (start_frame, end_frame, _session.gain_automation_buffer(), nframes); + if (am.locked() && gain_control()->list()->automation_playback()) { + apply_gain_automation = gain_control()->list()->curve().rt_safe_get_vector (start_frame, end_frame, _session.gain_automation_buffer(), nframes); } } @@ -696,9 +696,9 @@ AudioTrack::export_stuff (BufferSet& buffers, nframes_t start, nframes_t nframes } } - if (IO::gain_automation().automation_state() == Play) { + if (gain_control()->list()->automation_state() == Play) { - IO::gain_automation().curve().get_vector (start, start + nframes, gain_automation, nframes); + gain_control()->list()->curve().get_vector (start, start + nframes, gain_automation, nframes); for (BufferSet::audio_iterator bi = buffers.audio_begin(); bi != buffers.audio_end(); ++bi) { Sample *b = bi->data(); diff --git a/libs/ardour/audioregion.cc b/libs/ardour/audioregion.cc index a7a5fca912..359c729368 100644 --- a/libs/ardour/audioregion.cc +++ b/libs/ardour/audioregion.cc @@ -72,20 +72,20 @@ AudioRegion::init () /* constructor for use by derived types only */ AudioRegion::AudioRegion (nframes_t start, nframes_t length, string name) - : Region (start, length, name, DataType::AUDIO), - _fade_in (ParamID(FadeInAutomation), 0.0, 2.0, 1.0), - _fade_out (ParamID(FadeOutAutomation), 0.0, 2.0, 1.0), - _envelope (ParamID(EnvelopeAutomation), 0.0, 2.0, 1.0) + : Region (start, length, name, DataType::AUDIO) + , _fade_in (new AutomationList(ParamID(FadeInAutomation), 0.0, 2.0, 1.0)) + , _fade_out (new AutomationList(ParamID(FadeOutAutomation), 0.0, 2.0, 1.0)) + , _envelope (new AutomationList(ParamID(EnvelopeAutomation), 0.0, 2.0, 1.0)) { init (); } /** Basic AudioRegion constructor (one channel) */ AudioRegion::AudioRegion (boost::shared_ptr src, nframes_t start, nframes_t length) - : Region (src, start, length, PBD::basename_nosuffix(src->name()), DataType::AUDIO, 0, Region::Flag(Region::DefaultFlags|Region::External)), - _fade_in (ParamID(FadeInAutomation), 0.0, 2.0, 1.0), - _fade_out (ParamID(FadeOutAutomation), 0.0, 2.0, 1.0), - _envelope (ParamID(EnvelopeAutomation), 0.0, 2.0, 1.0) + : Region (src, start, length, PBD::basename_nosuffix(src->name()), DataType::AUDIO, 0, Region::Flag(Region::DefaultFlags|Region::External)) + , _fade_in (new AutomationList(ParamID(FadeInAutomation), 0.0, 2.0, 1.0)) + , _fade_out (new AutomationList(ParamID(FadeOutAutomation), 0.0, 2.0, 1.0)) + , _envelope (new AutomationList(ParamID(EnvelopeAutomation), 0.0, 2.0, 1.0)) { boost::shared_ptr afs = boost::dynamic_pointer_cast (src); if (afs) { @@ -98,9 +98,9 @@ AudioRegion::AudioRegion (boost::shared_ptr src, nframes_t start, n /* Basic AudioRegion constructor (one channel) */ AudioRegion::AudioRegion (boost::shared_ptr src, nframes_t start, nframes_t length, const string& name, layer_t layer, Flag flags) : Region (src, start, length, name, DataType::AUDIO, layer, flags) - , _fade_in (ParamID(FadeInAutomation), 0.0, 2.0, 1.0) - , _fade_out (ParamID(FadeOutAutomation), 0.0, 2.0, 1.0) - , _envelope (ParamID(EnvelopeAutomation), 0.0, 2.0, 1.0) + , _fade_in (new AutomationList(ParamID(FadeInAutomation), 0.0, 2.0, 1.0)) + , _fade_out (new AutomationList(ParamID(FadeOutAutomation), 0.0, 2.0, 1.0)) + , _envelope (new AutomationList(ParamID(EnvelopeAutomation), 0.0, 2.0, 1.0)) { boost::shared_ptr afs = boost::dynamic_pointer_cast (src); if (afs) { @@ -113,9 +113,9 @@ AudioRegion::AudioRegion (boost::shared_ptr src, nframes_t start, n /* Basic AudioRegion constructor (many channels) */ AudioRegion::AudioRegion (SourceList& srcs, nframes_t start, nframes_t length, const string& name, layer_t layer, Flag flags) : Region (srcs, start, length, name, DataType::AUDIO, layer, flags) - , _fade_in (ParamID(FadeInAutomation), 0.0, 2.0, 1.0) - , _fade_out (ParamID(FadeOutAutomation), 0.0, 2.0, 1.0) - , _envelope (ParamID(EnvelopeAutomation), 0.0, 2.0, 1.0) + , _fade_in (new AutomationList(ParamID(FadeInAutomation), 0.0, 2.0, 1.0)) + , _fade_out (new AutomationList(ParamID(FadeOutAutomation), 0.0, 2.0, 1.0)) + , _envelope (new AutomationList(ParamID(EnvelopeAutomation), 0.0, 2.0, 1.0)) { init (); } @@ -123,10 +123,10 @@ AudioRegion::AudioRegion (SourceList& srcs, nframes_t start, nframes_t length, c /** Create a new AudioRegion, that is part of an existing one */ AudioRegion::AudioRegion (boost::shared_ptr other, nframes_t offset, nframes_t length, const string& name, layer_t layer, Flag flags) - : Region (other, offset, length, name, layer, flags), - _fade_in (other->_fade_in), - _fade_out (other->_fade_out), - _envelope (other->_envelope, (double) offset, (double) offset + length) + : Region (other, offset, length, name, layer, flags) + , _fade_in (new AutomationList(ParamID(FadeInAutomation), 0.0, 2.0, 1.0)) + , _fade_out (new AutomationList(ParamID(FadeOutAutomation), 0.0, 2.0, 1.0)) + , _envelope (new AutomationList(ParamID(EnvelopeAutomation), 0.0, 2.0, 1.0)) { /* return to default fades if the existing ones are too long */ _fade_in_disabled = 0; @@ -134,7 +134,7 @@ AudioRegion::AudioRegion (boost::shared_ptr other, nframes_t if (_flags & LeftOfSplit) { - if (_fade_in.back()->when >= _length) { + if (_fade_in->back()->when >= _length) { set_default_fade_in (); } else { _fade_in_disabled = other->_fade_in_disabled; @@ -144,7 +144,7 @@ AudioRegion::AudioRegion (boost::shared_ptr other, nframes_t } if (_flags & RightOfSplit) { - if (_fade_out.back()->when >= _length) { + if (_fade_out->back()->when >= _length) { set_default_fade_out (); } else { _fade_out_disabled = other->_fade_out_disabled; @@ -161,10 +161,10 @@ AudioRegion::AudioRegion (boost::shared_ptr other, nframes_t } AudioRegion::AudioRegion (boost::shared_ptr other) - : Region (other), - _fade_in (other->_fade_in), - _fade_out (other->_fade_out), - _envelope (other->_envelope) + : Region (other) + , _fade_in (new AutomationList(ParamID(FadeInAutomation), 0.0, 2.0, 1.0)) + , _fade_out (new AutomationList(ParamID(FadeOutAutomation), 0.0, 2.0, 1.0)) + , _envelope (new AutomationList(ParamID(EnvelopeAutomation), 0.0, 2.0, 1.0)) { _scale_amplitude = other->_scale_amplitude; _envelope = other->_envelope; @@ -179,9 +179,9 @@ AudioRegion::AudioRegion (boost::shared_ptr other) AudioRegion::AudioRegion (boost::shared_ptr src, const XMLNode& node) : Region (src, node) - , _fade_in (ParamID(FadeInAutomation), 0.0, 2.0, 1.0) - , _fade_out (ParamID(FadeOutAutomation), 0.0, 2.0, 1.0) - , _envelope (ParamID(EnvelopeAutomation), 0.0, 2.0, 1.0) + , _fade_in (new AutomationList(ParamID(FadeInAutomation), 0.0, 2.0, 1.0)) + , _fade_out (new AutomationList(ParamID(FadeOutAutomation), 0.0, 2.0, 1.0)) + , _envelope (new AutomationList(ParamID(EnvelopeAutomation), 0.0, 2.0, 1.0)) { boost::shared_ptr afs = boost::dynamic_pointer_cast (src); if (afs) { @@ -201,9 +201,9 @@ AudioRegion::AudioRegion (boost::shared_ptr src, const XMLNode& nod AudioRegion::AudioRegion (SourceList& srcs, const XMLNode& node) : Region (srcs, node) - , _fade_in (ParamID(FadeInAutomation), 0.0, 2.0, 1.0) - , _fade_out (ParamID(FadeOutAutomation), 0.0, 2.0, 1.0) - , _envelope (ParamID(EnvelopeAutomation), 0.0, 2.0, 1.0) + , _fade_in (new AutomationList(ParamID(FadeInAutomation), 0.0, 2.0, 1.0)) + , _fade_out (new AutomationList(ParamID(FadeOutAutomation), 0.0, 2.0, 1.0)) + , _envelope (new AutomationList(ParamID(EnvelopeAutomation), 0.0, 2.0, 1.0)) { set_default_fades (); _scale_amplitude = 1.0; @@ -224,9 +224,9 @@ AudioRegion::~AudioRegion () void AudioRegion::listen_to_my_curves () { - _envelope.StateChanged.connect (mem_fun (*this, &AudioRegion::envelope_changed)); - _fade_in.StateChanged.connect (mem_fun (*this, &AudioRegion::fade_in_changed)); - _fade_out.StateChanged.connect (mem_fun (*this, &AudioRegion::fade_out_changed)); + _envelope->StateChanged.connect (mem_fun (*this, &AudioRegion::envelope_changed)); + _fade_in->StateChanged.connect (mem_fun (*this, &AudioRegion::fade_in_changed)); + _fade_out->StateChanged.connect (mem_fun (*this, &AudioRegion::fade_out_changed)); } bool @@ -395,7 +395,7 @@ AudioRegion::_read_at (const SourceList& srcs, Sample *buf, Sample *mixdown_buff if (_flags & FadeIn) { - nframes_t fade_in_length = (nframes_t) _fade_in.back()->when; + nframes_t fade_in_length = (nframes_t) _fade_in->back()->when; /* see if this read is within the fade in */ @@ -405,7 +405,7 @@ AudioRegion::_read_at (const SourceList& srcs, Sample *buf, Sample *mixdown_buff limit = min (to_read, fade_in_length - internal_offset); - _fade_in.curve().get_vector (internal_offset, internal_offset+limit, gain_buffer, limit); + _fade_in->curve().get_vector (internal_offset, internal_offset+limit, gain_buffer, limit); for (nframes_t n = 0; n < limit; ++n) { mixdown_buffer[n] *= gain_buffer[n]; @@ -436,7 +436,7 @@ AudioRegion::_read_at (const SourceList& srcs, Sample *buf, Sample *mixdown_buff */ - nframes_t fade_out_length = (nframes_t) _fade_out.back()->when; + nframes_t fade_out_length = (nframes_t) _fade_out->back()->when; nframes_t fade_interval_start = max(internal_offset, _length-fade_out_length); nframes_t fade_interval_end = min(internal_offset + to_read, _length); @@ -447,7 +447,7 @@ AudioRegion::_read_at (const SourceList& srcs, Sample *buf, Sample *mixdown_buff nframes_t curve_offset = fade_interval_start - (_length-fade_out_length); nframes_t fade_offset = fade_interval_start - internal_offset; - _fade_out.curve().get_vector (curve_offset,curve_offset+limit, gain_buffer, limit); + _fade_out->curve().get_vector (curve_offset,curve_offset+limit, gain_buffer, limit); for (nframes_t n = 0, m = fade_offset; n < limit; ++n, ++m) { mixdown_buffer[m] *= gain_buffer[n]; @@ -459,7 +459,7 @@ AudioRegion::_read_at (const SourceList& srcs, Sample *buf, Sample *mixdown_buff /* Regular gain curves */ if (envelope_active()) { - _envelope.curve().get_vector (internal_offset, internal_offset + to_read, gain_buffer, to_read); + _envelope->curve().get_vector (internal_offset, internal_offset + to_read, gain_buffer, to_read); if (_scale_amplitude != 1.0f) { for (nframes_t n = 0; n < to_read; ++n) { @@ -521,7 +521,7 @@ AudioRegion::state (bool full) if ((_flags & DefaultFadeIn)) { child->add_property (X_("default"), X_("yes")); } else { - child->add_child_nocopy (_fade_in.get_state ()); + child->add_child_nocopy (_fade_in->get_state ()); } child->add_property (X_("active"), _fade_in_disabled ? X_("no") : X_("yes")); @@ -531,7 +531,7 @@ AudioRegion::state (bool full) if ((_flags & DefaultFadeOut)) { child->add_property (X_("default"), X_("yes")); } else { - child->add_child_nocopy (_fade_out.get_state ()); + child->add_child_nocopy (_fade_out->get_state ()); } child->add_property (X_("active"), _fade_out_disabled ? X_("no") : X_("yes")); @@ -545,10 +545,10 @@ AudioRegion::state (bool full) // If there are only two points, the points are in the start of the region and the end of the region // so, if they are both at 1.0f, that means the default region. - if (_envelope.size() == 2 && - _envelope.front()->value == 1.0f && - _envelope.back()->value==1.0f) { - if (_envelope.front()->when == 0 && _envelope.back()->when == _length) { + if (_envelope->size() == 2 && + _envelope->front()->value == 1.0f && + _envelope->back()->value==1.0f) { + if (_envelope->front()->when == 0 && _envelope->back()->when == _length) { default_env = true; } } @@ -556,7 +556,7 @@ AudioRegion::state (bool full) if (default_env) { child->add_property ("default", "yes"); } else { - child->add_child_nocopy (_envelope.get_state ()); + child->add_child_nocopy (_envelope->get_state ()); } } else { @@ -617,28 +617,28 @@ AudioRegion::set_live_state (const XMLNode& node, Change& what_changed, bool sen if (child->name() == "Envelope") { - _envelope.clear (); + _envelope->clear (); - if ((prop = child->property ("default")) != 0 || _envelope.set_state (*child)) { + if ((prop = child->property ("default")) != 0 || _envelope->set_state (*child)) { set_default_envelope (); } - _envelope.set_max_xval (_length); - _envelope.truncate_end (_length); + _envelope->set_max_xval (_length); + _envelope->truncate_end (_length); } else if (child->name() == "FadeIn") { - _fade_in.clear (); + _fade_in->clear (); - if ((prop = child->property ("default")) != 0 || (prop = child->property ("steepness")) != 0 || _fade_in.set_state (*child)) { + if ((prop = child->property ("default")) != 0 || (prop = child->property ("steepness")) != 0 || _fade_in->set_state (*child)) { set_default_fade_in (); } } else if (child->name() == "FadeOut") { - _fade_out.clear (); + _fade_out->clear (); - if ((prop = child->property ("default")) != 0 || (prop = child->property ("steepness")) != 0 || _fade_out.set_state (*child)) { + if ((prop = child->property ("default")) != 0 || (prop = child->property ("steepness")) != 0 || _fade_out->set_state (*child)) { set_default_fade_out (); } } @@ -665,70 +665,70 @@ AudioRegion::set_state (const XMLNode& node) void AudioRegion::set_fade_in_shape (FadeShape shape) { - set_fade_in (shape, (nframes_t) _fade_in.back()->when); + set_fade_in (shape, (nframes_t) _fade_in->back()->when); } void AudioRegion::set_fade_out_shape (FadeShape shape) { - set_fade_out (shape, (nframes_t) _fade_out.back()->when); + set_fade_out (shape, (nframes_t) _fade_out->back()->when); } void AudioRegion::set_fade_in (FadeShape shape, nframes_t len) { - _fade_in.freeze (); - _fade_in.clear (); + _fade_in->freeze (); + _fade_in->clear (); switch (shape) { case Linear: - _fade_in.fast_simple_add (0.0, 0.0); - _fade_in.fast_simple_add (len, 1.0); + _fade_in->fast_simple_add (0.0, 0.0); + _fade_in->fast_simple_add (len, 1.0); break; case Fast: - _fade_in.fast_simple_add (0, 0); - _fade_in.fast_simple_add (len * 0.389401, 0.0333333); - _fade_in.fast_simple_add (len * 0.629032, 0.0861111); - _fade_in.fast_simple_add (len * 0.829493, 0.233333); - _fade_in.fast_simple_add (len * 0.9447, 0.483333); - _fade_in.fast_simple_add (len * 0.976959, 0.697222); - _fade_in.fast_simple_add (len, 1); + _fade_in->fast_simple_add (0, 0); + _fade_in->fast_simple_add (len * 0.389401, 0.0333333); + _fade_in->fast_simple_add (len * 0.629032, 0.0861111); + _fade_in->fast_simple_add (len * 0.829493, 0.233333); + _fade_in->fast_simple_add (len * 0.9447, 0.483333); + _fade_in->fast_simple_add (len * 0.976959, 0.697222); + _fade_in->fast_simple_add (len, 1); break; case Slow: - _fade_in.fast_simple_add (0, 0); - _fade_in.fast_simple_add (len * 0.0207373, 0.197222); - _fade_in.fast_simple_add (len * 0.0645161, 0.525); - _fade_in.fast_simple_add (len * 0.152074, 0.802778); - _fade_in.fast_simple_add (len * 0.276498, 0.919444); - _fade_in.fast_simple_add (len * 0.481567, 0.980556); - _fade_in.fast_simple_add (len * 0.767281, 1); - _fade_in.fast_simple_add (len, 1); + _fade_in->fast_simple_add (0, 0); + _fade_in->fast_simple_add (len * 0.0207373, 0.197222); + _fade_in->fast_simple_add (len * 0.0645161, 0.525); + _fade_in->fast_simple_add (len * 0.152074, 0.802778); + _fade_in->fast_simple_add (len * 0.276498, 0.919444); + _fade_in->fast_simple_add (len * 0.481567, 0.980556); + _fade_in->fast_simple_add (len * 0.767281, 1); + _fade_in->fast_simple_add (len, 1); break; case LogA: - _fade_in.fast_simple_add (0, 0); - _fade_in.fast_simple_add (len * 0.0737327, 0.308333); - _fade_in.fast_simple_add (len * 0.246544, 0.658333); - _fade_in.fast_simple_add (len * 0.470046, 0.886111); - _fade_in.fast_simple_add (len * 0.652074, 0.972222); - _fade_in.fast_simple_add (len * 0.771889, 0.988889); - _fade_in.fast_simple_add (len, 1); + _fade_in->fast_simple_add (0, 0); + _fade_in->fast_simple_add (len * 0.0737327, 0.308333); + _fade_in->fast_simple_add (len * 0.246544, 0.658333); + _fade_in->fast_simple_add (len * 0.470046, 0.886111); + _fade_in->fast_simple_add (len * 0.652074, 0.972222); + _fade_in->fast_simple_add (len * 0.771889, 0.988889); + _fade_in->fast_simple_add (len, 1); break; case LogB: - _fade_in.fast_simple_add (0, 0); - _fade_in.fast_simple_add (len * 0.304147, 0.0694444); - _fade_in.fast_simple_add (len * 0.529954, 0.152778); - _fade_in.fast_simple_add (len * 0.725806, 0.333333); - _fade_in.fast_simple_add (len * 0.847926, 0.558333); - _fade_in.fast_simple_add (len * 0.919355, 0.730556); - _fade_in.fast_simple_add (len, 1); + _fade_in->fast_simple_add (0, 0); + _fade_in->fast_simple_add (len * 0.304147, 0.0694444); + _fade_in->fast_simple_add (len * 0.529954, 0.152778); + _fade_in->fast_simple_add (len * 0.725806, 0.333333); + _fade_in->fast_simple_add (len * 0.847926, 0.558333); + _fade_in->fast_simple_add (len * 0.919355, 0.730556); + _fade_in->fast_simple_add (len, 1); break; } - _fade_in.thaw (); + _fade_in->thaw (); _fade_in_shape = shape; send_change (FadeInChanged); @@ -737,56 +737,56 @@ AudioRegion::set_fade_in (FadeShape shape, nframes_t len) void AudioRegion::set_fade_out (FadeShape shape, nframes_t len) { - _fade_out.freeze (); - _fade_out.clear (); + _fade_out->freeze (); + _fade_out->clear (); switch (shape) { case Fast: - _fade_out.fast_simple_add (len * 0, 1); - _fade_out.fast_simple_add (len * 0.023041, 0.697222); - _fade_out.fast_simple_add (len * 0.0553, 0.483333); - _fade_out.fast_simple_add (len * 0.170507, 0.233333); - _fade_out.fast_simple_add (len * 0.370968, 0.0861111); - _fade_out.fast_simple_add (len * 0.610599, 0.0333333); - _fade_out.fast_simple_add (len * 1, 0); + _fade_out->fast_simple_add (len * 0, 1); + _fade_out->fast_simple_add (len * 0.023041, 0.697222); + _fade_out->fast_simple_add (len * 0.0553, 0.483333); + _fade_out->fast_simple_add (len * 0.170507, 0.233333); + _fade_out->fast_simple_add (len * 0.370968, 0.0861111); + _fade_out->fast_simple_add (len * 0.610599, 0.0333333); + _fade_out->fast_simple_add (len * 1, 0); break; case LogA: - _fade_out.fast_simple_add (len * 0, 1); - _fade_out.fast_simple_add (len * 0.228111, 0.988889); - _fade_out.fast_simple_add (len * 0.347926, 0.972222); - _fade_out.fast_simple_add (len * 0.529954, 0.886111); - _fade_out.fast_simple_add (len * 0.753456, 0.658333); - _fade_out.fast_simple_add (len * 0.9262673, 0.308333); - _fade_out.fast_simple_add (len * 1, 0); + _fade_out->fast_simple_add (len * 0, 1); + _fade_out->fast_simple_add (len * 0.228111, 0.988889); + _fade_out->fast_simple_add (len * 0.347926, 0.972222); + _fade_out->fast_simple_add (len * 0.529954, 0.886111); + _fade_out->fast_simple_add (len * 0.753456, 0.658333); + _fade_out->fast_simple_add (len * 0.9262673, 0.308333); + _fade_out->fast_simple_add (len * 1, 0); break; case Slow: - _fade_out.fast_simple_add (len * 0, 1); - _fade_out.fast_simple_add (len * 0.305556, 1); - _fade_out.fast_simple_add (len * 0.548611, 0.991736); - _fade_out.fast_simple_add (len * 0.759259, 0.931129); - _fade_out.fast_simple_add (len * 0.918981, 0.68595); - _fade_out.fast_simple_add (len * 0.976852, 0.22865); - _fade_out.fast_simple_add (len * 1, 0); + _fade_out->fast_simple_add (len * 0, 1); + _fade_out->fast_simple_add (len * 0.305556, 1); + _fade_out->fast_simple_add (len * 0.548611, 0.991736); + _fade_out->fast_simple_add (len * 0.759259, 0.931129); + _fade_out->fast_simple_add (len * 0.918981, 0.68595); + _fade_out->fast_simple_add (len * 0.976852, 0.22865); + _fade_out->fast_simple_add (len * 1, 0); break; case LogB: - _fade_out.fast_simple_add (len * 0, 1); - _fade_out.fast_simple_add (len * 0.080645, 0.730556); - _fade_out.fast_simple_add (len * 0.277778, 0.289256); - _fade_out.fast_simple_add (len * 0.470046, 0.152778); - _fade_out.fast_simple_add (len * 0.695853, 0.0694444); - _fade_out.fast_simple_add (len * 1, 0); + _fade_out->fast_simple_add (len * 0, 1); + _fade_out->fast_simple_add (len * 0.080645, 0.730556); + _fade_out->fast_simple_add (len * 0.277778, 0.289256); + _fade_out->fast_simple_add (len * 0.470046, 0.152778); + _fade_out->fast_simple_add (len * 0.695853, 0.0694444); + _fade_out->fast_simple_add (len * 1, 0); break; case Linear: - _fade_out.fast_simple_add (len * 0, 1); - _fade_out.fast_simple_add (len * 1, 0); + _fade_out->fast_simple_add (len * 0, 1); + _fade_out->fast_simple_add (len * 1, 0); break; } - _fade_out.thaw (); + _fade_out->thaw (); _fade_out_shape = shape; send_change (FadeOutChanged); @@ -795,7 +795,7 @@ AudioRegion::set_fade_out (FadeShape shape, nframes_t len) void AudioRegion::set_fade_in_length (nframes_t len) { - bool changed = _fade_in.extend_to (len); + bool changed = _fade_in->extend_to (len); if (changed) { _flags = Flag (_flags & ~DefaultFadeIn); @@ -806,7 +806,7 @@ AudioRegion::set_fade_in_length (nframes_t len) void AudioRegion::set_fade_out_length (nframes_t len) { - bool changed = _fade_out.extend_to (len); + bool changed = _fade_out->extend_to (len); if (changed) { _flags = Flag (_flags & ~DefaultFadeOut); @@ -848,13 +848,13 @@ AudioRegion::set_fade_out_active (bool yn) bool AudioRegion::fade_in_is_default () const { - return _fade_in_shape == Linear && _fade_in.back()->when == 64; + return _fade_in_shape == Linear && _fade_in->back()->when == 64; } bool AudioRegion::fade_out_is_default () const { - return _fade_out_shape == Linear && _fade_out.back()->when == 64; + return _fade_out_shape == Linear && _fade_out->back()->when == 64; } void @@ -881,11 +881,11 @@ AudioRegion::set_default_fades () void AudioRegion::set_default_envelope () { - _envelope.freeze (); - _envelope.clear (); - _envelope.fast_simple_add (0, 1.0f); - _envelope.fast_simple_add (_length, 1.0f); - _envelope.thaw (); + _envelope->freeze (); + _envelope->clear (); + _envelope->fast_simple_add (0, 1.0f); + _envelope->fast_simple_add (_length, 1.0f); + _envelope->thaw (); } void @@ -895,18 +895,18 @@ AudioRegion::recompute_at_end () based on the the existing curve. */ - _envelope.freeze (); - _envelope.truncate_end (_length); - _envelope.set_max_xval (_length); - _envelope.thaw (); + _envelope->freeze (); + _envelope->truncate_end (_length); + _envelope->set_max_xval (_length); + _envelope->thaw (); - if (_fade_in.back()->when > _length) { - _fade_in.extend_to (_length); + if (_fade_in->back()->when > _length) { + _fade_in->extend_to (_length); send_change (FadeInChanged); } - if (_fade_out.back()->when > _length) { - _fade_out.extend_to (_length); + if (_fade_out->back()->when > _length) { + _fade_out->extend_to (_length); send_change (FadeOutChanged); } } @@ -916,15 +916,15 @@ AudioRegion::recompute_at_start () { /* as above, but the shift was from the front */ - _envelope.truncate_start (_length); + _envelope->truncate_start (_length); - if (_fade_in.back()->when > _length) { - _fade_in.extend_to (_length); + if (_fade_in->back()->when > _length) { + _fade_in->extend_to (_length); send_change (FadeInChanged); } - if (_fade_out.back()->when > _length) { - _fade_out.extend_to (_length); + if (_fade_out->back()->when > _length) { + _fade_out->extend_to (_length); send_change (FadeOutChanged); } } diff --git a/libs/ardour/automatable.cc b/libs/ardour/automatable.cc index 9f3ba6deb6..d7c570ecdf 100644 --- a/libs/ardour/automatable.cc +++ b/libs/ardour/automatable.cc @@ -54,7 +54,7 @@ Automatable::old_set_automation_state (const XMLNode& node) uint32_t what; stringstream sstr; - _visible_parameter_automation.clear (); + _visible_controls.clear (); sstr << prop->value(); while (1) { @@ -65,6 +65,8 @@ Automatable::old_set_automation_state (const XMLNode& node) mark_automation_visible (ParamID(PluginAutomation, what), true); } } + + _last_automation_snapshot = 0; return 0; } @@ -89,7 +91,9 @@ Automatable::load_automation (const string& path) Glib::Mutex::Lock lm (_automation_lock); set tosave; - _parameter_automation.clear (); + _controls.clear (); + + _last_automation_snapshot = 0; while (in) { double when; @@ -101,8 +105,8 @@ Automatable::load_automation (const string& path) in >> value; if (!in) goto bad; /* FIXME: this is legacy and only used for plugin inserts? I think? */ - AutomationList* al = automation_list (ParamID(PluginAutomation, port), true); - al->add (when, value); + boost::shared_ptr c = control (ParamID(PluginAutomation, port), true); + c->list()->add (when, value); tosave.insert (ParamID(PluginAutomation, port)); } @@ -110,32 +114,35 @@ Automatable::load_automation (const string& path) bad: error << string_compose(_("%1: cannot load automation data from %2"), _name, fullpath) << endmsg; - _parameter_automation.clear (); + _controls.clear (); return -1; } void -Automatable::add_automation_parameter(AutomationList* al) +Automatable::add_control(boost::shared_ptr ac) { - _parameter_automation[al->param_id()] = al; - - /* let derived classes do whatever they need with this */ - automation_list_creation_callback (al->param_id(), *al); + ParamID param = ac->list()->param_id(); - cerr << _name << ": added parameter " << al->param_id().to_string() << endl; + _controls[param] = ac; + + cerr << _name << ": added parameter " << param.to_string() << endl; // FIXME: sane default behaviour? - _visible_parameter_automation.insert(al->param_id()); - _can_automate_list.insert(al->param_id()); + _visible_controls.insert(param); + _can_automate_list.insert(param); + + // Sync everything (derived classes) up to initial values + auto_state_changed(param); } void Automatable::what_has_automation (set& s) const { Glib::Mutex::Lock lm (_automation_lock); - map::const_iterator li; + Controls::const_iterator li; - for (li = _parameter_automation.begin(); li != _parameter_automation.end(); ++li) { + // FIXME: correct semantics? + for (li = _controls.begin(); li != _controls.end(); ++li) { s.insert ((*li).first); } } @@ -146,42 +153,45 @@ Automatable::what_has_visible_automation (set& s) const Glib::Mutex::Lock lm (_automation_lock); set::const_iterator li; - for (li = _visible_parameter_automation.begin(); li != _visible_parameter_automation.end(); ++li) { + for (li = _visible_controls.begin(); li != _visible_controls.end(); ++li) { s.insert (*li); } } /** Returns NULL if we don't have an AutomationList for \a parameter. */ -AutomationList* -Automatable::automation_list (ParamID parameter, bool create_if_missing) +boost::shared_ptr +Automatable::control (ParamID parameter, bool create_if_missing) { - std::map::iterator i = _parameter_automation.find(parameter); + Controls::iterator i = _controls.find(parameter); - if (i != _parameter_automation.end()) { + if (i != _controls.end()) { return i->second; } else if (create_if_missing) { - AutomationList* al = new AutomationList (parameter, FLT_MIN, FLT_MAX, default_parameter_value (parameter)); - add_automation_parameter(al); - return al; + assert(parameter.type() != GainAutomation); + boost::shared_ptr al (new AutomationList ( + parameter, FLT_MIN, FLT_MAX, default_parameter_value (parameter))); + boost::shared_ptr ac (new AutomationControl(_session, al)); + add_control(ac); + return ac; } else { //warning << "AutomationList " << parameter.to_string() << " not found for " << _name << endmsg; - return NULL; + return boost::shared_ptr(); } } -const AutomationList* -Automatable::automation_list (ParamID parameter) const +boost::shared_ptr +Automatable::control (ParamID parameter) const { - std::map::const_iterator i = _parameter_automation.find(parameter); + Controls::const_iterator i = _controls.find(parameter); - if (i != _parameter_automation.end()) { + if (i != _controls.end()) { return i->second; } else { //warning << "AutomationList " << parameter.to_string() << " not found for " << _name << endmsg; - return NULL; + return boost::shared_ptr(); } } @@ -196,7 +206,7 @@ Automatable::describe_parameter (ParamID param) else if (param == ParamID(PanAutomation)) return _("Pan"); else if (param.type() == MidiCCAutomation) - return string_compose("MIDI CC %1", param.id()); + return string_compose("CC %1", param.id()); else return param.to_string(); } @@ -211,12 +221,12 @@ void Automatable::mark_automation_visible (ParamID what, bool yn) { if (yn) { - _visible_parameter_automation.insert (what); + _visible_controls.insert (what); } else { set::iterator i; - if ((i = _visible_parameter_automation.find (what)) != _visible_parameter_automation.end()) { - _visible_parameter_automation.erase (i); + if ((i = _visible_controls.find (what)) != _visible_controls.end()) { + _visible_controls.erase (i); } } } @@ -224,24 +234,24 @@ Automatable::mark_automation_visible (ParamID what, bool yn) bool Automatable::find_next_event (nframes_t now, nframes_t end, ControlEvent& next_event) const { - map::const_iterator li; + Controls::const_iterator li; AutomationList::TimeComparator cmp; next_event.when = max_frames; - for (li = _parameter_automation.begin(); li != _parameter_automation.end(); ++li) { + for (li = _controls.begin(); li != _controls.end(); ++li) { AutomationList::const_iterator i; - const AutomationList& alist (*((*li).second)); + boost::shared_ptr alist (li->second->list()); ControlEvent cp (now, 0.0f); - for (i = lower_bound (alist.const_begin(), alist.const_end(), &cp, cmp); i != alist.const_end() && (*i)->when < end; ++i) { + for (i = lower_bound (alist->const_begin(), alist->const_end(), &cp, cmp); i != alist->const_end() && (*i)->when < end; ++i) { if ((*i)->when > now) { break; } } - if (i != alist.const_end() && (*i)->when < end) { + if (i != alist->const_end() && (*i)->when < end) { if ((*i)->when < next_event.when) { next_event.when = (*i)->when; @@ -261,8 +271,9 @@ Automatable::set_automation_state (const XMLNode& node, ParamID legacy_param) { Glib::Mutex::Lock lm (_automation_lock); - _parameter_automation.clear (); - _visible_parameter_automation.clear (); + /* Don't clear controls, since some may be special derived Controllable classes */ + + _visible_controls.clear (); XMLNodeList nlist = node.children(); XMLNodeIterator niter; @@ -280,7 +291,7 @@ Automatable::set_automation_state (const XMLNode& node, ParamID legacy_param) ParamID param = (id_prop ? ParamID(id_prop->value()) : legacy_param); - AutomationList* al = new AutomationList(**niter, param); + boost::shared_ptr al (new AutomationList(**niter, param)); if (!id_prop) { warning << "AutomationList node without automation-id property, " @@ -288,13 +299,19 @@ Automatable::set_automation_state (const XMLNode& node, ParamID legacy_param) al->set_param_id(legacy_param); } - add_automation_parameter(al); + boost::shared_ptr existing = control(param); + if (existing) + existing->set_list(al); + else + add_control(boost::shared_ptr(new AutomationControl(_session, al))); } else { error << "Expected AutomationList node, got '" << (*niter)->name() << endmsg; } } + _last_automation_snapshot = 0; + return 0; } @@ -304,16 +321,12 @@ Automatable::get_automation_state () Glib::Mutex::Lock lm (_automation_lock); XMLNode* node = new XMLNode (X_("Automation")); - cerr << "'" << _name << "'->get_automation_state, # params = " << _parameter_automation.size() << endl; - - if (_parameter_automation.empty()) { + if (_controls.empty()) { return *node; } - map::iterator li; - - for (li = _parameter_automation.begin(); li != _parameter_automation.end(); ++li) { - node->add_child_nocopy (li->second->get_state ()); + for (Controls::iterator li = _controls.begin(); li != _controls.end(); ++li) { + node->add_child_nocopy (li->second->list()->get_state ()); } return *node; @@ -324,10 +337,8 @@ Automatable::clear_automation () { Glib::Mutex::Lock lm (_automation_lock); - map::iterator li; - - for (li = _parameter_automation.begin(); li != _parameter_automation.end(); ++li) - li->second->clear(); + for (Controls::iterator li = _controls.begin(); li != _controls.end(); ++li) + li->second->list()->clear(); } void @@ -335,10 +346,10 @@ Automatable::set_parameter_automation_state (ParamID param, AutoState s) { Glib::Mutex::Lock lm (_automation_lock); - AutomationList* al = automation_list (param, true); + boost::shared_ptr c = control (param, true); - if (s != al->automation_state()) { - al->set_automation_state (s); + if (s != c->list()->automation_state()) { + c->list()->set_automation_state (s); _session.set_dirty (); } } @@ -348,10 +359,10 @@ Automatable::get_parameter_automation_state (ParamID param) { Glib::Mutex::Lock lm (_automation_lock); - AutomationList* al = automation_list(param); + boost::shared_ptr c = control(param); - if (al) { - return al->automation_state(); + if (c) { + return c->list()->automation_state(); } else { return Off; } @@ -362,10 +373,10 @@ Automatable::set_parameter_automation_style (ParamID param, AutoStyle s) { Glib::Mutex::Lock lm (_automation_lock); - AutomationList* al = automation_list (param, true); + boost::shared_ptr c = control(param, true); - if (s != al->automation_style()) { - al->set_automation_style (s); + if (s != c->list()->automation_style()) { + c->list()->set_automation_style (s); _session.set_dirty (); } } @@ -375,10 +386,10 @@ Automatable::get_parameter_automation_style (ParamID param) { Glib::Mutex::Lock lm (_automation_lock); - AutomationList* al = automation_list(param); + boost::shared_ptr c = control(param); - if (al) { - return al->automation_style(); + if (c) { + return c->list()->automation_style(); } else { return Absolute; // whatever } @@ -393,14 +404,14 @@ Automatable::protect_automation () for (set::iterator i = automated_params.begin(); i != automated_params.end(); ++i) { - AutomationList* al = automation_list (*i); + boost::shared_ptr c = control(*i); - switch (al->automation_state()) { + switch (c->list()->automation_state()) { case Write: - al->set_automation_state (Off); + c->list()->set_automation_state (Off); break; case Touch: - al->set_automation_state (Play); + c->list()->set_automation_state (Play); break; default: break; @@ -408,3 +419,18 @@ Automatable::protect_automation () } } +void +Automatable::automation_snapshot (nframes_t now) +{ + if (_last_automation_snapshot > now || (now - _last_automation_snapshot) > _session.automation_interval()) { + + for (Controls::iterator i = _controls.begin(); i != _controls.end(); ++i) { + if (i->second->list()->automation_write()) { + i->second->list()->rt_add (now, i->second->user_value()); + } + } + + _last_automation_snapshot = now; + } +} + diff --git a/libs/ardour/automation_control.cc b/libs/ardour/automation_control.cc new file mode 100644 index 0000000000..8f8e40a641 --- /dev/null +++ b/libs/ardour/automation_control.cc @@ -0,0 +1,85 @@ +/* + Copyright (C) 2007 Paul Davis + Author: Dave Robillard + + 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 +#include +#include +#include + +using namespace std; +using namespace ARDOUR; +using namespace PBD; + + +AutomationControl::AutomationControl(Session& session, boost::shared_ptr list, string name) + : Controllable((name == "unnamed controllable") ? list->param_id().to_string() : name) + , _session(session) + , _list(list) + , _user_value(list->default_value()) +{ + cerr << "Created AutomationControl " << name << "(" << list->param_id().to_string() << ")" << endl; +} + + +/** Get the currently effective value (ie the one that corresponds to current output) + */ +float +AutomationControl::get_value() const +{ + if (_list->automation_playback()) + return _list->eval(_session.transport_frame()); + else + return _user_value; +} + + +void +AutomationControl::set_value(float value) +{ + _user_value = value; + + if (_session.transport_stopped() && _list->automation_write()) + _list->add(_session.transport_frame(), value); + + Changed(); /* EMIT SIGNAL */ +} + + +/** Get the latest user-set value, which may not equal get_value() when automation + * is playing back, etc. + * + * Automation write/touch works by periodically sampling this value and adding it + * to the AutomationList. + */ +float +AutomationControl::user_value() const +{ + return _user_value; +} + + +void +AutomationControl::set_list(boost::shared_ptr list) +{ + _list = list; + _user_value = list->default_value(); + Changed(); /* EMIT SIGNAL */ +} + diff --git a/libs/ardour/automation_event.cc b/libs/ardour/automation_event.cc index b620054558..9c1a6126f6 100644 --- a/libs/ardour/automation_event.cc +++ b/libs/ardour/automation_event.cc @@ -1195,8 +1195,6 @@ AutomationList::get_state () XMLNode& AutomationList::state (bool full) { - cerr << _param_id.to_string() << "->state()" << endl; - XMLNode* root = new XMLNode (X_("AutomationList")); char buf[64]; LocaleGuard lg (X_("POSIX")); @@ -1208,11 +1206,11 @@ AutomationList::state (bool full) snprintf (buf, sizeof (buf), "%.12g", _default_value); root->add_property ("default", buf); snprintf (buf, sizeof (buf), "%.12g", _min_yval); - root->add_property ("_min_yval", buf); + root->add_property ("min_yval", buf); snprintf (buf, sizeof (buf), "%.12g", _max_yval); - root->add_property ("_max_yval", buf); + root->add_property ("max_yval", buf); snprintf (buf, sizeof (buf), "%.12g", _max_xval); - root->add_property ("_max_xval", buf); + root->add_property ("max_xval", buf); if (full) { root->add_property ("state", auto_state_to_string (_state)); @@ -1390,19 +1388,19 @@ AutomationList::set_state (const XMLNode& node) _state = Off; } - if ((prop = node.property (X_("_min_yval"))) != 0) { + if ((prop = node.property (X_("min_yval"))) != 0) { _min_yval = atof (prop->value ()); } else { _min_yval = FLT_MIN; } - if ((prop = node.property (X_("_max_yval"))) != 0) { + if ((prop = node.property (X_("max_yval"))) != 0) { _max_yval = atof (prop->value ()); } else { _max_yval = FLT_MAX; } - if ((prop = node.property (X_("_max_xval"))) != 0) { + if ((prop = node.property (X_("max_xval"))) != 0) { _max_xval = atof (prop->value ()); } else { _max_xval = 0; // means "no limit ; diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc index b61a654b25..f04af47f8c 100644 --- a/libs/ardour/io.cc +++ b/libs/ardour/io.cc @@ -62,8 +62,6 @@ using namespace std; using namespace ARDOUR; using namespace PBD; -nframes_t IO::_automation_interval = 0; - const string IO::state_node_name = "IO"; bool IO::connecting_legal = false; bool IO::ports_legal = false; @@ -81,6 +79,7 @@ Glib::StaticMutex IO::m_meter_signal_lock = GLIBMM_STATIC_MUTEX_INIT; others can be imagined. */ +#if 0 static gain_t direct_control_to_gain (double fract) { /* XXX Marcus writes: this doesn't seem right to me. but i don't have a better answer ... */ /* this maxes at +6dB */ @@ -93,7 +92,7 @@ static double direct_gain_to_control (gain_t gain) { return pow((6.0*log(gain)/log(2.0)+192.0)/198.0, 8.0); } - +#endif /** @param default_type The type of port that will be created by ensure_io * and friends if no type is explicitly requested (to avoid breakage). @@ -104,7 +103,6 @@ IO::IO (Session& s, const string& name, : Automatable (s, name), _output_buffers (new BufferSet()), _default_type (default_type), - _gain_control (X_("gaincontrol"), *this), _input_minimum (ChanCount::ZERO), _input_maximum (ChanCount::INFINITE), _output_minimum (ChanCount::ZERO), @@ -135,15 +133,16 @@ IO::IO (Session& s, const string& name, _phase_invert = false; deferred_state = 0; - add_automation_parameter(new AutomationList(ParamID(GainAutomation), 0.0, 2.0, 1.0)); + boost::shared_ptr gl( + new AutomationList(ParamID(GainAutomation), 0.0, 2.0, 1.0)); + + _gain_control = boost::shared_ptr( + new GainControl(X_("gaincontrol"), *this, gl)); + + add_control(_gain_control); apply_gain_automation = false; - last_automation_snapshot = 0; - - /*_gain_automation_state = Off; - _gain_automation_style = Absolute;*/ - { // IO::Meter is emitted from another thread so the // Meter signal must be protected. @@ -154,14 +153,13 @@ IO::IO (Session& s, const string& name, // Connect to our own MoreChannels signal to connect output buffers IO::MoreChannels.connect (mem_fun (*this, &IO::attach_buffers)); - _session.add_controllable (&_gain_control); + _session.add_controllable (_gain_control); } IO::IO (Session& s, const XMLNode& node, DataType dt) : Automatable (s, "unnamed io"), _output_buffers (new BufferSet()), - _default_type (dt), - _gain_control (X_("gaincontrol"), *this) + _default_type (dt) { _meter = new PeakMeter (_session); @@ -174,6 +172,14 @@ IO::IO (Session& s, const XMLNode& node, DataType dt) _output_bundle = 0; apply_gain_automation = false; + + boost::shared_ptr gl( + new AutomationList(ParamID(GainAutomation), 0.0, 2.0, 1.0)); + + _gain_control = boost::shared_ptr( + new GainControl(X_("gaincontrol"), *this, gl)); + + add_control(_gain_control); set_state (node); @@ -187,7 +193,7 @@ IO::IO (Session& s, const XMLNode& node, DataType dt) // Connect to our own MoreChannels signal to connect output buffers IO::MoreChannels.connect (mem_fun (*this, &IO::attach_buffers)); - _session.add_controllable (&_gain_control); + _session.add_controllable (_gain_control); } IO::~IO () @@ -1129,8 +1135,8 @@ IO::ensure_outputs (ChanCount count, bool clear, bool lockit, void* src) gain_t IO::effective_gain () const { - if (gain_automation().automation_playback()) { - return _effective_gain; + if (_gain_control->list()->automation_playback()) { + return _gain_control->get_value(); } else { return _desired_gain; } @@ -1272,7 +1278,7 @@ IO::state (bool full_state) } node->add_child_nocopy (_panner->state (full_state)); - node->add_child_nocopy (_gain_control.get_state ()); + node->add_child_nocopy (_gain_control->get_state ()); snprintf (buf, sizeof(buf), "%2.12f", gain()); node->add_property ("gain", buf); @@ -1359,7 +1365,7 @@ IO::set_state (const XMLNode& node) if ((*iter)->name() == X_("controllable")) { if ((prop = (*iter)->property("name")) != 0 && prop->value() == "gaincontrol") { - _gain_control.set_state (**iter); + _gain_control->set_state (**iter); } } } @@ -1396,8 +1402,6 @@ IO::set_state (const XMLNode& node) pending_state_node = new XMLNode (node); } - last_automation_snapshot = 0; - return 0; } @@ -1458,7 +1462,7 @@ IO::load_automation (string path) switch (type) { case 'g': - gain_automation().fast_simple_add (when, value); + _gain_control->list()->fast_simple_add (when, value); break; case 's': @@ -2131,15 +2135,22 @@ IO::output_bundle_configuration_changed () } void -IO::GainControllable::set_value (float val) +IO::GainControl::set_value (float val) { - io.set_gain (direct_control_to_gain (val), this); + // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05)) + if (val > 1.99526231f) + val = 1.99526231f; + + _user_value = val; + _io.set_gain (val, this); + + Changed(); /* EMIT SIGNAL */ } float -IO::GainControllable::get_value (void) const +IO::GainControl::get_value (void) const { - return direct_gain_to_control (io.effective_gain()); + return AutomationControl::get_value(); } void @@ -2193,16 +2204,16 @@ IO::set_parameter_automation_state (ParamID param, AutoState state) { Glib::Mutex::Lock lm (_automation_lock); - ARDOUR::AutomationList& gain_auto = gain_automation(); + boost::shared_ptr gain_auto = _gain_control->list(); - if (state != gain_auto.automation_state()) { + if (state != gain_auto->automation_state()) { changed = true; - last_automation_snapshot = 0; - gain_auto.set_automation_state (state); + _last_automation_snapshot = 0; + gain_auto->set_automation_state (state); if (state != Off) { // FIXME: shouldn't this use Curve? - set_gain (gain_auto.eval (_session.transport_frame()), this); + set_gain (gain_auto->eval (_session.transport_frame()), this); } } } @@ -2229,7 +2240,15 @@ void IO::set_gain (gain_t val, void *src) { // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05)) - if (val>1.99526231f) val=1.99526231f; + if (val > 1.99526231f) + val = 1.99526231f; + + if (src != _gain_control.get()) { + _gain_control->set_value(val); + // bit twisty, this will come back and call us again + // (this keeps control in sync with reality) + return; + } { Glib::Mutex::Lock dm (declick_lock); @@ -2237,17 +2256,11 @@ IO::set_gain (gain_t val, void *src) } if (_session.transport_stopped()) { - _effective_gain = val; _gain = val; } - - gain_changed (src); - _gain_control.Changed (); /* EMIT SIGNAL */ - ARDOUR::AutomationList& gain_auto = gain_automation(); - - if (_session.transport_stopped() && src != 0 && src != this && gain_auto.automation_write()) { - gain_auto.add (_session.transport_frame(), val); + if (_session.transport_stopped() && src != 0 && src != this && _gain_control->list()->automation_write()) { + _gain_control->list()->add (_session.transport_frame(), val); } @@ -2258,7 +2271,7 @@ void IO::start_pan_touch (uint32_t which) { if (which < _panner->size()) { - (*_panner)[which]->automation().start_touch(); + (*_panner)[which]->automation()->start_touch(); } } @@ -2266,7 +2279,7 @@ void IO::end_pan_touch (uint32_t which) { if (which < _panner->size()) { - (*_panner)[which]->automation().stop_touch(); + (*_panner)[which]->automation()->stop_touch(); } } @@ -2274,35 +2287,26 @@ IO::end_pan_touch (uint32_t which) void IO::automation_snapshot (nframes_t now) { - if (last_automation_snapshot > now || (now - last_automation_snapshot) > _automation_interval) { + Automatable::automation_snapshot (now); - ARDOUR::AutomationList& gain_auto = gain_automation(); - - if (gain_auto.automation_write()) { - gain_auto.rt_add (now, gain()); - } - + if (_last_automation_snapshot > now || (now - _last_automation_snapshot) > _session.automation_interval()) { _panner->snapshot (now); - - last_automation_snapshot = now; } } void IO::transport_stopped (nframes_t frame) { - ARDOUR::AutomationList& gain_auto = gain_automation(); + _gain_control->list()->reposition_for_rt_add (frame); - gain_auto.reposition_for_rt_add (frame); - - if (gain_auto.automation_state() != Off) { + if (_gain_control->list()->automation_state() != Off) { /* the src=0 condition is a special signal to not propagate automation gain changes into the mix group when locating. */ // FIXME: shouldn't this use Curve? - set_gain (gain_auto.eval (frame), 0); + set_gain (_gain_control->list()->eval (frame), 0); } _panner->transport_stopped (frame); diff --git a/libs/ardour/midi_diskstream.cc b/libs/ardour/midi_diskstream.cc index 9114f689b2..6386714c16 100644 --- a/libs/ardour/midi_diskstream.cc +++ b/libs/ardour/midi_diskstream.cc @@ -596,7 +596,7 @@ MidiDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_t // XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX // Write into playback buffer here, and whatnot? - cerr << "MDS FIXME: collect playback" << endl; + //cerr << "MDS FIXME: collect playback" << endl; } @@ -1498,9 +1498,8 @@ MidiDiskstream::get_playback(MidiBuffer& dst, nframes_t start, nframes_t end) dst.clear(); assert(dst.size() == 0); - // I think this happens with reverse varispeed? maybe? + // Reverse. ... We just don't do reverse, ok? Back off. if (end <= start) { - cerr << "MDS: Reverse? Skipping" << endl; return; } diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc index 71a2735606..a10161bc72 100644 --- a/libs/ardour/midi_track.cc +++ b/libs/ardour/midi_track.cc @@ -193,8 +193,8 @@ MidiTrack::_set_state (const XMLNode& node, bool call_base) child = *niter; if (child->name() == X_("recenable")) { - _rec_enable_control.set_state (*child); - _session.add_controllable (&_rec_enable_control); + _rec_enable_control->set_state (*child); + _session.add_controllable (_rec_enable_control); } } @@ -249,7 +249,7 @@ MidiTrack::state(bool full_state) _diskstream->id().print (buf, sizeof(buf)); root.add_property ("diskstream-id", buf); - root.add_child_nocopy (_rec_enable_control.get_state()); + root.add_child_nocopy (_rec_enable_control->get_state()); return root; } @@ -426,6 +426,15 @@ MidiTrack::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, { int dret; boost::shared_ptr diskstream = midi_diskstream(); + + { + Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK); + if (lm.locked()) { + // automation snapshot can also be called from the non-rt context + // and it uses the redirect list, so we take the lock out here + automation_snapshot (start_frame); + } + } if (n_outputs().n_total() == 0 && _processors.empty()) { return 0; diff --git a/libs/ardour/panner.cc b/libs/ardour/panner.cc index d5a238e253..fa05ff4451 100644 --- a/libs/ardour/panner.cc +++ b/libs/ardour/panner.cc @@ -71,11 +71,11 @@ static double direct_pan_to_control (pan_t val) { StreamPanner::StreamPanner (Panner& p) : parent (p), - _control (X_("panner"), *this) + _control (new PanControllable(X_("panner"), *this)) { _muted = false; - parent.session().add_controllable (&_control); + parent.session().add_controllable (_control); x = 0.5; y = 0.5; @@ -132,7 +132,7 @@ StreamPanner::set_position (float xpos, bool link_call) x = xpos; update (); Changed (); - _control.Changed (); + _control->Changed (); } } @@ -190,7 +190,7 @@ StreamPanner::add_state (XMLNode& node) /*---------------------------------------------------------------------- */ BaseStereoPanner::BaseStereoPanner (Panner& p) - : StreamPanner (p), _automation (ParamID(PanAutomation), 0.0, 1.0, 0.5) + : StreamPanner (p), _automation (new AutomationList(ParamID(PanAutomation), 0.0, 1.0, 0.5)) { } @@ -201,36 +201,36 @@ BaseStereoPanner::~BaseStereoPanner () void BaseStereoPanner::snapshot (nframes_t now) { - if (_automation.automation_state() == Write || _automation.automation_state() == Touch) { - _automation.rt_add (now, x); + if (_automation->automation_state() == Write || _automation->automation_state() == Touch) { + _automation->rt_add (now, x); } } void BaseStereoPanner::transport_stopped (nframes_t frame) { - _automation.reposition_for_rt_add (frame); + _automation->reposition_for_rt_add (frame); - if (_automation.automation_state() != Off) { - set_position (_automation.eval (frame)); + if (_automation->automation_state() != Off) { + set_position (_automation->eval (frame)); } } void BaseStereoPanner::set_automation_style (AutoStyle style) { - _automation.set_automation_style (style); + _automation->set_automation_style (style); } void BaseStereoPanner::set_automation_state (AutoState state) { - if (state != _automation.automation_state()) { + if (state != _automation->automation_state()) { - _automation.set_automation_state (state); + _automation->set_automation_state (state); if (state != Off) { - set_position (_automation.eval (parent.session().transport_frame())); + set_position (_automation->eval (parent.session().transport_frame())); } } } @@ -241,7 +241,7 @@ BaseStereoPanner::load (istream& in, string path, uint32_t& linecnt) char line[128]; LocaleGuard lg (X_("POSIX")); - _automation.clear (); + _automation->clear (); while (in.getline (line, sizeof (line), '\n')) { nframes_t when; @@ -258,12 +258,12 @@ BaseStereoPanner::load (istream& in, string path, uint32_t& linecnt) continue; } - _automation.fast_simple_add (when, value); + _automation->fast_simple_add (when, value); } /* now that we are done loading */ - _automation.StateChanged (); + _automation->StateChanged (); return 0; } @@ -438,7 +438,7 @@ EqualPowerStereoPanner::distribute_automated (AudioBuffer& srcbuf, BufferSet& ob /* fetch positional data */ - if (!_automation.curve().rt_safe_get_vector (start, end, buffers[0], nframes)) { + if (!_automation->curve().rt_safe_get_vector (start, end, buffers[0], nframes)) { /* fallback */ if (!_muted) { distribute (srcbuf, obufs, 1.0, nframes); @@ -518,12 +518,12 @@ EqualPowerStereoPanner::state (bool full_state) root->add_property (X_("type"), EqualPowerStereoPanner::name); XMLNode* autonode = new XMLNode (X_("Automation")); - autonode->add_child_nocopy (_automation.state (full_state)); + autonode->add_child_nocopy (_automation->state (full_state)); root->add_child_nocopy (*autonode); StreamPanner::add_state (*root); - root->add_child_nocopy (_control.get_state ()); + root->add_child_nocopy (_control->get_state ()); return *root; } @@ -546,15 +546,15 @@ EqualPowerStereoPanner::set_state (const XMLNode& node) if ((*iter)->name() == X_("controllable")) { if ((prop = (*iter)->property("name")) != 0 && prop->value() == "panner") { - _control.set_state (**iter); + _control->set_state (**iter); } } else if ((*iter)->name() == X_("Automation")) { - _automation.set_state (*((*iter)->children().front())); + _automation->set_state (*((*iter)->children().front())); - if (_automation.automation_state() != Off) { - set_position (_automation.eval (parent.session().transport_frame())); + if (_automation->automation_state() != Off) { + set_position (_automation->eval (parent.session().transport_frame())); } } } @@ -565,7 +565,7 @@ EqualPowerStereoPanner::set_state (const XMLNode& node) /*----------------------------------------------------------------------*/ Multi2dPanner::Multi2dPanner (Panner& p) - : StreamPanner (p), _automation (ParamID(PanAutomation), 0.0, 1.0, 0.5) // XXX useless + : StreamPanner (p), _automation (new AutomationList(ParamID(PanAutomation), 0.0, 1.0, 0.5)) // XXX useless { update (); } @@ -930,10 +930,10 @@ Panner::reset (uint32_t nouts, uint32_t npans) if (changed || ((left == 0.5) && (right == 0.5))) { front()->set_position (0.0); - front()->automation().reset_default (0.0); + front()->automation()->reset_default (0.0); back()->set_position (1.0); - back()->automation().reset_default (1.0); + back()->automation()->reset_default (1.0); changed = true; } @@ -990,7 +990,7 @@ AutoState Panner::automation_state () const { if (!empty()) { - return front()->automation().automation_state (); + return front()->automation()->automation_state (); } else { return Off; } @@ -1000,7 +1000,7 @@ AutoStyle Panner::automation_style () const { if (!empty()) { - return front()->automation().automation_style (); + return front()->automation()->automation_style (); } else { return Absolute; } @@ -1026,7 +1026,7 @@ void Panner::clear_automation () { for (vector::iterator i = begin(); i != end(); ++i) { - (*i)->automation().clear (); + (*i)->automation()->clear (); } _session.set_dirty (); } @@ -1181,7 +1181,7 @@ bool Panner::touching () const { for (vector::const_iterator i = begin(); i != end(); ++i) { - if ((*i)->automation().touching ()) { + if ((*i)->automation()->touching ()) { return true; } } diff --git a/libs/ardour/plugin_insert.cc b/libs/ardour/plugin_insert.cc index a842277845..08a8343fbb 100644 --- a/libs/ardour/plugin_insert.cc +++ b/libs/ardour/plugin_insert.cc @@ -142,8 +142,6 @@ void PluginInsert::init () { set_automatable (); - - set::iterator s; } PluginInsert::~PluginInsert () @@ -151,22 +149,16 @@ PluginInsert::~PluginInsert () GoingAway (); /* EMIT SIGNAL */ } -void -PluginInsert::automation_list_creation_callback (ParamID which, AutomationList& alist) -{ - alist.automation_state_changed.connect (sigc::bind (mem_fun (*this, &PluginInsert::auto_state_changed), (which))); -} - void PluginInsert::auto_state_changed (ParamID which) { if (which.type() != PluginAutomation) return; - AutomationList* alist = automation_list (which); + boost::shared_ptr c = control (which); - if (alist && alist->automation_state() != Off) { - _plugins[0]->set_parameter (which.id(), alist->eval (_session.transport_frame())); + if (c && c->list()->automation_state() != Off) { + _plugins[0]->set_parameter (which.id(), c->list()->eval (_session.transport_frame())); } } @@ -213,12 +205,23 @@ PluginInsert::is_generator() const void PluginInsert::set_automatable () { - set a; - - a = _plugins.front()->automatable (); + set a = _plugins.front()->automatable (); + + Plugin::ParameterDescriptor desc; for (set::iterator i = a.begin(); i != a.end(); ++i) { - can_automate (*i); + if (i->type() == PluginAutomation) { + can_automate (*i); + _plugins.front()->get_parameter_descriptor(i->id(), desc); + boost::shared_ptr list(new AutomationList( + *i, + (desc.min_unbound ? FLT_MIN : desc.lower), + (desc.max_unbound ? FLT_MAX : desc.upper), + _plugins.front()->default_value(i->id()))); + + add_control(boost::shared_ptr( + new AutomationControl(_session, list))); + } } } @@ -276,21 +279,20 @@ PluginInsert::connect_and_run (BufferSet& bufs, nframes_t nframes, nframes_t off if (with_auto) { - map::iterator li; - uint32_t n; + uint32_t n = 0; - for (n = 0, li = _parameter_automation.begin(); li != _parameter_automation.end(); ++li, ++n) { + for (Controls::iterator li = _controls.begin(); li != _controls.end(); ++li, ++n) { - AutomationList& alist (*((*li).second)); + boost::shared_ptr c = li->second; - if (alist.param_id().type() == PluginAutomation && alist.automation_playback()) { + if (c->list()->param_id().type() == PluginAutomation && c->list()->automation_playback()) { bool valid; - float val = alist.rt_safe_eval (now, valid); + float val = c->list()->rt_safe_eval (now, valid); if (valid) { /* set the first plugin, the others will be set via signals */ - _plugins[0]->set_parameter ((*li).first, val); + _plugins[0]->set_parameter (c->list()->param_id(), val); } } @@ -307,16 +309,15 @@ PluginInsert::connect_and_run (BufferSet& bufs, nframes_t nframes, nframes_t off void PluginInsert::automation_snapshot (nframes_t now) { - map::iterator li; - - for (li =_parameter_automation.begin(); li !=_parameter_automation.end(); ++li) { + for (Controls::iterator li = _controls.begin(); li != _controls.end(); ++li) { - AutomationList *alist = ((*li).second); - if (alist != 0 && alist->param_id().type() == PluginAutomation - && alist->automation_write ()) { + boost::shared_ptr c = li->second; + + if (c->list() != 0 && c->list()->param_id().type() == PluginAutomation + && c->list()->automation_write ()) { - float val = _plugins[0]->get_parameter ((*li).first); - alist->rt_add (now, val); + float val = _plugins[0]->get_parameter (c->list()->param_id()); + c->list()->rt_add (now, val); _last_automation_snapshot = now; } } @@ -325,14 +326,14 @@ PluginInsert::automation_snapshot (nframes_t now) void PluginInsert::transport_stopped (nframes_t now) { - map::iterator li; + for (Controls::iterator li = _controls.begin(); li != _controls.end(); ++li) { + + boost::shared_ptr c = li->second; + + c->list()->reposition_for_rt_add (now); - for (li =_parameter_automation.begin(); li !=_parameter_automation.end(); ++li) { - AutomationList& alist (*(li->second)); - alist.reposition_for_rt_add (now); - - if (alist.param_id().type() == PluginAutomation && alist.automation_state() != Off) { - _plugins[0]->set_parameter (li->first, alist.eval (now)); + if (c->list()->param_id().type() == PluginAutomation && c->list()->automation_state() != Off) { + _plugins[0]->set_parameter (li->first, c->list()->eval (now)); } } } @@ -390,8 +391,10 @@ PluginInsert::set_parameter (ParamID param, float val) _plugins[0]->set_parameter (param.id(), val); - if (automation_list (param) && automation_list (param)->automation_write()) { - automation_list (param)->add (_session.audible_frame(), val); + boost::shared_ptr c = control (param); + + if (c && c->list()->automation_write()) { + c->list()->add (_session.audible_frame(), val); } _session.set_dirty(); @@ -660,7 +663,7 @@ PluginInsert::state (bool full) child->add_child_nocopy (automation_list (*x).state (full)); autonode->add_child_nocopy (*child); */ - autonode->add_child_nocopy (automation_list (*x)->state (full)); + autonode->add_child_nocopy (control(*x)->list()->state (full)); } node.add_child_nocopy (*autonode); @@ -791,7 +794,7 @@ PluginInsert::set_state(const XMLNode& node) } if (!child->children().empty()) { - automation_list (ParamID(PluginAutomation, port_id), true)->set_state (*child->children().front()); + control (ParamID(PluginAutomation, port_id), true)->list()->set_state (*child->children().front()); } else { if ((cprop = child->property("auto")) != 0) { @@ -799,13 +802,13 @@ PluginInsert::set_state(const XMLNode& node) int x; sscanf (cprop->value().c_str(), "0x%x", &x); - automation_list (ParamID(PluginAutomation, port_id), true)->set_automation_state (AutoState (x)); + control (ParamID(PluginAutomation, port_id), true)->list()->set_automation_state (AutoState (x)); } else { /* missing */ - automation_list (ParamID(PluginAutomation, port_id), true)->set_automation_state (Off); + control (ParamID(PluginAutomation, port_id), true)->list()->set_automation_state (Off); } } diff --git a/libs/ardour/processor.cc b/libs/ardour/processor.cc index b192eb85c1..76c780f2db 100644 --- a/libs/ardour/processor.cc +++ b/libs/ardour/processor.cc @@ -157,8 +157,8 @@ Processor::state (bool full_state) XMLNode& automation = Automatable::get_automation_state(); - for (set::iterator x = _visible_parameter_automation.begin(); x != _visible_parameter_automation.end(); ++x) { - if (x != _visible_parameter_automation.begin()) { + for (set::iterator x = _visible_controls.begin(); x != _visible_controls.end(); ++x) { + if (x != _visible_controls.begin()) { sstr << ' '; } sstr << *x; @@ -202,7 +202,7 @@ Processor::set_state (const XMLNode& node) uint32_t what; stringstream sstr; - _visible_parameter_automation.clear (); + _visible_controls.clear (); sstr << prop->value(); while (1) { diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index 507d337619..e8e469b446 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -58,16 +58,16 @@ uint32_t Route::order_key_cnt = 0; Route::Route (Session& sess, string name, int input_min, int input_max, int output_min, int output_max, Flag flg, DataType default_type) : IO (sess, name, input_min, input_max, output_min, output_max, default_type), _flags (flg), - _solo_control (X_("solo"), *this, ToggleControllable::SoloControl), - _mute_control (X_("mute"), *this, ToggleControllable::MuteControl) + _solo_control (new ToggleControllable (X_("solo"), *this, ToggleControllable::SoloControl)), + _mute_control (new ToggleControllable (X_("mute"), *this, ToggleControllable::MuteControl)) { init (); } Route::Route (Session& sess, const XMLNode& node, DataType default_type) : IO (sess, *node.child ("IO"), default_type), - _solo_control (X_("solo"), *this, ToggleControllable::SoloControl), - _mute_control (X_("mute"), *this, ToggleControllable::MuteControl) + _solo_control (new ToggleControllable (X_("solo"), *this, ToggleControllable::SoloControl)), + _mute_control (new ToggleControllable (X_("mute"), *this, ToggleControllable::MuteControl)) { init (); _set_state (node, false); @@ -177,33 +177,33 @@ Route::set_gain (gain_t val, void *src) if (_mix_group->is_relative()) { - - gain_t usable_gain = gain(); + gain_t usable_gain = gain(); if (usable_gain < 0.000001f) { - usable_gain=0.000001f; + usable_gain = 0.000001f; } gain_t delta = val; if (delta < 0.000001f) { - delta=0.000001f; + delta = 0.000001f; } delta -= usable_gain; - if (delta == 0.0f) return; + if (delta == 0.0f) + return; gain_t factor = delta / usable_gain; if (factor > 0.0f) { factor = _mix_group->get_max_factor(factor); if (factor == 0.0f) { - gain_changed (src); + _gain_control->Changed(); /* EMIT SIGNAL */ return; } } else { factor = _mix_group->get_min_factor(factor); if (factor == 0.0f) { - gain_changed (src); + _gain_control->Changed(); /* EMIT SIGNAL */ return; } } @@ -726,7 +726,7 @@ Route::set_solo (bool yn, void *src) if (_soloed != yn) { _soloed = yn; solo_changed (src); /* EMIT SIGNAL */ - _solo_control.Changed (); /* EMIT SIGNAL */ + _solo_control->Changed (); /* EMIT SIGNAL */ } } @@ -763,7 +763,7 @@ Route::set_mute (bool yn, void *src) _muted = yn; mute_changed (src); /* EMIT SIGNAL */ - _mute_control.Changed (); /* EMIT SIGNAL */ + _mute_control->Changed (); /* EMIT SIGNAL */ Glib::Mutex::Lock lm (declick_lock); desired_mute_gain = (yn?0.0f:1.0f); @@ -1491,8 +1491,8 @@ Route::state(bool full_state) node->add_property ("order-keys", order_string); node->add_child_nocopy (IO::state (full_state)); - node->add_child_nocopy (_solo_control.get_state ()); - node->add_child_nocopy (_mute_control.get_state ()); + node->add_child_nocopy (_solo_control->get_state ()); + node->add_child_nocopy (_mute_control->get_state ()); XMLNode* remote_control_node = new XMLNode (X_("remote_control")); snprintf (buf, sizeof (buf), "%d", _remote_control_id); @@ -1853,12 +1853,12 @@ Route::_set_state (const XMLNode& node, bool call_base) } else if (child->name() == X_("controllable") && (prop = child->property("name")) != 0) { if (prop->value() == "solo") { - _solo_control.set_state (*child); - _session.add_controllable (&_solo_control); + _solo_control->set_state (*child); + _session.add_controllable (_solo_control); } else if (prop->value() == "mute") { - _mute_control.set_state (*child); - _session.add_controllable (&_mute_control); + _mute_control->set_state (*child); + _session.add_controllable (_mute_control); } } else if (child->name() == X_("remote_control")) { @@ -2038,7 +2038,7 @@ Route::set_control_outs (const vector& ports) _control_outs = 0; } - if (control() || master()) { + if (is_control() || is_master()) { /* no control outs for these two special busses */ return 0; } @@ -2393,10 +2393,9 @@ Route::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, nfra if (am.locked() && _session.transport_rolling()) { - ARDOUR::AutomationList& gain_auto = gain_automation(); - - if (gain_auto.automation_playback()) { - apply_gain_automation = gain_auto.curve().rt_safe_get_vector (start_frame, end_frame, _session.gain_automation_buffer(), nframes); + if (_gain_control->list()->automation_playback()) { + apply_gain_automation = _gain_control->list()->curve().rt_safe_get_vector ( + start_frame, end_frame, _session.gain_automation_buffer(), nframes); } } } diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index c40dd6fd7a..d5c2817f54 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -122,7 +122,8 @@ Session::Session (AudioEngine &eng, routes (new RouteList), auditioner ((Auditioner*) 0), _click_io ((IO*) 0), - main_outs (0) + main_outs (0), + _automation_interval (0) { if (!eng.connected()) { throw failed_constructor(); @@ -221,7 +222,8 @@ Session::Session (AudioEngine &eng, _send_smpte_update (false), diskstreams (new DiskstreamList), routes (new RouteList), - main_outs (0) + main_outs (0), + _automation_interval (0) { if (!eng.connected()) { @@ -1267,7 +1269,7 @@ Session::set_frame_rate (nframes_t frames_per_second) sync_time_vars(); - Route::set_automation_interval ((nframes_t) ceil ((double) frames_per_second * 0.25)); + _automation_interval = ((nframes_t) ceil ((double) frames_per_second * 0.25)); // XXX we need some equivalent to this, somehow // SndFileSource::setup_standard_crossfades (frames_per_second); @@ -1504,7 +1506,7 @@ Session::new_midi_track (TrackMode mode, uint32_t how_many) for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { if (dynamic_cast((*i).get()) != 0) { - if (!(*i)->hidden()) { + if (!(*i)->is_hidden()) { n++; channels_used += (*i)->n_inputs().n_midi(); } @@ -1585,7 +1587,7 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { if (dynamic_cast((*i).get()) != 0) { - if (!(*i)->hidden()) { + if (!(*i)->is_hidden()) { n++; channels_used += (*i)->n_inputs().n_audio(); } @@ -1775,7 +1777,7 @@ Session::new_audio_route (int input_channels, int output_channels, uint32_t how_ for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { if (dynamic_cast((*i).get()) == 0) { - if (!(*i)->hidden() && (*i)->name() != _("master")) { + if (!(*i)->is_hidden() && (*i)->name() != _("master")) { bus_id++; } } @@ -1892,11 +1894,11 @@ Session::add_routes (RouteList& new_routes, bool save) (*x)->output_changed.connect (mem_fun (*this, &Session::set_worst_io_latencies_x)); (*x)->processors_changed.connect (bind (mem_fun (*this, &Session::update_latency_compensation), false, false)); - if ((*x)->master()) { + if ((*x)->is_master()) { _master_out = (*x); } - if ((*x)->control()) { + if ((*x)->is_control()) { _control_out = (*x); } } @@ -3436,7 +3438,7 @@ Session::set_all_solo (bool yn) shared_ptr r = routes.reader (); for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { - if (!(*i)->hidden()) { + if (!(*i)->is_hidden()) { (*i)->set_solo (yn, this); } } @@ -3450,7 +3452,7 @@ Session::set_all_mute (bool yn) shared_ptr r = routes.reader (); for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { - if (!(*i)->hidden()) { + if (!(*i)->is_hidden()) { (*i)->set_mute (yn, this); } } diff --git a/libs/ardour/session_process.cc b/libs/ardour/session_process.cc index dc71a40ca2..44b63e0875 100644 --- a/libs/ardour/session_process.cc +++ b/libs/ardour/session_process.cc @@ -101,7 +101,7 @@ Session::no_roll (nframes_t nframes, nframes_t offset) for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { - if ((*i)->hidden()) { + if ((*i)->is_hidden()) { continue; } @@ -140,7 +140,7 @@ Session::process_routes (nframes_t nframes, nframes_t offset) int ret; - if ((*i)->hidden()) { + if ((*i)->is_hidden()) { continue; } @@ -186,7 +186,7 @@ Session::silent_process_routes (nframes_t nframes, nframes_t offset) int ret; - if ((*i)->hidden()) { + if ((*i)->is_hidden()) { continue; } @@ -819,7 +819,7 @@ Session::process_audition (nframes_t nframes) boost::shared_ptr r = routes.reader (); for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { - if (!(*i)->hidden()) { + if (!(*i)->is_hidden()) { (*i)->silence (nframes, 0); } } diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index 65c48a2296..2924210e0c 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -939,7 +939,7 @@ Session::state(bool full_state) public_order.sort (cmp); for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) { - if (!(*i)->hidden()) { + if (!(*i)->is_hidden()) { if (full_state) { child->add_child_nocopy ((*i)->get_state()); } else { @@ -2055,7 +2055,7 @@ Session::get_global_route_boolean (bool (Route::*method)(void) const) boost::shared_ptr r = routes.reader (); for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { - if (!(*i)->hidden()) { + if (!(*i)->is_hidden()) { RouteBooleanState v; v.first =* i; @@ -2076,7 +2076,7 @@ Session::get_global_route_metering () boost::shared_ptr r = routes.reader (); for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { - if (!(*i)->hidden()) { + if (!(*i)->is_hidden()) { RouteMeterState v; v.first =* i; @@ -2622,7 +2622,7 @@ Session::set_deletion_in_progress () } void -Session::add_controllable (Controllable* c) +Session::add_controllable (boost::shared_ptr c) { /* this adds a controllable to the list managed by the Session. this is a subset of those managed by the Controllable class @@ -2633,6 +2633,8 @@ Session::add_controllable (Controllable* c) Glib::Mutex::Lock lm (controllables_lock); controllables.insert (c); } + +struct null_deleter { void operator()(void const *) const {} }; void Session::remove_controllable (Controllable* c) @@ -2643,14 +2645,15 @@ Session::remove_controllable (Controllable* c) Glib::Mutex::Lock lm (controllables_lock); - Controllables::iterator x = controllables.find (c); + Controllables::iterator x = controllables.find( + boost::shared_ptr(c, null_deleter())); if (x != controllables.end()) { controllables.erase (x); } } -Controllable* +boost::shared_ptr Session::controllable_by_id (const PBD::ID& id) { Glib::Mutex::Lock lm (controllables_lock); @@ -2661,7 +2664,7 @@ Session::controllable_by_id (const PBD::ID& id) } } - return 0; + return boost::shared_ptr(); } void diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc index 52f6346789..c122989b68 100644 --- a/libs/ardour/session_transport.cc +++ b/libs/ardour/session_transport.cc @@ -363,7 +363,7 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished) boost::shared_ptr r = routes.reader (); for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { - if (!(*i)->hidden()) { + if (!(*i)->is_hidden()) { (*i)->set_pending_declick (0); } } @@ -1262,7 +1262,7 @@ Session::update_latency_compensation (bool with_stop, bool abort) update_jack = true; } - if (!(*i)->hidden() && ((*i)->active())) { + if (!(*i)->is_hidden() && ((*i)->active())) { _worst_track_latency = max (_worst_track_latency, track_latency); } } diff --git a/libs/ardour/track.cc b/libs/ardour/track.cc index dd6d7a2067..052105cc85 100644 --- a/libs/ardour/track.cc +++ b/libs/ardour/track.cc @@ -40,7 +40,7 @@ using namespace PBD; Track::Track (Session& sess, string name, Route::Flag flag, TrackMode mode, DataType default_type) : Route (sess, name, 1, -1, -1, -1, flag, default_type) - , _rec_enable_control (*this) + , _rec_enable_control (new RecEnableControllable(*this)) { _declickable = true; _freeze_record.state = NoFreeze; @@ -50,7 +50,7 @@ Track::Track (Session& sess, string name, Route::Flag flag, TrackMode mode, Data Track::Track (Session& sess, const XMLNode& node, DataType default_type) : Route (sess, node) - , _rec_enable_control (*this) + , _rec_enable_control (new RecEnableControllable(*this)) { _freeze_record.state = NoFreeze; _declickable = true; @@ -188,7 +188,7 @@ Track::set_record_enable (bool yn, void *src) set_meter_point (_saved_meter_point, this); } - _rec_enable_control.Changed (); + _rec_enable_control->Changed (); } diff --git a/libs/gtkmm2ext/barcontroller.cc b/libs/gtkmm2ext/barcontroller.cc index c3c15b4281..142d224171 100644 --- a/libs/gtkmm2ext/barcontroller.cc +++ b/libs/gtkmm2ext/barcontroller.cc @@ -349,7 +349,8 @@ BarController::expose (GdkEventExpose* event) char buf[64]; buf[0] = '\0'; - label_callback (buf, 64); + if (label_callback) + label_callback (buf, 64); if (buf[0] != '\0') { diff --git a/libs/gtkmm2ext/gtkmm2ext/barcontroller.h b/libs/gtkmm2ext/gtkmm2ext/barcontroller.h index c91f4c8a06..ba2e1f3f7b 100644 --- a/libs/gtkmm2ext/gtkmm2ext/barcontroller.h +++ b/libs/gtkmm2ext/gtkmm2ext/barcontroller.h @@ -32,7 +32,10 @@ namespace Gtkmm2ext { class BarController : public Gtk::Frame { public: - BarController (Gtk::Adjustment& adj, PBD::Controllable&, sigc::slot); + typedef sigc::slot LabelCallback; + + BarController (Gtk::Adjustment& adj, PBD::Controllable&, LabelCallback lc = LabelCallback()); + virtual ~BarController () {} enum Style { @@ -40,6 +43,7 @@ class BarController : public Gtk::Frame RightToLeft, Line, CenterOut, + TopToBottom, BottomToTop }; @@ -64,7 +68,7 @@ class BarController : public Gtk::Frame Gtk::Adjustment& adjustment; BindingProxy binding_proxy; Gtk::DrawingArea darea; - sigc::slot label_callback; + LabelCallback label_callback; Glib::RefPtr layout; Style _style; bool grabbed; diff --git a/libs/surfaces/mackie/mackie_control_protocol.cc b/libs/surfaces/mackie/mackie_control_protocol.cc index 16b35397cf..5ef28d4549 100644 --- a/libs/surfaces/mackie/mackie_control_protocol.cc +++ b/libs/surfaces/mackie/mackie_control_protocol.cc @@ -228,9 +228,9 @@ MackieControlProtocol::Sorted MackieControlProtocol::get_sorted_routes() Route & route = **it; if ( route.active() - && !route.master() - && !route.hidden() - && !route.control() + && !route.is_master() + && !route.is_hidden() + && !route.is_control() && remote_ids.find( route.remote_control_id() ) == remote_ids.end() ) { @@ -1019,7 +1019,7 @@ void MackieControlProtocol::notify_panner_changed( RouteSignal * route_signal ) // TODO handle plugin automation polling void MackieControlProtocol::update_automation( RouteSignal & rs ) { - ARDOUR::AutoState gain_state = rs.route().gain_automation().automation_state(); + ARDOUR::AutoState gain_state = rs.route().gain_control()->list()->automation_state(); if ( gain_state == Touch || gain_state == Play ) { notify_gain_changed( &rs ); diff --git a/libs/surfaces/mackie/route_signal.cc b/libs/surfaces/mackie/route_signal.cc index 85c234436a..b01b5e0cf5 100644 --- a/libs/surfaces/mackie/route_signal.cc +++ b/libs/surfaces/mackie/route_signal.cc @@ -20,6 +20,7 @@ #include #include #include +#include #include "mackie_control_protocol.h" @@ -30,13 +31,13 @@ using namespace Mackie; void RouteSignal::connect() { if ( _strip.has_solo() ) - _solo_changed_connection = _route.solo_control().Changed.connect( sigc::bind ( mem_fun ( _mcp, &MackieControlProtocol::notify_solo_changed ), this ) ); + _solo_changed_connection = _route.solo_control()->Changed.connect( sigc::bind ( mem_fun ( _mcp, &MackieControlProtocol::notify_solo_changed ), this ) ); if ( _strip.has_mute() ) - _mute_changed_connection = _route.mute_control().Changed.connect( sigc::bind ( mem_fun ( _mcp, &MackieControlProtocol::notify_mute_changed ), this ) ); + _mute_changed_connection = _route.mute_control()->Changed.connect( sigc::bind ( mem_fun ( _mcp, &MackieControlProtocol::notify_mute_changed ), this ) ); if ( _strip.has_gain() ) - _gain_changed_connection = _route.gain_control().Changed.connect( sigc::bind ( mem_fun ( _mcp, &MackieControlProtocol::notify_gain_changed ), this ) ); + _gain_changed_connection = _route.control(ARDOUR::GainAutomation)->Changed.connect( sigc::bind ( mem_fun ( _mcp, &MackieControlProtocol::notify_gain_changed ), this ) ); _name_changed_connection = _route.NameChanged.connect( sigc::bind ( mem_fun ( _mcp, &MackieControlProtocol::notify_name_changed ), this ) ); @@ -48,7 +49,7 @@ void RouteSignal::connect() try { _record_enable_changed_connection = - dynamic_cast( _route ).rec_enable_control().Changed + dynamic_cast( _route ).rec_enable_control()->Changed .connect( sigc::bind ( mem_fun ( _mcp, &MackieControlProtocol::notify_record_enable_changed ), this ) ) ; }