Browse Source

Start rework of core UI class, special attention to size

Signed-off-by: falkTX <falktx@falktx.com>
pull/281/head
falkTX 4 years ago
parent
commit
358da5aa4d
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
10 changed files with 350 additions and 390 deletions
  1. +4
    -0
      dgl/Window.hpp
  2. +32
    -12
      distrho/DistrhoUI.hpp
  3. +3
    -0
      distrho/extra/ScopedPointer.hpp
  4. +4
    -6
      distrho/src/DistrhoPluginJack.cpp
  5. +2
    -7
      distrho/src/DistrhoPluginVST.cpp
  6. +43
    -77
      distrho/src/DistrhoUI.cpp
  7. +11
    -12
      distrho/src/DistrhoUIDSSI.cpp
  8. +107
    -246
      distrho/src/DistrhoUIInternal.hpp
  9. +9
    -7
      distrho/src/DistrhoUILV2.cpp
  10. +135
    -23
      distrho/src/DistrhoUIPrivateData.hpp

+ 4
- 0
dgl/Window.hpp View File

@@ -367,6 +367,10 @@ protected:
A function called when the window is attempted to be closed.
Returning true closes the window, which is the default behaviour.
Override this method and return false to prevent the window from being closed by the user.

This method is not used for embed windows, and not even made available in DISTRHO_NAMESPACE::UI.
For embed windows, closing is handled by the host/parent process and we have no control over it.
As such, a close action on embed windows will always succeed and cannot be cancelled.
*/
virtual bool onClose();



+ 32
- 12
distrho/DistrhoUI.hpp View File

@@ -237,26 +237,46 @@ protected:
* UI Callbacks (optional) */

/**
uiIdle.
@TODO Document this.
UI idle function, called to give idle time to the plugin UI directly from the host.
This is called right after OS event handling and Window idle events (within the same cycle).
There are no guarantees in terms of timing.
@see addIdleCallback(IdleCallback*, uint).
*/
virtual void uiIdle() {}

# ifndef DGL_FILE_BROWSER_DISABLED
/**
File browser selected function.
@see Window::onFileSelected(const char*)
Windows focus function, called when the window gains or loses the keyboard focus.
This function is for plugin UIs to be able to override Window::onFocus(bool, CrossingMode).

The default implementation does nothing.
*/
virtual void uiFileBrowserSelected(const char* filename);
# endif
virtual void uiFocus(bool focus, CrossingMode mode);

/**
OpenGL window reshape function, called when parent window is resized.
You can reimplement this function for a custom OpenGL state.
@see Window::onReshape(uint,uint)
Window reshape function, called when the window is resized.
This function is for plugin UIs to be able to override Window::onReshape(uint, uint).

The plugin UI size will be set right after this function.
The default implementation sets up drawing context where necessary.

You should almost never need to override this function.
The most common exception is custom OpenGL setup, but only really needed for custom OpenGL drawing code.
*/
virtual void uiReshape(uint width, uint height);

# ifndef DGL_FILE_BROWSER_DISABLED
/**
Window file selected function, called when a path is selected by the user, as triggered by openFileBrowser().
This function is for plugin UIs to be able to override Window::onFileSelected(const char*).

This action happens after the user confirms the action, so the file browser dialog will be closed at this point.
The default implementation does nothing.

If you need to use files as plugin state, please setup and use DISTRHO_PLUGIN_WANT_STATEFILES instead.
*/
virtual void uiFileBrowserSelected(const char* filename);
# endif

/* --------------------------------------------------------------------------------------------------------
* UI Resize Handling, internal */

@@ -265,7 +285,7 @@ protected:
This is overriden here so the host knows when the UI is resized by you.
@see Widget::onResize(const ResizeEvent&)
*/
void onResize(const ResizeEvent& ev) override;
// void onResize(const ResizeEvent& ev) override;
#endif

// -------------------------------------------------------------------------------------------------------
@@ -273,8 +293,8 @@ protected:
private:
struct PrivateData;
PrivateData* const uiData;
friend class PluginWindow;
friend class UIExporter;
friend class UIExporterWindow;

DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(UI)
};


+ 3
- 0
distrho/extra/ScopedPointer.hpp View File

@@ -145,6 +145,9 @@ public:
/** Returns the object that this ScopedPointer refers to. */
ObjectType* get() const noexcept { return object; }

/** Returns the object that this ScopedPointer refers to. */
ObjectType& getObject() const noexcept { return *object; }

