diff --git a/source/backend/engine/CarlaEngineJack.cpp b/source/backend/engine/CarlaEngineJack.cpp index a1f4b8e09..21d1a8712 100644 --- a/source/backend/engine/CarlaEngineJack.cpp +++ b/source/backend/engine/CarlaEngineJack.cpp @@ -58,6 +58,24 @@ CARLA_BACKEND_START_NAMESPACE class CarlaEngineJack; class CarlaEngineJackClient; +#ifndef BUILD_BRIDGE +// FIXME temporary function while jack2 client uuids are broken +static int buggy_jack2_uuid_parse(const char* b, jack_uuid_t* u) +{ + if (sscanf (b, P_UINT64, u) == 1) { + + if (*u < (0x1LL << 32)) { + // FIXME: bug in jack2, client bit not set + *u = (0x2LU << 32) | *u; + } + + return 0; + } + + return -1; +} +#endif + // ----------------------------------------------------------------------- // Fallback data @@ -834,7 +852,6 @@ public: fUsedGroups(), fUsedPorts(), fUsedConnections(), - fNewGroups(), fPatchbayProcThreadProtectionMutex(), fRetConns(), fPostPonedEvents(), @@ -860,7 +877,6 @@ public: fUsedGroups.clear(); fUsedPorts.clear(); fUsedConnections.clear(); - fNewGroups.clear(); CARLA_SAFE_ASSERT(fPostPonedEvents.count() == 0); #endif } @@ -1017,6 +1033,25 @@ public: } } + if (const char* const uuidchar = jackbridge_client_get_uuid(fClient)) + { + jack_uuid_t uuid; + + if (buggy_jack2_uuid_parse(uuidchar, &uuid) == 0) + { + const CarlaString& tcp(pData->osc.getServerPathTCP()); + const CarlaString& udp(pData->osc.getServerPathUDP()); + + if (tcp.isNotEmpty()) + jackbridge_set_property(fClient, uuid, + "https://kx.studio/ns/carla/osc-tcp", tcp.buffer(), "text/plain"); + + if (tcp.isNotEmpty()) + jackbridge_set_property(fClient, uuid, + "https://kx.studio/ns/carla/osc-udp", udp.buffer(), "text/plain"); + } + } + if (jackbridge_activate(fClient)) { if (opts.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK || @@ -1028,14 +1063,16 @@ public: std::getenv("NSM_URL") == nullptr) { char strBuf[STR_MAX]; - strBuf[STR_MAX-1] = '\0'; if (jackbridge_port_by_name(fClient, "system:capture_1") != nullptr) { - std::snprintf(strBuf, STR_MAX-2, "%s:audio-in1", jackClientName); + std::snprintf(strBuf, STR_MAX, "%s:audio-in1", jackClientName); + strBuf[STR_MAX-1] = '\0'; + jackbridge_connect(fClient, "system:capture_1", strBuf); - std::snprintf(strBuf, STR_MAX-2, "%s:audio-in2", jackClientName); + std::snprintf(strBuf, STR_MAX, "%s:audio-in2", jackClientName); + strBuf[STR_MAX-1] = '\0'; if (jackbridge_port_by_name(fClient, "system:capture_2") != nullptr) jackbridge_connect(fClient, "system:capture_2", strBuf); @@ -1045,10 +1082,13 @@ public: if (jackbridge_port_by_name(fClient, "system:playback_1") != nullptr) { - std::snprintf(strBuf, STR_MAX-2, "%s:audio-out1", jackClientName); + std::snprintf(strBuf, STR_MAX, "%s:audio-out1", jackClientName); + strBuf[STR_MAX-1] = '\0'; + jackbridge_connect(fClient, strBuf, "system:playback_1"); - std::snprintf(strBuf, STR_MAX-2, "%s:audio-out2", jackClientName); + std::snprintf(strBuf, STR_MAX, "%s:audio-out2", jackClientName); + strBuf[STR_MAX-1] = '\0'; if (jackbridge_port_by_name(fClient, "system:playback_2") != nullptr) jackbridge_connect(fClient, strBuf, "system:playback_2"); @@ -1119,7 +1159,6 @@ public: fUsedGroups.clear(); fUsedPorts.clear(); fUsedConnections.clear(); - fNewGroups.clear(); fPostPonedEvents.clear(); // clear rack/patchbay stuff @@ -1273,6 +1312,29 @@ public: jackbridge_set_latency_callback(client, carla_jack_latency_callback_plugin, plugin); jackbridge_set_process_callback(client, carla_jack_process_callback_plugin, plugin); jackbridge_on_shutdown(client, carla_jack_shutdown_callback_plugin, plugin); + + if (const char* const uuidchar = jackbridge_client_get_uuid(client)) + { + jack_uuid_t uuid; + + if (buggy_jack2_uuid_parse(uuidchar, &uuid) == 0) + { + char strBufId[24]; + std::snprintf(strBufId, 24, "%u", plugin->getId()); + strBufId[23] = '\0'; + + jackbridge_set_property(client, uuid, + "https://kx.studio/ns/carla/plugin-id", + strBufId, + "http://www.w3.org/2001/XMLSchema#integer"); + + if (const char* const pluginIcon = plugin->getIconName()) + jackbridge_set_property(client, uuid, + "https://kx.studio/ns/carla/plugin-icon", + pluginIcon, + "text/plain"); + } + } #else fClient = client; pData->bufferSize = jackbridge_get_buffer_size(client); @@ -1540,7 +1602,6 @@ public: fUsedGroups.clear(); fUsedPorts.clear(); fUsedConnections.clear(); - fNewGroups.clear(); initJackPatchbay(sendHost, sendOSC, jackbridge_get_client_name(fClient)); return true; @@ -2069,15 +2130,19 @@ protected: GroupNameToId groupNameToId; groupNameToId.setData(groupId, groupName); + int pluginId = -1; + PatchbayIcon icon = (jackPortFlags & JackPortIsPhysical) ? PATCHBAY_ICON_HARDWARE : PATCHBAY_ICON_APPLICATION; + + findPluginIdAndIcon(groupName, pluginId, icon); + callback(fExternalPatchbayHost, fExternalPatchbayOsc, ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, groupNameToId.group, - (jackPortFlags & JackPortIsPhysical) ? PATCHBAY_ICON_HARDWARE : PATCHBAY_ICON_APPLICATION, - -1, + icon, + pluginId, 0, 0.0f, groupNameToId.name); - fNewGroups.append(groupId); fUsedGroups.list.append(groupNameToId); } @@ -2307,60 +2372,65 @@ private: PatchbayGroupList fUsedGroups; PatchbayPortList fUsedPorts; PatchbayConnectionList fUsedConnections; - LinkedList fNewGroups; CarlaMutex fPatchbayProcThreadProtectionMutex; mutable CharStringListPtr fRetConns; - bool findPluginIdAndIcon(const char* const clientName, int& pluginId, PatchbayIcon& icon) noexcept + void findPluginIdAndIcon(const char* const clientName, int& pluginId, PatchbayIcon& icon) const noexcept { carla_debug("CarlaEngineJack::findPluginIdAndIcon(\"%s\", ...)", clientName); // TODO - this currently only works in multi-client mode if (pData->options.processMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS) - return false; + return; - for (uint i=0; i < pData->curPluginCount; ++i) - { - CarlaPlugin* const plugin(pData->plugins[i].plugin); + const char* const uuidstr = jackbridge_get_uuid_for_client_name(fClient, clientName); + CARLA_SAFE_ASSERT_RETURN(uuidstr != nullptr && uuidstr[0] != '\0',); - if (plugin == nullptr || ! plugin->isEnabled()) - continue; + jack_uuid_t uuid; + CARLA_SAFE_ASSERT_RETURN(buggy_jack2_uuid_parse(uuidstr, &uuid) == 0,); - const CarlaEngineJackClient* const engineClient((const CarlaEngineJackClient*)plugin->getEngineClient()); - CARLA_SAFE_ASSERT_CONTINUE(engineClient != nullptr); + { + char* value = nullptr; + char* type = nullptr; - const char* const engineClientName(engineClient->getJackClientName()); - CARLA_SAFE_ASSERT_CONTINUE(engineClientName != nullptr && engineClientName[0] != '\0'); + if (! jackbridge_get_property(uuid, "https://kx.studio/ns/carla/plugin-id", &value, &type)) + return; - if (std::strcmp(clientName, engineClientName) != 0) - continue; + CARLA_SAFE_ASSERT_RETURN(type != nullptr && type[0] != '\0',); + CARLA_SAFE_ASSERT_RETURN(value != nullptr && value[0] != '\0',); + CARLA_SAFE_ASSERT_RETURN(std::strcmp(type, "http://www.w3.org/2001/XMLSchema#integer") == 0,); - pluginId = static_cast(i); + pluginId = std::atoi(value); icon = PATCHBAY_ICON_PLUGIN; + } - if (const char* const pluginIcon = plugin->getIconName()) - { - if (pluginIcon[0] == '\0') - pass(); - else if (std::strcmp(pluginIcon, "app") == 0 || std::strcmp(pluginIcon, "application") == 0) - icon = PATCHBAY_ICON_APPLICATION; - else if (std::strcmp(pluginIcon, "plugin") == 0) - icon = PATCHBAY_ICON_PLUGIN; - else if (std::strcmp(pluginIcon, "hardware") == 0) - icon = PATCHBAY_ICON_HARDWARE; - else if (std::strcmp(pluginIcon, "carla") == 0) - icon = PATCHBAY_ICON_CARLA; - else if (std::strcmp(pluginIcon, "distrho") == 0) - icon = PATCHBAY_ICON_DISTRHO; - else if (std::strcmp(pluginIcon, "file") == 0) - icon = PATCHBAY_ICON_FILE; - } + { + char* value = nullptr; + char* type = nullptr; - return true; - } + if (! jackbridge_get_property(uuid, "https://kx.studio/ns/carla/plugin-icon", &value, &type)) + return; - return false; + CARLA_SAFE_ASSERT_RETURN(type != nullptr && type[0] != '\0',); + CARLA_SAFE_ASSERT_RETURN(value != nullptr && value[0] != '\0',); + CARLA_SAFE_ASSERT_RETURN(std::strcmp(type, "text/plain") == 0,); + + /**/ if (std::strcmp(value, "app") == 0) + icon = PATCHBAY_ICON_APPLICATION; + else if (std::strcmp(value, "application") == 0) + icon = PATCHBAY_ICON_APPLICATION; + else if (std::strcmp(value, "plugin") == 0) + icon = PATCHBAY_ICON_PLUGIN; + else if (std::strcmp(value, "hardware") == 0) + icon = PATCHBAY_ICON_HARDWARE; + else if (std::strcmp(value, "carla") == 0) + icon = PATCHBAY_ICON_CARLA; + else if (std::strcmp(value, "distrho") == 0) + icon = PATCHBAY_ICON_DISTRHO; + else if (std::strcmp(value, "file") == 0) + icon = PATCHBAY_ICON_FILE; + } } void initJackPatchbay(const bool sendHost, const bool sendOSC, const char* const ourName) @@ -2424,14 +2494,14 @@ private: groupId = ++fUsedGroups.lastId; parsedGroups.append(groupName); + GroupNameToId groupNameToId; + groupNameToId.setData(groupId, groupName); + int pluginId = -1; PatchbayIcon icon = (jackPortFlags & JackPortIsPhysical) ? PATCHBAY_ICON_HARDWARE : PATCHBAY_ICON_APPLICATION; findPluginIdAndIcon(groupName, pluginId, icon); - GroupNameToId groupNameToId; - groupNameToId.setData(groupId, groupName); - callback(sendHost, sendOSC, ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, groupNameToId.group, @@ -2653,7 +2723,6 @@ private: void run() override { LinkedList events; - LinkedList newPlugins; PostPonedJackEvent nullEvent; carla_zeroStruct(nullEvent); @@ -2668,17 +2737,14 @@ private: if (fPostPonedEvents.count() > 0) fPostPonedEvents.moveTo(events); - - if (fNewGroups.count() > 0) - fNewGroups.moveTo(newPlugins); } if (fClient == nullptr) break; - if (events.count() == 0 && newPlugins.count() == 0) + if (events.count() == 0) { - carla_msleep(fIsInternalClient ? 10 : 200); + carla_msleep(fIsInternalClient ? 50 : 200); continue; } @@ -2706,33 +2772,10 @@ private: } } - for (LinkedList::Itenerator it = newPlugins.begin2(); it.valid(); it.next()) - { - const uint groupId(it.getValue(0)); - CARLA_SAFE_ASSERT_CONTINUE(groupId > 0); - - const char* const groupName(fUsedGroups.getGroupName(groupId)); - CARLA_SAFE_ASSERT_CONTINUE(groupName != nullptr && groupName[0] != '\0'); - - int pluginId = -1; - PatchbayIcon icon = PATCHBAY_ICON_PLUGIN; - - if (findPluginIdAndIcon(groupName, pluginId, icon)) { - callback(fExternalPatchbayHost, fExternalPatchbayOsc, - ENGINE_CALLBACK_PATCHBAY_CLIENT_DATA_CHANGED, - groupId, - icon, - pluginId, - 0, 0.0f, nullptr); - } - } - events.clear(); - newPlugins.clear(); } events.clear(); - newPlugins.clear(); } #endif // BUILD_BRIDGE