enough with umpteen "i18n.h" files. Consolidate on pbd/i18n.h
[ardour.git] / libs / backends / jack / jack_portengine.cc
1 /*
2     Copyright (C) 2013 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 #include <string.h>
21 #include <stdint.h>
22
23 #include "pbd/error.h"
24
25 #include "jack_audiobackend.h"
26 #include "jack_connection.h"
27
28 #include "ardour/port_manager.h"
29
30 #include "pbd/i18n.h"
31
32 using namespace ARDOUR;
33 using namespace PBD;
34 using std::string;
35 using std::vector;
36
37 #define GET_PRIVATE_JACK_POINTER(localvar)  jack_client_t* localvar = _jack_connection->jack(); if (!(localvar)) { return; }
38 #define GET_PRIVATE_JACK_POINTER_RET(localvar,r) jack_client_t* localvar = _jack_connection->jack(); if (!(localvar)) { return r; }
39
40 static uint32_t
41 ardour_port_flags_to_jack_flags (PortFlags flags)
42 {
43         uint32_t jack_flags = 0;
44
45         if (flags & IsInput) {
46                 jack_flags |= JackPortIsInput;
47         }
48         if (flags & IsOutput) {
49                 jack_flags |= JackPortIsOutput;
50         }
51         if (flags & IsTerminal) {
52                 jack_flags |= JackPortIsTerminal;
53         }
54         if (flags & IsPhysical) {
55                 jack_flags |= JackPortIsPhysical;
56         }
57         if (flags & CanMonitor) {
58                 jack_flags |= JackPortCanMonitor;
59         }
60
61         return jack_flags;
62 }
63
64 static DataType
65 jack_port_type_to_ardour_data_type (const char* jack_type)
66 {
67         if (strcmp (jack_type, JACK_DEFAULT_AUDIO_TYPE) == 0) {
68                 return DataType::AUDIO;
69         } else if (strcmp (jack_type, JACK_DEFAULT_MIDI_TYPE) == 0) {
70                 return DataType::MIDI;
71         }
72         return DataType::NIL;
73 }
74
75 static const char*
76 ardour_data_type_to_jack_port_type (DataType d)
77 {
78         switch (d) {
79         case DataType::AUDIO:
80                 return JACK_DEFAULT_AUDIO_TYPE;
81         case DataType::MIDI:
82                 return JACK_DEFAULT_MIDI_TYPE;
83         }
84
85         return "";
86 }
87
88 void
89 JACKAudioBackend::when_connected_to_jack ()
90 {
91         /* register callbacks for stuff that is our responsibility */
92
93         jack_client_t* client = _jack_connection->jack();
94
95         if (!client) {
96                 /* how could this happen? it could ... */
97                 error << _("Already disconnected from JACK before PortEngine could register callbacks") << endmsg;
98                 return;
99         }
100
101         jack_set_port_registration_callback (client, _registration_callback, this);
102         jack_set_port_connect_callback (client, _connect_callback, this);
103         jack_set_graph_order_callback (client, _graph_order_callback, this);
104 }
105
106 int
107 JACKAudioBackend::set_port_name (PortHandle port, const std::string& name)
108 {
109 #if HAVE_JACK_PORT_RENAME
110         jack_client_t* client = _jack_connection->jack();
111         if (client) {
112                 return jack_port_rename (client, (jack_port_t*) port, name.c_str());
113         } else {
114                 return -1;
115         }
116 #else
117         return jack_port_set_name ((jack_port_t*) port, name.c_str());
118 #endif
119 }
120
121 string
122 JACKAudioBackend::get_port_name (PortHandle port) const
123 {
124         return jack_port_name ((jack_port_t*) port);
125 }
126
127 int
128 JACKAudioBackend::get_port_property (PortHandle port, const std::string& key, std::string& value, std::string& type) const
129 {
130 #ifdef HAVE_JACK_METADATA // really everyone ought to have this by now.
131         int rv = -1;
132         char *cvalue = NULL;
133         char *ctype = NULL;
134
135         jack_uuid_t uuid = jack_port_uuid((jack_port_t*) port);
136         rv = jack_get_property(uuid, key.c_str(), &cvalue, &ctype);
137
138         if (0 == rv) {
139                 value = cvalue;
140                 type = ctype;
141                 jack_free(cvalue);
142                 jack_free(ctype);
143         }
144         return rv;
145 #else
146         return -1;
147 #endif
148 }
149
150 int
151 JACKAudioBackend::set_port_property (PortHandle port, const std::string& key, const std::string& value, const std::string& type)
152 {
153 #ifdef HAVE_JACK_METADATA // really everyone ought to have this by now.
154         int rv = -1;
155         jack_client_t* client = _jack_connection->jack();
156         jack_uuid_t uuid = jack_port_uuid((jack_port_t*) port);
157         return jack_set_property(client, uuid, key.c_str(), value.c_str(), type.c_str());
158         return rv;
159 #else
160         return -1;
161 #endif
162 }
163
164 PortEngine::PortHandle
165 JACKAudioBackend:: get_port_by_name (const std::string& name) const
166 {
167         GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 0);
168         return (PortHandle) jack_port_by_name (_priv_jack, name.c_str());
169 }
170
171 void
172 JACKAudioBackend::_registration_callback (jack_port_id_t /*id*/, int /*reg*/, void* arg)
173 {
174         static_cast<JACKAudioBackend*> (arg)->manager.registration_callback ();
175 }
176
177 int
178 JACKAudioBackend::_graph_order_callback (void *arg)
179 {
180         return static_cast<JACKAudioBackend*> (arg)->manager.graph_order_callback ();
181 }
182
183 void
184 JACKAudioBackend::_connect_callback (jack_port_id_t id_a, jack_port_id_t id_b, int conn, void* arg)
185 {
186         static_cast<JACKAudioBackend*> (arg)->connect_callback (id_a, id_b, conn);
187 }
188
189 void
190 JACKAudioBackend::connect_callback (jack_port_id_t id_a, jack_port_id_t id_b, int conn)
191 {
192         if (manager.port_remove_in_progress()) {
193                 return;
194         }
195
196         GET_PRIVATE_JACK_POINTER (_priv_jack);
197
198         jack_port_t* a = jack_port_by_id (_priv_jack, id_a);
199         jack_port_t* b = jack_port_by_id (_priv_jack, id_b);
200
201         manager.connect_callback (jack_port_name (a), jack_port_name (b), conn == 0 ? false : true);
202 }
203
204 bool
205 JACKAudioBackend::connected (PortHandle port, bool process_callback_safe)
206 {
207         bool ret = false;
208
209         const char** ports;
210
211         if (process_callback_safe) {
212                 ports = jack_port_get_connections ((jack_port_t*)port);
213         } else {
214                 GET_PRIVATE_JACK_POINTER_RET (_priv_jack, false);
215                 ports = jack_port_get_all_connections (_priv_jack, (jack_port_t*)port);
216         }
217
218         if (ports) {
219                 ret = true;
220         }
221
222         jack_free (ports);
223
224         return ret;
225 }
226
227 bool
228 JACKAudioBackend::connected_to (PortHandle port, const std::string& other, bool process_callback_safe)
229 {
230         bool ret = false;
231         const char** ports;
232
233         if (process_callback_safe) {
234                 ports = jack_port_get_connections ((jack_port_t*)port);
235         } else {
236                 GET_PRIVATE_JACK_POINTER_RET (_priv_jack, false);
237                 ports = jack_port_get_all_connections (_priv_jack, (jack_port_t*)port);
238         }
239
240         if (ports) {
241                 for (int i = 0; ports[i]; ++i) {
242                         if (other == ports[i]) {
243                                 ret = true;
244                         }
245                 }
246                 jack_free (ports);
247         }
248
249         return ret;
250 }
251
252 bool
253 JACKAudioBackend::physically_connected (PortHandle p, bool process_callback_safe)
254 {
255         GET_PRIVATE_JACK_POINTER_RET (_priv_jack, false);
256         jack_port_t* port = (jack_port_t*) p;
257
258         const char** ports;
259
260         if (process_callback_safe) {
261                 ports = jack_port_get_connections ((jack_port_t*)port);
262         } else {
263                 GET_PRIVATE_JACK_POINTER_RET (_priv_jack, false);
264                 ports = jack_port_get_all_connections (_priv_jack, (jack_port_t*)port);
265         }
266
267         if (ports) {
268                 for (int i = 0; ports[i]; ++i) {
269
270                         jack_port_t* other = jack_port_by_name (_priv_jack, ports[i]);
271
272                         if (other && (jack_port_flags (other) & JackPortIsPhysical)) {
273                                 return true;
274                         }
275                 }
276                 jack_free (ports);
277         }
278
279         return false;
280 }
281
282 int
283 JACKAudioBackend::get_connections (PortHandle port, vector<string>& s, bool process_callback_safe)
284 {
285         const char** ports;
286
287         if (process_callback_safe) {
288                 ports = jack_port_get_connections ((jack_port_t*)port);
289         } else {
290                 GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 0);
291                 ports = jack_port_get_all_connections (_priv_jack, (jack_port_t*)port);
292         }
293
294         if (ports) {
295                 for (int i = 0; ports[i]; ++i) {
296                         s.push_back (ports[i]);
297                 }
298                 jack_free (ports);
299         }
300
301         return s.size();
302 }
303
304 DataType
305 JACKAudioBackend::port_data_type (PortHandle p) const
306 {
307         return jack_port_type_to_ardour_data_type (jack_port_type ((jack_port_t*) p));
308 }
309
310 const string&
311 JACKAudioBackend::my_name() const
312 {
313         return _jack_connection->client_name();
314 }
315
316 bool
317 JACKAudioBackend::port_is_physical (PortHandle ph) const
318 {
319         if (!ph) {
320                 return false;
321         }
322
323         return jack_port_flags ((jack_port_t*) ph) & JackPortIsPhysical;
324 }
325
326 int
327 JACKAudioBackend::get_ports (const string& port_name_pattern, DataType type, PortFlags flags, vector<string>& s) const
328 {
329
330         GET_PRIVATE_JACK_POINTER_RET (_priv_jack,0);
331
332         const char** ports =  jack_get_ports (_priv_jack, port_name_pattern.c_str(),
333                                               ardour_data_type_to_jack_port_type (type),
334                                               ardour_port_flags_to_jack_flags (flags));
335
336         if (ports == 0) {
337                 return 0;
338         }
339
340         for (uint32_t i = 0; ports[i]; ++i) {
341                 s.push_back (ports[i]);
342         }
343
344         jack_free (ports);
345
346         return s.size();
347 }
348
349 ChanCount
350 JACKAudioBackend::n_physical_inputs () const
351 {
352         return n_physical (JackPortIsInput);
353 }
354
355 ChanCount
356 JACKAudioBackend::n_physical_outputs () const
357 {
358         return n_physical (JackPortIsOutput);
359 }
360
361 void
362 JACKAudioBackend::get_physical (DataType type, unsigned long flags, vector<string>& phy) const
363 {
364         GET_PRIVATE_JACK_POINTER (_priv_jack);
365         const char ** ports;
366
367         if ((ports = jack_get_ports (_priv_jack, NULL, ardour_data_type_to_jack_port_type (type), JackPortIsPhysical | flags)) == 0) {
368                 return;
369         }
370
371         if (ports) {
372                 for (uint32_t i = 0; ports[i]; ++i) {
373                         if (strstr (ports[i], "Midi-Through")) {
374                                 continue;
375                         }
376                         phy.push_back (ports[i]);
377                 }
378                 jack_free (ports);
379         }
380 }
381
382 /** Get physical ports for which JackPortIsOutput is set; ie those that correspond to
383  *  a physical input connector.
384  */
385 void
386 JACKAudioBackend::get_physical_inputs (DataType type, vector<string>& ins)
387 {
388         get_physical (type, JackPortIsOutput, ins);
389 }
390
391 /** Get physical ports for which JackPortIsInput is set; ie those that correspond to
392  *  a physical output connector.
393  */
394 void
395 JACKAudioBackend::get_physical_outputs (DataType type, vector<string>& outs)
396 {
397         get_physical (type, JackPortIsInput, outs);
398 }
399
400
401 bool
402 JACKAudioBackend::can_monitor_input () const
403 {
404         GET_PRIVATE_JACK_POINTER_RET (_priv_jack,false);
405         const char ** ports;
406
407         if ((ports = jack_get_ports (_priv_jack, NULL, JACK_DEFAULT_AUDIO_TYPE, JackPortCanMonitor)) == 0) {
408                 return false;
409         }
410
411         jack_free (ports);
412
413         return true;
414 }
415
416 int
417 JACKAudioBackend::request_input_monitoring (PortHandle port, bool yn)
418 {
419         return jack_port_request_monitor ((jack_port_t*) port, yn);
420 }
421 int
422 JACKAudioBackend::ensure_input_monitoring (PortHandle port, bool yn)
423 {
424         return jack_port_ensure_monitor ((jack_port_t*) port, yn);
425 }
426 bool
427 JACKAudioBackend::monitoring_input (PortHandle port)
428 {
429         return jack_port_monitoring_input ((jack_port_t*) port);
430 }
431
432 PortEngine::PortHandle
433 JACKAudioBackend::register_port (const std::string& shortname, ARDOUR::DataType type, ARDOUR::PortFlags flags)
434 {
435         GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 0);
436         return jack_port_register (_priv_jack, shortname.c_str(),
437                                    ardour_data_type_to_jack_port_type (type),
438                                    ardour_port_flags_to_jack_flags (flags),
439                                    0);
440 }
441
442 void
443 JACKAudioBackend::unregister_port (PortHandle port)
444 {
445         GET_PRIVATE_JACK_POINTER (_priv_jack);
446         (void) jack_port_unregister (_priv_jack, (jack_port_t*) port);
447 }
448
449 int
450 JACKAudioBackend::connect (PortHandle port, const std::string& other)
451 {
452         GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
453         return jack_connect (_priv_jack, jack_port_name ((jack_port_t*) port), other.c_str());
454 }
455 int
456 JACKAudioBackend::connect (const std::string& src, const std::string& dst)
457 {
458         GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
459
460         int r = jack_connect (_priv_jack, src.c_str(), dst.c_str());
461         return r;
462 }
463
464 int
465 JACKAudioBackend::disconnect (PortHandle port, const std::string& other)
466 {
467         GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
468         return jack_disconnect (_priv_jack, jack_port_name ((jack_port_t*) port), other.c_str());
469 }
470
471 int
472 JACKAudioBackend::disconnect (const std::string& src, const std::string& dst)
473 {
474         GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
475         return jack_disconnect (_priv_jack, src.c_str(), dst.c_str());
476 }
477
478 int
479 JACKAudioBackend::disconnect_all (PortHandle port)
480 {
481         GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
482         return jack_port_disconnect (_priv_jack, (jack_port_t*) port);
483 }
484
485 int
486 JACKAudioBackend::midi_event_get (pframes_t& timestamp, size_t& size, uint8_t** buf, void* port_buffer, uint32_t event_index)
487 {
488         jack_midi_event_t ev;
489         int ret;
490
491         if ((ret = jack_midi_event_get (&ev, port_buffer, event_index)) == 0) {
492                 timestamp = ev.time;
493                 size = ev.size;
494                 *buf = ev.buffer;
495         }
496
497         return ret;
498 }
499
500 int
501 JACKAudioBackend::midi_event_put (void* port_buffer, pframes_t timestamp, const uint8_t* buffer, size_t size)
502 {
503         return jack_midi_event_write (port_buffer, timestamp, buffer, size);
504 }
505
506 uint32_t
507 JACKAudioBackend::get_midi_event_count (void* port_buffer)
508 {
509         return jack_midi_get_event_count (port_buffer);
510 }
511
512 void
513 JACKAudioBackend::midi_clear (void* port_buffer)
514 {
515         jack_midi_clear_buffer (port_buffer);
516 }
517
518 void
519 JACKAudioBackend::set_latency_range (PortHandle port, bool for_playback, LatencyRange r)
520 {
521         jack_latency_range_t range;
522
523         range.min = r.min;
524         range.max = r.max;
525
526         jack_port_set_latency_range ((jack_port_t*) port, for_playback ? JackPlaybackLatency : JackCaptureLatency, &range);
527 }
528
529 LatencyRange
530 JACKAudioBackend::get_latency_range (PortHandle port, bool for_playback)
531 {
532         jack_latency_range_t range;
533         LatencyRange ret;
534
535         jack_port_get_latency_range ((jack_port_t*) port, for_playback ? JackPlaybackLatency : JackCaptureLatency, &range);
536
537         ret.min = range.min;
538         ret.max = range.max;
539
540         return ret;
541 }
542
543 void*
544 JACKAudioBackend::get_buffer (PortHandle port, pframes_t nframes)
545 {
546         return jack_port_get_buffer ((jack_port_t*) port, nframes);
547 }
548
549 uint32_t
550 JACKAudioBackend::port_name_size() const
551 {
552         return jack_port_name_size ();
553 }