diff options
80 files changed, 1202 insertions, 811 deletions
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 "<Actions>/Editor/Autoconnect" "") ; (gtk_accel_path "<Actions>/Editor/Edit" "") (gtk_accel_path "<Actions>/Editor/playhead-to-previous-region-end" "<Control>comma") -; (gtk_accel_path "<Actions>/redirectmenu/copy" "") +; (gtk_accel_path "<Actions>/processormenu/copy" "") ; (gtk_accel_path "<Actions>/options/MeterFalloffFaster" "") (gtk_accel_path "<Actions>/Transport/ToggleRollForgetCapture" "<Control>space") (gtk_accel_path "<Actions>/Transport/Record" "<Shift>r") ; (gtk_accel_path "<Actions>/RegionList/SortByRegionLength" "") ; (gtk_accel_path "<Actions>/options/MeterFalloffSlowest" "") ; (gtk_accel_path "<Actions>/Editor/playhead-to-previous-region-sync" "") -; (gtk_accel_path "<Actions>/redirectmenu/deactivate_all" "") +; (gtk_accel_path "<Actions>/processormenu/deactivate_all" "") ; (gtk_accel_path "<Actions>/RegionList/SortByRegionPosition" "") ; (gtk_accel_path "<Actions>/Editor/ZoomFocus" "") ; (gtk_accel_path "<Actions>/options/MeterFalloffSlow" "") @@ -28,7 +28,7 @@ ; (gtk_accel_path "<Actions>/Zoom/zoom-focus-playhead" "") ; (gtk_accel_path "<Actions>/Editor/center-edit-cursor" "") ; (gtk_accel_path "<Actions>/Editor/Monitoring" "") -; (gtk_accel_path "<Actions>/redirectmenu/deactivate" "") +; (gtk_accel_path "<Actions>/processormenu/deactivate" "") ; (gtk_accel_path "<Actions>/options/LatchedRecordEnable" "") ; (gtk_accel_path "<Actions>/Transport/TogglePunchIn" "") ; (gtk_accel_path "<Actions>/ShuttleActions/SetShuttleUnitsPercentage" "") @@ -96,9 +96,9 @@ ; (gtk_accel_path "<Actions>/Zoom/zoom-focus-edit" "") (gtk_accel_path "<Actions>/Editor/playhead-to-previous-region-start" "comma") ; (gtk_accel_path "<Actions>/Editor/EditCursorMovementOptions" "") -; (gtk_accel_path "<Actions>/redirectmenu/activate_all" "") +; (gtk_accel_path "<Actions>/processormenu/activate_all" "") ; (gtk_accel_path "<Actions>/Editor/addExternalAudioAsTapeTrack" "") -; (gtk_accel_path "<Actions>/redirectmenu/paste" "") +; (gtk_accel_path "<Actions>/processormenu/paste" "") ; (gtk_accel_path "<Actions>/Editor/Smpte25" "") ; (gtk_accel_path "<Actions>/options/RegionEquivalentsOverlap" "") ; (gtk_accel_path "<Actions>/Main/MeteringFallOffRate" "") @@ -123,7 +123,7 @@ (gtk_accel_path "<Actions>/Editor/align-regions-sync-relative" "a") ; (gtk_accel_path "<Actions>/Editor/EditSelectRegionOptions" "") (gtk_accel_path "<Actions>/Editor/crop" "c") -; (gtk_accel_path "<Actions>/redirectmenu/newsend" "") +; (gtk_accel_path "<Actions>/processormenu/newsend" "") ; (gtk_accel_path "<Actions>/Editor/ToggleGeneric MIDISurfaceSubMenu" "") ; (gtk_accel_path "<Actions>/Editor/MeterFalloff" "") ; (gtk_accel_path "<Actions>/RegionList/rlRemove" "") @@ -136,7 +136,7 @@ (gtk_accel_path "<Actions>/Editor/align-regions-sync" "<Mod2>a") ; (gtk_accel_path "<Actions>/Main/Windows" "") ; (gtk_accel_path "<Actions>/Main/CleanupUnused" "") -; (gtk_accel_path "<Actions>/redirectmenu/deselectall" "") +; (gtk_accel_path "<Actions>/processormenu/deselectall" "") ; (gtk_accel_path "<Actions>/options/SoloViaBus" "") (gtk_accel_path "<Actions>/MouseMode/set-mouse-mode-zoom" "z") ; (gtk_accel_path "<Actions>/RegionList/rlAudition" "") @@ -202,7 +202,7 @@ (gtk_accel_path "<Actions>/Editor/temporal-zoom-in" "minus") ; (gtk_accel_path "<Actions>/JACK/Latency" "") (gtk_accel_path "<Actions>/Editor/edit-cursor-to-range-end" "F2") -; (gtk_accel_path "<Actions>/redirectmenu/rename" "") +; (gtk_accel_path "<Actions>/processormenu/rename" "") ; (gtk_accel_path "<Actions>/RegionList/rlShowAuto" "") (gtk_accel_path "<Actions>/Editor/select-all-before-playhead" "<Control>p") ; (gtk_accel_path "<Actions>/Editor/addExistingAudioFiles" "") @@ -231,7 +231,7 @@ (gtk_accel_path "<Actions>/Common/goto-mixer" "<Alt>m") ; (gtk_accel_path "<Actions>/Editor/addExternalAudioToTrack" "") ; (gtk_accel_path "<Actions>/RegionList/SortBySourceFileCreationDate" "") -; (gtk_accel_path "<Actions>/redirectmenu/activate" "") +; (gtk_accel_path "<Actions>/processormenu/activate" "") (gtk_accel_path "<Actions>/Editor/extend-range-to-start-of-region" "leftanglebracket") ; (gtk_accel_path "<Actions>/Editor/PullupMinus1" "") ; (gtk_accel_path "<Actions>/Editor/snap-normal" "") @@ -239,7 +239,7 @@ (gtk_accel_path "<Actions>/Common/ToggleBigClock" "<Alt>b") ; (gtk_accel_path "<Actions>/Snap/snap-to-asixteenthbeat" "") (gtk_accel_path "<Actions>/Editor/select-all-in-punch-range" "<Control>d") -; (gtk_accel_path "<Actions>/redirectmenu/edit" "") +; (gtk_accel_path "<Actions>/processormenu/edit" "") (gtk_accel_path "<Actions>/Editor/duplicate-region" "d") ; (gtk_accel_path "<Actions>/JACK/JACKLatency2048" "") ; (gtk_accel_path "<Actions>/Editor/ToggleWaveformsWhileRecording" "") @@ -248,8 +248,8 @@ ; (gtk_accel_path "<Actions>/options/FileHeaderFormatWAVE" "") (gtk_accel_path "<Actions>/Transport/GotoZero" "KP_Insert") (gtk_accel_path "<Actions>/Transport/GotoEnd" "End") -; (gtk_accel_path "<Actions>/redirectmenu/cut" "") -; (gtk_accel_path "<Actions>/redirectmenu/newinsert" "") +; (gtk_accel_path "<Actions>/processormenu/cut" "") +; (gtk_accel_path "<Actions>/processormenu/newinsert" "") ; (gtk_accel_path "<Actions>/options/UseMMC" "") ; (gtk_accel_path "<Actions>/options/MeterFalloffOff" "") (gtk_accel_path "<Actions>/MouseMode/set-mouse-mode-object" "o") @@ -296,7 +296,7 @@ ; (gtk_accel_path "<Actions>/Editor/toggle-xfades-active" "") ; (gtk_accel_path "<Actions>/Snap/snap-to-bar" "") ; (gtk_accel_path "<Actions>/Editor/LayerLaterHigher" "") -; (gtk_accel_path "<Actions>/redirectmenu/selectall" "") +; (gtk_accel_path "<Actions>/processormenu/selectall" "") (gtk_accel_path "<Actions>/Editor/editor-copy" "<Control>c") ; (gtk_accel_path "<Actions>/Snap/snap-to-quarters" "") (gtk_accel_path "<Actions>/Editor/temporal-zoom-out" "equal") @@ -306,13 +306,13 @@ ; (gtk_accel_path "<Actions>/options/OutputAutoConnectManual" "") ; (gtk_accel_path "<Actions>/Snap/snap-to-region-sync" "") (gtk_accel_path "<Actions>/Editor/edit-cursor-to-previous-region-sync" "apostrophe") -; (gtk_accel_path "<Actions>/redirectmenu/clear" "") +; (gtk_accel_path "<Actions>/processormenu/clear" "") ; (gtk_accel_path "<Actions>/Editor/ToggleGeneric MIDISurfaceFeedback" "") ; (gtk_accel_path "<Actions>/Editor/PullupPlus4Minus1" "") ; (gtk_accel_path "<Actions>/JACK/JACKLatency512" "") (gtk_accel_path "<Actions>/Editor/edit-cursor-to-next-region-end" "<Control>bracketright") ; (gtk_accel_path "<Actions>/Main/Recent" "") -; (gtk_accel_path "<Actions>/redirectmenu/newplugin" "") +; (gtk_accel_path "<Actions>/processormenu/newplugin" "") ; (gtk_accel_path "<Actions>/options/InputAutoConnectManual" "") ; (gtk_accel_path "<Actions>/options/MeterHoldLong" "") ; (gtk_accel_path "<Actions>/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 @@ </menu> </menubar> - <popup name='redirectmenu'> + <popup name='processormenu'> <menuitem action='newplugin'/> <menuitem action='newinsert'/> <menuitem action='newsend'/> 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<AudioRegion>(*(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<AutomationList>(audio_region()->envelope(), &before, &after)); + XMLNode &after = audio_region()->envelope()->get_state(); + trackview.session().add_command (new MementoCommand<AutomationList>(*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<ControlPoint *> (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<AutomationControl> 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 <pbd/error.h> +#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<AutomationControl> 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> +AutomationController::create(Session& s, boost::shared_ptr<AutomationList> al, boost::shared_ptr<AutomationControl> 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<AutomationControl>(new AutomationControl(s, al)); + } + return boost::shared_ptr<AutomationController>(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 <boost/shared_ptr.hpp> +#include <gtkmm.h> +#include <gtkmm2ext/barcontroller.h> + +namespace ARDOUR { + class Session; + class AutomationList; + class AutomationControl; +} + + +class AutomationController : public Gtkmm2ext::BarController { +public: + static boost::shared_ptr<AutomationController> create( + ARDOUR::Session& s, + boost::shared_ptr<ARDOUR::AutomationList> al, + boost::shared_ptr<ARDOUR::AutomationControl> ac); + + ~AutomationController(); + + boost::shared_ptr<ARDOUR::AutomationControl> controllable() { return _controllable; } + + void update_label(char* label, int label_len); + void display_effective_value(); + void value_adjusted(); + +private: + AutomationController(boost::shared_ptr<ARDOUR::AutomationControl> ac, Gtk::Adjustment* adj); + void start_touch(); + void end_touch(); + + bool _ignore_change; + boost::shared_ptr<ARDOUR::AutomationControl> _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<AutomationList> 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<ARDOUR::AutomationList>); 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<AutomationList> 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<AutomationList>(alist, &get_state(), 0)); + trackview.editor.current_session()->add_command (new MementoCommand<AutomationList>(*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<AutomationList>(alist, 0, &alist.get_state())); + trackview.editor.current_session()->add_command (new MementoCommand<AutomationList>(*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<AutomationList>(alist, &before, &alist.get_state())); + trackview.editor.current_session()->add_command(new MementoCommand<AutomationList>( + *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<AutomationLine>(*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<ARDOUR::AutomationList>); 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<ARDOUR::AutomationList> 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<ARDOUR::AutomationList> 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<AutomationList> 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<ARDOUR::AutomationList>); 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<AutomationList> 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<ARDOUR::AutomationList>); 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 <utility> #include <ardour/route.h> +#include <ardour/automation_control.h> #include <pbd/memento_command.h> +#include <gtkmm2ext/barcontroller.h> #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_ptr<Ro auto_play_item = 0; ignore_state_request = false; first_call_to_set_height = true; - + base_rect = new SimpleRect(*canvas_display); base_rect->property_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<AutomationLine*>::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<AutomationLine*>::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<GhostRegion*>::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<AutomationLine*>::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<AutomationLine*>::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<AutomationList> 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<AutomationList>(alist, &before, &alist.get_state())); + _session.add_command(new MementoCommand<AutomationList>(*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<AutomationList>(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<AutomationList>(*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<AutomationLine*>::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<AutomationList> alist(line.the_list()); - _session.add_command (new MementoCommand<AutomationList>(alist, &alist.get_state(), 0)); + _session.add_command (new MementoCommand<AutomationList>(*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<AutomationLine*>::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<AutomationList> 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<AutomationList>(alist, new XMLNode (before), &alist.get_state())); + _session.add_command (new MementoCommand<AutomationList>(*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<AutomationList>(alist, new XMLNode (before), &alist.get_state())); + if ((what_we_got = alist->cut ((*i).start, (*i).end)) != 0) { + _session.add_command (new MementoCommand<AutomationList>(*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<AutomationLine*>::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<AutomationList> 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<AutomationList>(alist, &before, &alist.get_state())); + XMLNode &before = alist->get_state(); + alist->paste (copy, pos, times); + _session.add_command (new MementoCommand<AutomationList>(*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<AutomationLine*>::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<Selectable*>& result) { - for (vector<AutomationLine*>::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<AutomationLine*>::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<AutomationLine*>::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<AutomationLine*>::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<AutomationLine*>::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<GhostRegion *>::iterator i=ghosts.begin(); i != ghosts.end(); i++ ) { - (*i)->set_colors(); +AutomationTimeAxisView::set_colors () +{ + for (list<GhostRegion*>::iterator i=ghosts.begin(); i != ghosts.end(); i++ ) { + (*i)->set_colors(); } - for( vector<AutomationLine *>::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 <vector> #include <list> #include <string> +#include <utility> #include <boost/shared_ptr.hpp> @@ -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<AutomationLine*> lines; + typedef vector<std::pair<AutomationLine*,boost::shared_ptr<AutomationController> > > Lines; + Lines lines; void set_selected_points (PointSelection&); void get_selectables (nframes_t start, nframes_t end, double top, double bot, list<Selectable *>&); @@ -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<RouteTimeAxisView*>(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<AudioRegionView*>(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<AutomationList> 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<AutomationList>(alist, &before, &after)); + XMLNode &after = alist->get_state(); + session->add_command(new MementoCommand<AutomationList>(*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<AudioRegionView*>(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<AutomationList> 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<AutomationList>(alist, &before, &after)); + XMLNode &after = alist->get_state(); + session->add_command(new MementoCommand<AutomationList>(*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<AudioRegionView*>(*i); if (arv) { - AutomationList& alist (arv->audio_region()->envelope()); - XMLNode& before (alist.get_state()); + boost::shared_ptr<AutomationList> alist (arv->audio_region()->envelope()); + XMLNode& before (alist->get_state()); arv->audio_region()->set_default_envelope (); - session->add_command (new MementoCommand<AutomationList>(arv->audio_region()->envelope(), &before, &alist.get_state())); + session->add_command (new MementoCommand<AutomationList>(*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<AutomationList> 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<AutomationList>(alist, &before, &after)); + XMLNode &after = alist->get_state(); + session->add_command(new MementoCommand<AutomationList>(*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<AutomationList> 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<AutomationList>(alist, &before, &after)); + XMLNode &after = alist->get_state(); + session->add_command(new MementoCommand<AutomationList>(*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> 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> 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<Route> r, PublicEditor& e, TimeAxisView& parent, - ArdourCanvas::Canvas& canvas, const string & n, ARDOUR::AutomationList& l) + ArdourCanvas::Canvas& canvas, const string & n, + boost::shared_ptr<ARDOUR::AutomationControl> 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<ARDOUR::AutomationList>(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<ARDOUR::AutomationList>(*_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<ARDOUR::AutomationControl> control); ~GainAutomationTimeAxisView(); void add_automation_event (ArdourCanvas::Item *item, GdkEvent *event, nframes_t, double); private: - ARDOUR::AutomationList& list; + boost::shared_ptr<ARDOUR::AutomationControl> _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> 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> io, Session& s) if ((r = dynamic_cast<Route*> (_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> 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> 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> 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<Gtkmm2ext::SliderController*>(gain_slider)->set_sensitive (!(_io->gain_automation().automation_state() & Play)); + static_cast<Gtkmm2ext::SliderController*>(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<Route*>(&_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 <ardour/automation_event.h> #include <ardour/route.h> #include <pbd/memento_command.h> +#include <pbd/controllable.h> #include "midi_controller_time_axis.h" #include "automation_line.h" @@ -34,12 +35,10 @@ using namespace Gtk; MidiControllerTimeAxisView::MidiControllerTimeAxisView (Session& s, boost::shared_ptr<Route> r, PublicEditor& e, TimeAxisView& parent, ArdourCanvas::Canvas& canvas, const string & n, - ParamID param, ARDOUR::AutomationList& l) - + boost::shared_ptr<AutomationControl> 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<ARDOUR::AutomationList>(_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<ARDOUR::AutomationList>(*_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<ARDOUR::AutomationControl> c); ~MidiControllerTimeAxisView(); void add_automation_event (ArdourCanvas::Item *item, GdkEvent *event, nframes_t, double); private: - ARDOUR::AutomationList& _list; - ARDOUR::ParamID _param; + boost::shared_ptr<ARDOUR::AutomationControl> _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<AutomationControl> c =_route->control(param); - if (!al) - al = new ARDOUR::AutomationList(param, 0, 127, 64); - - _route->add_automation_parameter(al); + if (!c) { + boost::shared_ptr<AutomationList> al(new ARDOUR::AutomationList(param, 0, 127, 64)); + c = boost::shared_ptr<AutomationControl>(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<Route> 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<AutomationList> 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> 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<AutomationList> 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<AutomationList>(alist, &before, &after)); + XMLNode &before = alist->get_state(); + alist->add (when, y); + XMLNode &after = alist->get_state(); + _session.add_command(new MementoCommand<AutomationList>(*alist.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<PBD::Controllable> 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 <gtkmm2ext/barcontroller.h> +#include <boost/shared_ptr.hpp> class PannerBar : public Gtkmm2ext::BarController { public: - PannerBar (Gtk::Adjustment& adj, PBD::Controllable&); + PannerBar (Gtk::Adjustment& adj, boost::shared_ptr<PBD::Controllable>); ~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<AutomationList> 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<AutomationList> 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::AutomationList>); - 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<AutomationList> 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<Gtk::Menu*>(ActionManager::get_widget("/redirectmenu") ); + processor_menu = dynamic_cast<Gtk::Menu*>(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<Gtk::ActionGroup> popup_act_grp = Gtk::ActionGroup::create(X_("redirectmenu")); + Glib::RefPtr<Gtk::ActionGroup> popup_act_grp = Gtk::ActionGroup::create(X_("processormenu")); Glib::RefPtr<Action> 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<AutomationList> 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<AudioRegion>(*(rv.audio_region().get()), &rv.audio_region()->get_state(), 0)); - rv.audio_region()->set_envelope_active(false); + trackview.session().add_command(new MementoCommand<AudioRegion>(*(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<AudioRegion>(*(rv.audio_region().get()), ®ion_before, ®ion_after)); + XMLNode ®ion_after = rv.audio_region()->get_state(); + trackview.session().add_command(new MementoCommand<AudioRegion>(*(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<AutomationList>(alist, &before, &alist.get_state())); + trackview.editor.current_session()->add_command (new MementoCommand<AutomationList>(*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<ARDOUR::AutomationList>); 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> 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<ARDOUR::ParamID, RouteAutomationNode*>::iterator i; for (i = _automation_tracks.begin(); i != _automation_tracks.end(); ++i) { // FIXME: only shown if /first/ line has points - if (!i->second->track->lines.empty() && i->second->track->lines[0]->npoints() > 0) { + 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<Processor> /* 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<Processor> if ((ran = find_processor_automation_node (processor, what)) != 0) { if (ran->view) { - return dynamic_cast<ProcessorAutomationLine*> (ran->view->lines.front()); + return dynamic_cast<ProcessorAutomationLine*> (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<ARDOUR::Route> 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<ARDOUR::Route> 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 <pbd/file_utils.h> #include <gtkmm2ext/utils.h> -//#include <ardour/ardour.h> #include <ardour/filesystem_paths.h> 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<AutomationList> fade_in() { return _fade_in; } + boost::shared_ptr<AutomationList> fade_out() { return _fade_out; } + boost::shared_ptr<AutomationList> 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<AutomationList> _fade_in; + FadeShape _fade_in_shape; + boost::shared_ptr<AutomationList> _fade_out; + FadeShape _fade_out_shape; + boost::shared_ptr<AutomationList> _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 <set> #include <map> +#include <boost/shared_ptr.hpp> #include <ardour/session_object.h> #include <ardour/automation_event.h> +#include <ardour/automation_control.h> #include <ardour/param_id.h> 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<AutomationControl> + 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<AutomationControl> control(ParamID id, bool create_if_missing=false); + virtual boost::shared_ptr<const AutomationControl> control(ParamID id) const; - virtual void add_automation_parameter(AutomationList* al); + virtual void add_control(boost::shared_ptr<AutomationControl>); - 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<ParamID,AutomationList*> _parameter_automation; - std::set<ParamID> _visible_parameter_automation; + + typedef std::map<ParamID,boost::shared_ptr<AutomationControl> > Controls; + + Controls _controls; + std::set<ParamID> _visible_controls; std::set<ParamID> _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 <boost/shared_ptr.hpp> +#include <pbd/controllable.h> + +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<ARDOUR::AutomationList>, + std::string name="unnamed controllable"); + + void set_value(float val); + float get_value() const; + float user_value() const; + + void set_list(boost::shared_ptr<ARDOUR::AutomationList>); + + boost::shared_ptr<ARDOUR::AutomationList> list() { return _list; } + boost::shared_ptr<const ARDOUR::AutomationList> list() const { return _list; } + +protected: + ARDOUR::Session& _session; + boost::shared_ptr<ARDOUR::AutomationList> _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 <ardour/port_set.h> #include <ardour/chan_count.h> #include <ardour/latent.h> +#include <ardour/automation_control.h> 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<void,IOChange,void*> input_changed; sigc::signal<void,IOChange,void*> output_changed; - sigc::signal<void,void*> 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<void,ChanCount> MoreChannels; static sigc::signal<int> 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<AutomationList> 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<GainControl> gain_control() { + return _gain_control; } - - static nframes_t automation_interval() { - return _automation_interval; + boost::shared_ptr<const GainControl> 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; - }; - - GainControllable _gain_control; + boost::shared_ptr<GainControl> _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<PBD::Controllable> 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<AutomationList> automation() = 0; sigc::signal<void> Changed; /* for position */ sigc::signal<void> 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<PanControllable> _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<AutomationList> 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<AutomationList> _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<AutomationList> 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<AutomationList> _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<PBD::Controllable> solo_control() { return _solo_control; } - PBD::Controllable& mute_control() { + boost::shared_ptr<PBD::Controllable> 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<ToggleControllable> _solo_control; + boost::shared_ptr<ToggleControllable> _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<void> NamedSelectionAdded; sigc::signal<void> 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<PBD::ID, PBD::StatefulThingWithGoingAway*> 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<PBD::Controllable> controllable_by_id (const PBD::ID&); - void add_controllable (PBD::Controllable*); + void add_controllable (boost::shared_ptr<PBD::Controllable>); 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<PBD::Controllable*> Controllables; + typedef std::set<boost::shared_ptr<PBD::Controllable> > 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<PBD::Controllable> 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<RecEnableControllable> _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<AudioSource> 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<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (src); if (afs) { @@ -98,9 +98,9 @@ AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> src, nframes_t start, n /* Basic AudioRegion constructor (one channel) */ AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> 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<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (src); if (afs) { @@ -113,9 +113,9 @@ AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> 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<const AudioRegion> 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<const AudioRegion> 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<const AudioRegion> 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<const AudioRegion> other, nframes_t } AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> 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<const AudioRegion> other) AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> 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<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (src); if (afs) { @@ -201,9 +201,9 @@ AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> 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<ParamID> 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<AutomationControl> 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<AutomationControl> 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<ParamID>& s) const { Glib::Mutex::Lock lm (_automation_lock); - map<ParamID,AutomationList*>::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<ParamID>& s) const Glib::Mutex::Lock lm (_automation_lock); set<ParamID>::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<AutomationControl> +Automatable::control (ParamID parameter, bool create_if_missing) { - std::map<ParamID,AutomationList*>::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<AutomationList> al (new AutomationList ( + parameter, FLT_MIN, FLT_MAX, default_parameter_value (parameter))); + boost::shared_ptr<AutomationControl> 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<AutomationControl>(); } } -const AutomationList* -Automatable::automation_list (ParamID parameter) const +boost::shared_ptr<const AutomationControl> +Automatable::control (ParamID parameter) const { - std::map<ParamID,AutomationList*>::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<AutomationControl>(); } } @@ -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<ParamID>::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<ParamID,AutomationList*>::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<const AutomationList> 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<AutomationList> 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<AutomationControl> existing = control(param); + if (existing) + existing->set_list(al); + else + add_control(boost::shared_ptr<AutomationControl>(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<ParamID,AutomationList*>::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<ParamID,AutomationList*>::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<AutomationControl> 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<AutomationControl> 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<AutomationControl> 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<AutomationControl> 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<ParamID>::iterator i = automated_params.begin(); i != automated_params.end(); ++i) { - AutomationList* al = automation_list (*i); + boost::shared_ptr<AutomationControl> 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 <iostream> +#include <ardour/automation_control.h> +#include <ardour/session.h> +#include <ardour/automatable.h> + +using namespace std; +using namespace ARDOUR; +using namespace PBD; + + +AutomationControl::AutomationControl(Session& session, boost::shared_ptr<AutomationList> 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<ARDOUR::AutomationList> 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<AutomationList> gl( + new AutomationList(ParamID(GainAutomation), 0.0, 2.0, 1.0)); - apply_gain_automation = false; - - last_automation_snapshot = 0; + _gain_control = boost::shared_ptr<GainControl>( + new GainControl(X_("gaincontrol"), *this, gl)); - /*_gain_automation_state = Off; - _gain_automation_style = Absolute;*/ + add_control(_gain_control); + apply_gain_automation = false; + { // 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<AutomationList> gl( + new AutomationList(ParamID(GainAutomation), 0.0, 2.0, 1.0)); + + _gain_control = boost::shared_ptr<GainControl>( + 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<AutomationList> 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) { - - ARDOUR::AutomationList& gain_auto = gain_automation(); + Automatable::automation_snapshot (now); - 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_auto.reposition_for_rt_add (frame); + _gain_control->list()->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<MidiDiskstream> 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<StreamPanner*>::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<StreamPanner*>::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<uint32_t>::iterator s; } PluginInsert::~PluginInsert () @@ -152,21 +150,15 @@ PluginInsert::~PluginInsert () } 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<AutomationControl> 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<ParamID> a; - - a = _plugins.front()->automatable (); + set<ParamID> a = _plugins.front()->automatable (); + + Plugin::ParameterDescriptor desc; for (set<ParamID>::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<AutomationList> 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<AutomationControl>( + new AutomationControl(_session, list))); + } } } @@ -276,21 +279,20 @@ PluginInsert::connect_and_run (BufferSet& bufs, nframes_t nframes, nframes_t off if (with_auto) { - map<ParamID,AutomationList*>::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<AutomationControl> 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<ParamID,AutomationList*>::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<AutomationControl> 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<ParamID,AutomationList*>::iterator li; - - for (li =_parameter_automation.begin(); li !=_parameter_automation.end(); ++li) { - AutomationList& alist (*(li->second)); - alist.reposition_for_rt_add (now); + for (Controls::iterator li = _controls.begin(); li != _controls.end(); ++li) { + + boost::shared_ptr<AutomationControl> c = li->second; + + c->list()->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<AutomationControl> 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<ParamID>::iterator x = _visible_parameter_automation.begin(); x != _visible_parameter_automation.end(); ++x) { - if (x != _visible_parameter_automation.begin()) { + for (set<ParamID>::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<string>& 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<MidiTrack*>((*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<AudioTrack*>((*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<AudioTrack*>((*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<RouteList> 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<RouteList> 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<RouteList> 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<RouteList> 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<RouteList> 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<Controllable> 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<Controllable>(c, null_deleter())); if (x != controllables.end()) { controllables.erase (x); } } -Controllable* +boost::shared_ptr<Controllable> 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<Controllable>(); } 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<RouteList> 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<void,char*,unsigned int>); + typedef sigc::slot<void,char*,unsigned int> 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<void,char*,unsigned int> label_callback; + LabelCallback label_callback; Glib::RefPtr<Pango::Layout> 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 <ardour/route.h> #include <ardour/track.h> #include <ardour/panner.h> +#include <ardour/types.h> #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<ARDOUR::Track&>( _route ).rec_enable_control().Changed + dynamic_cast<ARDOUR::Track&>( _route ).rec_enable_control()->Changed .connect( sigc::bind ( mem_fun ( _mcp, &MackieControlProtocol::notify_record_enable_changed ), this ) ) ; } |