2 * Carla JACK API for external applications
3 * Copyright (C) 2016-2022 Filipe Coelho <falktx@falktx.com>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of
8 * the License, or any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * For a full copy of the GNU General Public License see the doc/GPL.txt file.
18 #include "libjack.hpp"
20 CARLA_BACKEND_USE_NAMESPACE
22 // --------------------------------------------------------------------------------------------------------------------
24 static uint32_t gPortId
= JackPortState::kPortIdOffsetUser
;
27 jack_port_t
* jack_port_register(jack_client_t
* client
, const char* port_name
, const char* port_type
,
28 unsigned long flags
, unsigned long buffer_size
)
30 carla_debug("%s(%p, %s, %s, 0x%lx, %lu)", __FUNCTION__
, client
, port_name
, port_type
, flags
, buffer_size
);
32 JackClientState
* const jclient
= (JackClientState
*)client
;
33 CARLA_SAFE_ASSERT_RETURN(jclient
!= nullptr, nullptr);
35 CARLA_SAFE_ASSERT_RETURN(port_name
!= nullptr && port_name
[0] != '\0', nullptr);
36 CARLA_SAFE_ASSERT_RETURN(port_type
!= nullptr && port_type
[0] != '\0', nullptr);
38 const JackServerState
& jserver(jclient
->server
);
40 if (std::strcmp(port_type
, JACK_DEFAULT_AUDIO_TYPE
) == 0)
42 if (flags
& JackPortIsInput
)
44 const std::size_t index
= jclient
->audioIns
.count();
45 const uint gid
= ++gPortId
;
46 JackPortState
* const port
= new JackPortState(jclient
->name
, port_name
,
47 static_cast<uint
>(index
),
48 static_cast<int>(flags
),
50 false, false, index
< jserver
.numAudioIns
);
53 const CarlaMutexLocker
cms(jclient
->mutex
);
54 jclient
->audioIns
.append(port
);
57 jclient
->portIdMapping
[gid
] = port
;
58 jclient
->portNameMapping
[port
->fullname
] = port
;
59 return (jack_port_t
*)port
;
62 if (flags
& JackPortIsOutput
)
64 const std::size_t index
= jclient
->audioOuts
.count();
65 const uint gid
= ++gPortId
;
66 JackPortState
* const port
= new JackPortState(jclient
->name
, port_name
,
67 static_cast<uint
>(index
),
68 static_cast<int>(flags
),
70 false, false, index
< jserver
.numAudioOuts
);
73 const CarlaMutexLocker
cms(jclient
->mutex
);
74 jclient
->audioOuts
.append(port
);
77 jclient
->portIdMapping
[gid
] = port
;
78 jclient
->portNameMapping
[port
->fullname
] = port
;
79 return (jack_port_t
*)port
;
82 carla_stderr2("jack_port_register: invalid port flags '%x'", flags
);
86 if (std::strcmp(port_type
, JACK_DEFAULT_MIDI_TYPE
) == 0)
88 if (flags
& JackPortIsInput
)
90 const std::size_t index
= jclient
->midiIns
.count();
91 const uint gid
= ++gPortId
;
92 JackPortState
* const port
= new JackPortState(jclient
->name
, port_name
,
93 static_cast<uint
>(index
),
94 static_cast<int>(flags
),
96 true, false, index
< jserver
.numMidiIns
);
99 const CarlaMutexLocker
cms(jclient
->mutex
);
100 jclient
->midiIns
.append(port
);
103 jclient
->portIdMapping
[gid
] = port
;
104 jclient
->portNameMapping
[port
->fullname
] = port
;
105 return (jack_port_t
*)port
;
108 if (flags
& JackPortIsOutput
)
110 const std::size_t index
= jclient
->midiOuts
.count();
111 const uint gid
= ++gPortId
;
112 JackPortState
* const port
= new JackPortState(jclient
->name
, port_name
,
113 static_cast<uint
>(index
),
114 static_cast<int>(flags
),
116 true, false, index
< jserver
.numMidiOuts
);
119 const CarlaMutexLocker
cms(jclient
->mutex
);
120 jclient
->midiOuts
.append(port
);
123 jclient
->portIdMapping
[gid
] = port
;
124 jclient
->portNameMapping
[port
->fullname
] = port
;
125 return (jack_port_t
*)port
;
128 carla_stderr2("jack_port_register: invalid port flags '%x'", flags
);
132 carla_stderr2("jack_port_register: invalid port type '%s'", port_type
);
140 int jack_port_unregister(jack_client_t
* client
, jack_port_t
* port
)
142 carla_debug("%s(%p, %p)", __FUNCTION__
, client
, port
);
144 JackClientState
* const jclient
= (JackClientState
*)client
;
145 CARLA_SAFE_ASSERT_RETURN(jclient
!= nullptr, EINVAL
);
147 JackPortState
* const jport
= (JackPortState
*)port
;
148 CARLA_SAFE_ASSERT_RETURN(jport
!= nullptr, EINVAL
);
149 CARLA_SAFE_ASSERT_RETURN(! jport
->isSystem
, EINVAL
);
152 const CarlaMutexLocker
cms(jclient
->mutex
);
156 if (jport
->flags
& JackPortIsInput
)
158 CARLA_SAFE_ASSERT_RETURN(jclient
->midiIns
.removeOne(jport
), ENOENT
);
159 jclient
->portIdMapping
.erase(jport
->gid
);
160 jclient
->portNameMapping
.erase(jport
->fullname
);
164 if (jport
->flags
& JackPortIsOutput
)
166 CARLA_SAFE_ASSERT_RETURN(jclient
->midiOuts
.removeOne(jport
), ENOENT
);
167 jclient
->portIdMapping
.erase(jport
->gid
);
168 jclient
->portNameMapping
.erase(jport
->fullname
);
174 if (jport
->flags
& JackPortIsInput
)
176 CARLA_SAFE_ASSERT_RETURN(jclient
->audioIns
.removeOne(jport
), ENOENT
);
177 jclient
->portIdMapping
.erase(jport
->gid
);
178 jclient
->portNameMapping
.erase(jport
->fullname
);
182 if (jport
->flags
& JackPortIsOutput
)
184 CARLA_SAFE_ASSERT_RETURN(jclient
->audioOuts
.removeOne(jport
), ENOENT
);
185 jclient
->portIdMapping
.erase(jport
->gid
);
186 jclient
->portNameMapping
.erase(jport
->fullname
);
192 carla_stderr2("jack_port_register: invalid port '%s'", jport
->name
);
197 void* jack_port_get_buffer(jack_port_t
* port
, jack_nframes_t
)
199 JackPortState
* const jport
= (JackPortState
*)port
;
200 CARLA_SAFE_ASSERT_RETURN(jport
!= nullptr, nullptr);
202 return jport
->buffer
;
205 // --------------------------------------------------------------------------------------------------------------------
208 jack_uuid_t
jack_port_uuid(const jack_port_t
* port
)
210 carla_debug("%s(%p)", __FUNCTION__
, port
);
212 const JackPortState
* const jport
= (const JackPortState
*)port
;
213 CARLA_SAFE_ASSERT_RETURN(jport
!= nullptr, 0);
219 const char* jack_port_name(const jack_port_t
* port
)
221 carla_debug("%s(%p)", __FUNCTION__
, port
);
223 const JackPortState
* const jport
= (const JackPortState
*)port
;
224 CARLA_SAFE_ASSERT_RETURN(jport
!= nullptr, nullptr);
226 return jport
->fullname
;
230 const char* jack_port_short_name(const jack_port_t
* port
)
232 carla_debug("%s(%p)", __FUNCTION__
, port
);
234 const JackPortState
* const jport
= (const JackPortState
*)port
;
235 CARLA_SAFE_ASSERT_RETURN(jport
!= nullptr, nullptr);
241 int jack_port_flags(const jack_port_t
* port
)
243 carla_debug("%s(%p)", __FUNCTION__
, port
);
245 const JackPortState
* const jport
= (const JackPortState
*)port
;
246 CARLA_SAFE_ASSERT_RETURN(jport
!= nullptr, 0);
252 const char* jack_port_type(const jack_port_t
* port
)
254 carla_debug("%s(%p)", __FUNCTION__
, port
);
256 const JackPortState
* const jport
= (const JackPortState
*)port
;
257 CARLA_SAFE_ASSERT_RETURN(jport
!= nullptr, nullptr);
259 static const char* const kAudioType
= JACK_DEFAULT_AUDIO_TYPE
;
260 static const char* const kMidiType
= JACK_DEFAULT_MIDI_TYPE
;
262 return jport
->isMidi
? kMidiType
: kAudioType
;
266 uint32_t jack_port_type_id(const jack_port_t
* port
)
268 carla_debug("%s(%p)", __FUNCTION__
, port
);
270 const JackPortState
* const jport
= (const JackPortState
*)port
;
271 CARLA_SAFE_ASSERT_RETURN(jport
!= nullptr, 0);
273 return jport
->isMidi
? 1 : 0;
276 // --------------------------------------------------------------------------------------------------------------------
279 int jack_port_is_mine(const jack_client_t
*, const jack_port_t
* port
)
281 const JackPortState
* const jport
= (const JackPortState
*)port
;
282 CARLA_SAFE_ASSERT_RETURN(jport
!= nullptr, 0);
284 return jport
->isSystem
? 0 : 1;
288 int jack_port_connected(const jack_port_t
* port
)
290 const JackPortState
* const jport
= (const JackPortState
*)port
;
291 CARLA_SAFE_ASSERT_RETURN(jport
!= nullptr, 0);
293 return jport
->isConnected
? 1 : 0;
297 int jack_port_connected_to(const jack_port_t
* port
, const char* port_name
)
299 carla_stderr2("%s(%p, %s) WIP", __FUNCTION__
, port
, port_name
);
301 const JackPortState
* const jport
= (const JackPortState
*)port
;
302 CARLA_SAFE_ASSERT_RETURN(jport
!= nullptr, 0);
304 if (! jport
->isConnected
)
311 // --------------------------------------------------------------------------------------------------------------------
314 int jack_port_tie(jack_port_t
* src
, jack_port_t
* dst
)
316 carla_debug("%s(%p, %p)", __FUNCTION__
, src
, dst
);
325 int jack_port_untie(jack_port_t
* port
)
327 carla_debug("%s(%p)", __FUNCTION__
, port
);
334 // --------------------------------------------------------------------------------------------------------------------
337 int jack_port_set_name(jack_port_t
*port
, const char *port_name
)
339 carla_stderr2("%s(%p, %s)", __FUNCTION__
, port
, port_name
);
344 int jack_port_rename(jack_client_t
* client
, jack_port_t
*port
, const char *port_name
)
346 carla_stderr2("%s(%p, %p, %s) WIP", __FUNCTION__
, client
, port
, port_name
);
348 JackClientState
* const jclient
= (JackClientState
*)client
;
349 CARLA_SAFE_ASSERT_RETURN(jclient
!= nullptr, EINVAL
);
351 CARLA_SAFE_ASSERT_RETURN(port_name
!= nullptr && port_name
[0] != '\0', EINVAL
);
353 JackPortState
* const jport
= (JackPortState
*)port
;
354 CARLA_SAFE_ASSERT_RETURN(jport
!= nullptr, EINVAL
);
355 CARLA_SAFE_ASSERT_RETURN(! jport
->isSystem
, EINVAL
);
357 // TODO: verify uniqueness
359 char* const fullname
= (char*)std::malloc(STR_MAX
);
360 CARLA_SAFE_ASSERT_RETURN(fullname
!= nullptr, ENOMEM
);
362 std::snprintf(fullname
, STR_MAX
, "%s:%s", jclient
->name
, port_name
);
363 fullname
[STR_MAX
-1] = '\0';
365 jclient
->portNameMapping
.erase(jport
->fullname
);
366 jclient
->portNameMapping
[fullname
] = jport
;
368 std::free(jport
->name
);
369 std::free(jport
->fullname
);
371 jport
->name
= strdup(port_name
);
372 jport
->fullname
= fullname
;
374 // TODO: port rename callback
380 int jack_port_set_alias(jack_port_t
* port
, const char* alias
)
382 carla_stderr2("%s(%p, %s)", __FUNCTION__
, port
, alias
);
387 int jack_port_unset_alias(jack_port_t
* port
, const char* alias
)
389 carla_stderr2("%s(%p, %s)", __FUNCTION__
, port
, alias
);
394 int jack_port_get_aliases(const jack_port_t
*, char* const aliases
[2])
401 // --------------------------------------------------------------------------------------------------------------------
404 int jack_port_request_monitor(jack_port_t
* port
, int onoff
)
406 carla_stderr2("%s(%p, %i)", __FUNCTION__
, port
, onoff
);
411 int jack_port_request_monitor_by_name(jack_client_t
* client
, const char* port_name
, int onoff
)
413 carla_stderr2("%s(%p, %s, %i)", __FUNCTION__
, client
, port_name
, onoff
);
418 int jack_port_ensure_monitor(jack_port_t
* port
, int onoff
)
420 carla_stderr2("%s(%p, %i)", __FUNCTION__
, port
, onoff
);
425 int jack_port_monitoring_input(jack_port_t
* port
)
427 carla_stderr2("%s(%p)", __FUNCTION__
, port
);
431 // --------------------------------------------------------------------------------------------------------------------
434 int jack_connect(jack_client_t
* client
, const char* a
, const char* b
)
436 carla_stderr2("%s(%p, %s. %s)", __FUNCTION__
, client
, a
, b
);
441 int jack_disconnect(jack_client_t
* client
, const char* a
, const char* b
)
443 carla_stderr2("%s(%p, %s. %s)", __FUNCTION__
, client
, a
, b
);
448 int jack_port_disconnect(jack_client_t
* client
, jack_port_t
* port
)
450 carla_stderr2("%s(%p, %p)", __FUNCTION__
, client
, port
);
454 // --------------------------------------------------------------------------------------------------------------------
457 int jack_port_name_size(void)
463 int jack_port_type_size(void)
469 size_t jack_port_type_get_buffer_size(jack_client_t
* client
, const char* port_type
)
471 carla_debug("%s(%p, %s)", __FUNCTION__
, client
, port_type
);
472 CARLA_SAFE_ASSERT_RETURN(port_type
!= nullptr && port_type
[0] != '\0', 0);
474 if (std::strcmp(port_type
, JACK_DEFAULT_MIDI_TYPE
) == 0)
475 return JackMidiPortBufferBase::kMaxEventSize
;
483 // --------------------------------------------------------------------------------------------------------------------