/** Returns the object that this ScopedPointer refers to. */
ObjectType& operator*() const noexcept { return *object; }



+ 4
- 6
distrho/src/DistrhoPluginJack.cpp View File

@@ -17,7 +17,6 @@
#include "DistrhoPluginInternal.hpp"

#if DISTRHO_PLUGIN_HAS_UI
# define DISTRHO_UI_IS_STANDALONE true
# include "DistrhoUIInternal.hpp"
# include "../extra/RingBuffer.hpp"
#else
@@ -110,7 +109,9 @@ public:
PluginJack(jack_client_t* const client)
: fPlugin(this, writeMidiCallback, requestParameterValueChangeCallback),
#if DISTRHO_PLUGIN_HAS_UI
fUI(this, 0,
fUI(this,
0, // winId
d_lastSampleRate,
nullptr, // edit param
setParameterValueCallback,
setStateCallback,
@@ -301,7 +302,7 @@ protected:
}
}

fUI.exec_idle();
fUI.idle();
}
#endif

@@ -797,9 +798,6 @@ int main()

d_lastBufferSize = jack_get_buffer_size(client);
d_lastSampleRate = jack_get_sample_rate(client);
#if DISTRHO_PLUGIN_HAS_UI
d_lastUiSampleRate = d_lastSampleRate;
#endif

const PluginJack p(client);



+ 2
- 7
distrho/src/DistrhoPluginVST.cpp View File

