Browse Source

TESTING: Run NTK events on separate thread

gh-pages
falkTX 10 years ago
parent
commit
68d3e353cc
3 changed files with 201 additions and 37 deletions
  1. +168
    -37
      dgl/ntk/NtkApp.hpp
  2. +25
    -0
      distrho/DistrhoUIMain.cpp
  3. +8
    -0
      distrho/src/DistrhoUIInternal.hpp

+ 168
- 37
dgl/ntk/NtkApp.hpp View File

@@ -18,6 +18,8 @@
#define DGL_NTK_APP_HPP_INCLUDED

#include "../Base.hpp"
#include "../../distrho/DistrhoUI.hpp"
#include "../../distrho/extra/d_thread.hpp"

#ifdef override
# define override_defined
@@ -35,36 +37,65 @@
# undef override_defined
#endif

struct ScopedDisplayLock {
ScopedDisplayLock()
{
#ifdef DISTRHO_OS_LINUX
XLockDisplay(fl_display);
#endif
}

~ScopedDisplayLock()
{
#ifdef DISTRHO_OS_LINUX
XUnlockDisplay(fl_display);
#endif
}
};

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

namespace DISTRHO_NAMESPACE {
class UI;
}

START_NAMESPACE_DGL

class NtkWindow;

typedef DISTRHO_NAMESPACE::Mutex d_Mutex;
typedef DISTRHO_NAMESPACE::MutexLocker d_MutexLocker;
typedef DISTRHO_NAMESPACE::Thread d_Thread;
typedef DISTRHO_NAMESPACE::UI d_UI;

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

