CarlaBridgeUI::~CarlaBridgeUI() /*noexcept*/ { carla_debug("CarlaBridgeUI::~CarlaBridgeUI()"); if (fLib != nullptr) { lib_close(fLib); fLib = nullptr; } if (isPipeRunning() && ! fQuitReceived) { const CarlaMutexLocker cml(getPipeLock()); writeMessage("exiting\n", 8); flushMessages(); } if (fToolkit != nullptr) { fToolkit->quit(); delete fToolkit; fToolkit = nullptr; } closePipeClient(); }
static inline const char* getPluginTypeAsString(const PluginType& type) { carla_debug("CarlaBackend::getPluginTypeAsString(%s)", PluginType2Str(type)); switch (type) { case PLUGIN_NONE: return "NONE"; case PLUGIN_INTERNAL: return "INTERNAL"; case PLUGIN_LADSPA: return "LADSPA"; case PLUGIN_DSSI: return "DSSI"; case PLUGIN_LV2: return "LV2"; case PLUGIN_VST: return "VST"; case PLUGIN_VST3: return "VST3"; case PLUGIN_GIG: return "GIG"; case PLUGIN_SF2: return "SF2"; case PLUGIN_SFZ: return "SFZ"; } carla_stderr("CarlaBackend::getPluginTypeAsString(%i) - invalid type", type); return "NONE"; }
void CarlaEngineThread::startNow() { carla_debug("CarlaEngineThread::startNow()"); CARLA_ASSERT(fStopNow); fStopNow = false; start(); }
CARLA_BACKEND_START_NAMESPACE // ----------------------------------------------------------------------- CarlaEngineThread::CarlaEngineThread(CarlaEngine* const engine) : kEngine(engine), fStopNow(true) { carla_debug("CarlaEngineThread::CarlaEngineThread(%p)", engine); CARLA_ASSERT(engine != nullptr); }
CARLA_BACKEND_START_NAMESPACE // ----------------------------------------------------------------------- CarlaEngineThread::CarlaEngineThread(CarlaEngine* const engine) noexcept : CarlaThread("CarlaEngineThread"), kEngine(engine) { CARLA_SAFE_ASSERT(engine != nullptr); carla_debug("CarlaEngineThread::CarlaEngineThread(%p)", engine); }
void CarlaEngineThread::stopNow() { carla_debug("CarlaEngineThread::stopNow()"); if (fStopNow) return; fStopNow = true; const CarlaMutex::ScopedLocker sl(fMutex); if (isRunning() && ! wait(500)) terminate(); }
CARLA_EXPORT int XUnmapWindow(Display* display, Window window) { carla_debug("XUnmapWindow(%p, %lu)", display, window); if (gCurrentlyMappedWindow == window) { gCurrentlyMappedDisplay = nullptr; gCurrentlyMappedWindow = 0; gCurrentWindowType = WindowMapNone; gCurrentWindowMapped = false; gCurrentWindowVisible = false; if (gInterposedCallback != nullptr) gInterposedCallback(1, nullptr); } return real_XUnmapWindow(display, window); }
CARLA_BRIDGE_START_NAMESPACE // --------------------------------------------------------------------- CarlaBridgeUI::CarlaBridgeUI() noexcept : CarlaPipeClient(), fQuitReceived(false), fGotOptions(false), fLastMsgTimer(-1), fToolkit(nullptr), fLib(nullptr), fLibFilename() { carla_debug("CarlaBridgeUI::CarlaBridgeUI()"); try { fToolkit = CarlaBridgeToolkit::createNew(this); } CARLA_SAFE_EXCEPTION_RETURN("CarlaBridgeToolkit::createNew",); }
static inline PluginType getPluginTypeFromString(const char* const ctype) noexcept { CARLA_SAFE_ASSERT_RETURN(ctype != nullptr && ctype[0] != '\0', PLUGIN_NONE); carla_debug("CarlaBackend::getPluginTypeFromString(\"%s\")", ctype); CarlaString stype(ctype); if (stype.isEmpty()) return PLUGIN_NONE; stype.toLower(); if (stype == "none") return PLUGIN_NONE; if (stype == "internal") return PLUGIN_INTERNAL; if (stype == "ladspa") return PLUGIN_LADSPA; if (stype == "dssi") return PLUGIN_DSSI; if (stype == "lv2") return PLUGIN_LV2; if (stype == "vst") return PLUGIN_VST; if (stype == "vst3") return PLUGIN_VST3; if (stype == "au") return PLUGIN_AU; if (stype == "gig") return PLUGIN_GIG; if (stype == "sf2") return PLUGIN_SF2; if (stype == "sfz") return PLUGIN_SFZ; carla_stderr("CarlaBackend::getPluginTypeFromString(\"%s\") - invalid string type", ctype); return PLUGIN_NONE; }
static inline PluginType getPluginTypeFromString(const char* const stype) { CARLA_ASSERT(stype != nullptr); carla_debug("CarlaBackend::getPluginTypeFromString(\"%s\")", stype); if (stype == nullptr) { carla_stderr("CarlaBackend::getPluginTypeFromString() - null string type"); return PLUGIN_NONE; } if (std::strcmp(stype, "NONE") == 0) return PLUGIN_NONE; if (std::strcmp(stype, "INTERNAL") == 0 || std::strcmp(stype, "Internal") == 0) return PLUGIN_INTERNAL; if (std::strcmp(stype, "LADSPA") == 0) return PLUGIN_LADSPA; if (std::strcmp(stype, "DSSI") == 0) return PLUGIN_DSSI; if (std::strcmp(stype, "LV2") == 0) return PLUGIN_LV2; if (std::strcmp(stype, "VST") == 0) return PLUGIN_VST; if (std::strcmp(stype, "VST3") == 0) return PLUGIN_VST3; if (std::strcmp(stype, "GIG") == 0) return PLUGIN_GIG; if (std::strcmp(stype, "SF2") == 0) return PLUGIN_SF2; if (std::strcmp(stype, "SFZ") == 0) return PLUGIN_SFZ; carla_stderr("CarlaBackend::getPluginTypeFromString(\"%s\") - invalid string type", stype); return PLUGIN_NONE; }
static void test_CarlaUtils() { // ---------------------------------------------------------------------------------------------------------------- // misc functions { bool2str(false); bool2str(true); pass(); char strBuf[2]; nullStrBuf(strBuf); char* const strBuf2(strBuf+1); nullStrBuf(strBuf2); } // ---------------------------------------------------------------------------------------------------------------- // string print functions { carla_debug("DEBUG"); carla_stdout("STDOUT %s", bool2str(true)); carla_stderr("STDERR %s", bool2str(false)); carla_stderr2("STDERR2 " P_UINT64, 0xffffffff); // 4294967295 } // ---------------------------------------------------------------------------------------------------------------- // carla_*sleep { carla_sleep(1); carla_msleep(1); } // ---------------------------------------------------------------------------------------------------------------- // carla_setenv { carla_setenv("THIS", "THAT"); assert(std::strcmp(std::getenv("THIS"), "THAT") == 0); carla_unsetenv("THIS"); assert(std::getenv("THIS") == nullptr); } // ---------------------------------------------------------------------------------------------------------------- // carla_strdup { // with variables const char* const str1(carla_strdup("stringN")); const char* const strF(carla_strdup_free(strdup("stringF"))); const char* const str2(carla_strdup_safe("stringS")); delete[] str1; delete[] str2; delete[] strF; // without variables delete[] carla_strdup("string_normal"); delete[] carla_strdup_free(strdup("string_free")); delete[] carla_strdup_safe("string_safe"); } { // common use case in Carla code struct TestStruct { const char* strNull; const char* strNormal; const char* strFree; const char* strSafe; TestStruct() : strNull(nullptr), strNormal(carla_strdup("strNormal")), strFree(carla_strdup_free(strdup("strFree"))), strSafe(carla_strdup_safe("strSafe")) {} ~TestStruct() noexcept { if (strNull != nullptr) { delete[] strNull; strNull = nullptr; } if (strNormal != nullptr) { delete[] strNormal; strNormal = nullptr; } if (strFree != nullptr) { delete[] strFree; strFree = nullptr; } if (strSafe != nullptr) { delete[] strSafe; strSafe = nullptr; } } CARLA_DECLARE_NON_COPY_STRUCT(TestStruct) }; TestStruct a, b, c; } // ---------------------------------------------------------------------------------------------------------------- // memory functions { int a1[] = { 4, 3, 2, 1 }; int a2[] = { 4, 3, 2, 1 }; int b1[] = { 1, 2, 3, 4 }; int b2[] = { 1, 2, 3, 4 }; carla_add(a1, b1, 4); assert(a1[0] == 5); assert(a1[1] == 5); assert(a1[2] == 5); assert(a1[3] == 5); carla_add(b1, a2, 4); assert(b1[0] == 5); assert(b1[1] == 5); assert(b1[2] == 5); assert(b1[3] == 5); assert(a1[0] == b1[0]); assert(a1[1] == b1[1]); assert(a1[2] == b1[2]); assert(a1[3] == b1[3]); carla_copy(a1, b2, 4); assert(a1[0] != b1[0]); assert(a1[1] != b1[1]); assert(a1[2] != b1[2]); assert(a1[3] != b1[3]); assert(a1[0] == b2[0]); assert(a1[1] == b2[1]); assert(a1[2] == b2[2]); assert(a1[3] == b2[3]); carla_copy(a1, b1, 4); assert(a1[0] == b1[0]); assert(a1[1] == b1[1]); assert(a1[2] == b1[2]); assert(a1[3] == b1[3]); carla_copy(a1, b2, 2); assert(a1[0] != b1[0]); assert(a1[1] != b1[1]); assert(a1[2] == b1[2]); assert(a1[3] == b1[3]); carla_copy(a1+2, b2+2, 2); assert(a1[0] != b1[0]); assert(a1[1] != b1[1]); assert(a1[2] != b1[2]); assert(a1[3] != b1[3]); carla_copy(a1, b1, 2); assert(a1[0] == b1[0]); assert(a1[1] == b1[1]); assert(a1[2] != b1[2]); assert(a1[3] != b1[3]); carla_copy(a1+2, b1+2, 2); assert(a1[0] == b1[0]); assert(a1[1] == b1[1]); assert(a1[2] == b1[2]); assert(a1[3] == b1[3]); carla_fill(a1, 0, 4); assert(a1[0] == 0); assert(a1[1] == 0); assert(a1[2] == 0); assert(a1[3] == 0); carla_fill(a1, -11, 4); assert(a1[0] == -11); assert(a1[1] == -11); assert(a1[2] == -11); assert(a1[3] == -11); carla_fill(a1, 1791, 2); assert(a1[0] == 1791); assert(a1[1] == 1791); assert(a1[2] == -11); assert(a1[3] == -11); carla_fill(a1+2, 1791, 2); assert(a1[0] == 1791); assert(a1[1] == 1791); assert(a1[2] == 1791); assert(a1[3] == 1791); int16_t d = 1527, e = 0; carla_add(&d, &d, 1); assert(d == 1527*2); carla_add(&d, &d, 1); assert(d == 1527*4); carla_add(&d, &e, 1); assert(d == 1527*4); assert(e == 0); carla_add(&e, &d, 1); assert(d == e); carla_add(&e, &d, 1); assert(e == d*2); d = -e; carla_add(&d, &e, 1); assert(d == 0); } { bool x; const bool f = false, t = true; carla_copy(&x, &t, 1); assert(x); carla_copy(&x, &f, 1); assert(! x); carla_fill(&x, true, 1); assert(x); carla_fill(&x, false, 1); assert(! x); } { uint8_t a[] = { 3, 2, 1, 0 }; carla_zeroBytes(a, 1); assert(a[0] == 0); assert(a[1] == 2); assert(a[2] == 1); assert(a[3] == 0); carla_zeroBytes(a+1, 2); assert(a[0] == 0); assert(a[1] == 0); assert(a[2] == 0); assert(a[3] == 0); } { char a[501]; for (int i=500; --i>=0;) a[i] = 'a'; carla_zeroChars(a, 501); for (int i=501; --i>=0;) assert(a[i] == '\0'); for (int i=500; --i>=0;) a[i] = 'a'; assert(std::strlen(a) == 500); carla_fill(a+200, '\0', 1); assert(std::strlen(a) == 200); } { void* a[33]; carla_zeroPointers(a, 33); for (int i=33; --i>=0;) assert(a[i] == nullptr); } { struct Thing { char c; int i; int64_t h; bool operator==(const Thing& t) const noexcept { return (t.c == c && t.i == i && t.h == h); } bool operator!=(const Thing& t) const noexcept { return !operator==(t); } }; Thing a, b, c; a.c = 0; a.i = 0; a.h = 0; b.c = 64; b.i = 64; b.h = 64; c = a; carla_copyStruct(a, b); assert(a == b); carla_zeroStruct(a); assert(a == c); carla_copyStruct(c, b); assert(a != c); // make it non-zero a.c = 1; Thing d[3]; carla_zeroStructs(d, 3); assert(d[0] != a); assert(d[1] != b); assert(d[2] != c); carla_copyStructs(d, &a, 1); assert(d[0] == a); assert(d[1] != b); assert(d[2] != c); carla_copyStructs(&c, d+2, 1); assert(d[0] == a); assert(d[1] != b); assert(d[2] == c); } }
static inline PluginCategory getPluginCategoryFromName(const char* const name) { CARLA_ASSERT(name != nullptr); carla_debug("CarlaBackend::getPluginCategoryFromName(\"%s\")", name); if (name == nullptr) { carla_stderr("CarlaBackend::getPluginCategoryFromName() - null name"); return PLUGIN_CATEGORY_NONE; } CarlaString sname(name); if (sname.isEmpty()) return PLUGIN_CATEGORY_NONE; sname.toLower(); // generic tags first if (sname.contains("delay")) return PLUGIN_CATEGORY_DELAY; if (sname.contains("reverb")) return PLUGIN_CATEGORY_DELAY; // filter if (sname.contains("filter")) return PLUGIN_CATEGORY_FILTER; // dynamics if (sname.contains("dynamics")) return PLUGIN_CATEGORY_DYNAMICS; if (sname.contains("amplifier")) return PLUGIN_CATEGORY_DYNAMICS; if (sname.contains("compressor")) return PLUGIN_CATEGORY_DYNAMICS; if (sname.contains("enhancer")) return PLUGIN_CATEGORY_DYNAMICS; if (sname.contains("exciter")) return PLUGIN_CATEGORY_DYNAMICS; if (sname.contains("gate")) return PLUGIN_CATEGORY_DYNAMICS; if (sname.contains("limiter")) return PLUGIN_CATEGORY_DYNAMICS; // modulator if (sname.contains("modulator")) return PLUGIN_CATEGORY_MODULATOR; if (sname.contains("chorus")) return PLUGIN_CATEGORY_MODULATOR; if (sname.contains("flanger")) return PLUGIN_CATEGORY_MODULATOR; if (sname.contains("phaser")) return PLUGIN_CATEGORY_MODULATOR; if (sname.contains("saturator")) return PLUGIN_CATEGORY_MODULATOR; // utility if (sname.contains("utility")) return PLUGIN_CATEGORY_UTILITY; if (sname.contains("analyzer")) return PLUGIN_CATEGORY_UTILITY; if (sname.contains("converter")) return PLUGIN_CATEGORY_UTILITY; if (sname.contains("deesser")) return PLUGIN_CATEGORY_UTILITY; if (sname.contains("mixer")) return PLUGIN_CATEGORY_UTILITY; // common tags if (sname.contains("verb")) return PLUGIN_CATEGORY_DELAY; if (sname.contains("eq")) return PLUGIN_CATEGORY_EQ; if (sname.contains("tool")) return PLUGIN_CATEGORY_UTILITY; return PLUGIN_CATEGORY_NONE; }
CARLA_EXPORT int XMapRaised(Display* display, Window window) { carla_debug("XMapRaised(%p, %lu)", display, window); return carlaWindowMap(display, window, WindowMapRaised); }
CARLA_EXPORT int XMapWindow(Display* display, Window window) { carla_debug("XMapWindow(%p, %lu)", display, window); return carlaWindowMap(display, window, WindowMapNormal); }
bool CarlaBridgeUI::msgReceived(const char* const msg) noexcept { carla_debug("CarlaBridgeUI::msgReceived(\"%s\")", msg); if (! fGotOptions && std::strcmp(msg, "urid") != 0 && std::strcmp(msg, "uiOptions") != 0) { carla_stderr2("CarlaBridgeUI::msgReceived(\"%s\") - invalid message while waiting for options", msg); return true; } if (fLastMsgTimer > 0) --fLastMsgTimer; if (std::strcmp(msg, "control") == 0) { uint32_t index; float value; CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(index), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value), true); dspParameterChanged(index, value); return true; } if (std::strcmp(msg, "program") == 0) { uint32_t index; CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(index), true); dspProgramChanged(index); return true; } if (std::strcmp(msg, "midiprogram") == 0) { uint32_t bank, program; CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(bank), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(program), true); dspMidiProgramChanged(bank, program); return true; } if (std::strcmp(msg, "configure") == 0) { const char* key; const char* value; CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(key), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(value), true); dspStateChanged(key, value); delete[] key; delete[] value; return true; } if (std::strcmp(msg, "note") == 0) { bool onOff; uint8_t channel, note, velocity; CARLA_SAFE_ASSERT_RETURN(readNextLineAsBool(onOff), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsByte(channel), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsByte(note), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsByte(velocity), true); dspNoteReceived(onOff, channel, note, velocity); return true; } if (std::strcmp(msg, "atom") == 0) { uint32_t index, atomTotalSize; const char* base64atom; CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(index), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(atomTotalSize), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(base64atom), true); std::vector<uint8_t> chunk(carla_getChunkFromBase64String(base64atom)); delete[] base64atom; CARLA_SAFE_ASSERT_RETURN(chunk.size() >= sizeof(LV2_Atom), true); const LV2_Atom* const atom((const LV2_Atom*)chunk.data()); const uint32_t atomTotalSizeCheck(lv2_atom_total_size(atom)); CARLA_SAFE_ASSERT_RETURN(atomTotalSizeCheck == atomTotalSize, true); CARLA_SAFE_ASSERT_RETURN(atomTotalSizeCheck == chunk.size(), true); dspAtomReceived(index, atom); return true; } if (std::strcmp(msg, "urid") == 0) { uint32_t urid; const char* uri; CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(urid), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(uri), true); if (urid != 0) dspURIDReceived(urid, uri); delete[] uri; return true; } if (std::strcmp(msg, "uiOptions") == 0) { double sampleRate; bool useTheme, useThemeColors; const char* windowTitle; uint64_t transientWindowId; CARLA_SAFE_ASSERT_RETURN(readNextLineAsDouble(sampleRate), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsBool(useTheme), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsBool(useThemeColors), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(windowTitle), true); CARLA_SAFE_ASSERT_RETURN(readNextLineAsULong(transientWindowId), true); fGotOptions = true; uiOptionsChanged(sampleRate, useTheme, useThemeColors, windowTitle, static_cast<uintptr_t>(transientWindowId)); delete[] windowTitle; return true; } CARLA_SAFE_ASSERT_RETURN(fToolkit != nullptr, true); if (std::strcmp(msg, "show") == 0) { fToolkit->show(); return true; } if (std::strcmp(msg, "focus") == 0) { fToolkit->focus(); return true; } if (std::strcmp(msg, "hide") == 0) { fToolkit->hide(); return true; } if (std::strcmp(msg, "quit") == 0) { fQuitReceived = true; fToolkit->quit(); delete fToolkit; fToolkit = nullptr; return true; } if (std::strcmp(msg, "uiTitle") == 0) { const char* title; CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(title), true); fToolkit->setTitle(title); delete[] title; return true; } carla_stderr("CarlaBridgeUI::msgReceived : %s", msg); return false; }
CARLA_EXPORT int XMapSubwindows(Display* display, Window window) { carla_debug("XMapSubwindows(%p, %lu)", display, window); return carlaWindowMap(display, window, WindowMapSubwindows); }
CarlaEngineThread::~CarlaEngineThread() noexcept { carla_debug("CarlaEngineThread::~CarlaEngineThread()"); }
CARLA_EXPORT int jack_carla_interposed_action(int action, int value, void* ptr) { carla_debug("jack_carla_interposed_action(%i, %i, %p)", action, value, ptr); switch (action) { case 1: // set hints and callback gInterposedHints = value; gInterposedCallback = (CarlaInterposedCallback)ptr; return 1; case 2: // session manager gInterposedSessionManager = value; return 1; case 3: // show gui if (value != 0) { gCurrentWindowVisible = true; if (gCurrentlyMappedDisplay == nullptr || gCurrentlyMappedWindow == 0) return 0; gCurrentWindowMapped = true; switch (gCurrentWindowType) { case WindowMapNormal: return real_XMapWindow(gCurrentlyMappedDisplay, gCurrentlyMappedWindow); case WindowMapRaised: return real_XMapRaised(gCurrentlyMappedDisplay, gCurrentlyMappedWindow); case WindowMapSubwindows: return real_XMapSubwindows(gCurrentlyMappedDisplay, gCurrentlyMappedWindow); default: return 0; } } // hide gui else { gCurrentWindowVisible = false; if (gCurrentlyMappedDisplay == nullptr || gCurrentlyMappedWindow == 0) return 0; gCurrentWindowMapped = false; return real_XUnmapWindow(gCurrentlyMappedDisplay, gCurrentlyMappedWindow); } break; case 4: // close everything gCurrentWindowType = WindowMapNone; gCurrentWindowMapped = false; gCurrentWindowVisible = false; gCurrentlyMappedDisplay = nullptr; gCurrentlyMappedWindow = 0; return 0; } return -1; }
void CarlaEngineThread::run() { carla_debug("CarlaEngineThread::run()"); CARLA_ASSERT(kEngine->isRunning()); bool oscRegisted, usesSingleThread; unsigned int i, count; float value; while (kEngine->isRunning() && ! fStopNow) { const CarlaMutex::ScopedLocker sl(fMutex); #ifdef BUILD_BRIDGE oscRegisted = kEngine->isOscBridgeRegistered(); #else oscRegisted = kEngine->isOscControlRegistered(); #endif for (i=0, count = kEngine->currentPluginCount(); i < count; ++i) { CarlaPlugin* const plugin = kEngine->getPluginUnchecked(i); if (plugin == nullptr || ! plugin->enabled()) continue; CARLA_SAFE_ASSERT_INT2(i == plugin->id(), i, plugin->id()); usesSingleThread = (plugin->hints() & PLUGIN_HAS_SINGLE_THREAD); // ------------------------------------------------------- // Process postponed events if (oscRegisted || ! usesSingleThread) { if (! usesSingleThread) plugin->postRtEventsRun(); // --------------------------------------------------- // Update parameter outputs for (uint32_t j=0; j < plugin->parameterCount(); ++j) { if (! plugin->parameterIsOutput(j)) continue; value = plugin->getParameterValue(j); // Update UI if (! usesSingleThread) plugin->uiParameterChange(j, value); // Update OSC engine client if (oscRegisted) { #ifdef BUILD_BRIDGE kEngine->osc_send_bridge_set_parameter_value(j, value); #else kEngine->osc_send_control_set_parameter_value(i, j, value); #endif } } #ifndef BUILD_BRIDGE // --------------------------------------------------- // Update OSC control client peaks if (oscRegisted) kEngine->osc_send_control_set_peaks(i); #endif } } kEngine->idleOsc(); carla_msleep(oscRegisted ? 30 : 50); } }
static int carlaWindowMap(Display* const display, const Window window, const WindowMappingType fallbackFnType) { const ScopedLibOpen& slo(ScopedLibOpen::getInstance()); for (;;) { if (slo.winId < 0) break; Atom atom; int atomFormat; unsigned char* atomPtrs; unsigned long numItems, ignored; const Atom wmWindowType = XInternAtom(display, "_NET_WM_WINDOW_TYPE", False); if (XGetWindowProperty(display, window, wmWindowType, 0, ~0L, False, AnyPropertyType, &atom, &atomFormat, &numItems, &ignored, &atomPtrs) != Success) { carla_debug("carlaWindowMap(%p, %lu, %i) - XGetWindowProperty failed", display, window, fallbackFnType); break; } const Atom* const atomValues = (const Atom*)atomPtrs; bool isMainWindow = (numItems == 0); for (ulong i=0; i<numItems; ++i) { const char* const atomValue(XGetAtomName(display, atomValues[i])); CARLA_SAFE_ASSERT_CONTINUE(atomValue != nullptr && atomValue[0] != '\0'); if (std::strcmp(atomValue, "_NET_WM_WINDOW_TYPE_COMBO" ) == 0 || std::strcmp(atomValue, "_NET_WM_WINDOW_TYPE_DIALOG" ) == 0 || std::strcmp(atomValue, "_NET_WM_WINDOW_TYPE_DND" ) == 0 || std::strcmp(atomValue, "_NET_WM_WINDOW_TYPE_DOCK" ) == 0 || std::strcmp(atomValue, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU") == 0 || std::strcmp(atomValue, "_NET_WM_WINDOW_TYPE_MENU" ) == 0 || std::strcmp(atomValue, "_NET_WM_WINDOW_TYPE_NOTIFICATION" ) == 0 || std::strcmp(atomValue, "_NET_WM_WINDOW_TYPE_POPUP_MENU" ) == 0 || std::strcmp(atomValue, "_NET_WM_WINDOW_TYPE_SPLASH" ) == 0 || std::strcmp(atomValue, "_NET_WM_WINDOW_TYPE_TOOLBAR" ) == 0 || std::strcmp(atomValue, "_NET_WM_WINDOW_TYPE_TOOLTIP" ) == 0 || std::strcmp(atomValue, "_NET_WM_WINDOW_TYPE_UTILITY" ) == 0) { isMainWindow = false; continue; } if (std::strcmp(atomValue, "_NET_WM_WINDOW_TYPE_NORMAL") == 0) { // window is good, use it if no other types are set isMainWindow = true; } else { carla_stdout("=======================================> %s", atomValue); } } if (! isMainWindow) { // this has always bothered me... if (gCurrentlyMappedWindow != 0 && gCurrentWindowMapped && gCurrentWindowVisible) XSetTransientForHint(display, window, gCurrentlyMappedWindow); break; } Window transientWindow = 0; if (XGetTransientForHint(display, window, &transientWindow) == Success && transientWindow != 0) { carla_stdout("Window has transient set already, ignoring it"); break; } // got a new window, we may need to forget last one if (gCurrentlyMappedDisplay != nullptr && gCurrentlyMappedWindow != 0) { // ignore requests against the current mapped window if (gCurrentlyMappedWindow == window) return 0; // we already have a mapped window, with carla visible button on, should be a dialog of sorts.. if (gCurrentWindowMapped && gCurrentWindowVisible) { XSetTransientForHint(display, window, gCurrentlyMappedWindow); break; } // ignore empty windows created after the main one if (numItems == 0) break; carla_stdout("NOTICE: XMapWindow now showing previous window"); switch (gCurrentWindowType) { case WindowMapNone: break; case WindowMapNormal: real_XMapWindow(gCurrentlyMappedDisplay, gCurrentlyMappedWindow); break; case WindowMapRaised: real_XMapRaised(gCurrentlyMappedDisplay, gCurrentlyMappedWindow); break; case WindowMapSubwindows: real_XMapSubwindows(gCurrentlyMappedDisplay, gCurrentlyMappedWindow); break; } } gCurrentlyMappedDisplay = display; gCurrentlyMappedWindow = window; gCurrentWindowMapped = true; gCurrentWindowType = fallbackFnType; if (slo.winId > 0) XSetTransientForHint(display, window, static_cast<Window>(slo.winId)); if (gCurrentWindowVisible) { carla_stdout("JACK application window found, showing it now"); break; } gCurrentWindowMapped = false; carla_stdout("JACK application window found and captured"); return 0; } carla_debug("carlaWindowMap(%p, %lu, %i) - not captured", display, window, fallbackFnType); switch (fallbackFnType) { case 1: return real_XMapWindow(display, window); case 2: return real_XMapRaised(display, window); case 3: return real_XMapSubwindows(display, window); default: return 0; } }
CarlaEngineThread::~CarlaEngineThread() { carla_debug("CarlaEngineThread::~CarlaEngineThread()"); CARLA_ASSERT(fStopNow); }