@@ -25,7 +25,6 @@
#if DISTRHO_PLUGIN_HAS_UI
# undef DISTRHO_UI_USER_RESIZABLE
# define DISTRHO_UI_USER_RESIZABLE 0
# define DISTRHO_UI_IS_STANDALONE false
# include "DistrhoUIInternal.hpp"
# include "../extra/RingBuffer.hpp"
#endif
@@ -178,7 +177,7 @@ public:
fEffect(effect),
fUiHelper(uiHelper),
fPlugin(plugin),
fUI(this, winId,
fUI(this, winId, plugin->getSampleRate(),
editParameterCallback,
setParameterCallback,
setStateCallback,
@@ -671,9 +670,7 @@ public:
}
else
{
d_lastUiSampleRate = fPlugin.getSampleRate();

UIExporter tmpUI(nullptr, 0,
UIExporter tmpUI(nullptr, 0,fPlugin.getSampleRate(),
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
fPlugin.getInstancePointer(), fLastScaleFactor);
fVstRect.right = tmpUI.getWidth();
@@ -694,8 +691,6 @@ public:
return 0;
}
# endif
d_lastUiSampleRate = fPlugin.getSampleRate();

fVstUI = new UIVst(fAudioMaster, fEffect, this, &fPlugin, (intptr_t)ptr, fLastScaleFactor);

# if DISTRHO_PLUGIN_WANT_FULL_STATE


+ 43
- 77
distrho/src/DistrhoUI.cpp View File

@@ -20,71 +20,38 @@
# include "src/TopLevelWidgetPrivateData.hpp"
#endif

#include "NanoVG.hpp"

START_NAMESPACE_DISTRHO

/* ------------------------------------------------------------------------------------------------------------
* Static data, see DistrhoUIInternal.hpp and DistrhoUIPrivateData.hpp */
* Static data, see DistrhoUIInternal.hpp */

double d_lastUiSampleRate = 0.0;
void* d_lastUiDspPtr = nullptr;
#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
const char* g_nextBundlePath = nullptr;
double g_nextScaleFactor = 1.0;
uintptr_t g_nextWindowId = 0;
#else
Window* d_lastUiWindow = nullptr;
uintptr_t g_nextWindowId = 0;
double g_nextScaleFactor = 1.0;
const char* g_nextBundlePath = nullptr;
#endif

// -----------------------------------------------------------------------------------------------------------
/* ------------------------------------------------------------------------------------------------------------
* UI::PrivateData special handling */

#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
UI* createUiWrapper(void* const dspPtr, const uintptr_t winId, const double scaleFactor, const char* const bundlePath)
{
d_lastUiDspPtr = dspPtr;
g_nextWindowId = winId;
g_nextScaleFactor = scaleFactor;
g_nextBundlePath = bundlePath;
UI* const ret = createUI();
d_lastUiDspPtr = nullptr;
g_nextWindowId = 0;
g_nextScaleFactor = 1.0;
g_nextBundlePath = nullptr;
return ret;
}
#else
UI* createUiWrapper(void* const dspPtr, Window* const window)
{
d_lastUiDspPtr = dspPtr;
d_lastUiWindow = window;
UI* const ret = createUI();
d_lastUiDspPtr = nullptr;
d_lastUiWindow = nullptr;
return ret;
}
#endif // DISTRHO_PLUGIN_HAS_EXTERNAL_UI
UI::PrivateData* UI::PrivateData::s_nextPrivateData = nullptr;

PluginWindow& UI::PrivateData::createNextWindow(UI* const ui, const uint width, const uint height)
{
UI::PrivateData* const pData = s_nextPrivateData;
pData->window = new PluginWindow(ui, pData, width, height);
return pData->window.getObject();
}

/* ------------------------------------------------------------------------------------------------------------
* UI */

#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
UI::UI(uint width, uint height)
: UIWidget(width, height),
uiData(new PrivateData()) {}
#else
UI::UI(uint width, uint height)
: UIWidget(*d_lastUiWindow),
uiData(new PrivateData())
{
if (width > 0 && height > 0)
setSize(width, height);
}
#endif
UI::UI(const uint width, const uint height)
: UIWidget(UI::PrivateData::createNextWindow(this, width, height)),
uiData(UI::PrivateData::s_nextPrivateData) {}

UI::~UI()
{
delete uiData;
}

/* ------------------------------------------------------------------------------------------------------------
@@ -166,22 +133,22 @@ uintptr_t UI::getNextWindowId() noexcept
return g_nextWindowId;
}
# endif
#endif // DISTRHO_PLUGIN_HAS_EXTERNAL_UI
#endif

/* ------------------------------------------------------------------------------------------------------------
* DSP/Plugin Callbacks (optional) */

void UI::sampleRateChanged(double) {}
void UI::sampleRateChanged(double)
{
}

#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
/* ------------------------------------------------------------------------------------------------------------
* UI Callbacks (optional) */

# ifndef DGL_FILE_BROWSER_DISABLED
void UI::uiFileBrowserSelected(const char*)
void UI::uiFocus(bool, CrossingMode)
{
}
# endif

void UI::uiReshape(uint, uint)
{
@@ -189,33 +156,32 @@ void UI::uiReshape(uint, uint)
pData->fallbackOnResize();
}

/* ------------------------------------------------------------------------------------------------------------
* UI Resize Handling, internal */

void UI::onResize(const ResizeEvent& ev)
# ifndef DGL_FILE_BROWSER_DISABLED
void UI::uiFileBrowserSelected(const char*)
{
if (uiData->resizeInProgress)
return;

UIWidget::onResize(ev);
}
# endif

const uint width = ev.size.getWidth();
const uint height = ev.size.getHeight();
/* ------------------------------------------------------------------------------------------------------------
* UI Resize Handling, internal */

/*
pData->window.setSize(width, height);
*/
uiData->setSizeCallback(width, height);
}
// void UI::onResize(const ResizeEvent& ev)
// {
// if (uiData->resizeInProgress)
// return;
//
// UIWidget::onResize(ev);
//
// const uint width = ev.size.getWidth();
// const uint height = ev.size.getHeight();
//
// /*
// pData->window.setSize(width, height);
// */
// uiData->setSizeCallback(width, height);
// }
#endif // !DISTRHO_PLUGIN_HAS_EXTERNAL_UI

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

END_NAMESPACE_DISTRHO

// -----------------------------------------------------------------------
// Possible template data types

// template class NanoBaseWidget<SubWidget>;
// template class NanoBaseWidget<TopLevelWidget>;
// template class NanoBaseWidget<StandaloneWindow>;

+ 11
- 12
distrho/src/DistrhoUIDSSI.cpp View File

@@ -14,7 +14,6 @@
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

#define DISTRHO_UI_IS_STANDALONE true
#include "DistrhoUIInternal.hpp"

#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
@@ -97,8 +96,9 @@ struct OscData {
class UIDssi
{
public:
UIDssi(const OscData& oscData, const char* const uiTitle)
: fUI(this, 0, nullptr, setParameterCallback, setStateCallback, sendNoteCallback, setSizeCallback, nullptr),
UIDssi(const OscData& oscData, const char* const uiTitle, const double sampleRate)
: fUI(this, 0, sampleRate, nullptr,
setParameterCallback, setStateCallback, sendNoteCallback, setSizeCallback, nullptr),
fHostClosed(false),
fOscData(oscData)
{
@@ -252,16 +252,17 @@ private:
static OscData gOscData;
static const char* gUiTitle = nullptr;
static UIDssi* globalUI = nullptr;
static double sampleRate = 0.0;

static void initUiIfNeeded()
{
if (globalUI != nullptr)
return;

if (d_lastUiSampleRate == 0.0)
d_lastUiSampleRate = 44100.0;
if (sampleRate == 0.0)
sampleRate = 44100.0;

globalUI = new UIDssi(gOscData, gUiTitle);
globalUI = new UIDssi(gOscData, gUiTitle, sampleRate);
}

// -----------------------------------------------------------------------
@@ -337,10 +338,8 @@ int osc_program_handler(const char*, const char*, lo_arg** argv, int, lo_message

int osc_sample_rate_handler(const char*, const char*, lo_arg** argv, int, lo_message, void*)
{
const int32_t sampleRate = argv[0]->i;
d_debug("osc_sample_rate_handler(%i)", sampleRate);

d_lastUiSampleRate = sampleRate;
sampleRate = argv[0]->i;
d_debug("osc_sample_rate_handler(%f)", sampleRate);

if (globalUI != nullptr)
globalUI->dssiui_samplerate(sampleRate);
@@ -481,7 +480,7 @@ int main(int argc, char* argv[])
{
lo_server_recv(oscServer);

if (d_lastUiSampleRate != 0.0 || globalUI != nullptr)
if (sampleRate != 0.0 || globalUI != nullptr)
break;

d_msleep(50);
@@ -489,7 +488,7 @@ int main(int argc, char* argv[])

int ret = 1;

if (d_lastUiSampleRate != 0.0 || globalUI != nullptr)
if (sampleRate != 0.0 || globalUI != nullptr)
{
initUiIfNeeded();



+ 107
- 246
distrho/src/DistrhoUIInternal.hpp View File

@@ -21,13 +21,6 @@

#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
# include "../extra/Sleep.hpp"
using DGL_NAMESPACE::IdleCallback;
#else
# include "../../dgl/Application.hpp"
# include "../../dgl/Window.hpp"
using DGL_NAMESPACE::Application;
using DGL_NAMESPACE::IdleCallback;
using DGL_NAMESPACE::Window;
#endif

START_NAMESPACE_DISTRHO
@@ -35,121 +28,32 @@ START_NAMESPACE_DISTRHO
// -----------------------------------------------------------------------
// Static data, see DistrhoUI.cpp

extern double d_lastUiSampleRate;
extern void* d_lastUiDspPtr;
#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
extern const char* g_nextBundlePath;
extern double g_nextScaleFactor;
extern uintptr_t g_nextWindowId;
#else
extern Window* d_lastUiWindow;
#endif

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

#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
UI* createUiWrapper(void* const dspPtr, const uintptr_t winId, const double scaleFactor, const char* const bundlePath);
#else // DISTRHO_PLUGIN_HAS_EXTERNAL_UI
UI* createUiWrapper(void* const dspPtr, Window* const window);
#endif

#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
// -----------------------------------------------------------------------
// Plugin Application, will set class name based on plugin details

class PluginApplication : public Application
{
public:
PluginApplication()
: Application(DISTRHO_UI_IS_STANDALONE)
{
const char* const className = (
#ifdef DISTRHO_PLUGIN_BRAND
DISTRHO_PLUGIN_BRAND
#else
DISTRHO_MACRO_AS_STRING(DISTRHO_NAMESPACE)
extern double g_nextScaleFactor;
extern const char* g_nextBundlePath;
#endif
"-" DISTRHO_PLUGIN_NAME
);
setClassName(className);
}
};

// -----------------------------------------------------------------------
// Plugin Window, needed to take care of resize properly
// UI exporter class

class UIExporterWindow : public Window
class UIExporter
{
public:
UIExporterWindow(PluginApplication& app, const intptr_t winId, const double scaleFactor, void* const dspPtr)
: Window(app, winId, scaleFactor, DISTRHO_UI_USER_RESIZABLE),
fUI(createUiWrapper(dspPtr, this)),
fIsReady(false)
{
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(fUI->uiData != nullptr,);

setSize(fUI->getWidth(), fUI->getHeight());
}

~UIExporterWindow()
{
delete fUI;
}

UI* getUI() const noexcept
{
return fUI;
}

bool isReady() const noexcept
{
return fIsReady;
}

protected:
// custom window reshape
void onReshape(uint width, uint height) override
{
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);

UI::PrivateData* const uiData = fUI->uiData;
DISTRHO_SAFE_ASSERT_RETURN(uiData != nullptr,);

/*
uiData->resizeInProgress = true;
fUI->setSize(width, height);
uiData->resizeInProgress = false;
*/

fUI->uiReshape(width, height);
fIsReady = true;
}
// -------------------------------------------------------------------
// UI Widget and its private data

# ifndef DGL_FILE_BROWSER_DISABLED
// custom file-browser selected
void onFileSelected(const char* const filename) override
{
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);
UI* ui;
UI::PrivateData* uiData;

fUI->uiFileBrowserSelected(filename);
}
# endif
// prevent resize recursion
bool changingSizeRecursionCheck;

private:
UI* const fUI;
bool fIsReady;
};
#endif // DISTRHO_PLUGIN_HAS_EXTERNAL_UI

// -----------------------------------------------------------------------
// UI exporter class
// -------------------------------------------------------------------

class UIExporter
{
public:
UIExporter(void* const callbacksPtr,
const intptr_t winId,
const uintptr_t winId,
const double sampleRate,
const editParamFunc editParamCall,
const setParamFunc setParamCall,
const setStateFunc setStateCall,
@@ -161,139 +65,130 @@ public:
const double scaleFactor = 1.0,
const uint32_t bgColor = 0,
const uint32_t fgColor = 0xffffffff)
#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
: fUI(createUiWrapper(dspPtr, winId, scaleFactor, bundlePath)),
#else
: glApp(),
glWindow(glApp, winId, scaleFactor, dspPtr),
fChangingSize(false),
fUI(glWindow.getUI()),
#endif
fData((fUI != nullptr) ? fUI->uiData : nullptr)
: ui(nullptr),
uiData(new UI::PrivateData()),
changingSizeRecursionCheck(false)
{
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,);

fData->bgColor = bgColor;
fData->fgColor = fgColor;

fData->callbacksPtr = callbacksPtr;
fData->editParamCallbackFunc = editParamCall;
fData->setParamCallbackFunc = setParamCall;
fData->setStateCallbackFunc = setStateCall;
fData->sendNoteCallbackFunc = sendNoteCall;
fData->setSizeCallbackFunc = setSizeCall;
fData->fileRequestCallbackFunc = fileRequestCall;
uiData->sampleRate = sampleRate;
uiData->dspPtr = dspPtr;

uiData->bgColor = bgColor;
uiData->fgColor = fgColor;
#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
// unused
return; (void)bundlePath;
uiData->scaleFactor = scaleFactor;
uiData->winId = winId;
#endif
}

uiData->callbacksPtr = callbacksPtr;
uiData->editParamCallbackFunc = editParamCall;
uiData->setParamCallbackFunc = setParamCall;
uiData->setStateCallbackFunc = setStateCall;
uiData->sendNoteCallbackFunc = sendNoteCall;
uiData->setSizeCallbackFunc = setSizeCall;
uiData->fileRequestCallbackFunc = fileRequestCall;

#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
~UIExporter()
{
delete fUI;
}
g_nextWindowId = winId;
g_nextScaleFactor = scaleFactor;
g_nextBundlePath = bundlePath;
#endif
UI::PrivateData::s_nextPrivateData = uiData;

// -------------------------------------------------------------------
UI* const uiPtr = createUI();

#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
uint getWidth() const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr, 1);
return fUI->getWidth();
}
g_nextWindowId = 0;
g_nextScaleFactor = 0.0;
g_nextBundlePath = nullptr;
#endif
UI::PrivateData::s_nextPrivateData = nullptr;

uint getHeight() const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr, 1);
return fUI->getHeight();
}
DISTRHO_SAFE_ASSERT_RETURN(uiPtr != nullptr,);
ui = uiPtr;

bool isVisible() const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr, false);
return fUI->isRunning();
#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
// unused
(void)bundlePath;
#endif
}

