Browse Source

Support old linux vsts (eventProc)

tags/1.9.4
falkTX 10 years ago
parent
commit
a0248a3aa5
4 changed files with 132 additions and 23 deletions
  1. +40
    -2
      source/backend/engine/CarlaEngine.cpp
  2. +84
    -13
      source/backend/plugin/CarlaPluginUi.cpp
  3. +2
    -1
      source/backend/plugin/CarlaPluginUi.hpp
  4. +6
    -7
      source/backend/plugin/VstPlugin.cpp

+ 40
- 2
source/backend/engine/CarlaEngine.cpp View File

@@ -447,7 +447,9 @@ bool CarlaEngine::addPlugin(const BinaryType btype, const PluginType ptype, cons
else else
#endif // ! BUILD_BRIDGE #endif // ! BUILD_BRIDGE
{ {
#ifndef BUILD_BRIDGE
bool use16Outs; bool use16Outs;
#endif
setLastError("Invalid or unsupported plugin type"); setLastError("Invalid or unsupported plugin type");


switch (ptype) switch (ptype)
@@ -1217,8 +1219,44 @@ void CarlaEngine::callback(const EngineCallbackOpcode action, const uint pluginI
if (action == ENGINE_CALLBACK_IDLE) if (action == ENGINE_CALLBACK_IDLE)
pData->isIdling = true; pData->isIdling = true;
#ifdef BUILD_BRIDGE #ifdef BUILD_BRIDGE
else if (action == ENGINE_CALLBACK_UI_STATE_CHANGED && value1 != 1)
oscSend_bridge_configure("CarlaBridgeHideGUI", "");
else
{
switch (action)
{
case ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED:
CARLA_SAFE_ASSERT_BREAK(value1 >= 0);
oscSend_bridge_parameter_value(static_cast<uint>(value1), value3);
break;
case ENGINE_CALLBACK_PARAMETER_DEFAULT_CHANGED:
CARLA_SAFE_ASSERT_BREAK(value1 >= 0);
oscSend_bridge_default_value(static_cast<uint>(value1), value3);
break;
case ENGINE_CALLBACK_PARAMETER_MIDI_CC_CHANGED:
CARLA_SAFE_ASSERT_BREAK(value1 >= 0);
CARLA_SAFE_ASSERT_BREAK(value2 >= -1 && value2 <= 0x5F);
oscSend_bridge_parameter_midi_cc(static_cast<uint>(value1), static_cast<int16_t>(value2));
break;
case ENGINE_CALLBACK_PARAMETER_MIDI_CHANNEL_CHANGED:
CARLA_SAFE_ASSERT_BREAK(value1 >= 0);
CARLA_SAFE_ASSERT_BREAK(value2 >= 0 && value2 < MAX_MIDI_CHANNELS);
oscSend_bridge_parameter_midi_channel(static_cast<uint>(value1), static_cast<uint8_t>(value2));
break;
case ENGINE_CALLBACK_PROGRAM_CHANGED:
CARLA_SAFE_ASSERT_BREAK(value1 >= -1);
oscSend_bridge_current_program(value1);
break;
case ENGINE_CALLBACK_MIDI_PROGRAM_CHANGED:
CARLA_SAFE_ASSERT_BREAK(value1 >= -1);
oscSend_bridge_current_midi_program(value1);
break;
case ENGINE_CALLBACK_UI_STATE_CHANGED:
if (value1 != 1)
oscSend_bridge_configure("CarlaBridgeHideGUI", "");
break;
default:
break;
}
}
#endif #endif


if (pData->callback != nullptr) if (pData->callback != nullptr)


+ 84
- 13
source/backend/plugin/CarlaPluginUi.cpp View File

@@ -30,7 +30,16 @@
// ----------------------------------------------------- // -----------------------------------------------------
// X11 // X11


typedef void (*EventProcPtr)(XEvent* ev);

static const int X11Key_Escape = 9; static const int X11Key_Escape = 9;
static bool gErrorTriggered = false;

static int temporaryErrorHandler(Display*, XErrorEvent*)
{
gErrorTriggered = true;
return 0;
}


class X11PluginUi : public CarlaPluginUi class X11PluginUi : public CarlaPluginUi
{ {
@@ -39,7 +48,9 @@ public:
: CarlaPluginUi(cb), : CarlaPluginUi(cb),
fDisplay(nullptr), fDisplay(nullptr),
fWindow(0), fWindow(0),
fIsVisible(false)
fIsVisible(false),
fFirstShow(true),
fEventProc(nullptr)
{ {
fDisplay = XOpenDisplay(nullptr); fDisplay = XOpenDisplay(nullptr);
CARLA_SAFE_ASSERT_RETURN(fDisplay != nullptr,); CARLA_SAFE_ASSERT_RETURN(fDisplay != nullptr,);
@@ -66,11 +77,11 @@ public:
Atom wmDelete = XInternAtom(fDisplay, "WM_DELETE_WINDOW", True); Atom wmDelete = XInternAtom(fDisplay, "WM_DELETE_WINDOW", True);
XSetWMProtocols(fDisplay, fWindow, &wmDelete, 1); XSetWMProtocols(fDisplay, fWindow, &wmDelete, 1);


pid_t pid = getpid();
Atom _nwp = XInternAtom(fDisplay, "_NET_WM_PID", False);
const pid_t pid = getpid();
const Atom _nwp = XInternAtom(fDisplay, "_NET_WM_PID", False);
XChangeProperty(fDisplay, fWindow, _nwp, XA_CARDINAL, 32, PropModeReplace, (const uchar*)&pid, 1); XChangeProperty(fDisplay, fWindow, _nwp, XA_CARDINAL, 32, PropModeReplace, (const uchar*)&pid, 1);


Atom _nwi = XInternAtom(fDisplay, "_NET_WM_ICON", False);
const Atom _nwi = XInternAtom(fDisplay, "_NET_WM_ICON", False);
XChangeProperty(fDisplay, fWindow, _nwi, XA_CARDINAL, 32, PropModeReplace, (const uchar*)sCarlaX11Icon, sCarlaX11IconSize); XChangeProperty(fDisplay, fWindow, _nwi, XA_CARDINAL, 32, PropModeReplace, (const uchar*)sCarlaX11Icon, sCarlaX11IconSize);


if (parentId != 0) if (parentId != 0)
@@ -105,7 +116,34 @@ public:
CARLA_SAFE_ASSERT_RETURN(fDisplay != nullptr,); CARLA_SAFE_ASSERT_RETURN(fDisplay != nullptr,);
CARLA_SAFE_ASSERT_RETURN(fWindow != 0,); CARLA_SAFE_ASSERT_RETURN(fWindow != 0,);


if (fFirstShow)
{
if (const Window childWindow = getChildWindow())
{
const Atom _xevp = XInternAtom(fDisplay, "_XEventProc", False);

gErrorTriggered = false;
const XErrorHandler oldErrorHandler(XSetErrorHandler(temporaryErrorHandler));

Atom actualType;
int actualFormat;
ulong nitems, bytesAfter;
uchar* data = nullptr;

XGetWindowProperty(fDisplay, childWindow, _xevp, 0, 1, False, AnyPropertyType, &actualType, &actualFormat, &nitems, &bytesAfter, &data);
XSetErrorHandler(oldErrorHandler);

if (nitems == 1 && ! gErrorTriggered)
{
fEventProc = *reinterpret_cast<EventProcPtr*>(data);
XMapRaised(fDisplay, childWindow);
}
}
}

fIsVisible = true; fIsVisible = true;
fFirstShow = false;

XMapRaised(fDisplay, fWindow); XMapRaised(fDisplay, fWindow);
XFlush(fDisplay); XFlush(fDisplay);
} }
@@ -122,6 +160,11 @@ public:


void idle() override void idle() override
{ {
// prevent recursion
if (fIsIdling) return;

fIsIdling = true;

for (XEvent event; XPending(fDisplay) > 0;) for (XEvent event; XPending(fDisplay) > 0;)
{ {
XNextEvent(fDisplay, &event); XNextEvent(fDisplay, &event);
@@ -157,7 +200,11 @@ public:


if (type != nullptr) if (type != nullptr)
XFree(type); XFree(type);
else if (fEventProc != nullptr)
fEventProc(&event);
} }

fIsIdling = false;
} }


void focus() override void focus() override
@@ -219,10 +266,33 @@ public:
return fDisplay; return fDisplay;
} }


protected:
Window getChildWindow() const
{
CARLA_SAFE_ASSERT_RETURN(fDisplay != nullptr, 0);
CARLA_SAFE_ASSERT_RETURN(fWindow != 0, 0);

Window rootWindow, parentWindow, ret = 0;
Window* childWindows = nullptr;
uint numChildren = 0;

XQueryTree(fDisplay, fWindow, &rootWindow, &parentWindow, &childWindows, &numChildren);

if (numChildren > 0 && childWindows != nullptr)
{
ret = childWindows[0];
XFree(childWindows);
}

return ret;
}

private: private:
Display* fDisplay; Display* fDisplay;
Window fWindow; Window fWindow;
bool fIsVisible; bool fIsVisible;
bool fFirstShow;
EventProcPtr fEventProc;
}; };
#endif #endif


@@ -258,10 +328,10 @@ bool CarlaPluginUi::tryTransientWinIdMatch(const uintptr_t pid, const char* cons
const ScopedDisplay sd; const ScopedDisplay sd;
CARLA_SAFE_ASSERT_RETURN(sd.display != nullptr, true); CARLA_SAFE_ASSERT_RETURN(sd.display != nullptr, true);


Atom _ncl = XInternAtom(sd.display, "_NET_CLIENT_LIST" , False);
Atom _nwn = XInternAtom(sd.display, "_NET_WM_NAME", False);
Atom _nwp = XInternAtom(sd.display, "_NET_WM_PID", False);
Atom utf8 = XInternAtom(sd.display, "UTF8_STRING", True);
const Atom _ncl = XInternAtom(sd.display, "_NET_CLIENT_LIST" , False);
const Atom _nwn = XInternAtom(sd.display, "_NET_WM_NAME", False);
const Atom _nwp = XInternAtom(sd.display, "_NET_WM_PID", False);
const Atom utf8 = XInternAtom(sd.display, "UTF8_STRING", True);


Atom actualType; Atom actualType;
int actualFormat; int actualFormat;
@@ -360,13 +430,14 @@ bool CarlaPluginUi::tryTransientWinIdMatch(const uintptr_t pid, const char* cons
if (lastGoodWindow == 0) if (lastGoodWindow == 0)
return false; return false;


Atom _nwt = XInternAtom(sd.display ,"_NET_WM_STATE", False);
Atom _nws[2];
_nws[0] = XInternAtom(sd.display, "_NET_WM_STATE_SKIP_TASKBAR", False);
_nws[1] = XInternAtom(sd.display, "_NET_WM_STATE_SKIP_PAGER", False);
const Atom _nwt = XInternAtom(sd.display ,"_NET_WM_STATE", False);
const Atom _nws[2] = {
XInternAtom(sd.display, "_NET_WM_STATE_SKIP_TASKBAR", False),
XInternAtom(sd.display, "_NET_WM_STATE_SKIP_PAGER", False)
};
XChangeProperty(sd.display, lastGoodWindow, _nwt, XA_ATOM, 32, PropModeAppend, (const uchar*)_nws, 2); XChangeProperty(sd.display, lastGoodWindow, _nwt, XA_ATOM, 32, PropModeAppend, (const uchar*)_nws, 2);


Atom _nwi = XInternAtom(sd.display, "_NET_WM_ICON", False);
const Atom _nwi = XInternAtom(sd.display, "_NET_WM_ICON", False);
XChangeProperty(sd.display, lastGoodWindow, _nwi, XA_CARDINAL, 32, PropModeReplace, (const uchar*)sCarlaX11Icon, sCarlaX11IconSize); XChangeProperty(sd.display, lastGoodWindow, _nwi, XA_CARDINAL, 32, PropModeReplace, (const uchar*)sCarlaX11Icon, sCarlaX11IconSize);


XSetTransientForHint(sd.display, lastGoodWindow, (Window)winId); XSetTransientForHint(sd.display, lastGoodWindow, (Window)winId);


+ 2
- 1
source/backend/plugin/CarlaPluginUi.hpp View File

@@ -57,8 +57,9 @@ public:
#endif #endif


protected: protected:
bool fIsIdling;
CloseCallback* fCallback; CloseCallback* fCallback;
CarlaPluginUi(CloseCallback* const cb) noexcept : fCallback(cb) {}
CarlaPluginUi(CloseCallback* const cb) noexcept : fIsIdling(false), fCallback(cb) {}
}; };


// ----------------------------------------------------- // -----------------------------------------------------


+ 6
- 7
source/backend/plugin/VstPlugin.cpp View File

@@ -19,7 +19,7 @@
#include "CarlaEngine.hpp" #include "CarlaEngine.hpp"


#if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN) #if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)
# define USE_JUCE_FOR_VST 1
# define USE_JUCE_FOR_VST
#endif #endif


#ifndef USE_JUCE_FOR_VST #ifndef USE_JUCE_FOR_VST
@@ -1785,7 +1785,7 @@ protected:
{ {
#ifdef DEBUG #ifdef DEBUG
if (opcode != audioMasterGetTime) if (opcode != audioMasterGetTime)
carla_debug("VstPlugin::handleAudioMasterCallback(%02i:%s, %i, " P_INTPTR ", %p, %f)", opcode, vstEffectOpcode2str(opcode), index, value, ptr, opt);
carla_debug("VstPlugin::handleAudioMasterCallback(%02i:%s, %i, " P_INTPTR ", %p, %f)", opcode, vstMasterOpcode2str(opcode), index, value, ptr, opt);
#endif #endif


intptr_t ret = 0; intptr_t ret = 0;
@@ -1793,8 +1793,7 @@ protected:
switch (opcode) switch (opcode)
{ {
case audioMasterAutomate: { case audioMasterAutomate: {
if (! pData->enabled)
break;
CARLA_SAFE_ASSERT_BREAK(pData->enabled);


// plugins should never do this: // plugins should never do this:
CARLA_SAFE_ASSERT_INT(index >= 0 && index < static_cast<int32_t>(pData->param.count), index); CARLA_SAFE_ASSERT_INT(index >= 0 && index < static_cast<int32_t>(pData->param.count), index);
@@ -1835,8 +1834,8 @@ protected:
break; break;


case audioMasterIdle: case audioMasterIdle:
if (fUi.window != nullptr)
fUi.window->idle();
//pData->engine->callback(ENGINE_CALLBACK_IDLE, 0, 0, 0, 0.0f, nullptr);
//pData->engine->idle();
break; break;


#if ! VST_FORCE_DEPRECATED #if ! VST_FORCE_DEPRECATED
@@ -2543,7 +2542,7 @@ CarlaPlugin* CarlaPlugin::newVST(const Initializer& init)
{ {
carla_debug("CarlaPlugin::newVST({%p, \"%s\", \"%s\", " P_INT64 "})", init.engine, init.filename, init.name, init.uniqueId); carla_debug("CarlaPlugin::newVST({%p, \"%s\", \"%s\", " P_INT64 "})", init.engine, init.filename, init.name, init.uniqueId);


#if USE_JUCE_FOR_VST
#ifdef USE_JUCE_FOR_VST
return newJuce(init, "VST"); return newJuce(init, "VST");
#else #else
VstPlugin* const plugin(new VstPlugin(init.engine, init.id)); VstPlugin* const plugin(new VstPlugin(init.engine, init.id));


Loading…
Cancel
Save