Skip to content

Commit

Permalink
Pass parameter and touch UI events to LV2 host in main thread
Browse files Browse the repository at this point in the history
Fixes #52

Signed-off-by: falkTX <[email protected]>
  • Loading branch information
falkTX committed Jul 7, 2020
1 parent 4453ad0 commit a953bed
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,10 @@ class JuceLv2UIWrapper : public AudioProcessorListener,
public Timer
{
public:
#if JUCE_LINUX
static bool hostHasIdleInterface;
#endif

JuceLv2UIWrapper (AudioProcessor* filter_, LV2UI_Write_Function writeFunction_, LV2UI_Controller controller_,
LV2UI_Widget* widget, const LV2_Feature* const* features, bool isExternal_)
: filter (filter_),
Expand Down Expand Up @@ -527,13 +531,56 @@ class JuceLv2UIWrapper : public AudioProcessorListener,
}
}

int lv2Idle()
{
#if JUCE_LINUX
Array<IdleMessage> idleMessagesCopy;

{
const ScopedLock sl(idleMessagesLock);
idleMessages.swapWith(idleMessagesCopy);
}

for (auto& msg : idleMessagesCopy)
{
switch (msg.type)
{
case IdleMessage::kMessageParameterChanged:
writeFunction (controller, msg.index + controlPortOffset, sizeof (float), 0, &msg.value);
break;
case IdleMessage::kMessageGestureBegin:
uiTouch->touch (uiTouch->handle, msg.index + controlPortOffset, true);
break;
case IdleMessage::kMessageGestureEnd:
uiTouch->touch (uiTouch->handle, msg.index + controlPortOffset, false);
break;
}
}
#endif

return 0;
}

//==============================================================================
// Juce calls

void audioProcessorParameterChanged (AudioProcessor*, int index, float newValue)
{
if (writeFunction != nullptr && controller != nullptr)
if (writeFunction == nullptr || controller == nullptr)
return;

#if JUCE_LINUX
if (hostHasIdleInterface && ! isExternal)
{
const IdleMessage msg = { IdleMessage::kMessageParameterChanged, index, newValue };
const ScopedLock sl(idleMessagesLock);
idleMessages.add(msg);
}
else
#endif
{
writeFunction (controller, index + controlPortOffset, sizeof (float), 0, &newValue);
}
}

void audioProcessorChanged (AudioProcessor*)
Expand All @@ -552,14 +599,40 @@ class JuceLv2UIWrapper : public AudioProcessorListener,

void audioProcessorParameterChangeGestureBegin (AudioProcessor*, int parameterIndex)
{
if (uiTouch != nullptr)
if (uiTouch == nullptr)
return;

#if JUCE_LINUX
if (hostHasIdleInterface && ! isExternal)
{
const IdleMessage msg = { IdleMessage::kMessageGestureBegin, parameterIndex, 0.0f };
const ScopedLock sl(idleMessagesLock);
idleMessages.add(msg);
}
else
#endif
{
uiTouch->touch (uiTouch->handle, parameterIndex + controlPortOffset, true);
}
}

void audioProcessorParameterChangeGestureEnd (AudioProcessor*, int parameterIndex)
{
if (uiTouch != nullptr)
if (uiTouch == nullptr)
return;

#if JUCE_LINUX
if (hostHasIdleInterface && ! isExternal)
{
const IdleMessage msg = { IdleMessage::kMessageGestureEnd, parameterIndex, 0.0f };
const ScopedLock sl(idleMessagesLock);
idleMessages.add(msg);
}
else
#endif
{
uiTouch->touch (uiTouch->handle, parameterIndex + controlPortOffset, false);
}
}

void timerCallback()
Expand Down Expand Up @@ -639,9 +712,21 @@ class JuceLv2UIWrapper : public AudioProcessorListener,
ScopedPointer<JuceLv2ParentContainer> parentContainer;
const LV2UI_Resize* uiResize;

#if JUCE_LINUX
#if JUCE_LINUX
struct IdleMessage {
enum {
kMessageParameterChanged,
kMessageGestureBegin,
kMessageGestureEnd,
} type;
int index;
float value;
};
Array<IdleMessage> idleMessages;
CriticalSection idleMessagesLock;

ScopedXDisplay display;
#endif
#endif

//==============================================================================
void resetExternalUI (const LV2_Feature* const* features)
Expand Down Expand Up @@ -712,6 +797,9 @@ class JuceLv2UIWrapper : public AudioProcessorListener,
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JuceLv2UIWrapper)
};

#if JUCE_LINUX
bool JuceLv2UIWrapper::hostHasIdleInterface = false;
#endif
#endif /* JUCE_AUDIOPROCESSOR_NO_GUI */

//==============================================================================
Expand Down Expand Up @@ -1694,6 +1782,29 @@ static void juceLV2UI_Cleanup (LV2UI_Handle handle)
{
((JuceLv2UIWrapper*)handle)->lv2Cleanup();
}

//==============================================================================
// LV2 UI extended functions

static int juceLV2UI_idle (LV2UI_Handle handle)
{
return ((JuceLv2UIWrapper*)handle)->lv2Idle();
}

static const void* juceLV2UI_ExtensionData (const char* uri)
{
static const LV2UI_Idle_Interface idle = { juceLV2UI_idle };

if (strcmp(uri, LV2_UI__idleInterface) == 0)
{
#if JUCE_LINUX
JuceLv2UIWrapper::hostHasIdleInterface = true;
#endif
return &idle;
}

return nullptr;
}
#endif

//==============================================================================
Expand Down Expand Up @@ -1724,7 +1835,7 @@ static const LV2UI_Descriptor JuceLv2UI_Parent = {
juceLV2UI_InstantiateParent,
juceLV2UI_Cleanup,
nullptr,
nullptr
juceLV2UI_ExtensionData
};
#endif

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ static const String makeManifestFile (AudioProcessor* const filter, const String
text += " a <" LV2_EXTERNAL_UI__Widget "> ;\n";
text += " ui:binary <" + binary + PLUGIN_EXT "> ;\n";
text += " lv2:requiredFeature <" LV2_INSTANCE_ACCESS_URI "> ;\n";
text += " lv2:extensionData <" LV2_PROGRAMS__UIInterface "> .\n";
text += " lv2:optionalFeature ui:touch .\n";
text += "\n";

text += "<" + pluginURI + "#ParentUI>\n";
Expand All @@ -129,8 +129,8 @@ static const String makeManifestFile (AudioProcessor* const filter, const String
#endif
text += " ui:binary <" + binary + PLUGIN_EXT "> ;\n";
text += " lv2:requiredFeature <" LV2_INSTANCE_ACCESS_URI "> ;\n";
text += " lv2:optionalFeature ui:noUserResize ;\n";
text += " lv2:extensionData <" LV2_PROGRAMS__UIInterface "> .\n";
text += " lv2:optionalFeature ui:idleInterface, ui:noUserResize, ui:touch ;\n";
text += " lv2:extensionData ui:idleInterface .\n";
text += "\n";
}
#endif
Expand Down

0 comments on commit a953bed

Please sign in to comment.