Skip to content

Commit

Permalink
Merge pull request #109 from jpcima/vst-bitwig-hack
Browse files Browse the repository at this point in the history
VST stupid hack to make Bitwig Linux work
  • Loading branch information
jpcima authored Mar 12, 2020
2 parents eb587bf + d763ebd commit 74f7290
Show file tree
Hide file tree
Showing 7 changed files with 245 additions and 144 deletions.
5 changes: 4 additions & 1 deletion vst/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ set (VSTPLUGIN_BUNDLE_NAME "${PROJECT_NAME}.vst3")
set (VST3SDK_BASEDIR "${CMAKE_CURRENT_SOURCE_DIR}/external/VST_SDK/VST3_SDK")
set (VST3SDK_ARCHIVE "vst-sdk_3.6.14_build-24_2019-11-29.zip")

file (MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/external")

if (NOT EXISTS "${VST3SDK_BASEDIR}")
message (STATUS "VST3 SDK is not found, downloading")

Expand Down Expand Up @@ -41,7 +43,8 @@ add_library(${VSTPLUGIN_PRJ_NAME} MODULE
SfizzVstEditor.cpp
SfizzVstState.cpp
GUIComponents.cpp
VstPluginFactory.cpp)
VstPluginFactory.cpp
X11RunLoop.cpp)

if(WIN32)
target_sources(${VSTPLUGIN_PRJ_NAME} PRIVATE vst3.def)
Expand Down
45 changes: 39 additions & 6 deletions vst/SfizzVstEditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@
#include "SfizzVstState.h"
#include "GUIComponents.h"
#if !defined(__APPLE__) && !defined(_WIN32)
#include "x11runloop.h"
#include "X11RunLoop.h"
#endif

using namespace VSTGUI;

static ViewRect sfizzUiViewRect {0, 0, 684, 684};

