summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gtk2_ardour/SConscript1
-rw-r--r--gtk2_ardour/ardour.bindings.in30
-rw-r--r--gtk2_ardour/ardour.menus2
-rw-r--r--gtk2_ardour/audio_region_view.cc26
-rw-r--r--gtk2_ardour/audio_time_axis.cc13
-rw-r--r--gtk2_ardour/automation_controller.cc110
-rw-r--r--gtk2_ardour/automation_controller.h62
-rw-r--r--gtk2_ardour/automation_gain_line.cc2
-rw-r--r--gtk2_ardour/automation_gain_line.h2
-rw-r--r--gtk2_ardour/automation_line.cc48
-rw-r--r--gtk2_ardour/automation_line.h6
-rw-r--r--gtk2_ardour/automation_midi_cc_line.cc2
-rw-r--r--gtk2_ardour/automation_midi_cc_line.h2
-rw-r--r--gtk2_ardour/automation_pan_line.cc2
-rw-r--r--gtk2_ardour/automation_pan_line.h2
-rw-r--r--gtk2_ardour/automation_time_axis.cc162
-rw-r--r--gtk2_ardour/automation_time_axis.h10
-rw-r--r--gtk2_ardour/editor.cc2
-rw-r--r--gtk2_ardour/editor_mouse.cc20
-rw-r--r--gtk2_ardour/editor_ops.cc22
-rw-r--r--gtk2_ardour/editor_route_list.cc2
-rw-r--r--gtk2_ardour/export_dialog.cc2
-rw-r--r--gtk2_ardour/gain_automation_time_axis.cc23
-rw-r--r--gtk2_ardour/gain_automation_time_axis.h6
-rw-r--r--gtk2_ardour/gain_meter.cc36
-rw-r--r--gtk2_ardour/gain_meter.h2
-rw-r--r--gtk2_ardour/ladspa_pluginui.cc6
-rw-r--r--gtk2_ardour/midi_controller_time_axis.cc28
-rw-r--r--gtk2_ardour/midi_controller_time_axis.h7
-rw-r--r--gtk2_ardour/midi_time_axis.cc16
-rw-r--r--gtk2_ardour/mixer_strip.cc16
-rw-r--r--gtk2_ardour/mixer_ui.cc14
-rw-r--r--gtk2_ardour/pan_automation_time_axis.cc20
-rw-r--r--gtk2_ardour/pan_automation_time_axis.h1
-rw-r--r--gtk2_ardour/panner.cc4
-rw-r--r--gtk2_ardour/panner.h3
-rw-r--r--gtk2_ardour/panner_ui.cc6
-rw-r--r--gtk2_ardour/processor_automation_line.cc9
-rw-r--r--gtk2_ardour/processor_automation_line.h6
-rw-r--r--gtk2_ardour/processor_automation_time_axis.cc32
-rw-r--r--gtk2_ardour/processor_automation_time_axis.h1
-rw-r--r--gtk2_ardour/processor_box.cc4
-rw-r--r--gtk2_ardour/region_gain_line.cc18
-rw-r--r--gtk2_ardour/region_gain_line.h2
-rw-r--r--gtk2_ardour/route_params_ui.cc2
-rw-r--r--gtk2_ardour/route_time_axis.cc10
-rw-r--r--gtk2_ardour/route_ui.cc6
-rw-r--r--gtk2_ardour/utils.cc1
-rw-r--r--libs/ardour/SConscript1
-rw-r--r--libs/ardour/ardour/audioregion.h22
-rw-r--r--libs/ardour/ardour/automatable.h28
-rw-r--r--libs/ardour/ardour/automation_control.h59
-rw-r--r--libs/ardour/ardour/io.h54
-rw-r--r--libs/ardour/ardour/panner.h14
-rw-r--r--libs/ardour/ardour/plugin_insert.h1
-rw-r--r--libs/ardour/ardour/processor.h2
-rw-r--r--libs/ardour/ardour/route.h14
-rw-r--r--libs/ardour/ardour/session.h20
-rw-r--r--libs/ardour/ardour/track.h5
-rw-r--r--libs/ardour/audio_track.cc14
-rw-r--r--libs/ardour/audioregion.cc286
-rw-r--r--libs/ardour/automatable.cc164
-rw-r--r--libs/ardour/automation_control.cc85
-rw-r--r--libs/ardour/automation_event.cc14
-rw-r--r--libs/ardour/io.cc114
-rw-r--r--libs/ardour/midi_diskstream.cc5
-rw-r--r--libs/ardour/midi_track.cc15
-rw-r--r--libs/ardour/panner.cc60
-rw-r--r--libs/ardour/plugin_insert.cc89
-rw-r--r--libs/ardour/processor.cc6
-rw-r--r--libs/ardour/route.cc47
-rw-r--r--libs/ardour/session.cc22
-rw-r--r--libs/ardour/session_process.cc8
-rw-r--r--libs/ardour/session_state.cc17
-rw-r--r--libs/ardour/session_transport.cc4
-rw-r--r--libs/ardour/track.cc6
-rw-r--r--libs/gtkmm2ext/barcontroller.cc3
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/barcontroller.h8
-rw-r--r--libs/surfaces/mackie/mackie_control_protocol.cc8
-rw-r--r--libs/surfaces/mackie/route_signal.cc9
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 &region_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()), &region_before, &region_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 &region_before = rv.audio_region()->get_state();
+ XMLNode &region_before = rv.audio_region()->get_state();
rv.audio_region()->set_envelope_active(true);
- XMLNode &region_after = rv.audio_region()->get_state();
- trackview.session().add_command(new MementoCommand<AudioRegion>(*(rv.audio_region().get()), &region_before, &region_after));
+ XMLNode &region_after = rv.audio_region()->get_state();
+ trackview.session().add_command(new MementoCommand<AudioRegion>(*(rv.audio_region().get()), &region_before, &region_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 ) )
;
}