Signed-off-by: falkTX <falktx@falktx.com>tags/v2.1-rc1
| @@ -294,11 +294,11 @@ protected: | |||
| const ScopedEngineEnvironmentLocker _seel(kEngine); | |||
| const ScopedEnvVar sev2("LD_LIBRARY_PATH", libjackdir.buffer()); | |||
| const ScopedEnvVar sev1("LD_PRELOAD", ldpreload.isNotEmpty() ? ldpreload.buffer() : nullptr); | |||
| #ifdef HAVE_LIBLO | |||
| const ScopedEnvVar sev3("NSM_URL", lo_server_get_url(fOscServer)); | |||
| #endif | |||
| const ScopedEnvVar sev2("LD_LIBRARY_PATH", libjackdir.buffer()); | |||
| const ScopedEnvVar sev1("LD_PRELOAD", ldpreload.isNotEmpty() ? ldpreload.buffer() : nullptr); | |||
| if (kPlugin->getHints() & PLUGIN_HAS_CUSTOM_UI) | |||
| carla_setenv("CARLA_FRONTEND_WIN_ID", winIdStr); | |||
| @@ -49,6 +49,13 @@ enum InterposerAction { | |||
| LIBJACK_INTERPOSER_ACTION_CLOSE_EVERYTHING, | |||
| }; | |||
| enum InterposerCallbacks { | |||
| LIBJACK_INTERPOSER_CALLBACK_NONE = 0, | |||
| LIBJACK_INTERPOSER_CALLBACK_UI_HIDE, | |||
| }; | |||
| typedef int (*CarlaInterposedCallback)(int, void*); | |||
| int jack_carla_interposed_action(uint action, uint value, void* ptr); | |||
| #ifdef __cplusplus | |||
| @@ -64,7 +64,6 @@ struct ScopedLibOpen { | |||
| typedef int (*XWindowFunc)(Display*, Window); | |||
| typedef int (*XNextEventFunc)(Display*, XEvent*); | |||
| typedef int (*CarlaInterposedCallback)(int, void*); | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| // Current state | |||
| @@ -312,7 +311,7 @@ int XUnmapWindow(Display* display, Window window) | |||
| gCurrentWindowVisible = false; | |||
| if (gInterposedCallback != nullptr) | |||
| gInterposedCallback(1, nullptr); | |||
| gInterposedCallback(LIBJACK_INTERPOSER_CALLBACK_UI_HIDE, nullptr); | |||
| } | |||
| return real_XUnmapWindow(display, window); | |||
| @@ -344,7 +343,7 @@ int XNextEvent(Display* display, XEvent* event) | |||
| gCurrentWindowMapped = false; | |||
| if (gInterposedCallback != nullptr) | |||
| gInterposedCallback(1, nullptr); | |||
| gInterposedCallback(LIBJACK_INTERPOSER_CALLBACK_UI_HIDE, nullptr); | |||
| event->type = 0; | |||
| carla_stdout("XNextEvent close event catched, hiding UI instead"); | |||
| @@ -19,7 +19,7 @@ | |||
| #define CARLA_LIBJACK_API_H_INCLUDED | |||
| #include "CarlaLibJackHints.h" | |||
| #include "jackbridge/JackBridge.hpp" | |||
| #include "../jackbridge/JackBridge.hpp" | |||
| #include <pthread.h> | |||
| @@ -213,7 +213,7 @@ void jack_set_transport_info(jack_client_t*, void*); | |||
| #define JACK_UUID_SIZE 36 | |||
| #define JACK_UUID_STRING_SIZE (JACK_UUID_SIZE+1) /* includes trailing null */ | |||
| // #define JACK_UUID_EMPTY_INITIALIZER 0 | |||
| #define JACK_UUID_EMPTY_INITIALIZER 0 | |||
| jack_uuid_t jack_client_uuid_generate(); | |||
| jack_uuid_t jack_port_uuid_generate(uint32_t port_id); | |||
| @@ -25,12 +25,22 @@ | |||
| // --------------------------------------------------------------------------------------------------------------------- | |||
| typedef int (*CarlaInterposedCallback)(int, void*); | |||
| CARLA_EXPORT | |||
| int jack_carla_interposed_action(uint, uint, void*) | |||
| { | |||
| carla_stderr2("Non-export jack_carla_interposed_action called, this should not happen!!"); | |||
| static bool printWarning = true; | |||
| if (printWarning) | |||
| { | |||
| printWarning = false; | |||
| carla_stderr2("Non-exported jack_carla_interposed_action called, this should not happen!!"); | |||
| carla_stderr("Printing some info:"); | |||
| carla_stderr("\tLD_LIBRARY_PATH: '%s'", std::getenv("LD_LIBRARY_PATH")); | |||
| carla_stderr("\tLD_PRELOAD: '%s'", std::getenv("LD_PRELOAD")); | |||
| std::fflush(stderr); | |||
| } | |||
| // ::kill(::getpid(), SIGKILL); | |||
| return 1337; | |||
| } | |||
| @@ -111,10 +121,12 @@ class CarlaJackAppClient : public CarlaJackRealtimeThread::Callback, | |||
| public: | |||
| JackServerState fServer; | |||
| LinkedList<JackClientState*> fClients; | |||
| LinkedList<JackClientState*> fNewClients; | |||
| CarlaJackAppClient() | |||
| : fServer(this), | |||
| fClients(), | |||
| fNewClients(), | |||
| fShmAudioPool(), | |||
| fShmRtClientControl(), | |||
| fShmNonRtClientControl(), | |||
| @@ -133,6 +145,9 @@ public: | |||
| fRealtimeThread(this), | |||
| fNonRealtimeThread(this), | |||
| fRealtimeThreadMutex() | |||
| #ifdef DEBUG | |||
| ,leakDetector_CarlaJackAppClient() | |||
| #endif | |||
| { | |||
| carla_debug("CarlaJackAppClient::CarlaJackAppClient()"); | |||
| @@ -172,8 +187,13 @@ public: | |||
| fSessionManager = static_cast<uint>(libjackSetup[4] - '0'); | |||
| fSetupHints = static_cast<uint>(libjackSetup[5] - '0'); | |||
| jack_carla_interposed_action(LIBJACK_INTERPOSER_ACTION_SET_HINTS_AND_CALLBACK, fSetupHints, (void*)carla_interposed_callback); | |||
| jack_carla_interposed_action(LIBJACK_INTERPOSER_ACTION_SET_SESSION_MANAGER, fSessionManager, nullptr); | |||
| jack_carla_interposed_action(LIBJACK_INTERPOSER_ACTION_SET_HINTS_AND_CALLBACK, | |||
| fSetupHints, | |||
| (void*)carla_interposed_callback); | |||
| jack_carla_interposed_action(LIBJACK_INTERPOSER_ACTION_SET_SESSION_MANAGER, | |||
| fSessionManager, | |||
| nullptr); | |||
| fNonRealtimeThread.startThread(false); | |||
| } | |||
| @@ -223,6 +243,11 @@ public: | |||
| if (! fClients.append(jclient)) | |||
| return false; | |||
| if (! fNewClients.append(jclient)) | |||
| { | |||
| fClients.removeOne(jclient); | |||
| return false; | |||
| } | |||
| jclient->activated = true; | |||
| jclient->deactivated = false; | |||
| @@ -252,7 +277,7 @@ public: | |||
| switch (cb_action) | |||
| { | |||
| case 1: { | |||
| case LIBJACK_INTERPOSER_CALLBACK_UI_HIDE: { | |||
| const CarlaMutexLocker cml(fShmNonRtServerControl.mutex); | |||
| fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerUiClosed); | |||
| fShmNonRtServerControl.commitWrite(); | |||
| @@ -457,6 +482,20 @@ void CarlaJackAppClient::clearSharedMemory() noexcept | |||
| bool CarlaJackAppClient::handleRtData() | |||
| { | |||
| if (fNewClients.count() != 0) | |||
| { | |||
| for (LinkedList<JackClientState*>::Itenerator it = fNewClients.begin2(); it.valid(); it.next()) | |||
| { | |||
| JackClientState* const jclient(it.getValue(nullptr)); | |||
| CARLA_SAFE_ASSERT_CONTINUE(jclient != nullptr); | |||
| if (jclient->threadInitCb != nullptr) | |||
| jclient->threadInitCb(jclient->threadInitCbPtr); | |||
| } | |||
| fNewClients.clear(); | |||
| } | |||
| const BridgeRtClientControl::WaitHelper helper(fShmRtClientControl); | |||
| if (! helper.ok) | |||
| @@ -192,6 +192,9 @@ struct JackClientState { | |||
| JackSyncCallback syncCb; | |||
| void* syncCbPtr; | |||
| JackThreadInitCallback threadInitCb; | |||
| void* threadInitCbPtr; | |||
| JackClientState(const JackServerState& s, const char* const n) | |||
| : server(s), | |||
| mutex(), | |||
| @@ -216,7 +219,9 @@ struct JackClientState { | |||
| sampleRateCb(nullptr), | |||
| sampleRateCbPtr(nullptr), | |||
| syncCb(nullptr), | |||
| syncCbPtr(nullptr) {} | |||
| syncCbPtr(nullptr), | |||
| threadInitCb(nullptr), | |||
| threadInitCbPtr(nullptr) {} | |||
| ~JackClientState() | |||
| { | |||
| @@ -24,8 +24,15 @@ CARLA_BACKEND_USE_NAMESPACE | |||
| CARLA_EXPORT | |||
| int jack_set_thread_init_callback(jack_client_t* client, JackThreadInitCallback callback, void* arg) | |||
| { | |||
| carla_stderr2("%s(%p, %p, %p)", __FUNCTION__, client, callback, arg); | |||
| carla_debug("%s(%p, %p, %p)", __FUNCTION__, client, callback, arg); | |||
| JackClientState* const jclient = (JackClientState*)client; | |||
| CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, 1); | |||
| const CarlaMutexLocker cms(jclient->mutex); | |||
| jclient->threadInitCb = callback; | |||
| jclient->threadInitCbPtr = arg; | |||
| return 0; | |||
| } | |||
| @@ -47,16 +47,62 @@ const char* JACK_METADATA_ICON_LARGE = "http://jackaudio.org/metadata/icon-large | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| typedef struct { | |||
| jack_uuid_t uuid; | |||
| std::string key; | |||
| } MetadataKey; | |||
| typedef struct { | |||
| std::string type; | |||
| std::string value; | |||
| } MetadataValue; | |||
| typedef std::map<MetadataKey, MetadataValue> Metadata; | |||
| static Metadata sMetadata; | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| CARLA_EXPORT | |||
| int jack_set_property(jack_client_t*, jack_uuid_t, const char*, const char*, const char*) | |||
| int jack_set_property(jack_client_t*, jack_uuid_t uuid, const char* key, const char* value, const char* type) | |||
| { | |||
| return -1; | |||
| CARLA_SAFE_ASSERT_RETURN(uuid != JACK_UUID_EMPTY_INITIALIZER, -1); | |||
| CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0', -1); | |||
| CARLA_SAFE_ASSERT_RETURN(value != nullptr && value[0] != '\0', -1); | |||
| const MetadataKey mkey = { uuid, key }; | |||
| const MetadataValue mvalue = { value, type }; | |||
| // sMetadata[mkey] = mvalue; | |||
| return 0; | |||
| } | |||
| CARLA_EXPORT | |||
| int jack_get_property(jack_uuid_t, const char*, char**, char**) | |||
| int jack_get_property(jack_uuid_t uuid, const char* key, char** value, char** type) | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(uuid != JACK_UUID_EMPTY_INITIALIZER, -1); | |||
| CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0', -1); | |||
| // const MetadataKey mkey = { uuid, key }; | |||
| // const auto mvalueit = sMetadata.find(mkey); | |||
| // | |||
| // if (mvalueit == sMetadata.end()) | |||
| // return -1; | |||
| // | |||
| // const MetadataValue& mvalue = mvalueit->second; | |||
| // *value = strdup(mvalue.value.c_str()); | |||
| // | |||
| // if (mvalue.type.size() != 0) | |||
| // *type = strdup(mvalue.type.c_str()); | |||
| // else | |||
| // *type = nullptr; | |||
| return -1; | |||
| (void)value; | |||
| (void)type; | |||
| } | |||
| CARLA_EXPORT | |||
| @@ -77,21 +123,43 @@ int jack_get_all_properties(jack_description_t**) | |||
| } | |||
| CARLA_EXPORT | |||
| int jack_remove_property(jack_client_t*, jack_uuid_t, const char*) | |||
| int jack_remove_property(jack_client_t*, jack_uuid_t uuid, const char* key) | |||
| { | |||
| // const MetadataKey mkey = { uuid, key }; | |||
| // sMetadata.erase(mkey); | |||
| return -1; | |||
| (void)uuid; | |||
| (void)key; | |||
| } | |||
| CARLA_EXPORT | |||
| int jack_remove_properties(jack_client_t*, jack_uuid_t) | |||
| int jack_remove_properties(jack_client_t*, jack_uuid_t uuid) | |||
| { | |||
| return -1; | |||
| int count = 0; | |||
| // for (Metadata::const_iterator cit = sMetadata.begin(), cend = sMetadata.end(); cit != cend; ++cit) | |||
| { | |||
| // const MetadataKey& mkey = cit->first; | |||
| // if (mkey.uuid != uuid) | |||
| // continue; | |||
| // ++count; | |||
| // sMetadata.erase(mkey); | |||
| } | |||
| return count; | |||
| (void)uuid; | |||
| } | |||
| CARLA_EXPORT | |||
| int jack_remove_all_properties(jack_client_t*) | |||
| { | |||
| return -1; | |||
| // sMetadata = {}; | |||
| return 0; | |||
| } | |||
| CARLA_EXPORT | |||
| @@ -105,56 +173,76 @@ int jack_set_property_change_callback(jack_client_t*, JackPropertyChangeCallback | |||
| CARLA_EXPORT | |||
| jack_uuid_t jack_client_uuid_generate() | |||
| { | |||
| return 0; | |||
| static uint32_t uuid_cnt = 0; | |||
| jack_uuid_t uuid = 0x2; /* JackUUIDClient */; | |||
| uuid = (uuid << 32) | ++uuid_cnt; | |||
| return uuid; | |||
| } | |||
| CARLA_EXPORT | |||
| jack_uuid_t jack_port_uuid_generate(uint32_t) | |||
| jack_uuid_t jack_port_uuid_generate(uint32_t port_id) | |||
| { | |||
| return 0; | |||
| jack_uuid_t uuid = 0x1; /* JackUUIDPort */ | |||
| uuid = (uuid << 32) | (port_id + 1); | |||
| return uuid; | |||
| } | |||
| CARLA_EXPORT | |||
| uint32_t jack_uuid_to_index(jack_uuid_t) | |||
| uint32_t jack_uuid_to_index(jack_uuid_t u) | |||
| { | |||
| return 0; | |||
| return static_cast<uint32_t>(u & 0xffff) - 1; | |||
| } | |||
| CARLA_EXPORT | |||
| int jack_uuid_compare(jack_uuid_t, jack_uuid_t) | |||
| int jack_uuid_compare(jack_uuid_t a, jack_uuid_t b) | |||
| { | |||
| return 0; | |||
| if (a == b) { | |||
| return 0; | |||
| } | |||
| if (a < b) { | |||
| return -1; | |||
| } | |||
| return 1; | |||
| } | |||
| CARLA_EXPORT | |||
| void jack_uuid_copy(jack_uuid_t*, jack_uuid_t) | |||
| void jack_uuid_copy(jack_uuid_t* dst, jack_uuid_t src) | |||
| { | |||
| *dst = src; | |||
| } | |||
| CARLA_EXPORT | |||
| void jack_uuid_clear(jack_uuid_t*) | |||
| void jack_uuid_clear(jack_uuid_t* uuid) | |||
| { | |||
| *uuid = JACK_UUID_EMPTY_INITIALIZER; | |||
| } | |||
| CARLA_EXPORT | |||
| int jack_uuid_parse(const char*, jack_uuid_t*) | |||
| int jack_uuid_parse(const char* b, jack_uuid_t* u) | |||
| { | |||
| if (std::sscanf(b, P_UINT64, u) != 1) | |||
| return -1; | |||
| if (*u < (0x1LL << 32)) { | |||
| /* has not type bits set - not legal */ | |||
| return -1; | |||
| } | |||
| return 0; | |||
| } | |||
| CARLA_EXPORT | |||
| void jack_uuid_unparse(jack_uuid_t, char buf[JACK_UUID_STRING_SIZE]) | |||
| void jack_uuid_unparse(jack_uuid_t u, char buf[JACK_UUID_STRING_SIZE]) | |||
| { | |||
| return; | |||
| // unused | |||
| (void)buf; | |||
| std::snprintf(buf, JACK_UUID_STRING_SIZE, P_UINT64, u); | |||
| } | |||
| CARLA_EXPORT | |||
| int jack_uuid_empty(jack_uuid_t) | |||
| int jack_uuid_empty(jack_uuid_t u) | |||
| { | |||
| return 0; | |||
| return u == JACK_UUID_EMPTY_INITIALIZER; | |||
| } | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||