Signed-off-by: falkTX <falktx@falktx.com>tags/v2.2.0-RC1
| @@ -270,7 +270,7 @@ public: | |||
| return true; | |||
| } | |||
| const char* getClientNameFromUUID(jack_uuid_t uuid) const | |||
| const char* getClientNameFromUUID(const jack_uuid_t uuid) const noexcept | |||
| { | |||
| for (LinkedList<JackClientState*>::Itenerator it = fClients.begin2(); it.valid(); it.next()) | |||
| { | |||
| @@ -284,6 +284,20 @@ public: | |||
| return nullptr; | |||
| } | |||
| jack_uuid_t getUUIDForClientName(const char* const name) const noexcept | |||
| { | |||
| for (LinkedList<JackClientState*>::Itenerator it = fClients.begin2(); it.valid(); it.next()) | |||
| { | |||
| JackClientState* const jclient(it.getValue(nullptr)); | |||
| CARLA_SAFE_ASSERT_CONTINUE(jclient != nullptr); | |||
| if (std::strcmp(jclient->name, name) == 0) | |||
| return jclient->uuid; | |||
| } | |||
| return JACK_UUID_EMPTY_INITIALIZER; | |||
| } | |||
| pthread_t getRealtimeThreadId() const noexcept | |||
| { | |||
| return (pthread_t)fRealtimeThread.getThreadId(); | |||
| @@ -1404,6 +1418,9 @@ char* jack_get_client_name_by_uuid(jack_client_t* const client, const char* cons | |||
| const char* clientName; | |||
| if (jclient->server.uuid == uuid) | |||
| return strdup("system"); | |||
| if (jclient->uuid == uuid) | |||
| { | |||
| clientName = jclient->name; | |||
| @@ -1421,6 +1438,38 @@ char* jack_get_client_name_by_uuid(jack_client_t* const client, const char* cons | |||
| return strdup(clientName); | |||
| } | |||
| CARLA_EXPORT | |||
| char* jack_get_uuid_for_client_name(jack_client_t* client, const char* name) | |||
| { | |||
| carla_debug("%s(%p, %s)", __FUNCTION__, client, name); | |||
| JackClientState* const jclient = (JackClientState*)client; | |||
| CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, nullptr); | |||
| if (std::strcmp(name, "system") == 0) | |||
| { | |||
| char* const uuidstr = static_cast<char*>(std::malloc(JACK_UUID_STRING_SIZE)); | |||
| CARLA_SAFE_ASSERT_RETURN(uuidstr != nullptr, nullptr); | |||
| jack_uuid_unparse(jclient->server.uuid, uuidstr); | |||
| return uuidstr; | |||
| } | |||
| else | |||
| { | |||
| CarlaJackAppClient* const jackAppPtr = jclient->server.jackAppPtr; | |||
| CARLA_SAFE_ASSERT_RETURN(jackAppPtr != nullptr && jackAppPtr == &gClient, nullptr); | |||
| const jack_uuid_t uuid = jackAppPtr->getUUIDForClientName(name); | |||
| CARLA_SAFE_ASSERT_RETURN(uuid != JACK_UUID_EMPTY_INITIALIZER, nullptr); | |||
| char* const uuidstr = static_cast<char*>(std::malloc(JACK_UUID_STRING_SIZE)); | |||
| CARLA_SAFE_ASSERT_RETURN(uuidstr != nullptr, nullptr); | |||
| jack_uuid_unparse(jclient->uuid, uuidstr); | |||
| return uuidstr; | |||
| } | |||
| } | |||
| // --------------------------------------------------------------------------------------------------------------------- | |||
| CARLA_EXPORT | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * Carla JACK API for external applications | |||
| * Copyright (C) 2016-2019 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2016-2020 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| @@ -103,37 +103,53 @@ struct JackMidiPortBufferDummy : JackMidiPortBufferBase { | |||
| }; | |||
| struct JackPortState { | |||
| const char* name; | |||
| const char* fullname; | |||
| enum Offsets { | |||
| kPortIdOffsetAudioIn = 100, | |||
| kPortIdOffsetMidiIn = 300, | |||
| kPortIdOffsetAudioOut = 500, | |||
| kPortIdOffsetMidiOut = 700, | |||
| kPortIdOffsetUser = 1000, | |||
| }; | |||
| char* name; | |||
| char* fullname; | |||
| void* buffer; | |||
| uint index; | |||
| int flags; | |||
| uint gid; | |||
| jack_uuid_t uuid; | |||
| bool isMidi : 1; | |||
| bool isSystem : 1; | |||
| bool isConnected : 1; | |||
| bool unused : 1; | |||
| JackPortState() | |||
| : name(nullptr), | |||
| fullname(nullptr), | |||
| JackPortState(const char* const fullPortName, | |||
| const char* const portName, | |||
| const uint i, const int f, const uint id, | |||
| const bool midi, const bool con) | |||
| : name(portName != nullptr ? strdup(portName) : nullptr), | |||
| fullname(fullPortName != nullptr ? strdup(fullPortName) : nullptr), | |||
| buffer(nullptr), | |||
| index(0), | |||
| flags(0), | |||
| uuid(0), | |||
| isMidi(false), | |||
| isSystem(false), | |||
| isConnected(false), | |||
| index(i), | |||
| flags(f), | |||
| gid(id), | |||
| uuid(jack_port_uuid_generate(id)), | |||
| isMidi(midi), | |||
| isSystem(true), | |||
| isConnected(con), | |||
| unused(false) {} | |||
| JackPortState(const char* const clientName, const char* const portName, const uint i, const int f, | |||
| JackPortState(const char* const clientName, | |||
| const char* const portName, | |||
| const uint i, const int f, const uint id, | |||
| const bool midi, const bool sys, const bool con) | |||
| : name(portName != nullptr ? strdup(portName) : nullptr), | |||
| fullname(nullptr), | |||
| buffer(nullptr), | |||
| index(i), | |||
| flags(f), | |||
| uuid(0), | |||
| gid(id), | |||
| uuid(jack_port_uuid_generate(id)), | |||
| isMidi(midi), | |||
| isSystem(sys), | |||
| isConnected(con), | |||
| @@ -151,6 +167,11 @@ struct JackPortState { | |||
| ~JackPortState() | |||
| { | |||
| std::free(name); | |||
| name = nullptr; | |||
| std::free(fullname); | |||
| fullname = nullptr; | |||
| } | |||
| CARLA_DECLARE_NON_COPY_STRUCT(JackPortState) | |||
| @@ -171,6 +192,7 @@ struct JackClientState { | |||
| LinkedList<JackPortState*> midiIns; | |||
| LinkedList<JackPortState*> midiOuts; | |||
| std::map<uint, JackPortState*> portIdMapping; | |||
| std::map<std::string, JackPortState*> portNameMapping; | |||
| JackShutdownCallback shutdownCb; | |||
| @@ -208,6 +230,7 @@ struct JackClientState { | |||
| audioOuts(), | |||
| midiIns(), | |||
| midiOuts(), | |||
| portIdMapping(), | |||
| portNameMapping(), | |||
| shutdownCb(nullptr), | |||
| shutdownCbPtr(nullptr), | |||
| @@ -261,6 +284,9 @@ struct JackClientState { | |||
| audioOuts.clear(); | |||
| midiIns.clear(); | |||
| midiOuts.clear(); | |||
| portIdMapping.clear(); | |||
| portNameMapping.clear(); | |||
| } | |||
| CARLA_DECLARE_NON_COPY_STRUCT(JackClientState) | |||
| @@ -272,6 +298,8 @@ struct JackServerState { | |||
| uint32_t bufferSize; | |||
| double sampleRate; | |||
| jack_uuid_t uuid; | |||
| uint8_t numAudioIns; | |||
| uint8_t numAudioOuts; | |||
| uint8_t numMidiIns; | |||
| @@ -285,6 +313,7 @@ struct JackServerState { | |||
| : jackAppPtr(app), | |||
| bufferSize(0), | |||
| sampleRate(0.0), | |||
| uuid(jack_client_uuid_generate()), | |||
| numAudioIns(0), | |||
| numAudioOuts(0), | |||
| numMidiIns(0), | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * Carla JACK API for external applications | |||
| * Copyright (C) 2016-2018 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2016-2020 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| @@ -60,7 +60,7 @@ void jack_free(void* ptr) | |||
| { | |||
| carla_debug("%s(%p)", __FUNCTION__, ptr); | |||
| free(ptr); | |||
| std::free(ptr); | |||
| } | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| @@ -40,22 +40,6 @@ char* jack_get_client_name(jack_client_t* client) | |||
| return jclient->name; | |||
| } | |||
| CARLA_EXPORT | |||
| char* jack_get_uuid_for_client_name(jack_client_t* client, const char* name) | |||
| { | |||
| carla_debug("%s(%p, %s)", __FUNCTION__, client, name); | |||
| JackClientState* const jclient = (JackClientState*)client; | |||
| CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, nullptr); | |||
| char* const uuidstr = static_cast<char*>(std::malloc(JACK_UUID_STRING_SIZE)); | |||
| CARLA_SAFE_ASSERT_RETURN(uuidstr != nullptr, nullptr); | |||
| jack_uuid_unparse(jclient->uuid, uuidstr); | |||
| return uuidstr; | |||
| } | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| CARLA_EXPORT | |||
| @@ -23,13 +23,17 @@ CARLA_BACKEND_USE_NAMESPACE | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| static const char* allocate_port_name(const char* const prefix, const uint num) | |||
| static const char* allocate_port_name(const char* const prefixOrFullName, const uint num = UINT32_MAX) | |||
| { | |||
| static CarlaStringList portList; | |||
| char portName[STR_MAX]; | |||
| carla_zeroChars(portName, STR_MAX); | |||
| std::snprintf(portName, STR_MAX-1, "%s%u", prefix, num+1); | |||
| if (num == UINT32_MAX) | |||
| std::strncpy(portName, prefixOrFullName, STR_MAX-1); | |||
| else | |||
| std::snprintf(portName, STR_MAX-1, "%s%u", prefixOrFullName, num+1); | |||
| if (const char* const storedPortName = portList.containsAndReturnString(portName)) | |||
| return storedPortName; | |||
| @@ -44,17 +48,23 @@ static const char* allocate_port_name(const char* const prefix, const uint num) | |||
| CARLA_EXPORT | |||
| const char** jack_get_ports(jack_client_t* client, const char* a, const char* b, unsigned long flags) | |||
| { | |||
| carla_stdout("%s(%p, %s, %s, 0x%lx) WIP", __FUNCTION__, client, a, b, flags); | |||
| carla_stdout("%s(%p, %s, %s, 0x%lx)", __FUNCTION__, client, a, b, flags); | |||
| JackClientState* const jclient = (JackClientState*)client; | |||
| CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, nullptr); | |||
| const JackServerState& jserver(jclient->server); | |||
| const uint numIns = static_cast<uint>(jserver.numAudioIns + jserver.numMidiIns); | |||
| const uint numOuts = static_cast<uint>(jserver.numAudioOuts + jserver.numMidiOuts); | |||
| const uint numIns = static_cast<uint>(jclient->audioIns.count() + | |||
| jclient->midiIns.count() + | |||
| jserver.numAudioIns + | |||
| jserver.numMidiIns); | |||
| const uint numOuts = static_cast<uint>(jclient->audioOuts.count() + | |||
| jclient->midiOuts.count() + | |||
| jserver.numAudioOuts + | |||
| jserver.numMidiOuts); | |||
| if (flags == 0 || (flags & (JackPortIsInput|JackPortIsOutput)) == (JackPortIsInput|JackPortIsOutput)) | |||
| if (flags == 0x0 || (flags & (JackPortIsInput|JackPortIsOutput)) == (JackPortIsInput|JackPortIsOutput)) | |||
| { | |||
| if (const char** const ret = (const char**)calloc(numIns+numOuts+1, sizeof(const char*))) | |||
| { | |||
| @@ -68,10 +78,43 @@ const char** jack_get_ports(jack_client_t* client, const char* a, const char* b, | |||
| for (uint j=0; j<jserver.numMidiOuts; ++i, ++j) | |||
| ret[i] = allocate_port_name("system:midi_playback_", j); | |||
| if ((flags & (JackPortIsPhysical|JackPortIsTerminal)) == 0x0) | |||
| { | |||
| for (LinkedList<JackPortState*>::Itenerator it = jclient->audioIns.begin2(); it.valid(); it.next()) | |||
| { | |||
| JackPortState* const jport = it.getValue(nullptr); | |||
| CARLA_SAFE_ASSERT_CONTINUE(jport != nullptr); | |||
| ret[i++] = allocate_port_name(jport->fullname); | |||
| } | |||
| for (LinkedList<JackPortState*>::Itenerator it = jclient->midiIns.begin2(); it.valid(); it.next()) | |||
| { | |||
| JackPortState* const jport = it.getValue(nullptr); | |||
| CARLA_SAFE_ASSERT_CONTINUE(jport != nullptr); | |||
| ret[i++] = allocate_port_name(jport->fullname); | |||
| } | |||
| for (LinkedList<JackPortState*>::Itenerator it = jclient->audioOuts.begin2(); it.valid(); it.next()) | |||
| { | |||
| JackPortState* const jport = it.getValue(nullptr); | |||
| CARLA_SAFE_ASSERT_CONTINUE(jport != nullptr); | |||
| ret[i++] = allocate_port_name(jport->fullname); | |||
| } | |||
| for (LinkedList<JackPortState*>::Itenerator it = jclient->midiOuts.begin2(); it.valid(); it.next()) | |||
| { | |||
| JackPortState* const jport = it.getValue(nullptr); | |||
| CARLA_SAFE_ASSERT_CONTINUE(jport != nullptr); | |||
| ret[i++] = allocate_port_name(jport->fullname); | |||
| } | |||
| } | |||
| ret[i] = nullptr; | |||
| return ret; | |||
| } | |||
| return nullptr; | |||
| } | |||
| if (flags & JackPortIsInput) | |||
| @@ -84,10 +127,29 @@ const char** jack_get_ports(jack_client_t* client, const char* a, const char* b, | |||
| for (uint j=0; j<jserver.numMidiOuts; ++i, ++j) | |||
| ret[i] = allocate_port_name("system:midi_playback_", j); | |||
| if ((flags & (JackPortIsPhysical|JackPortIsTerminal)) == 0x0) | |||
| { | |||
| for (LinkedList<JackPortState*>::Itenerator it = jclient->audioIns.begin2(); it.valid(); it.next()) | |||
| { | |||
| JackPortState* const jport = it.getValue(nullptr); | |||
| CARLA_SAFE_ASSERT_CONTINUE(jport != nullptr); | |||
| ret[i++] = allocate_port_name(jport->fullname); | |||
| } | |||
| for (LinkedList<JackPortState*>::Itenerator it = jclient->midiIns.begin2(); it.valid(); it.next()) | |||
| { | |||
| JackPortState* const jport = it.getValue(nullptr); | |||
| CARLA_SAFE_ASSERT_CONTINUE(jport != nullptr); | |||
| ret[i++] = allocate_port_name(jport->fullname); | |||
| } | |||
| } | |||
| ret[i] = nullptr; | |||
| return ret; | |||
| } | |||
| return nullptr; | |||
| } | |||
| if (flags & JackPortIsOutput) | |||
| @@ -100,10 +162,29 @@ const char** jack_get_ports(jack_client_t* client, const char* a, const char* b, | |||
| for (uint j=0; j<jserver.numMidiIns; ++i, ++j) | |||
| ret[i] = allocate_port_name("system:midi_capture_", j); | |||
| if ((flags & (JackPortIsPhysical|JackPortIsTerminal)) == 0x0) | |||
| { | |||
| for (LinkedList<JackPortState*>::Itenerator it = jclient->audioOuts.begin2(); it.valid(); it.next()) | |||
| { | |||
| JackPortState* const jport = it.getValue(nullptr); | |||
| CARLA_SAFE_ASSERT_CONTINUE(jport != nullptr); | |||
| ret[i++] = allocate_port_name(jport->fullname); | |||
| } | |||
| for (LinkedList<JackPortState*>::Itenerator it = jclient->midiOuts.begin2(); it.valid(); it.next()) | |||
| { | |||
| JackPortState* const jport = it.getValue(nullptr); | |||
| CARLA_SAFE_ASSERT_CONTINUE(jport != nullptr); | |||
| ret[i++] = allocate_port_name(jport->fullname); | |||
| } | |||
| } | |||
| ret[i] = nullptr; | |||
| return ret; | |||
| } | |||
| return nullptr; | |||
| } | |||
| return nullptr; | |||
| @@ -119,29 +200,19 @@ jack_port_t* jack_port_by_name(jack_client_t* client, const char* name) | |||
| if (std::strncmp(name, "system:", 7) == 0) | |||
| { | |||
| static JackPortState retPort( | |||
| /* name */ nullptr, | |||
| /* fullname */ nullptr, | |||
| /* index */ 0, | |||
| /* flags */ 0x0, | |||
| /* isMidi */ false, | |||
| /* isSystem */ true, | |||
| /* isConnected */ false | |||
| ); | |||
| static CarlaString rname, rfullname; | |||
| static std::map<uint, JackPortState*> systemPortIdMapping; | |||
| const JackServerState& jserver(jclient->server); | |||
| const int commonFlags = JackPortIsPhysical|JackPortIsTerminal; | |||
| rfullname = name; | |||
| uint rindex, gid; | |||
| int flags; | |||
| bool isMidi, isConnected; | |||
| const char* const fullname = name; | |||
| const char* const portname = name + 7; | |||
| name += 7; | |||
| rname = name; | |||
| retPort.name = rname.buffer(); | |||
| retPort.fullname = rfullname.buffer(); | |||
| /**/ if (std::strncmp(name, "capture_", 8) == 0) | |||
| { | |||
| name += 8; | |||
| @@ -149,10 +220,11 @@ jack_port_t* jack_port_by_name(jack_client_t* client, const char* name) | |||
| const int index = std::atoi(name)-1; | |||
| CARLA_SAFE_ASSERT_RETURN(index >= 0 && index < jserver.numAudioIns, nullptr); | |||
| retPort.index = static_cast<uint>(index); | |||
| retPort.flags = commonFlags|JackPortIsOutput; | |||
| retPort.isMidi = false; | |||
| retPort.isConnected = jserver.numAudioIns > index; | |||
| rindex = static_cast<uint>(index); | |||
| flags = commonFlags|JackPortIsOutput; | |||
| gid = JackPortState::kPortIdOffsetAudioIn + rindex; | |||
| isMidi = false; | |||
| isConnected = jserver.numAudioIns > rindex; | |||
| } | |||
| else if (std::strncmp(name, "playback_", 9) == 0) | |||
| { | |||
| @@ -161,10 +233,11 @@ jack_port_t* jack_port_by_name(jack_client_t* client, const char* name) | |||
| const int index = std::atoi(name)-1; | |||
| CARLA_SAFE_ASSERT_RETURN(index >= 0 && index < jserver.numAudioOuts, nullptr); | |||
| retPort.index = static_cast<uint>(jserver.numAudioIns + index); | |||
| retPort.flags = commonFlags|JackPortIsInput; | |||
| retPort.isMidi = false; | |||
| retPort.isConnected = jserver.numAudioOuts > index; | |||
| rindex = static_cast<uint>(jserver.numAudioIns + index); | |||
| flags = commonFlags|JackPortIsInput; | |||
| gid = JackPortState::kPortIdOffsetAudioOut + rindex; | |||
| isMidi = false; | |||
| isConnected = jserver.numAudioOuts > rindex; | |||
| } | |||
| else if (std::strncmp(name, "midi_capture_", 13) == 0) | |||
| { | |||
| @@ -173,10 +246,11 @@ jack_port_t* jack_port_by_name(jack_client_t* client, const char* name) | |||
| const int index = std::atoi(name)-1; | |||
| CARLA_SAFE_ASSERT_RETURN(index >= 0 && index < jserver.numMidiIns, nullptr); | |||
| retPort.index = static_cast<uint>(index); | |||
| retPort.flags = commonFlags|JackPortIsOutput; | |||
| retPort.isMidi = true; | |||
| retPort.isConnected = jserver.numMidiIns > index; | |||
| rindex = static_cast<uint>(index); | |||
| flags = commonFlags|JackPortIsOutput; | |||
| gid = JackPortState::kPortIdOffsetMidiIn + rindex; | |||
| isMidi = true; | |||
| isConnected = jserver.numMidiIns > rindex; | |||
| } | |||
| else if (std::strncmp(name, "midi_playback_", 14) == 0) | |||
| { | |||
| @@ -185,10 +259,11 @@ jack_port_t* jack_port_by_name(jack_client_t* client, const char* name) | |||
| const int index = std::atoi(name)-1; | |||
| CARLA_SAFE_ASSERT_RETURN(index >= 0 && index < jserver.numMidiOuts, nullptr); | |||
| retPort.index = static_cast<uint>(jserver.numMidiIns + index); | |||
| retPort.flags = commonFlags|JackPortIsInput; | |||
| retPort.isMidi = true; | |||
| retPort.isConnected = jserver.numMidiOuts > index; | |||
| rindex = static_cast<uint>(jserver.numMidiIns + index); | |||
| flags = commonFlags|JackPortIsInput; | |||
| gid = JackPortState::kPortIdOffsetMidiOut + rindex; | |||
| isMidi = true; | |||
| isConnected = jserver.numMidiOuts > rindex; | |||
| } | |||
| else | |||
| { | |||
| @@ -196,7 +271,16 @@ jack_port_t* jack_port_by_name(jack_client_t* client, const char* name) | |||
| return nullptr; | |||
| } | |||
| return (jack_port_t*)&retPort; | |||
| if (JackPortState* const port = systemPortIdMapping[gid]) | |||
| return (jack_port_t*)port; | |||
| JackPortState* const port = new JackPortState(fullname, | |||
| portname, | |||
| rindex, flags, gid, | |||
| isMidi, isConnected); | |||
| systemPortIdMapping[gid] = port; | |||
| return (jack_port_t*)port; | |||
| } | |||
| else | |||
| { | |||
| @@ -211,7 +295,123 @@ jack_port_t* jack_port_by_name(jack_client_t* client, const char* name) | |||
| CARLA_EXPORT | |||
| jack_port_t* jack_port_by_id(jack_client_t* client, jack_port_id_t port_id) | |||
| { | |||
| carla_stderr2("%s(%p, %u)", __FUNCTION__, client, port_id); | |||
| carla_debug("%s(%p, %u)", __FUNCTION__, client, port_id); | |||
| CARLA_SAFE_ASSERT_UINT_RETURN(port_id >= JackPortState::kPortIdOffsetUser, port_id, nullptr); | |||
| JackClientState* const jclient = (JackClientState*)client; | |||
| CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, nullptr); | |||
| if (JackPortState* const port = jclient->portIdMapping[port_id]) | |||
| return (jack_port_t*)port; | |||
| carla_stderr2("jack_port_by_id: invalid port id %u", port_id); | |||
| return nullptr; | |||
| } | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| CARLA_EXPORT | |||
| const char** jack_port_get_connections(const jack_port_t* port) | |||
| { | |||
| carla_stderr2("%s(%p)", __FUNCTION__, port); | |||
| const JackPortState* const jport = (const JackPortState*)port; | |||
| CARLA_SAFE_ASSERT_RETURN(jport != nullptr, nullptr); | |||
| CARLA_SAFE_ASSERT_RETURN(! jport->isSystem, nullptr); | |||
| if (! jport->isConnected) | |||
| return nullptr; | |||
| return nullptr; | |||
| } | |||
| CARLA_EXPORT | |||
| const char** jack_port_get_all_connections(const jack_client_t* client, const jack_port_t* port) | |||
| { | |||
| carla_stdout("%s(%p, %p) WIP", __FUNCTION__, client, port); | |||
| JackClientState* const jclient = (JackClientState*)client; | |||
| CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, nullptr); | |||
| const JackPortState* const jport = (const JackPortState*)port; | |||
| CARLA_SAFE_ASSERT_RETURN(jport != nullptr, nullptr); | |||
| CARLA_SAFE_ASSERT_UINT_RETURN(jport->gid >= JackPortState::kPortIdOffsetAudioIn, jport->gid, nullptr); | |||
| if (! jport->isConnected) | |||
| return nullptr; | |||
| if (jport->isSystem) | |||
| { | |||
| const JackPortState* connectedPort; | |||
| /**/ if (jport->gid >= JackPortState::kPortIdOffsetMidiOut) | |||
| connectedPort = jclient->midiOuts.getAt(jport->gid - JackPortState::kPortIdOffsetMidiOut, nullptr); | |||
| else if (jport->gid >= JackPortState::kPortIdOffsetAudioOut) | |||
| connectedPort = jclient->audioOuts.getAt(jport->gid - JackPortState::kPortIdOffsetAudioOut, nullptr); | |||
| else if (jport->gid >= JackPortState::kPortIdOffsetMidiIn) | |||
| connectedPort = jclient->midiIns.getAt(jport->gid - JackPortState::kPortIdOffsetMidiIn, nullptr); | |||
| else | |||
| connectedPort = jclient->audioIns.getAt(jport->gid - JackPortState::kPortIdOffsetAudioIn, nullptr); | |||
| if (connectedPort == nullptr) | |||
| { | |||
| carla_debug("port %s has no connections?", jport->fullname); | |||
| return nullptr; | |||
| } | |||
| if (const char** const ret = static_cast<const char**>(malloc(sizeof(const char*)*2))) | |||
| { | |||
| carla_debug("port %s is connected to %s", jport->fullname, connectedPort->fullname); | |||
| ret[0] = connectedPort->fullname; | |||
| ret[1] = nullptr; | |||
| return ret; | |||
| } | |||
| } | |||
| else | |||
| { | |||
| const JackServerState& jserver(jclient->server); | |||
| const char* connectedPortName = nullptr; | |||
| if (jport->isMidi) | |||
| { | |||
| if (jport->flags & JackPortIsOutput) | |||
| { | |||
| if (jport->index < jserver.numMidiOuts) | |||
| connectedPortName = allocate_port_name("system:midi_playback_", jport->index); | |||
| } | |||
| else | |||
| { | |||
| if (jport->index < jserver.numMidiIns) | |||
| connectedPortName = allocate_port_name("system:midi_capture_", jport->index); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| if (jport->flags & JackPortIsOutput) | |||
| { | |||
| if (jport->index < jserver.numAudioOuts) | |||
| connectedPortName = allocate_port_name("system:playback_", jport->index); | |||
| } | |||
| else | |||
| { | |||
| if (jport->index < jserver.numAudioIns) | |||
| connectedPortName = allocate_port_name("system:capture_", jport->index); | |||
| } | |||
| } | |||
| if (connectedPortName != nullptr) | |||
| { | |||
| if (const char** const ret = static_cast<const char**>(malloc(sizeof(const char*)*2))) | |||
| { | |||
| carla_debug("port %s is connected to %s", jport->fullname, connectedPortName); | |||
| ret[0] = connectedPortName; | |||
| ret[1] = nullptr; | |||
| return ret; | |||
| } | |||
| } | |||
| } | |||
| return nullptr; | |||
| } | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * Carla JACK API for external applications | |||
| * Copyright (C) 2016-2019 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2016-2020 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| @@ -21,6 +21,8 @@ CARLA_BACKEND_USE_NAMESPACE | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| static uint32_t gPortId = JackPortState::kPortIdOffsetUser; | |||
| CARLA_EXPORT | |||
| jack_port_t* jack_port_register(jack_client_t* client, const char* port_name, const char* port_type, | |||
| unsigned long flags, unsigned long buffer_size) | |||
| @@ -40,9 +42,11 @@ jack_port_t* jack_port_register(jack_client_t* client, const char* port_name, co | |||
| if (flags & JackPortIsInput) | |||
| { | |||
| const std::size_t index = jclient->audioIns.count(); | |||
| const uint gid = ++gPortId; | |||
| JackPortState* const port = new JackPortState(jclient->name, port_name, | |||
| static_cast<uint>(index), | |||
| static_cast<int>(flags), | |||
| gid, | |||
| false, false, index < jserver.numAudioIns); | |||
| { | |||
| @@ -50,6 +54,7 @@ jack_port_t* jack_port_register(jack_client_t* client, const char* port_name, co | |||
| jclient->audioIns.append(port); | |||
| } | |||
| jclient->portIdMapping[gid] = port; | |||
| jclient->portNameMapping[port->fullname] = port; | |||
| return (jack_port_t*)port; | |||
| } | |||
| @@ -57,9 +62,11 @@ jack_port_t* jack_port_register(jack_client_t* client, const char* port_name, co | |||
| if (flags & JackPortIsOutput) | |||
| { | |||
| const std::size_t index = jclient->audioOuts.count(); | |||
| const uint gid = ++gPortId; | |||
| JackPortState* const port = new JackPortState(jclient->name, port_name, | |||
| static_cast<uint>(index), | |||
| static_cast<int>(flags), | |||
| gid, | |||
| false, false, index < jserver.numAudioOuts); | |||
| { | |||
| @@ -67,6 +74,7 @@ jack_port_t* jack_port_register(jack_client_t* client, const char* port_name, co | |||
| jclient->audioOuts.append(port); | |||
| } | |||
| jclient->portIdMapping[gid] = port; | |||
| jclient->portNameMapping[port->fullname] = port; | |||
| return (jack_port_t*)port; | |||
| } | |||
| @@ -80,9 +88,11 @@ jack_port_t* jack_port_register(jack_client_t* client, const char* port_name, co | |||
| if (flags & JackPortIsInput) | |||
| { | |||
| const std::size_t index = jclient->midiIns.count(); | |||
| const uint gid = ++gPortId; | |||
| JackPortState* const port = new JackPortState(jclient->name, port_name, | |||
| static_cast<uint>(index), | |||
| static_cast<int>(flags), | |||
| gid, | |||
| true, false, index < jserver.numMidiIns); | |||
| { | |||
| @@ -90,6 +100,7 @@ jack_port_t* jack_port_register(jack_client_t* client, const char* port_name, co | |||
| jclient->midiIns.append(port); | |||
| } | |||
| jclient->portIdMapping[gid] = port; | |||
| jclient->portNameMapping[port->fullname] = port; | |||
| return (jack_port_t*)port; | |||
| } | |||
| @@ -97,9 +108,11 @@ jack_port_t* jack_port_register(jack_client_t* client, const char* port_name, co | |||
| if (flags & JackPortIsOutput) | |||
| { | |||
| const std::size_t index = jclient->midiOuts.count(); | |||
| const uint gid = ++gPortId; | |||
| JackPortState* const port = new JackPortState(jclient->name, port_name, | |||
| static_cast<uint>(index), | |||
| static_cast<int>(flags), | |||
| gid, | |||
| true, false, index < jserver.numMidiOuts); | |||
| { | |||
| @@ -107,6 +120,7 @@ jack_port_t* jack_port_register(jack_client_t* client, const char* port_name, co | |||
| jclient->midiOuts.append(port); | |||
| } | |||
| jclient->portIdMapping[gid] = port; | |||
| jclient->portNameMapping[port->fullname] = port; | |||
| return (jack_port_t*)port; | |||
| } | |||
| @@ -142,6 +156,7 @@ int jack_port_unregister(jack_client_t* client, jack_port_t* port) | |||
| if (jport->flags & JackPortIsInput) | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(jclient->midiIns.removeOne(jport), ENOENT); | |||
| jclient->portIdMapping.erase(jport->gid); | |||
| jclient->portNameMapping.erase(jport->fullname); | |||
| return 0; | |||
| } | |||
| @@ -149,6 +164,7 @@ int jack_port_unregister(jack_client_t* client, jack_port_t* port) | |||
| if (jport->flags & JackPortIsOutput) | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(jclient->midiOuts.removeOne(jport), ENOENT); | |||
| jclient->portIdMapping.erase(jport->gid); | |||
| jclient->portNameMapping.erase(jport->fullname); | |||
| return 0; | |||
| } | |||
| @@ -158,6 +174,7 @@ int jack_port_unregister(jack_client_t* client, jack_port_t* port) | |||
| if (jport->flags & JackPortIsInput) | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(jclient->audioIns.removeOne(jport), ENOENT); | |||
| jclient->portIdMapping.erase(jport->gid); | |||
| jclient->portNameMapping.erase(jport->fullname); | |||
| return 0; | |||
| } | |||
| @@ -165,6 +182,7 @@ int jack_port_unregister(jack_client_t* client, jack_port_t* port) | |||
| if (jport->flags & JackPortIsOutput) | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(jclient->audioOuts.removeOne(jport), ENOENT); | |||
| jclient->portIdMapping.erase(jport->gid); | |||
| jclient->portNameMapping.erase(jport->fullname); | |||
| return 0; | |||
| } | |||
| @@ -292,22 +310,6 @@ int jack_port_connected_to(const jack_port_t* port, const char* port_name) | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| CARLA_EXPORT | |||
| const char** jack_port_get_connections(const jack_port_t* port) | |||
| { | |||
| carla_stderr2("%s(%p)", __FUNCTION__, port); | |||
| return nullptr; | |||
| } | |||
| CARLA_EXPORT | |||
| const char** jack_port_get_all_connections(const jack_client_t* client, const jack_port_t* port) | |||
| { | |||
| carla_stderr2("%s(%p, %p)", __FUNCTION__, client, port); | |||
| return nullptr; | |||
| } | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| CARLA_EXPORT | |||
| int jack_port_tie(jack_port_t* src, jack_port_t* dst) | |||
| { | |||
| @@ -352,23 +354,22 @@ int jack_port_rename(jack_client_t* client, jack_port_t *port, const char *port_ | |||
| CARLA_SAFE_ASSERT_RETURN(jport != nullptr, EINVAL); | |||
| CARLA_SAFE_ASSERT_RETURN(! jport->isSystem, EINVAL); | |||
| static CarlaString rname, rfullname; | |||
| // TODO: verify uniqueness | |||
| rname = port_name; | |||
| CARLA_SAFE_ASSERT_RETURN(rname.isNotEmpty(), ENOMEM); | |||
| char* const fullname = (char*)std::malloc(STR_MAX); | |||
| CARLA_SAFE_ASSERT_RETURN(fullname != nullptr, ENOMEM); | |||
| std::snprintf(fullname, STR_MAX, "%s:%s", jclient->name, port_name); | |||
| fullname[STR_MAX-1] = '\0'; | |||
| jport->name = rname.buffer(); | |||
| jport->fullname = rfullname.buffer(); | |||
| jclient->portNameMapping.erase(jport->fullname); | |||
| jclient->portNameMapping[fullname] = jport; | |||
| std::free(jport->name); | |||
| std::free(jport->fullname); | |||
| std::free(fullname); | |||
| jport->name = strdup(port_name); | |||
| jport->fullname = fullname; | |||
| // TODO: port rename callback | |||