/**
DGL compatible App class that uses NTK instead of OpenGL.
@see App
*/
class NtkApp
class NtkApp : d_Thread
{
public:
/**
Constructor.
*/
NtkApp()
: fIsRunning(true),
fWindows()
: d_Thread("NtkApp"),
fWindows(),
fWindowMutex(),
fNextUI(),
fDoNextUI(false),
fInitialized(false)
{
static bool initialized = false;

if (! initialized)
{
initialized = true;
fl_register_images();
#ifdef DISTRHO_OS_LINUX
fl_open_display();
//XInitThreads();
#endif
}

startThread();

for (; ! fInitialized;)
d_msleep(10);
}

/**
@@ -72,20 +103,15 @@ public:
*/
~NtkApp()
{
DISTRHO_SAFE_ASSERT(! fIsRunning);

stopThread(-1);
fWindows.clear();
}

/**
Idle function.
This calls the NTK event-loop once (and all idle callbacks).
This calls does nothing.
*/
void idle()
{
Fl::check();
Fl::flush();
}
void idle() {}

/**
Run the application event-loop until all Windows are closed.
@@ -93,9 +119,8 @@ public:
*/
void exec()
{
fIsRunning = true;
Fl::run();
fIsRunning = false;
while (isThreadRunning() && ! shouldThreadExit())
d_sleep(1);
}

/**
@@ -104,13 +129,7 @@ public:
*/
void quit()
{
fIsRunning = false;

for (std::list<Fl_Double_Window*>::reverse_iterator rit = fWindows.rbegin(), rite = fWindows.rend(); rit != rite; ++rit)
{
Fl_Double_Window* const window(*rit);
window->hide();
}
signalThreadShouldExit();
}

/**
@@ -119,23 +138,91 @@ public:
*/
bool isQuiting() const noexcept
{
return !fIsRunning;
if (isThreadRunning() && ! shouldThreadExit())
return false;
return true;
}

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

/**
Create UI on our separate thread.
Blocks until the UI is created and returns it.
*/
d_UI* createUI(void* const func)
{
DISTRHO_SAFE_ASSERT_RETURN(isThreadRunning(), nullptr);
DISTRHO_SAFE_ASSERT_RETURN(! fDoNextUI, nullptr);

fNextUI.create = true;
fNextUI.func = (NextUI::UiFunc)func;
fDoNextUI = true;

for (; fDoNextUI;)
d_msleep(10);

return fNextUI.ui;
}

/**
Delete UI on our separate thread.
Blocks until the UI is deleted.
*/
void deleteUI(d_UI* const ui)
{
DISTRHO_SAFE_ASSERT_RETURN(! fDoNextUI,);

fNextUI.create = false;
fNextUI.ui = ui;
fDoNextUI = true;

if (isThreadRunning())
{
for (; fDoNextUI;)
d_msleep(10);
}
else
{
fNextUI.run();
fDoNextUI = false;
}
}

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

private:
bool fIsRunning;
std::list<Fl_Double_Window*> fWindows;
struct NextUI {
typedef d_UI* (*UiFunc)();

friend class NtkWindow;
bool create;

union {
UiFunc func;
d_UI* ui;
};

NextUI()
: create(false),
func(nullptr) {}

void run();
};

std::list<Fl_Double_Window*> fWindows;
d_Mutex fWindowMutex;
NextUI fNextUI;
volatile bool fDoNextUI;
volatile bool fInitialized;

/** @internal used by NtkWindow. */
void addWindow(Fl_Double_Window* const window)
{
DISTRHO_SAFE_ASSERT_RETURN(window != nullptr,);

if (fWindows.size() == 0)
fIsRunning = true;
if (fWindows.size() == 0 && ! isThreadRunning())
startThread();

const d_MutexLocker sl(fWindowMutex);
fWindows.push_back(window);
}

@@ -144,15 +231,59 @@ private:
{
DISTRHO_SAFE_ASSERT_RETURN(window != nullptr,);

const d_MutexLocker sl(fWindowMutex);
fWindows.remove(window);

if (fWindows.size() == 0)
fIsRunning = false;
signalThreadShouldExit();
}

/** @internal */
void run() override
{
static bool initialized = false;

if (! initialized)
{
initialized = true;
fl_register_images();
#ifdef DISTRHO_OS_LINUX
fl_open_display();
#endif
}

fInitialized = true;

for (; ! shouldThreadExit();)
{
if (fDoNextUI)
{
const ScopedDisplayLock csdl;
fNextUI.run();
fDoNextUI = false;
}

const ScopedDisplayLock csdl;
Fl::check();
Fl::flush();

d_msleep(20);
}

const d_MutexLocker sl(fWindowMutex);
const ScopedDisplayLock csdl;

for (std::list<Fl_Double_Window*>::reverse_iterator rit = fWindows.rbegin(), rite = fWindows.rend(); rit != rite; ++rit)
{
Fl_Double_Window* const window(*rit);
window->hide();
}
}

friend class NtkWindow;

DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(NtkApp)
};

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

END_NAMESPACE_DGL


+ 25
- 0
distrho/DistrhoUIMain.cpp View File

@@ -27,3 +27,28 @@
#elif defined(DISTRHO_PLUGIN_TARGET_VST)
// nothing
#endif

#ifdef DGL_NTK_APP_HPP_INCLUDED

START_NAMESPACE_DGL

void NtkApp::NextUI::run()
{
if (create)
{
d_stdout("Creating NTK UI in separate thread...");
d_UI* const ui2 = (func)();
ui = ui2;
}
else
{
d_stdout("Destroying NTK UI in separate thread...");
d_UI* const ui2 = ui;
ui = nullptr;
delete ui2;
}
}

END_NAMESPACE_DGL

#endif

+ 8
- 0
distrho/src/DistrhoUIInternal.hpp View File

@@ -141,7 +141,11 @@ UI* createUiWrapper(void* const dspPtr, UIWindow* const window)
{
d_lastUiDspPtr = dspPtr;
d_lastUiWindow = window;
#if DISTRHO_UI_USE_NTK
UI* const ret = window->getApp().createUI((void*)createUI);
#else
UI* const ret = createUI();
#endif
d_lastUiDspPtr = nullptr;
d_lastUiWindow = nullptr;
return ret;
@@ -164,7 +168,11 @@ public:

~UIExporterWindow()
{
#if DISTRHO_UI_USE_NTK
getApp().deleteUI(fUI);
#else
delete fUI;
#endif
}

UI* getUI() const noexcept


Loading…
Cancel
Save