@@ -0,0 +1,264 @@ | |||||
diff --git a/modules/juce_audio_plugin_client/LV2/juce_LV2_Wrapper.cpp b/modules/juce_audio_plugin_client/LV2/juce_LV2_Wrapper.cpp | |||||
index 2f4b727..97e8a96 100644 | |||||
--- a/modules/juce_audio_plugin_client/LV2/juce_LV2_Wrapper.cpp | |||||
+++ b/modules/juce_audio_plugin_client/LV2/juce_LV2_Wrapper.cpp | |||||
@@ -52,7 +52,7 @@ | |||||
#define JucePlugin_WantsLV2State 1 | |||||
#endif | |||||
-#if JUCE_LINUX | |||||
+#if JUCE_LINUX && ! JUCE_LINUX_EMBED | |||||
#include <X11/Xlib.h> | |||||
#undef KeyPress | |||||
#endif | |||||
@@ -79,12 +79,12 @@ | |||||
#include "../utility/juce_IncludeModuleHeaders.h" | |||||
+#if JUCE_LINUX && ! JUCE_LINUX_EMBED | |||||
namespace juce | |||||
{ | |||||
- #if JUCE_LINUX | |||||
extern Display* display; | |||||
- #endif | |||||
} | |||||
+#endif | |||||
#define JUCE_LV2_STATE_STRING_URI "urn:juce:stateString" | |||||
#define JUCE_LV2_STATE_BINARY_URI "urn:juce:stateBinary" | |||||
@@ -200,6 +200,7 @@ const String makeManifestFile (AudioProcessor* const filter, const String& binar | |||||
text += " rdfs:seeAlso <" + binary + ".ttl> .\n"; | |||||
text += "\n"; | |||||
+#if ! JUCE_LINUX_EMBED | |||||
// UIs | |||||
if (filter->hasEditor()) | |||||
{ | |||||
@@ -211,19 +212,20 @@ const String makeManifestFile (AudioProcessor* const filter, const String& binar | |||||
text += "\n"; | |||||
text += "<" + pluginURI + "#ParentUI>\n"; | |||||
-#if JUCE_MAC | |||||
+ #if JUCE_MAC | |||||
text += " a ui:CocoaUI ;\n"; | |||||
-#elif JUCE_LINUX | |||||
+ #elif JUCE_LINUX | |||||
text += " a ui:X11UI ;\n"; | |||||
-#elif JUCE_WINDOWS | |||||
+ #elif JUCE_WINDOWS | |||||
text += " a ui:WindowsUI ;\n"; | |||||
-#endif | |||||
+ #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 += "\n"; | |||||
} | |||||
+#endif | |||||
#if JucePlugin_WantsLV2Presets | |||||
const String presetSeparator(pluginURI.contains("#") ? ":" : "#"); | |||||
@@ -273,6 +275,7 @@ const String makePluginFile (AudioProcessor* const filter, const int maxNumInput | |||||
text += " <" LV2_PROGRAMS__Interface "> ;\n"; | |||||
text += "\n"; | |||||
+#if ! JUCE_LINUX_EMBED | |||||
// UIs | |||||
if (filter->hasEditor()) | |||||
{ | |||||
@@ -280,6 +283,7 @@ const String makePluginFile (AudioProcessor* const filter, const int maxNumInput | |||||
text += " <" + pluginURI + "#ParentUI> ;\n"; | |||||
text += "\n"; | |||||
} | |||||
+#endif | |||||
uint32 portIndex = 0; | |||||
@@ -570,6 +574,7 @@ private: | |||||
}; | |||||
#endif | |||||
+#if ! JUCE_LINUX_EMBED | |||||
//============================================================================== | |||||
/** | |||||
Lightweight DocumentWindow subclass for external ui | |||||
@@ -1105,6 +1110,8 @@ private: | |||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JuceLv2UIWrapper) | |||||
}; | |||||
+#endif /* JUCE_LINUX_EMBED */ | |||||
+ | |||||
//============================================================================== | |||||
/** | |||||
Juce LV2 handle | |||||
@@ -1249,7 +1256,9 @@ public: | |||||
{ | |||||
const MessageManagerLock mmLock; | |||||
+#if ! JUCE_LINUX_EMBED | |||||
ui = nullptr; | |||||
+#endif | |||||
filter = nullptr; | |||||
if (progDesc.name != nullptr) | |||||
@@ -1818,8 +1827,10 @@ public: | |||||
String stateData (CharPointer_UTF8(static_cast<const char*>(data))); | |||||
filter->setStateInformationString (stateData); | |||||
+ #if ! JUCE_LINUX_EMBED | |||||
if (ui != nullptr) | |||||
ui->repaint(); | |||||
+ #endif | |||||
return LV2_STATE_SUCCESS; | |||||
} | |||||
@@ -1828,8 +1839,10 @@ public: | |||||
{ | |||||
filter->setCurrentProgramStateInformation (data, size); | |||||
+ #if ! JUCE_LINUX_EMBED | |||||
if (ui != nullptr) | |||||
ui->repaint(); | |||||
+ #endif | |||||
return LV2_STATE_SUCCESS; | |||||
} | |||||
@@ -1852,6 +1865,7 @@ public: | |||||
#endif | |||||
} | |||||
+#if ! JUCE_LINUX_EMBED | |||||
//============================================================================== | |||||
JuceLv2UIWrapper* getUI (LV2UI_Write_Function writeFunction, LV2UI_Controller controller, LV2UI_Widget* widget, | |||||
const LV2_Feature* const* features, bool isExternal) | |||||
@@ -1865,6 +1879,7 @@ public: | |||||
return ui; | |||||
} | |||||
+#endif | |||||
private: | |||||
#if JUCE_LINUX | |||||
@@ -1874,7 +1889,9 @@ private: | |||||
#endif | |||||
ScopedPointer<AudioProcessor> filter; | |||||
+#if ! JUCE_LINUX_EMBED | |||||
ScopedPointer<JuceLv2UIWrapper> ui; | |||||
+#endif | |||||
HeapBlock<float*> channels; | |||||
MidiBuffer midiEvents; | |||||
int numInChans, numOutChans; | |||||
@@ -2033,6 +2050,7 @@ static const void* juceLV2_ExtensionData (const char* uri) | |||||
return nullptr; | |||||
} | |||||
+#if ! JUCE_LINUX_EMBED | |||||
//============================================================================== | |||||
// LV2 UI descriptor functions | |||||
@@ -2068,6 +2086,7 @@ static void juceLV2UI_Cleanup (LV2UI_Handle handle) | |||||
{ | |||||
((JuceLv2UIWrapper*)handle)->lv2Cleanup(); | |||||
} | |||||
+#endif | |||||
//============================================================================== | |||||
// static LV2 Descriptor objects | |||||
@@ -2083,6 +2102,7 @@ static const LV2_Descriptor JuceLv2Plugin = { | |||||
juceLV2_ExtensionData | |||||
}; | |||||
+#if ! JUCE_LINUX_EMBED | |||||
static const LV2UI_Descriptor JuceLv2UI_External = { | |||||
strdup(String(getPluginURI() + "#ExternalUI").toRawUTF8()), | |||||
juceLV2UI_InstantiateExternal, | |||||
@@ -2098,14 +2118,17 @@ static const LV2UI_Descriptor JuceLv2UI_Parent = { | |||||
nullptr, | |||||
nullptr | |||||
}; | |||||
+#endif | |||||
static const struct DescriptorCleanup { | |||||
DescriptorCleanup() {} | |||||
~DescriptorCleanup() | |||||
{ | |||||
free((void*)JuceLv2Plugin.URI); | |||||
+#if ! JUCE_LINUX_EMBED | |||||
free((void*)JuceLv2UI_External.URI); | |||||
free((void*)JuceLv2UI_Parent.URI); | |||||
+#endif | |||||
} | |||||
} _descCleanup; | |||||
@@ -2130,6 +2153,7 @@ JUCE_EXPORTED_FUNCTION const LV2_Descriptor* lv2_descriptor (uint32 index) | |||||
return (index == 0) ? &JuceLv2Plugin : nullptr; | |||||
} | |||||
+#if ! JUCE_LINUX_EMBED | |||||
JUCE_EXPORTED_FUNCTION const LV2UI_Descriptor* lv2ui_descriptor (uint32 index); | |||||
JUCE_EXPORTED_FUNCTION const LV2UI_Descriptor* lv2ui_descriptor (uint32 index) | |||||
{ | |||||
@@ -2143,5 +2167,6 @@ JUCE_EXPORTED_FUNCTION const LV2UI_Descriptor* lv2ui_descriptor (uint32 index) | |||||
return nullptr; | |||||
} | |||||
} | |||||
+#endif | |||||
#endif | |||||
diff --git a/modules/juce_audio_processors/juce_audio_processors.cpp b/modules/juce_audio_processors/juce_audio_processors.cpp | |||||
index 8df41ca..4c0a6a1 100644 | |||||
--- a/modules/juce_audio_processors/juce_audio_processors.cpp | |||||
+++ b/modules/juce_audio_processors/juce_audio_processors.cpp | |||||
@@ -47,7 +47,7 @@ | |||||
#endif | |||||
#endif | |||||
-#if JUCE_PLUGINHOST_VST && JUCE_LINUX | |||||
+#if JUCE_PLUGINHOST_VST && JUCE_LINUX && ! JUCE_LINUX_EMBED | |||||
#include <X11/Xlib.h> | |||||
#include <X11/Xutil.h> | |||||
#undef KeyPress | |||||
@@ -161,7 +161,9 @@ void AutoResizingNSViewComponentWithParent::timerCallback() | |||||
#include "format/juce_AudioPluginFormat.cpp" | |||||
#include "format/juce_AudioPluginFormatManager.cpp" | |||||
#include "processors/juce_AudioProcessor.cpp" | |||||
-#include "processors/juce_AudioProcessorEditor.cpp" | |||||
+#if ! JUCE_LINUX_EMBED | |||||
+ #include "processors/juce_AudioProcessorEditor.cpp" | |||||
+#endif | |||||
#include "processors/juce_AudioProcessorGraph.cpp" | |||||
#include "processors/juce_GenericAudioProcessorEditor.cpp" | |||||
#include "processors/juce_PluginDescription.cpp" | |||||
diff --git a/modules/juce_events/juce_events.cpp b/modules/juce_events/juce_events.cpp | |||||
index 729a78f..6d69c40 100644 | |||||
--- a/modules/juce_events/juce_events.cpp | |||||
+++ b/modules/juce_events/juce_events.cpp | |||||
@@ -55,10 +55,12 @@ | |||||
#import <IOKit/pwr_mgt/IOPMLib.h> | |||||
#elif JUCE_LINUX | |||||
- #include <X11/Xlib.h> | |||||
- #include <X11/Xresource.h> | |||||
- #include <X11/Xutil.h> | |||||
- #undef KeyPress | |||||
+ #if ! JUCE_LINUX_EMBED | |||||
+ #include <X11/Xlib.h> | |||||
+ #include <X11/Xresource.h> | |||||
+ #include <X11/Xutil.h> | |||||
+ #undef KeyPress | |||||
+ #endif | |||||
#include <unistd.h> | |||||
#endif | |||||
@@ -91,6 +93,9 @@ namespace juce | |||||
#elif JUCE_WINDOWS | |||||
#include "native/juce_win32_Messaging.cpp" | |||||
+#elif JUCE_LINUX_EMBED | |||||
+ #include "native/juce_linux-embed_Messaging.cpp" | |||||
+ | |||||
#elif JUCE_LINUX | |||||
#include "native/juce_ScopedXLock.h" | |||||
#include "native/juce_linux_Messaging.cpp" |
@@ -13,6 +13,7 @@ | |||||
#include "../utility/juce_CheckSettingMacros.h" | #include "../utility/juce_CheckSettingMacros.h" | ||||
#include "../../juce_core/system/juce_TargetPlatform.h" // for JUCE_LINUX | #include "../../juce_core/system/juce_TargetPlatform.h" // for JUCE_LINUX | ||||
#if JucePlugin_Build_LV2 | #if JucePlugin_Build_LV2 | ||||
/** Plugin requires processing with a fixed/constant block size */ | /** Plugin requires processing with a fixed/constant block size */ | ||||
@@ -51,7 +52,7 @@ | |||||
#define JucePlugin_WantsLV2State 1 | #define JucePlugin_WantsLV2State 1 | ||||
#endif | #endif | ||||
#if JUCE_LINUX | |||||
#if JUCE_LINUX && ! JUCE_LINUX_EMBED | |||||
#include <X11/Xlib.h> | #include <X11/Xlib.h> | ||||
#undef KeyPress | #undef KeyPress | ||||
#endif | #endif | ||||
@@ -78,12 +79,12 @@ | |||||
#include "../utility/juce_IncludeModuleHeaders.h" | #include "../utility/juce_IncludeModuleHeaders.h" | ||||
#if JUCE_LINUX && ! JUCE_LINUX_EMBED | |||||
namespace juce | namespace juce | ||||
{ | { | ||||
#if JUCE_LINUX | |||||
extern Display* display; | extern Display* display; | ||||
#endif | |||||
} | } | ||||
#endif | |||||
#define JUCE_LV2_STATE_STRING_URI "urn:juce:stateString" | #define JUCE_LV2_STATE_STRING_URI "urn:juce:stateString" | ||||
#define JUCE_LV2_STATE_BINARY_URI "urn:juce:stateBinary" | #define JUCE_LV2_STATE_BINARY_URI "urn:juce:stateBinary" | ||||
@@ -199,6 +200,7 @@ const String makeManifestFile (AudioProcessor* const filter, const String& binar | |||||
text += " rdfs:seeAlso <" + binary + ".ttl> .\n"; | text += " rdfs:seeAlso <" + binary + ".ttl> .\n"; | ||||
text += "\n"; | text += "\n"; | ||||
#if ! JUCE_LINUX_EMBED | |||||
// UIs | // UIs | ||||
if (filter->hasEditor()) | if (filter->hasEditor()) | ||||
{ | { | ||||
@@ -210,19 +212,20 @@ const String makeManifestFile (AudioProcessor* const filter, const String& binar | |||||
text += "\n"; | text += "\n"; | ||||
text += "<" + pluginURI + "#ParentUI>\n"; | text += "<" + pluginURI + "#ParentUI>\n"; | ||||
#if JUCE_MAC | |||||
#if JUCE_MAC | |||||
text += " a ui:CocoaUI ;\n"; | text += " a ui:CocoaUI ;\n"; | ||||
#elif JUCE_LINUX | |||||
#elif JUCE_LINUX | |||||
text += " a ui:X11UI ;\n"; | text += " a ui:X11UI ;\n"; | ||||
#elif JUCE_WINDOWS | |||||
#elif JUCE_WINDOWS | |||||
text += " a ui:WindowsUI ;\n"; | text += " a ui:WindowsUI ;\n"; | ||||
#endif | |||||
#endif | |||||
text += " ui:binary <" + binary + PLUGIN_EXT "> ;\n"; | text += " ui:binary <" + binary + PLUGIN_EXT "> ;\n"; | ||||
text += " lv2:requiredFeature <" LV2_INSTANCE_ACCESS_URI "> ;\n"; | text += " lv2:requiredFeature <" LV2_INSTANCE_ACCESS_URI "> ;\n"; | ||||
text += " lv2:optionalFeature ui:noUserResize ;\n"; | text += " lv2:optionalFeature ui:noUserResize ;\n"; | ||||
text += " lv2:extensionData <" LV2_PROGRAMS__UIInterface "> .\n"; | text += " lv2:extensionData <" LV2_PROGRAMS__UIInterface "> .\n"; | ||||
text += "\n"; | text += "\n"; | ||||
} | } | ||||
#endif | |||||
#if JucePlugin_WantsLV2Presets | #if JucePlugin_WantsLV2Presets | ||||
const String presetSeparator(pluginURI.contains("#") ? ":" : "#"); | const String presetSeparator(pluginURI.contains("#") ? ":" : "#"); | ||||
@@ -243,7 +246,7 @@ const String makeManifestFile (AudioProcessor* const filter, const String& binar | |||||
} | } | ||||
/** Create the -plugin-.ttl file contents */ | /** Create the -plugin-.ttl file contents */ | ||||
const String makePluginFile (AudioProcessor* const filter) | |||||
const String makePluginFile (AudioProcessor* const filter, const int maxNumInputChannels, const int maxNumOutputChannels) | |||||
{ | { | ||||
const String& pluginURI(getPluginURI()); | const String& pluginURI(getPluginURI()); | ||||
String text; | String text; | ||||
@@ -272,6 +275,7 @@ const String makePluginFile (AudioProcessor* const filter) | |||||
text += " <" LV2_PROGRAMS__Interface "> ;\n"; | text += " <" LV2_PROGRAMS__Interface "> ;\n"; | ||||
text += "\n"; | text += "\n"; | ||||
#if ! JUCE_LINUX_EMBED | |||||
// UIs | // UIs | ||||
if (filter->hasEditor()) | if (filter->hasEditor()) | ||||
{ | { | ||||
@@ -279,6 +283,7 @@ const String makePluginFile (AudioProcessor* const filter) | |||||
text += " <" + pluginURI + "#ParentUI> ;\n"; | text += " <" + pluginURI + "#ParentUI> ;\n"; | ||||
text += "\n"; | text += "\n"; | ||||
} | } | ||||
#endif | |||||
uint32 portIndex = 0; | uint32 portIndex = 0; | ||||
@@ -345,7 +350,7 @@ const String makePluginFile (AudioProcessor* const filter) | |||||
#endif | #endif | ||||
// Audio inputs | // Audio inputs | ||||
for (int i=0; i < JucePlugin_MaxNumInputChannels; ++i) | |||||
for (int i=0; i < maxNumInputChannels; ++i) | |||||
{ | { | ||||
if (i == 0) | if (i == 0) | ||||
text += " lv2:port [\n"; | text += " lv2:port [\n"; | ||||
@@ -357,14 +362,14 @@ const String makePluginFile (AudioProcessor* const filter) | |||||
text += " lv2:symbol \"lv2_audio_in_" + String(i+1) + "\" ;\n"; | text += " lv2:symbol \"lv2_audio_in_" + String(i+1) + "\" ;\n"; | ||||
text += " lv2:name \"Audio Input " + String(i+1) + "\" ;\n"; | text += " lv2:name \"Audio Input " + String(i+1) + "\" ;\n"; | ||||
if (i+1 == JucePlugin_MaxNumInputChannels) | |||||
if (i+1 == maxNumInputChannels) | |||||
text += " ] ;\n\n"; | text += " ] ;\n\n"; | ||||
else | else | ||||
text += " ] ,\n"; | text += " ] ,\n"; | ||||
} | } | ||||
// Audio outputs | // Audio outputs | ||||
for (int i=0; i < JucePlugin_MaxNumOutputChannels; ++i) | |||||
for (int i=0; i < maxNumOutputChannels; ++i) | |||||
{ | { | ||||
if (i == 0) | if (i == 0) | ||||
text += " lv2:port [\n"; | text += " lv2:port [\n"; | ||||
@@ -376,7 +381,7 @@ const String makePluginFile (AudioProcessor* const filter) | |||||
text += " lv2:symbol \"lv2_audio_out_" + String(i+1) + "\" ;\n"; | text += " lv2:symbol \"lv2_audio_out_" + String(i+1) + "\" ;\n"; | ||||
text += " lv2:name \"Audio Output " + String(i+1) + "\" ;\n"; | text += " lv2:name \"Audio Output " + String(i+1) + "\" ;\n"; | ||||
if (i+1 == JucePlugin_MaxNumOutputChannels) | |||||
if (i+1 == maxNumOutputChannels) | |||||
text += " ] ;\n\n"; | text += " ] ;\n\n"; | ||||
else | else | ||||
text += " ] ,\n"; | text += " ] ,\n"; | ||||
@@ -519,7 +524,7 @@ void createLv2Files(const char* basename) | |||||
std::cout << "Writing " << binary << ".ttl..."; std::cout.flush(); | std::cout << "Writing " << binary << ".ttl..."; std::cout.flush(); | ||||
std::fstream plugin(binaryTTL.toUTF8(), std::ios::out); | std::fstream plugin(binaryTTL.toUTF8(), std::ios::out); | ||||
plugin << makePluginFile(filter) << std::endl; | |||||
plugin << makePluginFile(filter, JucePlugin_MaxNumInputChannels, JucePlugin_MaxNumOutputChannels) << std::endl; | |||||
plugin.close(); | plugin.close(); | ||||
std::cout << " done!" << std::endl; | std::cout << " done!" << std::endl; | ||||
@@ -569,6 +574,7 @@ private: | |||||
}; | }; | ||||
#endif | #endif | ||||
#if ! JUCE_LINUX_EMBED | |||||
//============================================================================== | //============================================================================== | ||||
/** | /** | ||||
Lightweight DocumentWindow subclass for external ui | Lightweight DocumentWindow subclass for external ui | ||||
@@ -914,8 +920,12 @@ public: | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
if (parentContainer != nullptr && parentContainer->isOnDesktop()) | |||||
parentContainer->removeFromDesktop(); | |||||
if (parentContainer) | |||||
{ | |||||
parentContainer->setVisible (false); | |||||
if (parentContainer->isOnDesktop()) | |||||
parentContainer->removeFromDesktop(); | |||||
} | |||||
} | } | ||||
} | } | ||||
@@ -1100,6 +1110,8 @@ private: | |||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JuceLv2UIWrapper) | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JuceLv2UIWrapper) | ||||
}; | }; | ||||
#endif /* JUCE_LINUX_EMBED */ | |||||
//============================================================================== | //============================================================================== | ||||
/** | /** | ||||
Juce LV2 handle | Juce LV2 handle | ||||
@@ -1244,7 +1256,9 @@ public: | |||||
{ | { | ||||
const MessageManagerLock mmLock; | const MessageManagerLock mmLock; | ||||
#if ! JUCE_LINUX_EMBED | |||||
ui = nullptr; | ui = nullptr; | ||||
#endif | |||||
filter = nullptr; | filter = nullptr; | ||||
if (progDesc.name != nullptr) | if (progDesc.name != nullptr) | ||||
@@ -1682,6 +1696,8 @@ public: | |||||
uint32_t lv2GetOptions (LV2_Options_Option* options) | uint32_t lv2GetOptions (LV2_Options_Option* options) | ||||
{ | { | ||||
// currently unused | // currently unused | ||||
ignoreUnused(options); | |||||
return LV2_OPTIONS_SUCCESS; | return LV2_OPTIONS_SUCCESS; | ||||
} | } | ||||
@@ -1811,8 +1827,10 @@ public: | |||||
String stateData (CharPointer_UTF8(static_cast<const char*>(data))); | String stateData (CharPointer_UTF8(static_cast<const char*>(data))); | ||||
filter->setStateInformationString (stateData); | filter->setStateInformationString (stateData); | ||||
#if ! JUCE_LINUX_EMBED | |||||
if (ui != nullptr) | if (ui != nullptr) | ||||
ui->repaint(); | ui->repaint(); | ||||
#endif | |||||
return LV2_STATE_SUCCESS; | return LV2_STATE_SUCCESS; | ||||
} | } | ||||
@@ -1821,8 +1839,10 @@ public: | |||||
{ | { | ||||
filter->setCurrentProgramStateInformation (data, size); | filter->setCurrentProgramStateInformation (data, size); | ||||
#if ! JUCE_LINUX_EMBED | |||||
if (ui != nullptr) | if (ui != nullptr) | ||||
ui->repaint(); | ui->repaint(); | ||||
#endif | |||||
return LV2_STATE_SUCCESS; | return LV2_STATE_SUCCESS; | ||||
} | } | ||||
@@ -1840,10 +1860,12 @@ public: | |||||
info = curPosInfo; | info = curPosInfo; | ||||
return true; | return true; | ||||
#else | #else | ||||
ignoreUnused(info); | |||||
return false; | return false; | ||||
#endif | #endif | ||||
} | } | ||||
#if ! JUCE_LINUX_EMBED | |||||
//============================================================================== | //============================================================================== | ||||
JuceLv2UIWrapper* getUI (LV2UI_Write_Function writeFunction, LV2UI_Controller controller, LV2UI_Widget* widget, | JuceLv2UIWrapper* getUI (LV2UI_Write_Function writeFunction, LV2UI_Controller controller, LV2UI_Widget* widget, | ||||
const LV2_Feature* const* features, bool isExternal) | const LV2_Feature* const* features, bool isExternal) | ||||
@@ -1857,6 +1879,7 @@ public: | |||||
return ui; | return ui; | ||||
} | } | ||||
#endif | |||||
private: | private: | ||||
#if JUCE_LINUX | #if JUCE_LINUX | ||||
@@ -1866,7 +1889,9 @@ private: | |||||
#endif | #endif | ||||
ScopedPointer<AudioProcessor> filter; | ScopedPointer<AudioProcessor> filter; | ||||
#if ! JUCE_LINUX_EMBED | |||||
ScopedPointer<JuceLv2UIWrapper> ui; | ScopedPointer<JuceLv2UIWrapper> ui; | ||||
#endif | |||||
HeapBlock<float*> channels; | HeapBlock<float*> channels; | ||||
MidiBuffer midiEvents; | MidiBuffer midiEvents; | ||||
int numInChans, numOutChans; | int numInChans, numOutChans; | ||||
@@ -2025,6 +2050,7 @@ static const void* juceLV2_ExtensionData (const char* uri) | |||||
return nullptr; | return nullptr; | ||||
} | } | ||||
#if ! JUCE_LINUX_EMBED | |||||
//============================================================================== | //============================================================================== | ||||
// LV2 UI descriptor functions | // LV2 UI descriptor functions | ||||
@@ -2060,6 +2086,7 @@ static void juceLV2UI_Cleanup (LV2UI_Handle handle) | |||||
{ | { | ||||
((JuceLv2UIWrapper*)handle)->lv2Cleanup(); | ((JuceLv2UIWrapper*)handle)->lv2Cleanup(); | ||||
} | } | ||||
#endif | |||||
//============================================================================== | //============================================================================== | ||||
// static LV2 Descriptor objects | // static LV2 Descriptor objects | ||||
@@ -2075,6 +2102,7 @@ static const LV2_Descriptor JuceLv2Plugin = { | |||||
juceLV2_ExtensionData | juceLV2_ExtensionData | ||||
}; | }; | ||||
#if ! JUCE_LINUX_EMBED | |||||
static const LV2UI_Descriptor JuceLv2UI_External = { | static const LV2UI_Descriptor JuceLv2UI_External = { | ||||
strdup(String(getPluginURI() + "#ExternalUI").toRawUTF8()), | strdup(String(getPluginURI() + "#ExternalUI").toRawUTF8()), | ||||
juceLV2UI_InstantiateExternal, | juceLV2UI_InstantiateExternal, | ||||
@@ -2090,14 +2118,17 @@ static const LV2UI_Descriptor JuceLv2UI_Parent = { | |||||
nullptr, | nullptr, | ||||
nullptr | nullptr | ||||
}; | }; | ||||
#endif | |||||
static const struct DescriptorCleanup { | static const struct DescriptorCleanup { | ||||
DescriptorCleanup() {} | DescriptorCleanup() {} | ||||
~DescriptorCleanup() | ~DescriptorCleanup() | ||||
{ | { | ||||
free((void*)JuceLv2Plugin.URI); | free((void*)JuceLv2Plugin.URI); | ||||
#if ! JUCE_LINUX_EMBED | |||||
free((void*)JuceLv2UI_External.URI); | free((void*)JuceLv2UI_External.URI); | ||||
free((void*)JuceLv2UI_Parent.URI); | free((void*)JuceLv2UI_Parent.URI); | ||||
#endif | |||||
} | } | ||||
} _descCleanup; | } _descCleanup; | ||||
@@ -2122,6 +2153,7 @@ JUCE_EXPORTED_FUNCTION const LV2_Descriptor* lv2_descriptor (uint32 index) | |||||
return (index == 0) ? &JuceLv2Plugin : nullptr; | return (index == 0) ? &JuceLv2Plugin : nullptr; | ||||
} | } | ||||
#if ! JUCE_LINUX_EMBED | |||||
JUCE_EXPORTED_FUNCTION const LV2UI_Descriptor* lv2ui_descriptor (uint32 index); | JUCE_EXPORTED_FUNCTION const LV2UI_Descriptor* lv2ui_descriptor (uint32 index); | ||||
JUCE_EXPORTED_FUNCTION const LV2UI_Descriptor* lv2ui_descriptor (uint32 index) | JUCE_EXPORTED_FUNCTION const LV2UI_Descriptor* lv2ui_descriptor (uint32 index) | ||||
{ | { | ||||
@@ -2135,5 +2167,6 @@ JUCE_EXPORTED_FUNCTION const LV2UI_Descriptor* lv2ui_descriptor (uint32 index) | |||||
return nullptr; | return nullptr; | ||||
} | } | ||||
} | } | ||||
#endif | |||||
#endif | #endif |
@@ -47,7 +47,7 @@ | |||||
#endif | #endif | ||||
#endif | #endif | ||||
#if JUCE_PLUGINHOST_VST && JUCE_LINUX | |||||
#if JUCE_PLUGINHOST_VST && JUCE_LINUX && ! JUCE_LINUX_EMBED | |||||
#include <X11/Xlib.h> | #include <X11/Xlib.h> | ||||
#include <X11/Xutil.h> | #include <X11/Xutil.h> | ||||
#undef KeyPress | #undef KeyPress | ||||
@@ -161,7 +161,9 @@ void AutoResizingNSViewComponentWithParent::timerCallback() | |||||
#include "format/juce_AudioPluginFormat.cpp" | #include "format/juce_AudioPluginFormat.cpp" | ||||
#include "format/juce_AudioPluginFormatManager.cpp" | #include "format/juce_AudioPluginFormatManager.cpp" | ||||
#include "processors/juce_AudioProcessor.cpp" | #include "processors/juce_AudioProcessor.cpp" | ||||
#include "processors/juce_AudioProcessorEditor.cpp" | |||||
#if ! JUCE_LINUX_EMBED | |||||
#include "processors/juce_AudioProcessorEditor.cpp" | |||||
#endif | |||||
#include "processors/juce_AudioProcessorGraph.cpp" | #include "processors/juce_AudioProcessorGraph.cpp" | ||||
#include "processors/juce_GenericAudioProcessorEditor.cpp" | #include "processors/juce_GenericAudioProcessorEditor.cpp" | ||||
#include "processors/juce_PluginDescription.cpp" | #include "processors/juce_PluginDescription.cpp" | ||||
@@ -55,10 +55,12 @@ | |||||
#import <IOKit/pwr_mgt/IOPMLib.h> | #import <IOKit/pwr_mgt/IOPMLib.h> | ||||
#elif JUCE_LINUX | #elif JUCE_LINUX | ||||
#include <X11/Xlib.h> | |||||
#include <X11/Xresource.h> | |||||
#include <X11/Xutil.h> | |||||
#undef KeyPress | |||||
#if ! JUCE_LINUX_EMBED | |||||
#include <X11/Xlib.h> | |||||
#include <X11/Xresource.h> | |||||
#include <X11/Xutil.h> | |||||
#undef KeyPress | |||||
#endif | |||||
#include <unistd.h> | #include <unistd.h> | ||||
#endif | #endif | ||||
@@ -91,6 +93,9 @@ namespace juce | |||||
#elif JUCE_WINDOWS | #elif JUCE_WINDOWS | ||||
#include "native/juce_win32_Messaging.cpp" | #include "native/juce_win32_Messaging.cpp" | ||||
#elif JUCE_LINUX_EMBED | |||||
#include "native/juce_linux-embed_Messaging.cpp" | |||||
#elif JUCE_LINUX | #elif JUCE_LINUX | ||||
#include "native/juce_ScopedXLock.h" | #include "native/juce_ScopedXLock.h" | ||||
#include "native/juce_linux_Messaging.cpp" | #include "native/juce_linux_Messaging.cpp" | ||||
@@ -0,0 +1,153 @@ | |||||
/* | |||||
============================================================================== | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2016 - ROLI Ltd. | |||||
Permission is granted to use this software under the terms of the ISC license | |||||
http://www.isc.org/downloads/software-support-policy/isc-license/ | |||||
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 permission notice appear in all copies. | |||||
THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD | |||||
TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND | |||||
FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, | |||||
OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF | |||||
USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | |||||
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | |||||
OF THIS SOFTWARE. | |||||
----------------------------------------------------------------------------- | |||||
To release a closed-source product which uses other parts of JUCE not | |||||
licensed under the ISC terms, commercial licenses are available: visit | |||||
www.juce.com for more information. | |||||
============================================================================== | |||||
*/ | |||||
//============================================================================== | |||||
class EventsThread : public Thread | |||||
{ | |||||
public: | |||||
EventsThread() | |||||
: Thread("EventsThread"), | |||||
initializing(false) {} | |||||
~EventsThread() | |||||
{ | |||||
signalThreadShouldExit(); | |||||
stopThread(2000); | |||||
const ScopedLock sl(queueLock); | |||||
jassert(queue.size() == 0); | |||||
queue.clear(); | |||||
} | |||||
bool postMessage(MessageManager::MessageBase* const msg) | |||||
{ | |||||
const ScopedLock sl(queueLock); | |||||
queue.add(msg); | |||||
return true; | |||||
} | |||||
bool isInitializing() const noexcept | |||||
{ | |||||
return initializing; | |||||
} | |||||
protected: | |||||
void run() override | |||||
{ | |||||
/* | |||||
* We need to know when we're initializing because MessageManager::setCurrentThreadAsMessageThread() | |||||
* calls doPlatformSpecificInitialisation/Shutdown, in which we started this thread previously. | |||||
* To avoid a deadlock we do not call start/stopThread if still initializing. | |||||
*/ | |||||
initializing = true; | |||||
if (MessageManager* const msgMgr = MessageManager::getInstance()) | |||||
msgMgr->setCurrentThreadAsMessageThread(); | |||||
initializing = false; | |||||
for (; ! threadShouldExit();) | |||||
{ | |||||
// dispatch messages until no more present, then sleep | |||||
for (; dispatchNextInternalMessage();) {} | |||||
sleep(25); | |||||
} | |||||
} | |||||
private: | |||||
volatile bool initializing; | |||||
ReferenceCountedArray<MessageManager::MessageBase> queue; | |||||
CriticalSection queueLock; | |||||
MessageManager::MessageBase::Ptr popNextMessage() | |||||
{ | |||||
const ScopedLock sl(queueLock); | |||||
return queue.removeAndReturn(0); | |||||
} | |||||
bool dispatchNextInternalMessage() | |||||
{ | |||||
if (const MessageManager::MessageBase::Ptr msg = popNextMessage()) | |||||
{ | |||||
JUCE_TRY | |||||
{ | |||||
msg->messageCallback(); | |||||
return true; | |||||
} | |||||
JUCE_CATCH_EXCEPTION | |||||
} | |||||
return false; | |||||
} | |||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(EventsThread) | |||||
}; | |||||
static EventsThread& getEventsThreadInstance() | |||||
{ | |||||
static EventsThread eventsThread; | |||||
return eventsThread; | |||||
} | |||||
//============================================================================== | |||||
void MessageManager::doPlatformSpecificInitialisation() | |||||
{ | |||||
EventsThread& eventsThread(getEventsThreadInstance()); | |||||
if (! eventsThread.isInitializing()) | |||||
eventsThread.startThread(); | |||||
} | |||||
void MessageManager::doPlatformSpecificShutdown() | |||||
{ | |||||
EventsThread& eventsThread(getEventsThreadInstance()); | |||||
if (! eventsThread.isInitializing()) | |||||
eventsThread.stopThread(-1); | |||||
} | |||||
bool MessageManager::postMessageToSystemQueue (MessageManager::MessageBase* const message) | |||||
{ | |||||
EventsThread& eventsThread(getEventsThreadInstance()); | |||||
return eventsThread.postMessage(message); | |||||
} | |||||
void MessageManager::broadcastMessage (const String& /* value */) | |||||
{ | |||||
/* TODO */ | |||||
} | |||||
// this function expects that it will NEVER be called simultaneously for two concurrent threads | |||||
bool MessageManager::dispatchNextMessageOnSystemQueue (bool returnIfNoPendingMessages) | |||||
{ | |||||
DBG ("MessageManager::dispatchNextMessageOnSystemQueue() unsupported"); | |||||
return false; | |||||
} |