1 /*
2  * Copyright (C) 2006-2009 David Robillard <d@drobilla.net>
3  * Copyright (C) 2006-2017 Paul Davis <paul@linuxaudiosystems.com>
4  * Copyright (C) 2015-2016 Tim Mayberry <mojofunk@gmail.com>
5  * Copyright (C) 2015-2017 Robin Gareus <robin@gareus.org>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21 
22 #include "pbd/convert.h"
23 #include "pbd/error.h"
24 
25 #include "ardour/control_protocol_manager.h"
26 #include "ardour/gain_control.h"
27 #include "ardour/session.h"
28 #include "ardour/record_enable_control.h"
29 #include "ardour/route.h"
30 #include "ardour/audio_track.h"
31 #include "ardour/meter.h"
32 #include "ardour/amp.h"
33 #include "ardour/selection.h"
34 #include "control_protocol/control_protocol.h"
35 
36 using namespace ARDOUR;
37 using namespace std;
38 using namespace PBD;
39 
40 Signal0<void>       ControlProtocol::ZoomToSession;
41 Signal0<void>       ControlProtocol::ZoomOut;
42 Signal0<void>       ControlProtocol::ZoomIn;
43 Signal0<void>       ControlProtocol::Enter;
44 Signal0<void>       ControlProtocol::Undo;
45 Signal0<void>       ControlProtocol::Redo;
46 Signal1<void,float> ControlProtocol::ScrollTimeline;
47 Signal1<void,uint32_t> ControlProtocol::GotoView;
48 Signal0<void> ControlProtocol::CloseDialog;
49 PBD::Signal0<void> ControlProtocol::VerticalZoomInAll;
50 PBD::Signal0<void> ControlProtocol::VerticalZoomOutAll;
51 PBD::Signal0<void> ControlProtocol::VerticalZoomInSelected;
52 PBD::Signal0<void> ControlProtocol::VerticalZoomOutSelected;
53 PBD::Signal0<void>          ControlProtocol::StepTracksDown;
54 PBD::Signal0<void>          ControlProtocol::StepTracksUp;
55 
56 StripableNotificationList ControlProtocol::_last_selected;
57 PBD::ScopedConnection ControlProtocol::selection_connection;
58 bool ControlProtocol::selection_connected = false;
59 
60 const std::string ControlProtocol::state_node_name ("Protocol");
61 
ControlProtocol(Session & s,string str)62 ControlProtocol::ControlProtocol (Session& s, string str)
63 	: BasicUI (s)
64 	, _name (str)
65 	, _active (false)
66 {
67 	if (!selection_connected) {
68 		/* this is all static, connect it only once (and early), for all ControlProtocols */
69 		ControlProtocolManager::StripableSelectionChanged.connect_same_thread (selection_connection, boost::bind (&ControlProtocol::notify_stripable_selection_changed, _1));
70 		selection_connected = true;
71 	}
72 }
73 
~ControlProtocol()74 ControlProtocol::~ControlProtocol ()
75 {
76 }
77 
78 int
set_active(bool yn)79 ControlProtocol::set_active (bool yn)
80 {
81 	_active = yn;
82 	return 0;
83 }
84 
85 void
next_track(uint32_t initial_id)86 ControlProtocol::next_track (uint32_t initial_id)
87 {
88 	// STRIPABLE route_table[0] = _session->get_nth_stripable (++initial_id, RemoteControlID::Route);
89 }
90 
91 void
prev_track(uint32_t initial_id)92 ControlProtocol::prev_track (uint32_t initial_id)
93 {
94 	if (!initial_id) {
95 		return;
96 	}
97 	// STRIPABLE route_table[0] = _session->get_nth_stripable (--initial_id, RemoteControlID::Route);
98 }
99 
100 void
set_route_table_size(uint32_t size)101 ControlProtocol::set_route_table_size (uint32_t size)
102 {
103 	while (route_table.size() < size) {
104 		route_table.push_back (boost::shared_ptr<Route> ((Route*) 0));
105 	}
106 }
107 
108 void
set_route_table(uint32_t table_index,boost::shared_ptr<ARDOUR::Route> r)109 ControlProtocol::set_route_table (uint32_t table_index, boost::shared_ptr<ARDOUR::Route> r)
110 {
111 	if (table_index >= route_table.size()) {
112 		return;
113 	}
114 
115 	route_table[table_index] = r;
116 
117 	// XXX SHAREDPTR need to handle r->GoingAway
118 }
119 
120 bool
set_route_table(uint32_t table_index,uint32_t remote_control_id)121 ControlProtocol::set_route_table (uint32_t table_index, uint32_t remote_control_id)
122 {
123 #if 0 // STRIPABLE
124 	boost::shared_ptr<Route> r = session->route_by_remote_id (remote_control_id);
125 
126 	if (!r) {
127 		return false;
128 	}
129 
130 	set_route_table (table_index, r);
131 #endif
132 	return true;
133 }
134 
135 void
route_set_rec_enable(uint32_t table_index,bool yn)136 ControlProtocol::route_set_rec_enable (uint32_t table_index, bool yn)
137 {
138 	if (table_index > route_table.size()) {
139 		return;
140 	}
141 
142 	boost::shared_ptr<Route> r = route_table[table_index];
143 
144 	boost::shared_ptr<AudioTrack> at = boost::dynamic_pointer_cast<AudioTrack>(r);
145 
146 	if (at) {
147 		at->rec_enable_control()->set_value (1.0, Controllable::UseGroup);
148 	}
149 }
150 
151 bool
route_get_rec_enable(uint32_t table_index)152 ControlProtocol::route_get_rec_enable (uint32_t table_index)
153 {
154 	if (table_index > route_table.size()) {
155 		return false;
156 	}
157 
158 	boost::shared_ptr<Route> r = route_table[table_index];
159 
160 	boost::shared_ptr<AudioTrack> at = boost::dynamic_pointer_cast<AudioTrack>(r);
161 
162 	if (at) {
163 		return at->rec_enable_control()->get_value();
164 	}
165 
166 	return false;
167 }
168 
169 
170 float
route_get_gain(uint32_t table_index)171 ControlProtocol::route_get_gain (uint32_t table_index)
172 {
173 	if (table_index > route_table.size()) {
174 		return 0.0f;
175 	}
176 
177 	boost::shared_ptr<Route> r = route_table[table_index];
178 
179 	if (r == 0) {
180 		return 0.0f;
181 	}
182 
183 	return r->gain_control()->get_value();
184 }
185 
186 void
route_set_gain(uint32_t table_index,float gain)187 ControlProtocol::route_set_gain (uint32_t table_index, float gain)
188 {
189 	if (table_index > route_table.size()) {
190 		return;
191 	}
192 
193 	boost::shared_ptr<Route> r = route_table[table_index];
194 
195 	if (r != 0) {
196 		r->gain_control()->set_value (gain, Controllable::UseGroup);
197 	}
198 }
199 
200 float
route_get_effective_gain(uint32_t table_index)201 ControlProtocol::route_get_effective_gain (uint32_t table_index)
202 {
203 	if (table_index > route_table.size()) {
204 		return 0.0f;
205 	}
206 
207 	boost::shared_ptr<Route> r = route_table[table_index];
208 
209 	if (r == 0) {
210 		return 0.0f;
211 	}
212 
213 	return r->amp()->gain_control()->get_value();
214 }
215 
216 
217 float
route_get_peak_input_power(uint32_t table_index,uint32_t which_input)218 ControlProtocol::route_get_peak_input_power (uint32_t table_index, uint32_t which_input)
219 {
220 	if (table_index > route_table.size()) {
221 		return 0.0f;
222 	}
223 
224 	boost::shared_ptr<Route> r = route_table[table_index];
225 
226 	if (r == 0) {
227 		return 0.0f;
228 	}
229 
230 	return r->peak_meter()->meter_level (which_input, MeterPeak);
231 }
232 
233 bool
route_get_muted(uint32_t table_index)234 ControlProtocol::route_get_muted (uint32_t table_index)
235 {
236 	if (table_index > route_table.size()) {
237 		return false;
238 	}
239 
240 	boost::shared_ptr<Route> r = route_table[table_index];
241 
242 	if (r == 0) {
243 		return false;
244 	}
245 
246 	return r->mute_control()->muted ();
247 }
248 
249 void
route_set_muted(uint32_t table_index,bool yn)250 ControlProtocol::route_set_muted (uint32_t table_index, bool yn)
251 {
252 	if (table_index > route_table.size()) {
253 		return;
254 	}
255 
256 	boost::shared_ptr<Route> r = route_table[table_index];
257 
258 	if (r != 0) {
259 		r->mute_control()->set_value (yn ? 1.0 : 0.0, Controllable::UseGroup);
260 	}
261 }
262 
263 
264 bool
route_get_soloed(uint32_t table_index)265 ControlProtocol::route_get_soloed (uint32_t table_index)
266 {
267 	if (table_index > route_table.size()) {
268 		return false;
269 	}
270 
271 	boost::shared_ptr<Route> r = route_table[table_index];
272 
273 	if (r == 0) {
274 		return false;
275 	}
276 
277 	return r->soloed ();
278 }
279 
280 void
route_set_soloed(uint32_t table_index,bool yn)281 ControlProtocol::route_set_soloed (uint32_t table_index, bool yn)
282 {
283 	if (table_index > route_table.size()) {
284 		return;
285 	}
286 
287 	boost::shared_ptr<Route> r = route_table[table_index];
288 
289 	if (r != 0) {
290 		session->set_control (r->solo_control(), yn ? 1.0 : 0.0, Controllable::UseGroup);
291 	}
292 }
293 
294 string
route_get_name(uint32_t table_index)295 ControlProtocol:: route_get_name (uint32_t table_index)
296 {
297 	if (table_index > route_table.size()) {
298 		return "";
299 	}
300 
301 	boost::shared_ptr<Route> r = route_table[table_index];
302 
303 	if (r == 0) {
304 		return "";
305 	}
306 
307 	return r->name();
308 }
309 
310 list<boost::shared_ptr<Bundle> >
bundles()311 ControlProtocol::bundles ()
312 {
313 	return list<boost::shared_ptr<Bundle> > ();
314 }
315 
316 XMLNode&
get_state()317 ControlProtocol::get_state ()
318 {
319 	XMLNode* node = new XMLNode (state_node_name);
320 
321 	node->set_property ("name", _name);
322 	node->set_property ("feedback", get_feedback());
323 
324 	return *node;
325 }
326 
327 int
set_state(XMLNode const & node,int)328 ControlProtocol::set_state (XMLNode const & node, int /* version */)
329 {
330 	bool feedback;
331 	if (node.get_property ("feedback", feedback)) {
332 		set_feedback (feedback);
333 	}
334 
335 	return 0;
336 }
337 
338 boost::shared_ptr<Stripable>
first_selected_stripable() const339 ControlProtocol::first_selected_stripable () const
340 {
341 	return session->selection().first_selected_stripable ();
342 }
343 
344 void
add_stripable_to_selection(boost::shared_ptr<ARDOUR::Stripable> s)345 ControlProtocol::add_stripable_to_selection (boost::shared_ptr<ARDOUR::Stripable> s)
346 {
347 	session->selection().add (s, boost::shared_ptr<AutomationControl>());
348 }
349 
350 void
set_stripable_selection(boost::shared_ptr<ARDOUR::Stripable> s)351 ControlProtocol::set_stripable_selection (boost::shared_ptr<ARDOUR::Stripable> s)
352 {
353 	session->selection().select_stripable_and_maybe_group (s, true, true, 0);
354 }
355 
356 void
toggle_stripable_selection(boost::shared_ptr<ARDOUR::Stripable> s)357 ControlProtocol::toggle_stripable_selection (boost::shared_ptr<ARDOUR::Stripable> s)
358 {
359 	session->selection().toggle (s, boost::shared_ptr<AutomationControl>());
360 }
361 
362 void
remove_stripable_from_selection(boost::shared_ptr<ARDOUR::Stripable> s)363 ControlProtocol::remove_stripable_from_selection (boost::shared_ptr<ARDOUR::Stripable> s)
364 {
365 	session->selection().remove (s, boost::shared_ptr<AutomationControl>());
366 }
367 
368 void
clear_stripable_selection()369 ControlProtocol::clear_stripable_selection ()
370 {
371 	session->selection().clear_stripables ();
372 }
373 
374 void
notify_stripable_selection_changed(StripableNotificationListPtr sp)375 ControlProtocol::notify_stripable_selection_changed (StripableNotificationListPtr sp)
376 {
377 	_last_selected = *sp;
378 }
379