uintptr_t getNativeWindowHandle() const noexcept
~UIExporter()
{
return 0;
delete ui;
delete uiData;
}
#else

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

uint getWidth() const noexcept
{
return glWindow.getWidth();
return uiData->window->getWidth();
}

uint getHeight() const noexcept
{
return glWindow.getHeight();
return uiData->window->getHeight();
}

bool isVisible() const noexcept
{
return glWindow.isVisible();
return uiData->window->isVisible();
}

uintptr_t getNativeWindowHandle() const noexcept
{
return glWindow.getNativeWindowHandle();
return uiData->window->getNativeWindowHandle();
}
#endif

uint getBackgroundColor() const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0);
DISTRHO_SAFE_ASSERT_RETURN(uiData != nullptr, 0);

return fData->bgColor;
return uiData->bgColor;
}

uint getForegroundColor() const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0xffffffff);
DISTRHO_SAFE_ASSERT_RETURN(uiData != nullptr, 0xffffffff);

return fData->fgColor;
return uiData->fgColor;
}

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

uint32_t getParameterOffset() const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0);
DISTRHO_SAFE_ASSERT_RETURN(uiData != nullptr, 0);

return fData->parameterOffset;
return uiData->parameterOffset;
}

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

void parameterChanged(const uint32_t index, const float value)
{
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,);

