@@ -644,6 +644,16 @@ protected: | |||||
virtual void loadProgram(uint32_t index) = 0; | virtual void loadProgram(uint32_t index) = 0; | ||||
#endif | #endif | ||||
#if DISTRHO_PLUGIN_WANT_FULL_STATE | |||||
/** | |||||
Get the value of an internal state.@n | |||||
The host may call this function from any non-realtime context.@n | |||||
Must be implemented by your plugin class if DISTRHO_PLUGIN_WANT_PROGRAMS or DISTRHO_PLUGIN_WANT_FULL_STATE is enabled. | |||||
@note The use of this function breaks compatibility with the DSSI format. | |||||
*/ | |||||
virtual String getState(const char* key) const = 0; | |||||
#endif | |||||
#if DISTRHO_PLUGIN_WANT_STATE | #if DISTRHO_PLUGIN_WANT_STATE | ||||
/** | /** | ||||
Change an internal state @a key to @a value.@n | Change an internal state @a key to @a value.@n | ||||
@@ -73,6 +73,10 @@ | |||||
# define DISTRHO_PLUGIN_WANT_STATE 0 | # define DISTRHO_PLUGIN_WANT_STATE 0 | ||||
#endif | #endif | ||||
#ifndef DISTRHO_PLUGIN_WANT_FULL_STATE | |||||
# define DISTRHO_PLUGIN_WANT_FULL_STATE 0 | |||||
#endif | |||||
#ifndef DISTRHO_PLUGIN_WANT_TIMEPOS | #ifndef DISTRHO_PLUGIN_WANT_TIMEPOS | ||||
# define DISTRHO_PLUGIN_WANT_TIMEPOS 0 | # define DISTRHO_PLUGIN_WANT_TIMEPOS 0 | ||||
#endif | #endif | ||||
@@ -104,6 +108,14 @@ | |||||
# error Synths need MIDI input to work! | # error Synths need MIDI input to work! | ||||
#endif | #endif | ||||
// ----------------------------------------------------------------------- | |||||
// Enable full state if plugin exports presets | |||||
#if DISTRHO_PLUGIN_WANT_PROGRAMS && DISTRHO_PLUGIN_WANT_STATE | |||||
# undef DISTRHO_PLUGIN_WANT_FULL_STATE | |||||
# define DISTRHO_PLUGIN_WANT_FULL_STATE 1 | |||||
#endif | |||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
// Disable UI if DGL is not available | // Disable UI if DGL is not available | ||||
@@ -385,6 +385,16 @@ public: | |||||
return fData->stateDefValues[index]; | return fData->stateDefValues[index]; | ||||
} | } | ||||
# if DISTRHO_PLUGIN_WANT_FULL_STATE | |||||
String getState(const char* key) const | |||||
{ | |||||
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, sFallbackString); | |||||
DISTRHO_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0', sFallbackString); | |||||
return fPlugin->getState(key); | |||||
} | |||||
# endif | |||||
void setState(const char* const key, const char* const value) | void setState(const char* const key, const char* const value) | ||||
{ | { | ||||
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,); | DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,); | ||||
@@ -40,6 +40,10 @@ | |||||
# error DISTRHO_PLUGIN_URI undefined! | # error DISTRHO_PLUGIN_URI undefined! | ||||
#endif | #endif | ||||
#ifndef DISTRHO_PLUGIN_LV2_STATE_PREFIX | |||||
# define DISTRHO_PLUGIN_LV2_STATE_PREFIX "urn:distrho:" | |||||
#endif | |||||
#define DISTRHO_LV2_USE_EVENTS_IN (DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_TIMEPOS || (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI)) | #define DISTRHO_LV2_USE_EVENTS_IN (DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_TIMEPOS || (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI)) | ||||
#define DISTRHO_LV2_USE_EVENTS_OUT (DISTRHO_PLUGIN_WANT_MIDI_OUTPUT || (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI)) | #define DISTRHO_LV2_USE_EVENTS_OUT (DISTRHO_PLUGIN_WANT_MIDI_OUTPUT || (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI)) | ||||
@@ -752,7 +756,7 @@ public: | |||||
const String& key = cit->first; | const String& key = cit->first; | ||||
const String& value = cit->second; | const String& value = cit->second; | ||||
const String urnKey("urn:distrho:" + key); | |||||
const String urnKey(DISTRHO_PLUGIN_LV2_STATE_PREFIX + key); | |||||
// some hosts need +1 for the null terminator, even though the type is string | // some hosts need +1 for the null terminator, even though the type is string | ||||
store(handle, fUridMap->map(fUridMap->handle, urnKey.buffer()), value.buffer(), value.length()+1, fURIDs.atomString, LV2_STATE_IS_POD|LV2_STATE_IS_PORTABLE); | store(handle, fUridMap->map(fUridMap->handle, urnKey.buffer()), value.buffer(), value.length()+1, fURIDs.atomString, LV2_STATE_IS_POD|LV2_STATE_IS_PORTABLE); | ||||
@@ -769,7 +773,7 @@ public: | |||||
for (uint32_t i=0, count=fPlugin.getStateCount(); i < count; ++i) | for (uint32_t i=0, count=fPlugin.getStateCount(); i < count; ++i) | ||||
{ | { | ||||
const String& key(fPlugin.getStateKey(i)); | const String& key(fPlugin.getStateKey(i)); | ||||
const String urnKey("urn:distrho:" + key); | |||||
const String urnKey(DISTRHO_PLUGIN_LV2_STATE_PREFIX + key); | |||||
size = 0; | size = 0; | ||||
type = 0; | type = 0; | ||||
@@ -909,7 +913,7 @@ private: | |||||
atomLong(uridMap->map(uridMap->handle, LV2_ATOM__Long)), | atomLong(uridMap->map(uridMap->handle, LV2_ATOM__Long)), | ||||
atomSequence(uridMap->map(uridMap->handle, LV2_ATOM__Sequence)), | atomSequence(uridMap->map(uridMap->handle, LV2_ATOM__Sequence)), | ||||
atomString(uridMap->map(uridMap->handle, LV2_ATOM__String)), | atomString(uridMap->map(uridMap->handle, LV2_ATOM__String)), | ||||
distrhoState(uridMap->map(uridMap->handle, "urn:distrho:keyValueState")), | |||||
distrhoState(uridMap->map(uridMap->handle, DISTRHO_PLUGIN_LV2_STATE_PREFIX "KeyValueState")), | |||||
midiEvent(uridMap->map(uridMap->handle, LV2_MIDI__MidiEvent)), | midiEvent(uridMap->map(uridMap->handle, LV2_MIDI__MidiEvent)), | ||||
timePosition(uridMap->map(uridMap->handle, LV2_TIME__Position)), | timePosition(uridMap->map(uridMap->handle, LV2_TIME__Position)), | ||||
timeBar(uridMap->map(uridMap->handle, LV2_TIME__bar)), | timeBar(uridMap->map(uridMap->handle, LV2_TIME__bar)), | ||||
@@ -1161,15 +1165,13 @@ static const void* lv2_extension_data(const char* uri) | |||||
#endif | #endif | ||||
#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | #if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | ||||
# define DISTRHO_DIRECT_ACCESS_URI "urn:distrho:direct-access" | |||||
struct LV2_DirectAccess_Interface { | struct LV2_DirectAccess_Interface { | ||||
void* (*get_instance_pointer)(LV2_Handle handle); | void* (*get_instance_pointer)(LV2_Handle handle); | ||||
}; | }; | ||||
static const LV2_DirectAccess_Interface directaccess = { lv2_get_instance_pointer }; | static const LV2_DirectAccess_Interface directaccess = { lv2_get_instance_pointer }; | ||||
if (std::strcmp(uri, DISTRHO_DIRECT_ACCESS_URI) == 0) | |||||
if (std::strcmp(uri, DISTRHO_PLUGIN_LV2_STATE_PREFIX "direct-access") == 0) | |||||
return &directaccess; | return &directaccess; | ||||
#endif | #endif | ||||
@@ -589,7 +589,7 @@ void lv2_generate_ttl(const char* const basename) | |||||
const uint32_t numParameters = plugin.getParameterCount(); | const uint32_t numParameters = plugin.getParameterCount(); | ||||
const uint32_t numPrograms = plugin.getProgramCount(); | const uint32_t numPrograms = plugin.getProgramCount(); | ||||
# if DISTRHO_PLUGIN_WANT_STATE | |||||
# if DISTRHO_PLUGIN_WANT_FULL_STATE | |||||
const uint32_t numStates = plugin.getStateCount(); | const uint32_t numStates = plugin.getStateCount(); | ||||
# endif | # endif | ||||
@@ -608,20 +608,23 @@ void lv2_generate_ttl(const char* const basename) | |||||
presetString = "<" DISTRHO_PLUGIN_URI + presetSeparator + "preset" + strBuf + ">\n"; | presetString = "<" DISTRHO_PLUGIN_URI + presetSeparator + "preset" + strBuf + ">\n"; | ||||
# if DISTRHO_PLUGIN_WANT_STATE | |||||
# warning "Exporting LV2 Presets with state not supported yet" | |||||
# if 0 | |||||
# if DISTRHO_PLUGIN_WANT_FULL_STATE | |||||
for (uint32_t j=0; j<numStates; ++j) | for (uint32_t j=0; j<numStates; ++j) | ||||
{ | { | ||||
const String key = plugin.getStateKey(j); | |||||
const String value = plugin.getState(key); | |||||
if (j == 0) | if (j == 0) | ||||
presetString += " state:state [\n"; | presetString += " state:state [\n"; | ||||
else | else | ||||
presetString += " [\n"; | presetString += " [\n"; | ||||
presetString += " <urn:distrho:" + plugin.getStateKey(j) + ">\n"; | |||||
presetString += "\"\"\"\n"; | |||||
presetString += plugin.getState(j); | |||||
presetString += "\"\"\"\n"; | |||||
presetString += " <urn:distrho:" + key + ">\n"; | |||||
if (value.length() < 10) | |||||
presetString += " \"" + value + "\" ;\n"; | |||||
else | |||||
presetString += "\"\"\"\n" + value + "\"\"\" ;\n"; | |||||
if (j+1 == numStates) | if (j+1 == numStates) | ||||
{ | { | ||||
@@ -635,7 +638,6 @@ void lv2_generate_ttl(const char* const basename) | |||||
presetString += " ] ,\n"; | presetString += " ] ,\n"; | ||||
} | } | ||||
} | } | ||||
# endif | |||||
# endif | # endif | ||||
for (uint32_t j=0; j <numParameters; ++j) | for (uint32_t j=0; j <numParameters; ++j) | ||||
@@ -28,6 +28,10 @@ | |||||
#include "lv2/lv2_kxstudio_properties.h" | #include "lv2/lv2_kxstudio_properties.h" | ||||
#include "lv2/lv2_programs.h" | #include "lv2/lv2_programs.h" | ||||
#ifndef DISTRHO_PLUGIN_LV2_STATE_PREFIX | |||||
# define DISTRHO_PLUGIN_LV2_STATE_PREFIX "urn:distrho:" | |||||
#endif | |||||
START_NAMESPACE_DISTRHO | START_NAMESPACE_DISTRHO | ||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
@@ -46,7 +50,7 @@ public: | |||||
fController(controller), | fController(controller), | ||||
fWriteFunction(writeFunc), | fWriteFunction(writeFunc), | ||||
fEventTransferURID(uridMap->map(uridMap->handle, LV2_ATOM__eventTransfer)), | fEventTransferURID(uridMap->map(uridMap->handle, LV2_ATOM__eventTransfer)), | ||||
fKeyValueURID(uridMap->map(uridMap->handle, "urn:distrho:keyValueState")), | |||||
fKeyValueURID(uridMap->map(uridMap->handle, DISTRHO_PLUGIN_LV2_STATE_PREFIX "KeyValueState")), | |||||
fWinIdWasNull(winId == 0) | fWinIdWasNull(winId == 0) | ||||
{ | { | ||||
if (fUiResize != nullptr && winId != 0) | if (fUiResize != nullptr && winId != 0) | ||||
@@ -331,8 +335,6 @@ static LV2UI_Handle lv2ui_instantiate(const LV2UI_Descriptor*, const char* uri, | |||||
void* instance = nullptr; | void* instance = nullptr; | ||||
#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | #if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | ||||
# define DISTRHO_DIRECT_ACCESS_URI "urn:distrho:direct-access" | |||||
struct LV2_DirectAccess_Interface { | struct LV2_DirectAccess_Interface { | ||||
void* (*get_instance_pointer)(LV2_Handle handle); | void* (*get_instance_pointer)(LV2_Handle handle); | ||||
}; | }; | ||||
@@ -381,7 +383,7 @@ static LV2UI_Handle lv2ui_instantiate(const LV2UI_Descriptor*, const char* uri, | |||||
return nullptr; | return nullptr; | ||||
} | } | ||||
if (const LV2_DirectAccess_Interface* const directAccess = (const LV2_DirectAccess_Interface*)extData->data_access(DISTRHO_DIRECT_ACCESS_URI)) | |||||
if (const LV2_DirectAccess_Interface* const directAccess = (const LV2_DirectAccess_Interface*)extData->data_access(DISTRHO_PLUGIN_LV2_STATE_PREFIX "direct-access")) | |||||
instance = directAccess->get_instance_pointer(instance); | instance = directAccess->get_instance_pointer(instance); | ||||
else | else | ||||
instance = nullptr; | instance = nullptr; | ||||