Signed-off-by: falkTX <falktx@falktx.com>tags/v2.1-rc1
| @@ -294,11 +294,11 @@ protected: | |||||
| const ScopedEngineEnvironmentLocker _seel(kEngine); | 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 | #ifdef HAVE_LIBLO | ||||
| const ScopedEnvVar sev3("NSM_URL", lo_server_get_url(fOscServer)); | const ScopedEnvVar sev3("NSM_URL", lo_server_get_url(fOscServer)); | ||||
| #endif | #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) | if (kPlugin->getHints() & PLUGIN_HAS_CUSTOM_UI) | ||||
| carla_setenv("CARLA_FRONTEND_WIN_ID", winIdStr); | carla_setenv("CARLA_FRONTEND_WIN_ID", winIdStr); | ||||
| @@ -49,6 +49,13 @@ enum InterposerAction { | |||||
| LIBJACK_INTERPOSER_ACTION_CLOSE_EVERYTHING, | 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); | int jack_carla_interposed_action(uint action, uint value, void* ptr); | ||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||
| @@ -64,7 +64,6 @@ struct ScopedLibOpen { | |||||
| typedef int (*XWindowFunc)(Display*, Window); | typedef int (*XWindowFunc)(Display*, Window); | ||||
| typedef int (*XNextEventFunc)(Display*, XEvent*); | typedef int (*XNextEventFunc)(Display*, XEvent*); | ||||
| typedef int (*CarlaInterposedCallback)(int, void*); | |||||
| // -------------------------------------------------------------------------------------------------------------------- | // -------------------------------------------------------------------------------------------------------------------- | ||||
| // Current state | // Current state | ||||
| @@ -312,7 +311,7 @@ int XUnmapWindow(Display* display, Window window) | |||||
| gCurrentWindowVisible = false; | gCurrentWindowVisible = false; | ||||
| if (gInterposedCallback != nullptr) | if (gInterposedCallback != nullptr) | ||||
| gInterposedCallback(1, nullptr); | |||||
| gInterposedCallback(LIBJACK_INTERPOSER_CALLBACK_UI_HIDE, nullptr); | |||||
| } | } | ||||
| return real_XUnmapWindow(display, window); | return real_XUnmapWindow(display, window); | ||||
| @@ -344,7 +343,7 @@ int XNextEvent(Display* display, XEvent* event) | |||||
| gCurrentWindowMapped = false; | gCurrentWindowMapped = false; | ||||
| if (gInterposedCallback != nullptr) | if (gInterposedCallback != nullptr) | ||||
| gInterposedCallback(1, nullptr); | |||||
| gInterposedCallback(LIBJACK_INTERPOSER_CALLBACK_UI_HIDE, nullptr); | |||||
| event->type = 0; | event->type = 0; | ||||
| carla_stdout("XNextEvent close event catched, hiding UI instead"); | carla_stdout("XNextEvent close event catched, hiding UI instead"); | ||||
| @@ -19,7 +19,7 @@ | |||||
| #define CARLA_LIBJACK_API_H_INCLUDED | #define CARLA_LIBJACK_API_H_INCLUDED | ||||
| #include "CarlaLibJackHints.h" | #include "CarlaLibJackHints.h" | ||||
| #include "jackbridge/JackBridge.hpp" | |||||
| #include "../jackbridge/JackBridge.hpp" | |||||
| #include <pthread.h> | #include <pthread.h> | ||||
| @@ -213,7 +213,7 @@ void jack_set_transport_info(jack_client_t*, void*); | |||||
| #define JACK_UUID_SIZE 36 | #define JACK_UUID_SIZE 36 | ||||
| #define JACK_UUID_STRING_SIZE (JACK_UUID_SIZE+1) /* includes trailing null */ | #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_client_uuid_generate(); | ||||
| jack_uuid_t jack_port_uuid_generate(uint32_t port_id); | jack_uuid_t jack_port_uuid_generate(uint32_t port_id); | ||||
| @@ -25,12 +25,22 @@ | |||||
| // --------------------------------------------------------------------------------------------------------------------- | // --------------------------------------------------------------------------------------------------------------------- | ||||
| typedef int (*CarlaInterposedCallback)(int, void*); | |||||
| CARLA_EXPORT | CARLA_EXPORT | ||||
| int jack_carla_interposed_action(uint, uint, void*) | 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; | return 1337; | ||||
| } | } | ||||
| @@ -111,10 +121,12 @@ class CarlaJackAppClient : public CarlaJackRealtimeThread::Callback, | |||||
| public: | public: | ||||
| JackServerState fServer; | JackServerState fServer; | ||||
| LinkedList<JackClientState*> fClients; | LinkedList<JackClientState*> fClients; | ||||
| LinkedList<JackClientState*> fNewClients; | |||||
| CarlaJackAppClient() | CarlaJackAppClient() | ||||
| : fServer(this), | : fServer(this), | ||||
| fClients(), | fClients(), | ||||
| fNewClients(), | |||||
| fShmAudioPool(), | fShmAudioPool(), | ||||
| fShmRtClientControl(), | fShmRtClientControl(), | ||||
| fShmNonRtClientControl(), | fShmNonRtClientControl(), | ||||
| @@ -133,6 +145,9 @@ public: | |||||
| fRealtimeThread(this), | fRealtimeThread(this), | ||||
| fNonRealtimeThread(this), | fNonRealtimeThread(this), | ||||
| fRealtimeThreadMutex() | fRealtimeThreadMutex() | ||||
| #ifdef DEBUG | |||||
| ,leakDetector_CarlaJackAppClient() | |||||
| #endif | |||||
| { | { | ||||
| carla_debug("CarlaJackAppClient::CarlaJackAppClient()"); | carla_debug("CarlaJackAppClient::CarlaJackAppClient()"); | ||||
| @@ -172,8 +187,13 @@ public: | |||||
| fSessionManager = static_cast<uint>(libjackSetup[4] - '0'); | fSessionManager = static_cast<uint>(libjackSetup[4] - '0'); | ||||
| fSetupHints = static_cast<uint>(libjackSetup[5] - '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); | fNonRealtimeThread.startThread(false); | ||||
| } | } | ||||
| @@ -223,6 +243,11 @@ public: | |||||
| if (! fClients.append(jclient)) | if (! fClients.append(jclient)) | ||||
| return false; | return false; | ||||
| if (! fNewClients.append(jclient)) | |||||
| { | |||||
| fClients.removeOne(jclient); | |||||
| return false; | |||||
| } | |||||
| jclient->activated = true; | jclient->activated = true; | ||||
| jclient->deactivated = false; | jclient->deactivated = false; | ||||
| @@ -252,7 +277,7 @@ public: | |||||
| switch (cb_action) | switch (cb_action) | ||||
| { | { | ||||
| case 1: { | |||||
| case LIBJACK_INTERPOSER_CALLBACK_UI_HIDE: { | |||||
| const CarlaMutexLocker cml(fShmNonRtServerControl.mutex); | const CarlaMutexLocker cml(fShmNonRtServerControl.mutex); | ||||
| fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerUiClosed); | fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerUiClosed); | ||||
| fShmNonRtServerControl.commitWrite(); | fShmNonRtServerControl.commitWrite(); | ||||
| @@ -457,6 +482,20 @@ void CarlaJackAppClient::clearSharedMemory() noexcept | |||||
| bool CarlaJackAppClient::handleRtData() | 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); | const BridgeRtClientControl::WaitHelper helper(fShmRtClientControl); | ||||
| if (! helper.ok) | if (! helper.ok) | ||||
| @@ -192,6 +192,9 @@ struct JackClientState { | |||||
| JackSyncCallback syncCb; | JackSyncCallback syncCb; | ||||
| void* syncCbPtr; | void* syncCbPtr; | ||||
| JackThreadInitCallback threadInitCb; | |||||
| void* threadInitCbPtr; | |||||
| JackClientState(const JackServerState& s, const char* const n) | JackClientState(const JackServerState& s, const char* const n) | ||||
| : server(s), | : server(s), | ||||
| mutex(), | mutex(), | ||||
| @@ -216,7 +219,9 @@ struct JackClientState { | |||||
| sampleRateCb(nullptr), | sampleRateCb(nullptr), | ||||
| sampleRateCbPtr(nullptr), | sampleRateCbPtr(nullptr), | ||||
| syncCb(nullptr), | syncCb(nullptr), | ||||
| syncCbPtr(nullptr) {} | |||||
| syncCbPtr(nullptr), | |||||
| threadInitCb(nullptr), | |||||
| threadInitCbPtr(nullptr) {} | |||||
| ~JackClientState() | ~JackClientState() | ||||
| { | { | ||||
| @@ -24,8 +24,15 @@ CARLA_BACKEND_USE_NAMESPACE | |||||
| CARLA_EXPORT | CARLA_EXPORT | ||||
| int jack_set_thread_init_callback(jack_client_t* client, JackThreadInitCallback callback, void* arg) | 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; | 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 | 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 | 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; | return -1; | ||||
| (void)value; | |||||
| (void)type; | |||||
| } | } | ||||
| CARLA_EXPORT | CARLA_EXPORT | ||||
| @@ -77,21 +123,43 @@ int jack_get_all_properties(jack_description_t**) | |||||
| } | } | ||||
| CARLA_EXPORT | 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; | return -1; | ||||
| (void)uuid; | |||||
| (void)key; | |||||
| } | } | ||||
| CARLA_EXPORT | 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 | CARLA_EXPORT | ||||
| int jack_remove_all_properties(jack_client_t*) | int jack_remove_all_properties(jack_client_t*) | ||||
| { | { | ||||
| return -1; | |||||
| // sMetadata = {}; | |||||
| return 0; | |||||
| } | } | ||||
| CARLA_EXPORT | CARLA_EXPORT | ||||
| @@ -105,56 +173,76 @@ int jack_set_property_change_callback(jack_client_t*, JackPropertyChangeCallback | |||||
| CARLA_EXPORT | CARLA_EXPORT | ||||
| jack_uuid_t jack_client_uuid_generate() | 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 | 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 | 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 | 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 | 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 | CARLA_EXPORT | ||||
| void jack_uuid_clear(jack_uuid_t*) | |||||
| void jack_uuid_clear(jack_uuid_t* uuid) | |||||
| { | { | ||||
| *uuid = JACK_UUID_EMPTY_INITIALIZER; | |||||
| } | } | ||||
| CARLA_EXPORT | 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; | return 0; | ||||
| } | } | ||||
| CARLA_EXPORT | 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 | 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; | |||||
| } | } | ||||
| // -------------------------------------------------------------------------------------------------------------------- | // -------------------------------------------------------------------------------------------------------------------- | ||||