fUI->parameterChanged(index, value);
ui->parameterChanged(index, value);
}

#if DISTRHO_PLUGIN_WANT_PROGRAMS
void programLoaded(const uint32_t index)
{
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,);

fUI->programLoaded(index);
ui->programLoaded(index);
}
#endif

#if DISTRHO_PLUGIN_WANT_STATE
void stateChanged(const char* const key, const char* const value)
{
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
DISTRHO_SAFE_ASSERT_RETURN(value != nullptr,);

fUI->stateChanged(key, value);
ui->stateChanged(key, value);
}
#endif

@@ -303,12 +198,12 @@ public:
void exec(IdleCallback* const cb)
{
DISTRHO_SAFE_ASSERT_RETURN(cb != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,);

fUI->setVisible(true);
ui->setVisible(true);
cb->idleCallback();

while (fUI->isRunning())
while (ui->isRunning())
{
d_msleep(10);
cb->idleCallback();
@@ -330,49 +225,38 @@ public:

void quit()
{
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,);

fUI->setVisible(false);
fUI->terminateAndWaitForProcess();
ui->setVisible(false);
ui->terminateAndWaitForProcess();
}
#else
void exec(IdleCallback* const cb)
{
DISTRHO_SAFE_ASSERT_RETURN(cb != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);

glWindow.setVisible(true);
glApp.addIdleCallback(cb);
glApp.exec();
}

void exec_idle()
{
if (glWindow.isReady())
fUI->uiIdle();
uiData->window->show();
uiData->app.addIdleCallback(cb);
uiData->app.exec();
}

void focus()
{
glWindow.focus();
uiData->window->focus();
}

bool idle()
{
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr, false);
DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr, false);