SfizzVstEditor::SfizzVstEditor(void *controller)
: VSTGUIEditor(controller),
: VSTGUIEditor(controller, &sfizzUiViewRect),
_logo("logo.png")
{
getController()->addSfizzStateListener(this);
Expand All @@ -29,15 +31,17 @@ bool PLUGIN_API SfizzVstEditor::open(void* parent, const VSTGUI::PlatformType& p
{
fprintf(stderr, "[sfizz] about to open view with parent %p\n", parent);

CRect wsize(0, 0, _logo.getWidth(), _logo.getHeight());
CRect wsize(0, 0, sfizzUiViewRect.getWidth(), sfizzUiViewRect.getHeight());
CFrame *frame = new CFrame(wsize, this);
this->frame = frame;

IPlatformFrameConfig* config = nullptr;

#if !defined(__APPLE__) && !defined(_WIN32)
X11::FrameConfig x11config;
x11config.runLoop = VSTGUI::owned(new RunLoop(plugFrame));
if (!_runLoop)
_runLoop = new RunLoop(plugFrame);
x11config.runLoop = _runLoop;
config = &x11config;
#endif

Expand All @@ -56,8 +60,13 @@ void PLUGIN_API SfizzVstEditor::close()
{
CFrame *frame = this->frame;
if (frame) {
frame->forget();
this->frame = nullptr;
frame->removeAll();
if (frame->getNbReference() != 1)
frame->forget ();
else {
frame->close();
this->frame = nullptr;
}
}
}

Expand Down Expand Up @@ -134,6 +143,30 @@ void SfizzVstEditor::controlEndEdit(CControl* ctl)
enterOrLeaveEdit(ctl, false);
}

CMessageResult SfizzVstEditor::notify(CBaseObject* sender, const char* message)
{
CMessageResult result = VSTGUIEditor::notify(sender, message);

if (result != kMessageNotified)
return result;

#if !defined(__APPLE__) && !defined(_WIN32)
if (message == CVSTGUITimer::kMsgTimer) {
SharedPointer<VSTGUI::RunLoop> runLoop = RunLoop::get();
if (runLoop) {
// note(jpc) I don't find a reliable way to check if the host
// notifier of X11 events is working. If there is, remove this and
// avoid polluting Linux hosts which implement the loop correctly.
runLoop->processSomeEvents();

runLoop->cleanupDeadHandlers();
}
}
#endif

return result;
}

void SfizzVstEditor::onStateChanged()
{
updateStateDisplay();
Expand Down
10 changes: 10 additions & 0 deletions vst/SfizzVstEditor.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
#pragma once
#include "SfizzVstController.h"
#include "public.sdk/source/vst/vstguieditor.h"
#if !defined(__APPLE__) && !defined(_WIN32)
namespace VSTGUI { class RunLoop; }
#endif

using namespace Steinberg;
using namespace VSTGUI;
Expand All @@ -30,6 +33,9 @@ class SfizzVstEditor : public Vst::VSTGUIEditor, public IControlListener, public
void controlBeginEdit(CControl* ctl) override;
void controlEndEdit(CControl* ctl) override;

// VSTGUIEditor
CMessageResult notify(CBaseObject* sender, const char* message) override;

// SfizzVstController::StateListener
void onStateChanged() override;

Expand Down Expand Up @@ -75,4 +81,8 @@ class SfizzVstEditor : public Vst::VSTGUIEditor, public IControlListener, public
CSliderBase *_numVoicesSlider = nullptr;
CSliderBase *_oversamplingSlider = nullptr;
CSliderBase *_preloadSizeSlider = nullptr;

#if !defined(__APPLE__) && !defined(_WIN32)
SharedPointer<RunLoop> _runLoop;
#endif
};
145 changes: 145 additions & 0 deletions vst/X11RunLoop.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
// SPDX-License-Identifier: GPL-3.0

#if !defined(__APPLE__) && !defined(_WIN32)
#include "X11RunLoop.h"
#include "vstgui/lib/platform/linux/x11platform.h"
#include "base/source/fobject.h"

namespace VSTGUI {

RunLoop::RunLoop(Steinberg::FUnknown* runLoop)
: runLoop(runLoop)
{
}

RunLoop::~RunLoop() {}

SharedPointer<RunLoop> RunLoop::get()
{
return X11::RunLoop::get().cast<VSTGUI::RunLoop>();
}

struct RunLoop::EventHandler final : Steinberg::Linux::IEventHandler, public Steinberg::FObject {
X11::IEventHandler* handler { nullptr };
bool alive { false };

void PLUGIN_API onFDIsSet(Steinberg::Linux::FileDescriptor) override
{
if (alive && handler)
handler->onEvent();
}

DELEGATE_REFCOUNT(Steinberg::FObject)
DEFINE_INTERFACES
DEF_INTERFACE(Steinberg::Linux::IEventHandler)
END_DEFINE_INTERFACES(Steinberg::FObject)
};

struct RunLoop::TimerHandler final : Steinberg::Linux::ITimerHandler, public Steinberg::FObject {
X11::ITimerHandler* handler { nullptr };
bool alive { false };

void PLUGIN_API onTimer() override
{
if (alive && handler)
handler->onTimer();
}

DELEGATE_REFCOUNT(Steinberg::FObject)
DEFINE_INTERFACES
DEF_INTERFACE(Steinberg::Linux::ITimerHandler)
END_DEFINE_INTERFACES(Steinberg::FObject)
};


void RunLoop::processSomeEvents()
{
for (size_t i = 0; i < eventHandlers.size(); ++i) {
const auto& eh = eventHandlers[i];
if (eh->alive && eh->handler) {
eh->handler->onEvent();
}
}
}

void RunLoop::cleanupDeadHandlers()
{
for (size_t i = 0; i < eventHandlers.size(); ++i) {
const auto& eh = eventHandlers[i];
if (!eh->alive) {
runLoop->unregisterEventHandler(eh);
eventHandlers.erase(eventHandlers.begin() + i--);
}
}
for (size_t i = 0; i < timerHandlers.size(); ++i) {
const auto& th = timerHandlers[i];
if (!th->alive) {
runLoop->unregisterTimer(th);
timerHandlers.erase(timerHandlers.begin() + i--);
}
}
}

bool RunLoop::registerEventHandler(int fd, X11::IEventHandler* handler)
{
if (!runLoop)
return false;

auto smtgHandler = Steinberg::owned(new EventHandler());
smtgHandler->handler = handler;
smtgHandler->alive = true;
if (runLoop->registerEventHandler(smtgHandler, fd) == Steinberg::kResultTrue) {
eventHandlers.push_back(smtgHandler);
return true;
}
return false;
}

bool RunLoop::unregisterEventHandler(X11::IEventHandler* handler)
{
if (!runLoop)
return false;

for (size_t i = 0; i < eventHandlers.size(); ++i) {
const auto& eh = eventHandlers[i];
if (eh->alive && eh->handler == handler) {
eh->alive = false;
return true;
}
}
return false;
}

bool RunLoop::registerTimer(uint64_t interval, X11::ITimerHandler* handler)
{
if (!runLoop)
return false;

auto smtgHandler = Steinberg::owned(new TimerHandler());
smtgHandler->handler = handler;
smtgHandler->alive = true;
if (runLoop->registerTimer(smtgHandler, interval) == Steinberg::kResultTrue) {
timerHandlers.push_back(smtgHandler);
return true;
}
return false;
}

bool RunLoop::unregisterTimer(X11::ITimerHandler* handler)
{
if (!runLoop)
return false;

for (size_t i = 0; i < timerHandlers.size(); ++i) {
const auto& th = timerHandlers[i];
if (th->alive && th->handler == handler) {
th->alive = false;
return true;
}
}
return false;
}

} // namespace VSTGUI

#endif
47 changes: 47 additions & 0 deletions vst/X11RunLoop.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// SPDX-License-Identifier: GPL-3.0
/*
This is a modified version the X11 run loop from vst3editor.cpp.
This version is edited to add more safeguards to protect against host bugs.
It also permits to call event processing externally in case the host has a
defective X11 event loop notifier.
*/

#pragma once
#if !defined(__APPLE__) && !defined(_WIN32)
#include "vstgui/lib/platform/linux/x11frame.h"
#include "pluginterfaces/gui/iplugview.h"

namespace VSTGUI {

class RunLoop final : public X11::IRunLoop, public AtomicReferenceCounted {
public:
explicit RunLoop(Steinberg::FUnknown* runLoop);
~RunLoop();

static SharedPointer<RunLoop> get();

void processSomeEvents();
void cleanupDeadHandlers();

// X11::IRunLoop
bool registerEventHandler(int fd, X11::IEventHandler* handler);
bool unregisterEventHandler(X11::IEventHandler* handler);
bool registerTimer(uint64_t interval, X11::ITimerHandler* handler);
bool unregisterTimer(X11::ITimerHandler* handler);

private:
struct EventHandler;
struct TimerHandler;

private:
using EventHandlers = std::vector<Steinberg::IPtr<EventHandler>>;
using TimerHandlers = std::vector<Steinberg::IPtr<TimerHandler>>;
EventHandlers eventHandlers;
TimerHandlers timerHandlers;
Steinberg::FUnknownPtr<Steinberg::Linux::IRunLoop> runLoop;
};

} // namespace VSTGUI

#endif
27 changes: 0 additions & 27 deletions vst/external/steinberg/LICENSE

This file was deleted.

Loading

0 comments on commit 74f7290

Please sign in to comment.