break out Route controllables code into its own source module
[ardour.git] / libs / ardour / route_controls.cc
1 /*
2     Copyright (C) 2000 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #ifdef WAF_BUILD
21 #include "libardour-config.h"
22 #endif
23
24 #include "ardour/automation_control.h"
25 #include "ardour/route.h"
26 #include "ardour/session.h"
27
28 #include "i18n.h"
29
30 using namespace std;
31 using namespace ARDOUR;
32 using namespace PBD;
33
34 void
35 Route::set_control (AutomationType type, double val, PBD::Controllable::GroupControlDisposition group_override)
36 {
37         boost::shared_ptr<RouteList> rl;
38
39         switch (type) {
40         case GainAutomation:
41                 /* route must mediate group control */
42                 set_gain (val, group_override);
43                 return;
44                 break;
45
46         case TrimAutomation:
47                 /* route must mediate group control */
48                 set_trim (val, group_override);
49                 return;
50                 break;
51
52         case RecEnableAutomation:
53                 /* session must mediate group control */
54                 rl.reset (new RouteList);
55                 rl->push_back (shared_from_this());
56                 _session.set_record_enabled (rl, val >= 0.5 ? true : false, Session::rt_cleanup, group_override);
57                 return;
58                 break;
59
60         case SoloAutomation:
61                 /* session must mediate group control */
62                 rl.reset (new RouteList);
63                 rl->push_back (shared_from_this());
64                 if (Config->get_solo_control_is_listen_control()) {
65                         _session.set_listen (rl, val >= 0.5 ? true : false, Session::rt_cleanup, group_override);
66                 } else {
67                         _session.set_solo (rl, val >= 0.5 ? true : false);
68                 }
69
70                 return;
71                 break;
72
73         case MuteAutomation:
74                 /* session must mediate group control */
75                 rl.reset (new RouteList);
76                 rl->push_back (shared_from_this());
77                 _session.set_mute (rl, !muted(), Session::rt_cleanup, group_override);
78                 return;
79                 break;
80
81         default:
82                 /* Not a route automation control */
83                 fatal << string_compose (_("programming error: %1%2\n"), X_("illegal type of route automation control passed to Route::set_control(): "), enum_2_string(type)) << endmsg;
84                 /*NOTREACHED*/
85                 return;
86         }
87 }
88
89
90 Route::RouteAutomationControl::RouteAutomationControl (const std::string& name,
91                                                        AutomationType atype,
92                                                        boost::shared_ptr<AutomationList> alist,
93                                                        boost::shared_ptr<Route> r)
94         : AutomationControl (r->session(), Evoral::Parameter (atype),
95                              ParameterDescriptor (Evoral::Parameter (atype)),
96                              alist, name)
97         , _route (r)
98 {
99 }
100
101 Route::GainControllable::GainControllable (Session& s, AutomationType atype, boost::shared_ptr<Route> r)
102         : GainControl (s, Evoral::Parameter(atype))
103         , _route (r)
104 {
105
106 }
107
108 Route::SoloControllable::SoloControllable (std::string name, boost::shared_ptr<Route> r)
109         : RouteAutomationControl (name, SoloAutomation, boost::shared_ptr<AutomationList>(), r)
110 {
111         boost::shared_ptr<AutomationList> gl(new AutomationList(Evoral::Parameter(SoloAutomation)));
112         gl->set_interpolation(Evoral::ControlList::Discrete);
113         set_list (gl);
114 }
115
116 void
117 Route::SoloControllable::set_value (double val, PBD::Controllable::GroupControlDisposition group_override)
118 {
119         if (writable()) {
120                 _set_value (val, group_override);
121         }
122 }
123
124 void
125 Route::SoloControllable::_set_value (double val, PBD::Controllable::GroupControlDisposition group_override)
126 {
127         const bool bval = ((val >= 0.5) ? true : false);
128
129         boost::shared_ptr<RouteList> rl (new RouteList);
130
131         boost::shared_ptr<Route> r = _route.lock ();
132         if (!r) {
133                 return;
134         }
135
136         rl->push_back (r);
137
138         if (Config->get_solo_control_is_listen_control()) {
139                 _session.set_listen (rl, bval, Session::rt_cleanup, group_override);
140         } else {
141                 _session.set_solo (rl, bval, Session::rt_cleanup, group_override);
142         }
143 }
144
145 void
146 Route::SoloControllable::set_value_unchecked (double val)
147 {
148         /* Used only by automation playback */
149
150         _set_value (val, Controllable::NoGroup);
151 }
152
153 double
154 Route::SoloControllable::get_value () const
155 {
156         boost::shared_ptr<Route> r = _route.lock ();
157         if (!r) {
158                 return 0;
159         }
160
161         if (Config->get_solo_control_is_listen_control()) {
162                 return r->listening_via_monitor() ? GAIN_COEFF_UNITY : GAIN_COEFF_ZERO;
163         } else {
164                 return r->self_soloed() ? GAIN_COEFF_UNITY : GAIN_COEFF_ZERO;
165         }
166 }
167
168 Route::MuteControllable::MuteControllable (std::string name, boost::shared_ptr<Route> r)
169         : RouteAutomationControl (name, MuteAutomation, boost::shared_ptr<AutomationList>(), r)
170         , _route (r)
171 {
172         boost::shared_ptr<AutomationList> gl(new AutomationList(Evoral::Parameter(MuteAutomation)));
173         gl->set_interpolation(Evoral::ControlList::Discrete);
174         set_list (gl);
175 }
176
177 void
178 Route::MuteControllable::set_superficial_value(bool muted)
179 {
180         /* Note we can not use AutomationControl::set_value here since it will emit
181            Changed(), but the value will not be correct to the observer. */
182
183         const bool to_list = _list && ((AutomationList*)_list.get ())->automation_write ();
184         const double where = _session.audible_frame ();
185         if (to_list) {
186                 /* Note that we really need this:
187                  *  if (as == Touch && _list->in_new_write_pass ()) {
188                  *       alist->start_write_pass (_session.audible_frame ());
189                  *  }
190                  * here in the case of the user calling from a GUI or whatever.
191                  * Without the ability to distinguish between user and
192                  * automation-initiated changes, we lose the "touch mute"
193                  * behaviour we have in AutomationController::toggled ().
194                  */
195                 _list->set_in_write_pass (true, false, where);
196         }
197
198         Control::set_double (muted, where, to_list);
199 }
200
201 void
202 Route::MuteControllable::set_value (double val, PBD::Controllable::GroupControlDisposition group_override)
203 {
204         if (writable()) {
205                 _set_value (val, group_override);
206         }
207 }
208
209 void
210 Route::MuteControllable::set_value_unchecked (double val)
211 {
212         /* used only automation playback */
213         _set_value (val, Controllable::NoGroup);
214 }
215
216 void
217 Route::MuteControllable::_set_value (double val, Controllable::GroupControlDisposition group_override)
218 {
219         const bool bval = ((val >= 0.5) ? true : false);
220
221         boost::shared_ptr<Route> r = _route.lock ();
222         if (!r) {
223                 return;
224         }
225
226         if (_list && ((AutomationList*)_list.get())->automation_playback()) {
227                 // Set superficial/automation value to drive controller (and possibly record)
228                 set_superficial_value (bval);
229                 // Playing back automation, set route mute directly
230                 r->set_mute (bval, Controllable::NoGroup);
231         } else {
232                 // Set from user, queue mute event
233                 boost::shared_ptr<RouteList> rl (new RouteList);
234                 rl->push_back (r);
235                 _session.set_mute (rl, bval, Session::rt_cleanup, group_override);
236         }
237 }
238
239 double
240 Route::MuteControllable::get_value () const
241 {
242         if (_list && ((AutomationList*)_list.get())->automation_playback()) {
243                 // Playing back automation, get the value from the list
244                 return AutomationControl::get_value();
245         }
246
247         // Not playing back automation, get the actual route mute value
248         boost::shared_ptr<Route> r = _route.lock ();
249         return (r && r->muted()) ? GAIN_COEFF_UNITY : GAIN_COEFF_ZERO;
250 }
251
252 Route::PhaseControllable::PhaseControllable (std::string name, boost::shared_ptr<Route> r)
253         : RouteAutomationControl (name, PhaseAutomation, boost::shared_ptr<AutomationList>(), r)
254 {
255         boost::shared_ptr<AutomationList> gl(new AutomationList(Evoral::Parameter(PhaseAutomation)));
256         gl->set_interpolation(Evoral::ControlList::Discrete);
257         set_list (gl);
258 }
259
260 void
261 Route::PhaseControllable::set_value (double v, PBD::Controllable::GroupControlDisposition /* group_override */)
262 {
263         boost::shared_ptr<Route> r = _route.lock ();
264         if (r->phase_invert().size()) {
265                 if (v == 0 || (v < 1 && v > 0.9) ) {
266                         r->set_phase_invert (_current_phase, false);
267                 } else {
268                         r->set_phase_invert (_current_phase, true);
269                 }
270         }
271 }
272
273 double
274 Route::PhaseControllable::get_value () const
275 {
276         boost::shared_ptr<Route> r = _route.lock ();
277         return (double) r->phase_invert (_current_phase);
278 }
279
280 void
281 Route::PhaseControllable::set_channel (uint32_t c)
282 {
283         _current_phase = c;
284 }
285
286 uint32_t
287 Route::PhaseControllable::channel () const
288 {
289         return _current_phase;
290 }
291