glApp.idle();

if (glWindow.isReady())
fUI->uiIdle();

return ! glApp.isQuiting();
ui->uiIdle();
return ! uiData->app.isQuiting();
}

void quit()
{
glWindow.close();
glApp.quit();
uiData->window->close();
uiData->app.quit();
}

#endif
@@ -381,52 +265,46 @@ public:
#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
void setWindowTitle(const char* const uiTitle)
{
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,);

fUI->setTitle(uiTitle);
ui->setTitle(uiTitle);
}

void setWindowSize(const uint width, const uint height, const bool = false)
void setWindowSize(const uint width, const uint height)
{
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,);

fUI->setSize(width, height);
ui->setSize(width, height);
}

void setWindowTransientWinId(const uintptr_t winId)
{
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,);

fUI->setTransientWinId(winId);
ui->setTransientWinId(winId);
}

bool setWindowVisible(const bool yesNo)
{
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr, false);
DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr, false);

fUI->setVisible(yesNo);
ui->setVisible(yesNo);

return fUI->isRunning();
return ui->isRunning();
}
#else
void setWindowTitle(const char* const uiTitle)
{
glWindow.setTitle(uiTitle);
// glWindow.setTitle(uiTitle);
}

void setWindowSize(const uint width, const uint height, const bool updateUI = false)
void setWindowSize(const uint width, const uint height)
{
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(! fChangingSize,);

fChangingSize = true;
DISTRHO_SAFE_ASSERT_RETURN(! changingSizeRecursionCheck,);

if (updateUI)
fUI->setSize(width, height);

glWindow.setSize(width, height);

fChangingSize = false;
changingSizeRecursionCheck = true;
// glWindow.setSize(width, height);
changingSizeRecursionCheck = false;
}

void setWindowTransientWinId(const uintptr_t /*winId*/)
@@ -438,9 +316,10 @@ public:

bool setWindowVisible(const bool yesNo)
{
glWindow.setVisible(yesNo);
// glWindow.setVisible(yesNo);

return ! glApp.isQuiting();
// return ! glApp.isQuiting();
return true;
}

bool handlePluginKeyboard(const bool /*press*/, const uint /*key*/, const uint16_t /*mods*/)
@@ -464,37 +343,19 @@ public:

void setSampleRate(const double sampleRate, const bool doCallback = false)
{
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(uiData != nullptr,);
DISTRHO_SAFE_ASSERT(sampleRate > 0.0);

if (d_isEqual(fData->sampleRate, sampleRate))
if (d_isEqual(uiData->sampleRate, sampleRate))
return;

fData->sampleRate = sampleRate;
uiData->sampleRate = sampleRate;

if (doCallback)
fUI->sampleRateChanged(sampleRate);
ui->sampleRateChanged(sampleRate);
}

private:
#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
// -------------------------------------------------------------------
// DGL Application and Window for this widget

PluginApplication glApp;
UIExporterWindow glWindow;

// prevent recursion
bool fChangingSize;
#endif

// -------------------------------------------------------------------
// Widget and DistrhoUI data

UI* const fUI;
UI::PrivateData* const fData;

DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(UIExporter)
};



+ 9
- 7
distrho/src/DistrhoUILV2.cpp View File

@@ -14,7 +14,6 @@
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

#define DISTRHO_UI_IS_STANDALONE false
#include "DistrhoUIInternal.hpp"

#include "../extra/String.hpp"
@@ -73,10 +72,11 @@ public:
const LV2UI_Write_Function writeFunc,
LV2UI_Widget* const widget,
void* const dspPtr,
const float sampleRate,
const float scaleFactor,
const uint32_t bgColor,
const uint32_t fgColor)
: fUI(this, winId,
: fUI(this, winId, sampleRate,
editParameterCallback,
setParameterCallback,
setStateCallback,
@@ -208,7 +208,8 @@ public:

int lv2ui_resize(uint width, uint height)
{
fUI.setWindowSize(width, height, true);
// FIXME
// fUI.setWindowSize(width, height, true);
return 0;
}

@@ -526,6 +527,7 @@ static LV2UI_Handle lv2ui_instantiate(const LV2UI_Descriptor*,
#endif

const intptr_t winId = (intptr_t)parentId;
float sampleRate = 0.0f;
float scaleFactor = 1.0f;
uint32_t bgColor = 0;
uint32_t fgColor = 0xffffffff;
@@ -544,7 +546,7 @@ static LV2UI_Handle lv2ui_instantiate(const LV2UI_Descriptor*,
/**/ if (options[i].key == uridSampleRate)
{
if (options[i].type == uridAtomFloat)
d_lastUiSampleRate = *(const float*)options[i].value;
sampleRate = *(const float*)options[i].value;
else
d_stderr("Host provides UI sample-rate but has wrong value type");
}
@@ -572,15 +574,15 @@ static LV2UI_Handle lv2ui_instantiate(const LV2UI_Descriptor*,
}
}

if (d_lastUiSampleRate < 1.0)
if (sampleRate < 1.0)
{
d_stdout("WARNING: this host does not send sample-rate information for LV2 UIs, using 44100 as fallback (this could be wrong)");
d_lastUiSampleRate = 44100.0;
sampleRate = 44100.0;
}

return new UiLv2(bundlePath, winId, options, uridMap, features,
controller, writeFunction, widget, instance,
scaleFactor, bgColor, fgColor);
sampleRate, scaleFactor, bgColor, fgColor);
}

#define uiPtr ((UiLv2*)ui)


+ 135
- 23
distrho/src/DistrhoUIPrivateData.hpp View File

@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2020 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
@@ -18,14 +18,22 @@
#define DISTRHO_UI_PRIVATE_DATA_HPP_INCLUDED

#include "../DistrhoUI.hpp"
#include "../../dgl/Application.hpp"

START_NAMESPACE_DISTRHO
#ifndef DISTRHO_PLUGIN_HAS_EXTERNAL_UI
# include "../../dgl/Window.hpp"
#endif

// -----------------------------------------------------------------------
// Static data, see DistrhoUI.cpp
#if defined(DISTRHO_PLUGIN_TARGET_JACK) || defined(DISTRHO_PLUGIN_TARGET_DSSI)
# define DISTRHO_UI_IS_STANDALONE true
#else
# define DISTRHO_UI_IS_STANDALONE false
#endif

extern double d_lastUiSampleRate;
extern void* d_lastUiDspPtr;
START_NAMESPACE_DISTRHO

using DGL_NAMESPACE::Application;
using DGL_NAMESPACE::Window;

// -----------------------------------------------------------------------
// UI callbacks
@@ -37,24 +45,51 @@ typedef void (*sendNoteFunc) (void* ptr, uint8_t channel, uint8_t note, uint8
typedef void (*setSizeFunc) (void* ptr, uint width, uint height);
typedef bool (*fileRequestFunc) (void* ptr, const char* key);

// -----------------------------------------------------------------------
// Plugin Application, will set class name based on plugin details

class PluginApplication : public Application
{
public:
explicit PluginApplication()
: Application(DISTRHO_UI_IS_STANDALONE)
{
const char* const className = (
#ifdef DISTRHO_PLUGIN_BRAND
DISTRHO_PLUGIN_BRAND
#else
DISTRHO_MACRO_AS_STRING(DISTRHO_NAMESPACE)
#endif
"-" DISTRHO_PLUGIN_NAME
);
setClassName(className);
}

DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginApplication)
};

class PluginWindow;

// -----------------------------------------------------------------------
// UI private data

struct UI::PrivateData {
// DGL
PluginApplication app;
ScopedPointer<PluginWindow> window;

// DSP
double sampleRate;
uint32_t parameterOffset;
#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
void* dspPtr;
#endif

// UI
bool automaticallyScale;
bool resizeInProgress;
uint minWidth;
uint minHeight;
uint bgColor;
uint fgColor;
#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
double scaleFactor;
uintptr_t winId;
#endif

// Callbacks
void* callbacksPtr;
@@ -66,17 +101,19 @@ struct UI::PrivateData {
fileRequestFunc fileRequestCallbackFunc;

PrivateData() noexcept
: sampleRate(d_lastUiSampleRate),
parameterOffset(0),
#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
dspPtr(d_lastUiDspPtr),
: app(),
#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
window(nullptr),
#endif
automaticallyScale(false),
resizeInProgress(false),
minWidth(0),
minHeight(0),
sampleRate(0),
parameterOffset(0),
dspPtr(nullptr),
bgColor(0),
fgColor(0),
fgColor(0xffffffff),
#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
scaleFactor(1.0),
winId(0),
#endif
callbacksPtr(nullptr),
editParamCallbackFunc(nullptr),
setParamCallbackFunc(nullptr),
@@ -85,8 +122,6 @@ struct UI::PrivateData {
setSizeCallbackFunc(nullptr),
fileRequestCallbackFunc(nullptr)
{
DISTRHO_SAFE_ASSERT(d_isNotZero(sampleRate));

#if defined(DISTRHO_PLUGIN_TARGET_DSSI) || defined(DISTRHO_PLUGIN_TARGET_LV2)
parameterOffset += DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS;
# if DISTRHO_PLUGIN_WANT_LATENCY
@@ -143,7 +178,84 @@ struct UI::PrivateData {

return false;
}

static UI::PrivateData* s_nextPrivateData;
static PluginWindow& createNextWindow(UI* ui, uint width, uint height);
};

// -----------------------------------------------------------------------
// Plugin Window, will pass some Window events to UI

#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
// TODO external ui stuff
class PluginWindow
{
UI* const ui;

public:
explicit PluginWindow(UI* const uiPtr, UI::PrivateData* const pData, const uint width, const uint height)
: Window(pData->app, pData->winId, pData->scaleFactor, width, height, DISTRHO_UI_USER_RESIZABLE),
ui(uiPtr) {}

uint getWidth() const noexcept
{
return ui->getWidth();
}

uint getHeight() const noexcept
{
return ui->getHeight();
}

bool isVisible() const noexcept
{
return ui->isRunning();
}

uintptr_t getNativeWindowHandle() const noexcept
{
return 0;
}

DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginWindow)
};
#else
class PluginWindow : public Window
{
UI* const ui;

public:
explicit PluginWindow(UI* const uiPtr, UI::PrivateData* const pData, const uint width, const uint height)
: Window(pData->app, pData->winId, width, height, pData->scaleFactor, DISTRHO_UI_USER_RESIZABLE),
ui(uiPtr) {}

protected:
void onFocus(const bool focus, const CrossingMode mode) override
{
DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,);

ui->uiFocus(focus, mode);
}

void onReshape(const uint width, const uint height) override
{
DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,);

ui->uiReshape(width, height);
}

# ifndef DGL_FILE_BROWSER_DISABLED
void onFileSelected(const char* const filename) override
{
DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,);

ui->uiFileBrowserSelected(filename);
}
# endif

DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginWindow)
};
#endif // !DISTRHO_PLUGIN_HAS_EXTERNAL_UI

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



Loading…
Cancel
Save