Signed-off-by: falkTX <falktx@falktx.com>pull/232/head
@@ -1,6 +1,6 @@ | |||||
/* | /* | ||||
* DISTRHO Plugin Framework (DPF) | * DISTRHO Plugin Framework (DPF) | ||||
* Copyright (C) 2012-2018 Filipe Coelho <falktx@falktx.com> | |||||
* Copyright (C) 2012-2020 Filipe Coelho <falktx@falktx.com> | |||||
* | * | ||||
* Permission to use, copy, modify, and/or distribute this software for any purpose with | * 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 | * or without fee is hereby granted, provided that the above copyright notice and this | ||||
@@ -830,6 +830,13 @@ protected: | |||||
virtual void initState(uint32_t index, String& stateKey, String& defaultStateValue) = 0; | virtual void initState(uint32_t index, String& stateKey, String& defaultStateValue) = 0; | ||||
#endif | #endif | ||||
#if DISTRHO_PLUGIN_WANT_STATEFILES | |||||
/** | |||||
TODO API under construction | |||||
*/ | |||||
virtual bool isStateFile(uint32_t index) = 0; | |||||
#endif | |||||
/* -------------------------------------------------------------------------------------------------------- | /* -------------------------------------------------------------------------------------------------------- | ||||
* Internal data */ | * Internal data */ | ||||
@@ -1,6 +1,6 @@ | |||||
/* | /* | ||||
* DISTRHO Plugin Framework (DPF) | * DISTRHO Plugin Framework (DPF) | ||||
* Copyright (C) 2012-2019 Filipe Coelho <falktx@falktx.com> | |||||
* Copyright (C) 2012-2020 Filipe Coelho <falktx@falktx.com> | |||||
* | * | ||||
* Permission to use, copy, modify, and/or distribute this software for any purpose with | * 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 | * or without fee is hereby granted, provided that the above copyright notice and this | ||||
@@ -98,7 +98,7 @@ public: | |||||
/** | /** | ||||
setParameterValue. | setParameterValue. | ||||
Change a parameter value in the Plugin. | Change a parameter value in the Plugin. | ||||
*/ | */ | ||||
void setParameterValue(uint32_t index, float value); | void setParameterValue(uint32_t index, float value); | ||||
@@ -111,6 +111,19 @@ public: | |||||
void setState(const char* key, const char* value); | void setState(const char* key, const char* value); | ||||
#endif | #endif | ||||
#if DISTRHO_PLUGIN_WANT_STATEFILES | |||||
/** | |||||
Request a new file from the host, matching the properties of a state key.@n | |||||
This will use the native host file browser if available, otherwise a DPF built-in file browser is used.@n | |||||
Response will be sent asynchronously to stateChanged, with the matching key and the new file as the value.@n | |||||
It is not possible to know if the action was cancelled by the user. | |||||
@return Success if a file-browser was opened, otherwise false. | |||||
@note You cannot request more than one file at a time. | |||||
*/ | |||||
bool requestStateFile(const char* key); | |||||
#endif | |||||
#if DISTRHO_PLUGIN_WANT_MIDI_INPUT | #if DISTRHO_PLUGIN_WANT_MIDI_INPUT | ||||
/** | /** | ||||
sendNote. | sendNote. | ||||
@@ -77,6 +77,10 @@ | |||||
# define DISTRHO_PLUGIN_WANT_STATE 0 | # define DISTRHO_PLUGIN_WANT_STATE 0 | ||||
#endif | #endif | ||||
#ifndef DISTRHO_PLUGIN_WANT_STATEFILES | |||||
# define DISTRHO_PLUGIN_WANT_STATEFILES 0 | |||||
#endif | |||||
#ifndef DISTRHO_PLUGIN_WANT_FULL_STATE | #ifndef DISTRHO_PLUGIN_WANT_FULL_STATE | ||||
# define DISTRHO_PLUGIN_WANT_FULL_STATE 0 | # define DISTRHO_PLUGIN_WANT_FULL_STATE 0 | ||||
#endif | #endif | ||||
@@ -108,7 +112,7 @@ | |||||
// Define DISTRHO_UI_URI if needed | // Define DISTRHO_UI_URI if needed | ||||
#ifndef DISTRHO_UI_URI | #ifndef DISTRHO_UI_URI | ||||
# define DISTRHO_UI_URI DISTRHO_PLUGIN_URI "#UI" | |||||
# define DISTRHO_UI_URI DISTRHO_PLUGIN_URI "#DPF_UI" | |||||
#endif | #endif | ||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
@@ -127,6 +131,14 @@ | |||||
# error Synths need MIDI input to work! | # error Synths need MIDI input to work! | ||||
#endif | #endif | ||||
// ----------------------------------------------------------------------- | |||||
// Enable state if plugin wants state files | |||||
#if DISTRHO_PLUGIN_WANT_STATEFILES && ! DISTRHO_PLUGIN_WANT_STATE | |||||
# undef DISTRHO_PLUGIN_WANT_STATE | |||||
# define DISTRHO_PLUGIN_WANT_STATE 1 | |||||
#endif | |||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
// Enable full state if plugin exports presets | // Enable full state if plugin exports presets | ||||
@@ -486,6 +486,15 @@ public: | |||||
return fData->stateDefValues[index]; | return fData->stateDefValues[index]; | ||||
} | } | ||||
# if DISTRHO_PLUGIN_WANT_STATEFILES | |||||
bool isStateFile(const uint32_t index) const | |||||
{ | |||||
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->stateCount, false); | |||||
return fPlugin->isStateFile(index); | |||||
} | |||||
# endif | |||||
# if DISTRHO_PLUGIN_WANT_FULL_STATE | # if DISTRHO_PLUGIN_WANT_FULL_STATE | ||||
String getState(const char* key) const | String getState(const char* key) const | ||||
{ | { | ||||
@@ -1,6 +1,6 @@ | |||||
/* | /* | ||||
* DISTRHO Plugin Framework (DPF) | * DISTRHO Plugin Framework (DPF) | ||||
* Copyright (C) 2012-2018 Filipe Coelho <falktx@falktx.com> | |||||
* Copyright (C) 2012-2020 Filipe Coelho <falktx@falktx.com> | |||||
* | * | ||||
* This program is free software; you can redistribute it and/or | * This program is free software; you can redistribute it and/or | ||||
* modify it under the terms of the GNU Lesser General Public | * modify it under the terms of the GNU Lesser General Public | ||||
@@ -101,7 +101,15 @@ public: | |||||
PluginJack(jack_client_t* const client) | PluginJack(jack_client_t* const client) | ||||
: fPlugin(this, writeMidiCallback), | : fPlugin(this, writeMidiCallback), | ||||
#if DISTRHO_PLUGIN_HAS_UI | #if DISTRHO_PLUGIN_HAS_UI | ||||
fUI(this, 0, nullptr, setParameterValueCallback, setStateCallback, nullptr, setSizeCallback, getDesktopScaleFactor(), fPlugin.getInstancePointer()), | |||||
fUI(this, 0, | |||||
nullptr, // edit param | |||||
setParameterValueCallback, | |||||
setStateCallback, | |||||
nullptr, // send note | |||||
setSizeCallback, | |||||
nullptr, // file request | |||||
getDesktopScaleFactor(), | |||||
fPlugin.getInstancePointer()), | |||||
#endif | #endif | ||||
fClient(client) | fClient(client) | ||||
{ | { | ||||
@@ -1,6 +1,6 @@ | |||||
/* | /* | ||||
* DISTRHO Plugin Framework (DPF) | * DISTRHO Plugin Framework (DPF) | ||||
* Copyright (C) 2012-2018 Filipe Coelho <falktx@falktx.com> | |||||
* Copyright (C) 2012-2020 Filipe Coelho <falktx@falktx.com> | |||||
* | * | ||||
* Permission to use, copy, modify, and/or distribute this software for any purpose with | * 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 | * or without fee is hereby granted, provided that the above copyright notice and this | ||||
@@ -24,6 +24,7 @@ | |||||
#include "lv2/midi.h" | #include "lv2/midi.h" | ||||
#include "lv2/options.h" | #include "lv2/options.h" | ||||
#include "lv2/parameters.h" | #include "lv2/parameters.h" | ||||
#include "lv2/patch.h" | |||||
#include "lv2/state.h" | #include "lv2/state.h" | ||||
#include "lv2/time.h" | #include "lv2/time.h" | ||||
#include "lv2/urid.h" | #include "lv2/urid.h" | ||||
@@ -54,7 +55,8 @@ | |||||
START_NAMESPACE_DISTRHO | START_NAMESPACE_DISTRHO | ||||
typedef std::map<const String, String> StringMap; | |||||
typedef std::map<const String, String> StringToStringMap; | |||||
typedef std::map<const LV2_URID, String> UridToStringMap; | |||||
#if ! DISTRHO_PLUGIN_WANT_MIDI_OUTPUT | #if ! DISTRHO_PLUGIN_WANT_MIDI_OUTPUT | ||||
static const writeMidiFunc writeMidiCallback = nullptr; | static const writeMidiFunc writeMidiCallback = nullptr; | ||||
@@ -65,7 +67,10 @@ static const writeMidiFunc writeMidiCallback = nullptr; | |||||
class PluginLv2 | class PluginLv2 | ||||
{ | { | ||||
public: | public: | ||||
PluginLv2(const double sampleRate, const LV2_URID_Map* const uridMap, const LV2_Worker_Schedule* const worker, const bool usingNominal) | |||||
PluginLv2(const double sampleRate, | |||||
const LV2_URID_Map* const uridMap, | |||||
const LV2_Worker_Schedule* const worker, | |||||
const bool usingNominal) | |||||
: fPlugin(this, writeMidiCallback), | : fPlugin(this, writeMidiCallback), | ||||
fUsingNominal(usingNominal), | fUsingNominal(usingNominal), | ||||
#ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD | #ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD | ||||
@@ -127,6 +132,15 @@ public: | |||||
const String& dkey(fPlugin.getStateKey(i)); | const String& dkey(fPlugin.getStateKey(i)); | ||||
fStateMap[dkey] = fPlugin.getStateDefaultValue(i); | fStateMap[dkey] = fPlugin.getStateDefaultValue(i); | ||||
# if DISTRHO_PLUGIN_WANT_STATEFILES | |||||
if (fPlugin.isStateFile(i)) | |||||
{ | |||||
const String dpf_lv2_key(DISTRHO_PLUGIN_URI "#" + dkey); | |||||
const LV2_URID urid = uridMap->map(uridMap->handle, dpf_lv2_key.buffer()); | |||||
fUridStateFileMap[urid] = dkey; | |||||
} | |||||
# endif | |||||
} | } | ||||
} | } | ||||
else | else | ||||
@@ -521,16 +535,16 @@ public: | |||||
} | } | ||||
#endif | #endif | ||||
// check for messages from UI | |||||
#if DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI | |||||
// check for messages from UI or files | |||||
#if DISTRHO_PLUGIN_WANT_STATE && (DISTRHO_PLUGIN_HAS_UI || DISTRHO_PLUGIN_WANT_STATEFILES) | |||||
LV2_ATOM_SEQUENCE_FOREACH(fPortEventsIn, event) | LV2_ATOM_SEQUENCE_FOREACH(fPortEventsIn, event) | ||||
{ | { | ||||
if (event == nullptr) | if (event == nullptr) | ||||
break; | break; | ||||
if (event->body.type == fURIDs.distrhoState && fWorker != nullptr) | |||||
if (event->body.type == fURIDs.dpfKeyValue) | |||||
{ | { | ||||
const void* const data((const void*)(event + 1)); | |||||
const void* const data = (const void*)(event + 1); | |||||
// check if this is our special message | // check if this is our special message | ||||
if (std::strcmp((const char*)data, "__dpf_ui_data__") == 0) | if (std::strcmp((const char*)data, "__dpf_ui_data__") == 0) | ||||
@@ -538,12 +552,28 @@ public: | |||||
for (uint32_t i=0, count=fPlugin.getStateCount(); i < count; ++i) | for (uint32_t i=0, count=fPlugin.getStateCount(); i < count; ++i) | ||||
fNeededUiSends[i] = true; | fNeededUiSends[i] = true; | ||||
} | } | ||||
else | |||||
// no, send to DSP as usual | // no, send to DSP as usual | ||||
else if (fWorker != nullptr) | |||||
{ | { | ||||
fWorker->schedule_work(fWorker->handle, event->body.size, data); | |||||
fWorker->schedule_work(fWorker->handle, sizeof(LV2_Atom)+event->body.size, &event->body); | |||||
} | } | ||||
} | } | ||||
# if DISTRHO_PLUGIN_WANT_STATEFILES | |||||
else if (event->body.type == fURIDs.atomObject && fWorker != nullptr) | |||||
{ | |||||
const LV2_Atom_Object* const object = (const LV2_Atom_Object*)&event->body; | |||||
const LV2_Atom* property = nullptr; | |||||
const LV2_Atom* value = nullptr; | |||||
lv2_atom_object_get(object, fURIDs.patchProperty, &property, fURIDs.patchValue, &value, nullptr); | |||||
if (property != nullptr && property->type == fURIDs.atomURID && | |||||
value != nullptr && value->type == fURIDs.atomPath) | |||||
{ | |||||
fWorker->schedule_work(fWorker->handle, sizeof(LV2_Atom)+event->body.size, &event->body); | |||||
} | |||||
} | |||||
# endif | |||||
} | } | ||||
#endif | #endif | ||||
@@ -653,19 +683,19 @@ public: | |||||
if (! fNeededUiSends[i]) | if (! fNeededUiSends[i]) | ||||
continue; | continue; | ||||
const String& key = fPlugin.getStateKey(i); | |||||
const String& curKey(fPlugin.getStateKey(i)); | |||||
for (StringMap::const_iterator cit=fStateMap.begin(), cite=fStateMap.end(); cit != cite; ++cit) | |||||
for (StringToStringMap::const_iterator cit=fStateMap.begin(), cite=fStateMap.end(); cit != cite; ++cit) | |||||
{ | { | ||||
const String& curKey = cit->first; | |||||
const String& key(cit->first); | |||||
if (curKey != key) | if (curKey != key) | ||||
continue; | continue; | ||||
const String& value = cit->second; | |||||
const String& value(cit->second); | |||||
// set msg size (key + value + separator + 2x null terminator) | // set msg size (key + value + separator + 2x null terminator) | ||||
const size_t msgSize(key.length()+value.length()+3); | |||||
const size_t msgSize = key.length()+value.length()+3; | |||||
if (sizeof(LV2_Atom_Event) + msgSize > capacity - fEventsOutData.offset) | if (sizeof(LV2_Atom_Event) + msgSize > capacity - fEventsOutData.offset) | ||||
{ | { | ||||
@@ -673,21 +703,18 @@ public: | |||||
break; | break; | ||||
} | } | ||||
// reserve msg space | |||||
// FIXME create a large enough buffer beforehand | |||||
char msgBuf[msgSize]; | |||||
std::memset(msgBuf, 0, msgSize); | |||||
// write key and value in atom bufer | |||||
std::memcpy(msgBuf, key.buffer(), key.length()+1); | |||||
std::memcpy(msgBuf+(key.length()+1), value.buffer(), value.length()+1); | |||||
// put data | // put data | ||||
aev = (LV2_Atom_Event*)(LV2_ATOM_CONTENTS(LV2_Atom_Sequence, fEventsOutData.port) + fEventsOutData.offset); | aev = (LV2_Atom_Event*)(LV2_ATOM_CONTENTS(LV2_Atom_Sequence, fEventsOutData.port) + fEventsOutData.offset); | ||||
aev->time.frames = 0; | aev->time.frames = 0; | ||||
aev->body.type = fURIDs.distrhoState; | |||||
aev->body.type = fURIDs.dpfKeyValue; | |||||
aev->body.size = msgSize; | aev->body.size = msgSize; | ||||
std::memcpy(LV2_ATOM_BODY(&aev->body), msgBuf, msgSize); | |||||
uint8_t* const msgBuf = LV2_ATOM_BODY(&aev->body); | |||||
std::memset(msgBuf, 0, msgSize); | |||||
// write key and value in atom buffer | |||||
std::memcpy(msgBuf, key.buffer(), key.length()+1); | |||||
std::memcpy(msgBuf+(key.length()+1), value.buffer(), value.length()+1); | |||||
fEventsOutData.growBy(lv2_atom_pad_size(sizeof(LV2_Atom_Event) + msgSize)); | fEventsOutData.growBy(lv2_atom_pad_size(sizeof(LV2_Atom_Event) + msgSize)); | ||||
@@ -795,7 +822,7 @@ public: | |||||
# if DISTRHO_PLUGIN_WANT_FULL_STATE | # if DISTRHO_PLUGIN_WANT_FULL_STATE | ||||
// Update state | // Update state | ||||
for (StringMap::const_iterator cit=fStateMap.begin(), cite=fStateMap.end(); cit != cite; ++cit) | |||||
for (StringToStringMap::const_iterator cit=fStateMap.begin(), cite=fStateMap.end(); cit != cite; ++cit) | |||||
{ | { | ||||
const String& key = cit->first; | const String& key = cit->first; | ||||
fStateMap[key] = fPlugin.getState(key); | fStateMap[key] = fPlugin.getState(key); | ||||
@@ -811,22 +838,52 @@ public: | |||||
{ | { | ||||
# if DISTRHO_PLUGIN_WANT_FULL_STATE | # if DISTRHO_PLUGIN_WANT_FULL_STATE | ||||
// Update current state | // Update current state | ||||
for (StringMap::const_iterator cit=fStateMap.begin(), cite=fStateMap.end(); cit != cite; ++cit) | |||||
for (StringToStringMap::const_iterator cit=fStateMap.begin(), cite=fStateMap.end(); cit != cite; ++cit) | |||||
{ | { | ||||
const String& key = cit->first; | const String& key = cit->first; | ||||
fStateMap[key] = fPlugin.getState(key); | fStateMap[key] = fPlugin.getState(key); | ||||
} | } | ||||
# endif | # endif | ||||
for (StringMap::const_iterator cit=fStateMap.begin(), cite=fStateMap.end(); cit != cite; ++cit) | |||||
String dpf_lv2_key; | |||||
LV2_URID urid; | |||||
for (uint32_t i=0, count=fPlugin.getStateCount(); i < count; ++i) | |||||
{ | { | ||||
const String& key = cit->first; | |||||
const String& value = cit->second; | |||||
const String& curKey(fPlugin.getStateKey(i)); | |||||
for (StringToStringMap::const_iterator cit=fStateMap.begin(), cite=fStateMap.end(); cit != cite; ++cit) | |||||
{ | |||||
const String& key(cit->first); | |||||
if (curKey != key) | |||||
continue; | |||||
const String& value(cit->second); | |||||
const String urnKey(DISTRHO_PLUGIN_LV2_STATE_PREFIX + key); | |||||
# if DISTRHO_PLUGIN_WANT_STATEFILES | |||||
if (fPlugin.isStateFile(i)) | |||||
{ | |||||
dpf_lv2_key = DISTRHO_PLUGIN_URI "#"; | |||||
urid = fURIDs.atomPath; | |||||
} | |||||
else | |||||
# endif | |||||
{ | |||||
dpf_lv2_key = DISTRHO_PLUGIN_LV2_STATE_PREFIX; | |||||
urid = fURIDs.atomString; | |||||
} | |||||
// 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); | |||||
dpf_lv2_key += key; | |||||
// some hosts need +1 for the null terminator, even though the type is string | |||||
store(handle, | |||||
fUridMap->map(fUridMap->handle, dpf_lv2_key.buffer()), | |||||
value.buffer(), | |||||
value.length()+1, | |||||
urid, | |||||
LV2_STATE_IS_POD|LV2_STATE_IS_PORTABLE); | |||||
} | |||||
} | } | ||||
return LV2_STATE_SUCCESS; | return LV2_STATE_SUCCESS; | ||||
@@ -837,23 +894,42 @@ public: | |||||
size_t size; | size_t size; | ||||
uint32_t type, flags; | uint32_t type, flags; | ||||
String dpf_lv2_key; | |||||
LV2_URID urid; | |||||
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(DISTRHO_PLUGIN_LV2_STATE_PREFIX + key); | |||||
# if DISTRHO_PLUGIN_WANT_STATEFILES | |||||
if (fPlugin.isStateFile(i)) | |||||
{ | |||||
dpf_lv2_key = DISTRHO_PLUGIN_URI "#"; | |||||
urid = fURIDs.atomPath; | |||||
} | |||||
else | |||||
# endif | |||||
{ | |||||
dpf_lv2_key = DISTRHO_PLUGIN_LV2_STATE_PREFIX; | |||||
urid = fURIDs.atomString; | |||||
} | |||||
dpf_lv2_key += key; | |||||
size = 0; | size = 0; | ||||
type = 0; | type = 0; | ||||
flags = LV2_STATE_IS_POD|LV2_STATE_IS_PORTABLE; | flags = LV2_STATE_IS_POD|LV2_STATE_IS_PORTABLE; | ||||
const void* data = retrieve(handle, fUridMap->map(fUridMap->handle, urnKey.buffer()), &size, &type, &flags); | |||||
const void* data = retrieve(handle, | |||||
fUridMap->map(fUridMap->handle, dpf_lv2_key.buffer()), | |||||
&size, &type, &flags); | |||||
if (data == nullptr || size == 0) | if (data == nullptr || size == 0) | ||||
continue; | continue; | ||||
DISTRHO_SAFE_ASSERT_CONTINUE(type == fURIDs.atomString); | |||||
DISTRHO_SAFE_ASSERT_CONTINUE(type == urid); | |||||
const char* const value((const char*)data); | |||||
const std::size_t length(std::strlen(value)); | |||||
const char* const value = (const char*)data; | |||||
const std::size_t length = std::strlen(value); | |||||
DISTRHO_SAFE_ASSERT_CONTINUE(length == size || length+1 == size); | DISTRHO_SAFE_ASSERT_CONTINUE(length == size || length+1 == size); | ||||
setState(key, value); | setState(key, value); | ||||
@@ -871,12 +947,55 @@ public: | |||||
LV2_Worker_Status lv2_work(const void* const data) | LV2_Worker_Status lv2_work(const void* const data) | ||||
{ | { | ||||
const char* const key((const char*)data); | |||||
const char* const value(key+std::strlen(key)+1); | |||||
const LV2_Atom* const eventBody = (const LV2_Atom*)data; | |||||
setState(key, value); | |||||
if (eventBody->type == fURIDs.dpfKeyValue) | |||||
{ | |||||
const char* const key = (const char*)(eventBody + 1); | |||||
const char* const value = key + (std::strlen(key) + 1U); | |||||
return LV2_WORKER_SUCCESS; | |||||
setState(key, value); | |||||
return LV2_WORKER_SUCCESS; | |||||
} | |||||
# if DISTRHO_PLUGIN_WANT_STATEFILES | |||||
if (eventBody->type == fURIDs.atomObject) | |||||
{ | |||||
const LV2_Atom_Object* const object = (const LV2_Atom_Object*)eventBody; | |||||
const LV2_Atom* property = nullptr; | |||||
const LV2_Atom* value = nullptr; | |||||
lv2_atom_object_get(object, fURIDs.patchProperty, &property, fURIDs.patchValue, &value, nullptr); | |||||
DISTRHO_SAFE_ASSERT_RETURN(property != nullptr, LV2_WORKER_ERR_UNKNOWN); | |||||
DISTRHO_SAFE_ASSERT_RETURN(property->type == fURIDs.atomURID, LV2_WORKER_ERR_UNKNOWN); | |||||
DISTRHO_SAFE_ASSERT_RETURN(value != nullptr, LV2_WORKER_ERR_UNKNOWN); | |||||
DISTRHO_SAFE_ASSERT_RETURN(value->type == fURIDs.atomPath, LV2_WORKER_ERR_UNKNOWN); | |||||
const LV2_URID urid = ((const LV2_Atom_URID*)property)->body; | |||||
const char* const filename = (const char*)(value + 1); | |||||
String key; | |||||
try { | |||||
key = fUridStateFileMap[urid]; | |||||
} DISTRHO_SAFE_EXCEPTION_RETURN("lv2_work fUridStateFileMap[urid]", LV2_WORKER_ERR_UNKNOWN); | |||||
setState(key, filename); | |||||
for (uint32_t i=0, count=fPlugin.getStateCount(); i < count; ++i) | |||||
{ | |||||
if (fPlugin.getStateKey(i) == key) | |||||
{ | |||||
fNeededUiSends[i] = true; | |||||
break; | |||||
} | |||||
} | |||||
return LV2_WORKER_SUCCESS; | |||||
} | |||||
# endif | |||||
return LV2_WORKER_ERR_UNKNOWN; | |||||
} | } | ||||
LV2_Worker_Status lv2_work_response(uint32_t, const void*) | LV2_Worker_Status lv2_work_response(uint32_t, const void*) | ||||
@@ -995,16 +1114,21 @@ private: | |||||
// LV2 URIDs | // LV2 URIDs | ||||
struct URIDs { | struct URIDs { | ||||
const LV2_URID_Map* _uridMap; | |||||
LV2_URID atomBlank; | LV2_URID atomBlank; | ||||
LV2_URID atomObject; | LV2_URID atomObject; | ||||
LV2_URID atomDouble; | LV2_URID atomDouble; | ||||
LV2_URID atomFloat; | LV2_URID atomFloat; | ||||
LV2_URID atomInt; | LV2_URID atomInt; | ||||
LV2_URID atomLong; | LV2_URID atomLong; | ||||
LV2_URID atomPath; | |||||
LV2_URID atomSequence; | LV2_URID atomSequence; | ||||
LV2_URID atomString; | LV2_URID atomString; | ||||
LV2_URID distrhoState; | |||||
LV2_URID atomURID; | |||||
LV2_URID dpfKeyValue; | |||||
LV2_URID midiEvent; | LV2_URID midiEvent; | ||||
LV2_URID patchProperty; | |||||
LV2_URID patchValue; | |||||
LV2_URID timePosition; | LV2_URID timePosition; | ||||
LV2_URID timeBar; | LV2_URID timeBar; | ||||
LV2_URID timeBarBeat; | LV2_URID timeBarBeat; | ||||
@@ -1016,25 +1140,35 @@ private: | |||||
LV2_URID timeSpeed; | LV2_URID timeSpeed; | ||||
URIDs(const LV2_URID_Map* const uridMap) | URIDs(const LV2_URID_Map* const uridMap) | ||||
: atomBlank(uridMap->map(uridMap->handle, LV2_ATOM__Blank)), | |||||
atomObject(uridMap->map(uridMap->handle, LV2_ATOM__Object)), | |||||
atomDouble(uridMap->map(uridMap->handle, LV2_ATOM__Double)), | |||||
atomFloat(uridMap->map(uridMap->handle, LV2_ATOM__Float)), | |||||
atomInt(uridMap->map(uridMap->handle, LV2_ATOM__Int)), | |||||
atomLong(uridMap->map(uridMap->handle, LV2_ATOM__Long)), | |||||
atomSequence(uridMap->map(uridMap->handle, LV2_ATOM__Sequence)), | |||||
atomString(uridMap->map(uridMap->handle, LV2_ATOM__String)), | |||||
distrhoState(uridMap->map(uridMap->handle, DISTRHO_PLUGIN_LV2_STATE_PREFIX "KeyValueState")), | |||||
midiEvent(uridMap->map(uridMap->handle, LV2_MIDI__MidiEvent)), | |||||
timePosition(uridMap->map(uridMap->handle, LV2_TIME__Position)), | |||||
timeBar(uridMap->map(uridMap->handle, LV2_TIME__bar)), | |||||
timeBarBeat(uridMap->map(uridMap->handle, LV2_TIME__barBeat)), | |||||
timeBeatUnit(uridMap->map(uridMap->handle, LV2_TIME__beatUnit)), | |||||
timeBeatsPerBar(uridMap->map(uridMap->handle, LV2_TIME__beatsPerBar)), | |||||
timeBeatsPerMinute(uridMap->map(uridMap->handle, LV2_TIME__beatsPerMinute)), | |||||
timeTicksPerBeat(uridMap->map(uridMap->handle, LV2_KXSTUDIO_PROPERTIES__TimePositionTicksPerBeat)), | |||||
timeFrame(uridMap->map(uridMap->handle, LV2_TIME__frame)), | |||||
timeSpeed(uridMap->map(uridMap->handle, LV2_TIME__speed)) {} | |||||
: _uridMap(uridMap), | |||||
atomBlank(map(LV2_ATOM__Blank)), | |||||
atomObject(map(LV2_ATOM__Object)), | |||||
atomDouble(map(LV2_ATOM__Double)), | |||||
atomFloat(map(LV2_ATOM__Float)), | |||||
atomInt(map(LV2_ATOM__Int)), | |||||
atomLong(map(LV2_ATOM__Long)), | |||||
atomPath(map(LV2_ATOM__Path)), | |||||
atomSequence(map(LV2_ATOM__Sequence)), | |||||
atomString(map(LV2_ATOM__String)), | |||||
atomURID(map(LV2_ATOM__URID)), | |||||
dpfKeyValue(map(DISTRHO_PLUGIN_LV2_STATE_PREFIX "KeyValueState")), | |||||
midiEvent(map(LV2_MIDI__MidiEvent)), | |||||
patchProperty(map(LV2_PATCH__property)), | |||||
patchValue(map(LV2_PATCH__value)), | |||||
timePosition(map(LV2_TIME__Position)), | |||||
timeBar(map(LV2_TIME__bar)), | |||||
timeBarBeat(map(LV2_TIME__barBeat)), | |||||
timeBeatUnit(map(LV2_TIME__beatUnit)), | |||||
timeBeatsPerBar(map(LV2_TIME__beatsPerBar)), | |||||
timeBeatsPerMinute(map(LV2_TIME__beatsPerMinute)), | |||||
timeTicksPerBeat(map(LV2_KXSTUDIO_PROPERTIES__TimePositionTicksPerBeat)), | |||||
timeFrame(map(LV2_TIME__frame)), | |||||
timeSpeed(map(LV2_TIME__speed)) {} | |||||
inline LV2_URID map(const char* const uri) const | |||||
{ | |||||
return _uridMap->map(_uridMap->handle, uri); | |||||
} | |||||
} fURIDs; | } fURIDs; | ||||
// LV2 features | // LV2 features | ||||
@@ -1042,7 +1176,7 @@ private: | |||||
const LV2_Worker_Schedule* const fWorker; | const LV2_Worker_Schedule* const fWorker; | ||||
#if DISTRHO_PLUGIN_WANT_STATE | #if DISTRHO_PLUGIN_WANT_STATE | ||||
StringMap fStateMap; | |||||
StringToStringMap fStateMap; | |||||
bool* fNeededUiSends; | bool* fNeededUiSends; | ||||
void setState(const char* const key, const char* const newValue) | void setState(const char* const key, const char* const newValue) | ||||
@@ -1054,7 +1188,7 @@ private: | |||||
return; | return; | ||||
// check if key already exists | // check if key already exists | ||||
for (StringMap::iterator it=fStateMap.begin(), ite=fStateMap.end(); it != ite; ++it) | |||||
for (StringToStringMap::iterator it=fStateMap.begin(), ite=fStateMap.end(); it != ite; ++it) | |||||
{ | { | ||||
const String& dkey(it->first); | const String& dkey(it->first); | ||||
@@ -1067,6 +1201,10 @@ private: | |||||
d_stderr("Failed to find plugin state with key \"%s\"", key); | d_stderr("Failed to find plugin state with key \"%s\"", key); | ||||
} | } | ||||
# if DISTRHO_PLUGIN_WANT_STATEFILES | |||||
UridToStringMap fUridStateFileMap; | |||||
# endif | |||||
#endif | #endif | ||||
void updateParameterOutputsAndTriggers() | void updateParameterOutputsAndTriggers() | ||||
@@ -1,6 +1,6 @@ | |||||
/* | /* | ||||
* DISTRHO Plugin Framework (DPF) | * DISTRHO Plugin Framework (DPF) | ||||
* Copyright (C) 2012-2019 Filipe Coelho <falktx@falktx.com> | |||||
* Copyright (C) 2012-2020 Filipe Coelho <falktx@falktx.com> | |||||
* | * | ||||
* Permission to use, copy, modify, and/or distribute this software for any purpose with | * 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 | * or without fee is hereby granted, provided that the above copyright notice and this | ||||
@@ -22,6 +22,7 @@ | |||||
#include "lv2/instance-access.h" | #include "lv2/instance-access.h" | ||||
#include "lv2/midi.h" | #include "lv2/midi.h" | ||||
#include "lv2/options.h" | #include "lv2/options.h" | ||||
#include "lv2/patch.h" | |||||
#include "lv2/port-props.h" | #include "lv2/port-props.h" | ||||
#include "lv2/presets.h" | #include "lv2/presets.h" | ||||
#include "lv2/resize-port.h" | #include "lv2/resize-port.h" | ||||
@@ -45,6 +46,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 | |||||
#ifndef DISTRHO_PLUGIN_MINIMUM_BUFFER_SIZE | #ifndef DISTRHO_PLUGIN_MINIMUM_BUFFER_SIZE | ||||
# define DISTRHO_PLUGIN_MINIMUM_BUFFER_SIZE 2048 | # define DISTRHO_PLUGIN_MINIMUM_BUFFER_SIZE 2048 | ||||
#endif | #endif | ||||
@@ -139,6 +144,9 @@ static const char* const lv2ManifestUiOptionalFeatures[] = | |||||
"ui:parent", | "ui:parent", | ||||
"ui:resize", | "ui:resize", | ||||
"ui:touch", | "ui:touch", | ||||
#endif | |||||
#if DISTRHO_PLUGIN_WANT_STATEFILES | |||||
"ui:requestValue", | |||||
#endif | #endif | ||||
nullptr | nullptr | ||||
}; | }; | ||||
@@ -220,8 +228,8 @@ void lv2_generate_ttl(const char* const basename) | |||||
d_lastBufferSize = 0; | d_lastBufferSize = 0; | ||||
d_lastSampleRate = 0.0; | d_lastSampleRate = 0.0; | ||||
String pluginDLL(basename); | |||||
String pluginTTL(pluginDLL + ".ttl"); | |||||
const String pluginDLL(basename); | |||||
const String pluginTTL(pluginDLL + ".ttl"); | |||||
#if DISTRHO_PLUGIN_HAS_UI | #if DISTRHO_PLUGIN_HAS_UI | ||||
String pluginUI(pluginDLL); | String pluginUI(pluginDLL); | ||||
@@ -317,26 +325,45 @@ void lv2_generate_ttl(const char* const basename) | |||||
// header | // header | ||||
#if DISTRHO_LV2_USE_EVENTS_IN || DISTRHO_LV2_USE_EVENTS_OUT | #if DISTRHO_LV2_USE_EVENTS_IN || DISTRHO_LV2_USE_EVENTS_OUT | ||||
pluginString += "@prefix atom: <" LV2_ATOM_PREFIX "> .\n"; | |||||
pluginString += "@prefix atom: <" LV2_ATOM_PREFIX "> .\n"; | |||||
#endif | #endif | ||||
pluginString += "@prefix doap: <http://usefulinc.com/ns/doap#> .\n"; | |||||
pluginString += "@prefix foaf: <http://xmlns.com/foaf/0.1/> .\n"; | |||||
pluginString += "@prefix lv2: <" LV2_CORE_PREFIX "> .\n"; | |||||
pluginString += "@prefix doap: <http://usefulinc.com/ns/doap#> .\n"; | |||||
pluginString += "@prefix foaf: <http://xmlns.com/foaf/0.1/> .\n"; | |||||
pluginString += "@prefix lv2: <" LV2_CORE_PREFIX "> .\n"; | |||||
#ifdef DISTRHO_PLUGIN_BRAND | #ifdef DISTRHO_PLUGIN_BRAND | ||||
pluginString += "@prefix mod: <http://moddevices.com/ns/mod#> .\n"; | |||||
pluginString += "@prefix mod: <http://moddevices.com/ns/mod#> .\n"; | |||||
#endif | #endif | ||||
pluginString += "@prefix opts: <" LV2_OPTIONS_PREFIX "> .\n"; | |||||
pluginString += "@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .\n"; | |||||
pluginString += "@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n"; | |||||
pluginString += "@prefix opts: <" LV2_OPTIONS_PREFIX "> .\n"; | |||||
pluginString += "@prefix patch: <" LV2_PATCH_PREFIX "> .\n"; | |||||
pluginString += "@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .\n"; | |||||
pluginString += "@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n"; | |||||
#if DISTRHO_LV2_USE_EVENTS_IN || DISTRHO_LV2_USE_EVENTS_OUT | #if DISTRHO_LV2_USE_EVENTS_IN || DISTRHO_LV2_USE_EVENTS_OUT | ||||
pluginString += "@prefix rsz: <" LV2_RESIZE_PORT_PREFIX "> .\n"; | |||||
pluginString += "@prefix rsz: <" LV2_RESIZE_PORT_PREFIX "> .\n"; | |||||
#endif | #endif | ||||
#if DISTRHO_PLUGIN_HAS_UI | #if DISTRHO_PLUGIN_HAS_UI | ||||
pluginString += "@prefix ui: <" LV2_UI_PREFIX "> .\n"; | |||||
pluginString += "@prefix ui: <" LV2_UI_PREFIX "> .\n"; | |||||
#endif | #endif | ||||
pluginString += "@prefix unit: <" LV2_UNITS_PREFIX "> .\n"; | |||||
pluginString += "@prefix unit: <" LV2_UNITS_PREFIX "> .\n"; | |||||
pluginString += "\n"; | pluginString += "\n"; | ||||
#if DISTRHO_PLUGIN_WANT_STATEFILES | |||||
// define writable states as lv2 parameters | |||||
bool hasStateFiles = false; | |||||
for (uint32_t i=0, count=plugin.getStateCount(); i < count; ++i) | |||||
{ | |||||
if (! plugin.isStateFile(i)) | |||||
continue; | |||||
const String& key(plugin.getStateKey(i)); | |||||
pluginString += "<" DISTRHO_PLUGIN_URI "#" + key + ">\n"; | |||||
pluginString += " a lv2:Parameter ;\n"; | |||||
pluginString += " rdfs:label \"" + key + "\" ;\n"; | |||||
pluginString += " rdfs:range atom:Path .\n\n"; | |||||
hasStateFiles = true; | |||||
} | |||||
#endif | |||||
// plugin | // plugin | ||||
pluginString += "<" DISTRHO_PLUGIN_URI ">\n"; | pluginString += "<" DISTRHO_PLUGIN_URI ">\n"; | ||||
#ifdef DISTRHO_PLUGIN_LV2_CATEGORY | #ifdef DISTRHO_PLUGIN_LV2_CATEGORY | ||||
@@ -353,6 +380,21 @@ void lv2_generate_ttl(const char* const basename) | |||||
addAttribute(pluginString, "lv2:requiredFeature", lv2ManifestPluginRequiredFeatures, 4); | addAttribute(pluginString, "lv2:requiredFeature", lv2ManifestPluginRequiredFeatures, 4); | ||||
addAttribute(pluginString, "opts:supportedOption", lv2ManifestPluginSupportedOptions, 4); | addAttribute(pluginString, "opts:supportedOption", lv2ManifestPluginSupportedOptions, 4); | ||||
#if DISTRHO_PLUGIN_WANT_STATEFILES | |||||
if (hasStateFiles) | |||||
{ | |||||
for (uint32_t i=0, count=plugin.getStateCount(); i < count; ++i) | |||||
{ | |||||
if (! plugin.isStateFile(i)) | |||||
continue; | |||||
const String& key(plugin.getStateKey(i)); | |||||
pluginString += " patch:writable <" DISTRHO_PLUGIN_URI "#" + key + ">;\n"; | |||||
} | |||||
pluginString += "\n"; | |||||
} | |||||
#endif | |||||
// UI | // UI | ||||
#if DISTRHO_PLUGIN_HAS_UI | #if DISTRHO_PLUGIN_HAS_UI | ||||
pluginString += " ui:ui <" DISTRHO_UI_URI "> ;\n"; | pluginString += " ui:ui <" DISTRHO_UI_URI "> ;\n"; | ||||
@@ -582,33 +624,36 @@ void lv2_generate_ttl(const char* const basename) | |||||
// unit | // unit | ||||
const String& unit(plugin.getParameterUnit(i)); | const String& unit(plugin.getParameterUnit(i)); | ||||
if (! unit.isEmpty()) | |||||
if (unit.isNotEmpty() && ! unit.contains(" ")) | |||||
{ | { | ||||
if (unit == "db" || unit == "dB") | |||||
String lunit(unit); | |||||
lunit.toLower(); | |||||
/**/ if (lunit == "db") | |||||
{ | { | ||||
pluginString += " unit:unit unit:db ;\n"; | pluginString += " unit:unit unit:db ;\n"; | ||||
} | } | ||||
else if (unit == "hz" || unit == "Hz") | |||||
else if (lunit == "hz") | |||||
{ | { | ||||
pluginString += " unit:unit unit:hz ;\n"; | pluginString += " unit:unit unit:hz ;\n"; | ||||
} | } | ||||
else if (unit == "khz" || unit == "kHz") | |||||
else if (lunit == "khz") | |||||
{ | { | ||||
pluginString += " unit:unit unit:khz ;\n"; | pluginString += " unit:unit unit:khz ;\n"; | ||||
} | } | ||||
else if (unit == "mhz" || unit == "mHz") | |||||
else if (lunit == "mhz") | |||||
{ | { | ||||
pluginString += " unit:unit unit:mhz ;\n"; | pluginString += " unit:unit unit:mhz ;\n"; | ||||
} | } | ||||
else if (unit == "ms") | |||||
else if (lunit == "ms") | |||||
{ | { | ||||
pluginString += " unit:unit unit:ms ;\n"; | pluginString += " unit:unit unit:ms ;\n"; | ||||
} | } | ||||
else if (unit == "s") | |||||
else if (lunit == "s") | |||||
{ | { | ||||
pluginString += " unit:unit unit:s ;\n"; | pluginString += " unit:unit unit:s ;\n"; | ||||
} | } | ||||
else if (unit == "%") | |||||
else if (lunit == "%") | |||||
{ | { | ||||
pluginString += " unit:unit unit:pc ;\n"; | pluginString += " unit:unit unit:pc ;\n"; | ||||
} | } | ||||
@@ -796,7 +841,7 @@ void lv2_generate_ttl(const char* const basename) | |||||
const String key = plugin.getStateKey(j); | const String key = plugin.getStateKey(j); | ||||
const String value = plugin.getState(key); | const String value = plugin.getState(key); | ||||
presetString += " <urn:distrho:" + key + ">"; | |||||
presetString += " <" DISTRHO_PLUGIN_LV2_STATE_PREFIX + key + ">"; | |||||
if (value.length() < 10) | if (value.length() < 10) | ||||
presetString += " \"" + value + "\" ;\n"; | presetString += " \"" + value + "\" ;\n"; | ||||
@@ -1,6 +1,6 @@ | |||||
/* | /* | ||||
* DISTRHO Plugin Framework (DPF) | * DISTRHO Plugin Framework (DPF) | ||||
* Copyright (C) 2012-2018 Filipe Coelho <falktx@falktx.com> | |||||
* Copyright (C) 2012-2020 Filipe Coelho <falktx@falktx.com> | |||||
* | * | ||||
* Permission to use, copy, modify, and/or distribute this software for any purpose with | * 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 | * or without fee is hereby granted, provided that the above copyright notice and this | ||||
@@ -161,12 +161,24 @@ public: | |||||
class UIVst | class UIVst | ||||
{ | { | ||||
public: | public: | ||||
UIVst(const audioMasterCallback audioMaster, AEffect* const effect, ParameterCheckHelper* const uiHelper, PluginExporter* const plugin, const intptr_t winId, const float scaleFactor) | |||||
UIVst(const audioMasterCallback audioMaster, | |||||
AEffect* const effect, | |||||
ParameterCheckHelper* const uiHelper, | |||||
PluginExporter* const plugin, | |||||
const intptr_t winId, const float scaleFactor) | |||||
: fAudioMaster(audioMaster), | : fAudioMaster(audioMaster), | ||||
fEffect(effect), | fEffect(effect), | ||||
fUiHelper(uiHelper), | fUiHelper(uiHelper), | ||||
fPlugin(plugin), | fPlugin(plugin), | ||||
fUI(this, winId, editParameterCallback, setParameterCallback, setStateCallback, sendNoteCallback, setSizeCallback, scaleFactor, plugin->getInstancePointer()), | |||||
fUI(this, winId, | |||||
editParameterCallback, | |||||
setParameterCallback, | |||||
setStateCallback, | |||||
sendNoteCallback, | |||||
setSizeCallback, | |||||
nullptr, // TODO file request | |||||
scaleFactor, | |||||
plugin->getInstancePointer()), | |||||
fShouldCaptureVstKeys(false) | fShouldCaptureVstKeys(false) | ||||
{ | { | ||||
// FIXME only needed for windows? | // FIXME only needed for windows? | ||||
@@ -581,7 +593,9 @@ public: | |||||
// TODO | // TODO | ||||
const float scaleFactor = 1.0f; | const float scaleFactor = 1.0f; | ||||
UIExporter tmpUI(nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr, scaleFactor, fPlugin.getInstancePointer()); | |||||
UIExporter tmpUI(nullptr, 0, | |||||
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, | |||||
scaleFactor, fPlugin.getInstancePointer()); | |||||
fVstRect.right = tmpUI.getWidth(); | fVstRect.right = tmpUI.getWidth(); | ||||
fVstRect.bottom = tmpUI.getHeight(); | fVstRect.bottom = tmpUI.getHeight(); | ||||
tmpUI.quit(); | tmpUI.quit(); | ||||
@@ -1,6 +1,6 @@ | |||||
/* | /* | ||||
* DISTRHO Plugin Framework (DPF) | * DISTRHO Plugin Framework (DPF) | ||||
* Copyright (C) 2012-2019 Filipe Coelho <falktx@falktx.com> | |||||
* Copyright (C) 2012-2020 Filipe Coelho <falktx@falktx.com> | |||||
* | * | ||||
* Permission to use, copy, modify, and/or distribute this software for any purpose with | * 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 | * or without fee is hereby granted, provided that the above copyright notice and this | ||||
@@ -103,6 +103,13 @@ void UI::setState(const char* key, const char* value) | |||||
} | } | ||||
#endif | #endif | ||||
#if DISTRHO_PLUGIN_WANT_STATEFILES | |||||
bool UI::requestStateFile(const char* key) | |||||
{ | |||||
return pData->fileRequestCallback(key); | |||||
} | |||||
#endif | |||||
#if DISTRHO_PLUGIN_WANT_MIDI_INPUT | #if DISTRHO_PLUGIN_WANT_MIDI_INPUT | ||||
void UI::sendNote(uint8_t channel, uint8_t note, uint8_t velocity) | void UI::sendNote(uint8_t channel, uint8_t note, uint8_t velocity) | ||||
{ | { | ||||
@@ -97,7 +97,7 @@ class UIDssi | |||||
{ | { | ||||
public: | public: | ||||
UIDssi(const OscData& oscData, const char* const uiTitle) | UIDssi(const OscData& oscData, const char* const uiTitle) | ||||
: fUI(this, 0, nullptr, setParameterCallback, setStateCallback, sendNoteCallback, setSizeCallback), | |||||
: fUI(this, 0, nullptr, setParameterCallback, setStateCallback, sendNoteCallback, setSizeCallback, nullptr), | |||||
fHostClosed(false), | fHostClosed(false), | ||||
fOscData(oscData) | fOscData(oscData) | ||||
{ | { | ||||
@@ -1,6 +1,6 @@ | |||||
/* | /* | ||||
* DISTRHO Plugin Framework (DPF) | * DISTRHO Plugin Framework (DPF) | ||||
* Copyright (C) 2012-2019 Filipe Coelho <falktx@falktx.com> | |||||
* Copyright (C) 2012-2020 Filipe Coelho <falktx@falktx.com> | |||||
* | * | ||||
* Permission to use, copy, modify, and/or distribute this software for any purpose with | * 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 | * or without fee is hereby granted, provided that the above copyright notice and this | ||||
@@ -48,11 +48,12 @@ extern Window* d_lastUiWindow; | |||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
// UI callbacks | // UI callbacks | ||||
typedef void (*editParamFunc) (void* ptr, uint32_t rindex, bool started); | |||||
typedef void (*setParamFunc) (void* ptr, uint32_t rindex, float value); | |||||
typedef void (*setStateFunc) (void* ptr, const char* key, const char* value); | |||||
typedef void (*sendNoteFunc) (void* ptr, uint8_t channel, uint8_t note, uint8_t velo); | |||||
typedef void (*setSizeFunc) (void* ptr, uint width, uint height); | |||||
typedef void (*editParamFunc) (void* ptr, uint32_t rindex, bool started); | |||||
typedef void (*setParamFunc) (void* ptr, uint32_t rindex, float value); | |||||
typedef void (*setStateFunc) (void* ptr, const char* key, const char* value); | |||||
typedef void (*sendNoteFunc) (void* ptr, uint8_t channel, uint8_t note, uint8_t velo); | |||||
typedef void (*setSizeFunc) (void* ptr, uint width, uint height); | |||||
typedef bool (*fileRequestFunc) (void* ptr, const char* key); | |||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
// UI private data | // UI private data | ||||
@@ -72,12 +73,13 @@ struct UI::PrivateData { | |||||
uint minHeight; | uint minHeight; | ||||
// Callbacks | // Callbacks | ||||
void* callbacksPtr; | |||||
editParamFunc editParamCallbackFunc; | |||||
setParamFunc setParamCallbackFunc; | |||||
setStateFunc setStateCallbackFunc; | |||||
sendNoteFunc sendNoteCallbackFunc; | |||||
setSizeFunc setSizeCallbackFunc; | |||||
void* callbacksPtr; | |||||
editParamFunc editParamCallbackFunc; | |||||
setParamFunc setParamCallbackFunc; | |||||
setStateFunc setStateCallbackFunc; | |||||
sendNoteFunc sendNoteCallbackFunc; | |||||
setSizeFunc setSizeCallbackFunc; | |||||
fileRequestFunc fileRequestCallbackFunc; | |||||
PrivateData() noexcept | PrivateData() noexcept | ||||
: sampleRate(d_lastUiSampleRate), | : sampleRate(d_lastUiSampleRate), | ||||
@@ -94,7 +96,8 @@ struct UI::PrivateData { | |||||
setParamCallbackFunc(nullptr), | setParamCallbackFunc(nullptr), | ||||
setStateCallbackFunc(nullptr), | setStateCallbackFunc(nullptr), | ||||
sendNoteCallbackFunc(nullptr), | sendNoteCallbackFunc(nullptr), | ||||
setSizeCallbackFunc(nullptr) | |||||
setSizeCallbackFunc(nullptr), | |||||
fileRequestCallbackFunc(nullptr) | |||||
{ | { | ||||
DISTRHO_SAFE_ASSERT(d_isNotZero(sampleRate)); | DISTRHO_SAFE_ASSERT(d_isNotZero(sampleRate)); | ||||
@@ -144,6 +147,16 @@ struct UI::PrivateData { | |||||
if (setSizeCallbackFunc != nullptr) | if (setSizeCallbackFunc != nullptr) | ||||
setSizeCallbackFunc(callbacksPtr, width, height); | setSizeCallbackFunc(callbacksPtr, width, height); | ||||
} | } | ||||
bool fileRequestCallback(const char* key) | |||||
{ | |||||
if (fileRequestCallbackFunc != nullptr) | |||||
return fileRequestCallbackFunc(callbacksPtr, key); | |||||
// TODO use old style DPF dialog here | |||||
return false; | |||||
} | |||||
}; | }; | ||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
@@ -258,6 +271,7 @@ public: | |||||
const setStateFunc setStateCall, | const setStateFunc setStateCall, | ||||
const sendNoteFunc sendNoteCall, | const sendNoteFunc sendNoteCall, | ||||
const setSizeFunc setSizeCall, | const setSizeFunc setSizeCall, | ||||
const fileRequestFunc fileRequestCall, | |||||
const float scaleFactor = 1.0f, | const float scaleFactor = 1.0f, | ||||
void* const dspPtr = nullptr, | void* const dspPtr = nullptr, | ||||
const char* const bundlePath = nullptr) | const char* const bundlePath = nullptr) | ||||
@@ -274,12 +288,13 @@ public: | |||||
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,); | DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,); | ||||
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,); | DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,); | ||||
fData->callbacksPtr = callbacksPtr; | |||||
fData->editParamCallbackFunc = editParamCall; | |||||
fData->setParamCallbackFunc = setParamCall; | |||||
fData->setStateCallbackFunc = setStateCall; | |||||
fData->sendNoteCallbackFunc = sendNoteCall; | |||||
fData->setSizeCallbackFunc = setSizeCall; | |||||
fData->callbacksPtr = callbacksPtr; | |||||
fData->editParamCallbackFunc = editParamCall; | |||||
fData->setParamCallbackFunc = setParamCall; | |||||
fData->setStateCallbackFunc = setStateCall; | |||||
fData->sendNoteCallbackFunc = sendNoteCall; | |||||
fData->setSizeCallbackFunc = setSizeCall; | |||||
fData->fileRequestCallbackFunc = fileRequestCall; | |||||
#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI | #if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI | ||||
// unused | // unused | ||||
@@ -1,6 +1,6 @@ | |||||
/* | /* | ||||
* DISTRHO Plugin Framework (DPF) | * DISTRHO Plugin Framework (DPF) | ||||
* Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com> | |||||
* Copyright (C) 2012-2020 Filipe Coelho <falktx@falktx.com> | |||||
* | * | ||||
* Permission to use, copy, modify, and/or distribute this software for any purpose with | * 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 | * or without fee is hereby granted, provided that the above copyright notice and this | ||||
@@ -19,12 +19,14 @@ | |||||
#include "../extra/String.hpp" | #include "../extra/String.hpp" | ||||
#include "lv2/atom.h" | #include "lv2/atom.h" | ||||
#include "lv2/atom-forge.h" | |||||
#include "lv2/atom-util.h" | #include "lv2/atom-util.h" | ||||
#include "lv2/data-access.h" | #include "lv2/data-access.h" | ||||
#include "lv2/instance-access.h" | #include "lv2/instance-access.h" | ||||
#include "lv2/midi.h" | #include "lv2/midi.h" | ||||
#include "lv2/options.h" | #include "lv2/options.h" | ||||
#include "lv2/parameters.h" | #include "lv2/parameters.h" | ||||
#include "lv2/patch.h" | |||||
#include "lv2/ui.h" | #include "lv2/ui.h" | ||||
#include "lv2/urid.h" | #include "lv2/urid.h" | ||||
#include "lv2/lv2_kxstudio_properties.h" | #include "lv2/lv2_kxstudio_properties.h" | ||||
@@ -47,22 +49,46 @@ static const sendNoteFunc sendNoteCallback = nullptr; | |||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
template <class LV2F> | |||||
static const LV2F* getLv2Feature(const LV2_Feature* const* features, const char* const uri) | |||||
{ | |||||
for (int i=0; features[i] != nullptr; ++i) | |||||
{ | |||||
if (std::strcmp(features[i]->URI, uri) == 0) | |||||
return (const LV2F*)features[i]->data; | |||||
} | |||||
return nullptr; | |||||
} | |||||
class UiLv2 | class UiLv2 | ||||
{ | { | ||||
public: | public: | ||||
UiLv2(const char* const bundlePath, const intptr_t winId, | |||||
const LV2_Options_Option* options, const LV2_URID_Map* const uridMap, const LV2UI_Resize* const uiResz, const LV2UI_Touch* uiTouch, | |||||
const LV2UI_Controller controller, const LV2UI_Write_Function writeFunc, | |||||
const float scaleFactor, LV2UI_Widget* const widget, void* const dspPtr) | |||||
: fUI(this, winId, editParameterCallback, setParameterCallback, setStateCallback, sendNoteCallback, setSizeCallback, scaleFactor, dspPtr, bundlePath), | |||||
UiLv2(const char* const bundlePath, | |||||
const intptr_t winId, | |||||
const LV2_Options_Option* options, | |||||
const LV2_URID_Map* const uridMap, | |||||
const LV2_Feature* const* const features, | |||||
const LV2UI_Controller controller, | |||||
const LV2UI_Write_Function writeFunc, | |||||
const float scaleFactor, | |||||
LV2UI_Widget* const widget, | |||||
void* const dspPtr) | |||||
: fUI(this, winId, | |||||
editParameterCallback, | |||||
setParameterCallback, | |||||
setStateCallback, | |||||
sendNoteCallback, | |||||
setSizeCallback, | |||||
fileRequestCallback, | |||||
scaleFactor, dspPtr, bundlePath), | |||||
fUridMap(uridMap), | fUridMap(uridMap), | ||||
fUiResize(uiResz), | |||||
fUiTouch(uiTouch), | |||||
fUiRequestValue(getLv2Feature<LV2UI_Request_Value>(features, LV2_UI__requestValue)), | |||||
fUiResize(getLv2Feature<LV2UI_Resize>(features, LV2_UI__resize)), | |||||
fUiTouch(getLv2Feature<LV2UI_Touch>(features, LV2_UI__touch)), | |||||
fController(controller), | fController(controller), | ||||
fWriteFunction(writeFunc), | fWriteFunction(writeFunc), | ||||
fEventTransferURID(uridMap->map(uridMap->handle, LV2_ATOM__eventTransfer)), | |||||
fMidiEventURID(uridMap->map(uridMap->handle, LV2_MIDI__MidiEvent)), | |||||
fKeyValueURID(uridMap->map(uridMap->handle, DISTRHO_PLUGIN_LV2_STATE_PREFIX "KeyValueState")), | |||||
fURIDs(uridMap), | |||||
fWinIdWasNull(winId == 0) | fWinIdWasNull(winId == 0) | ||||
{ | { | ||||
if (fUiResize != nullptr && winId != 0) | if (fUiResize != nullptr && winId != 0) | ||||
@@ -82,8 +108,8 @@ public: | |||||
// if winId == 0 then options must not be null | // if winId == 0 then options must not be null | ||||
DISTRHO_SAFE_ASSERT_RETURN(options != nullptr,); | DISTRHO_SAFE_ASSERT_RETURN(options != nullptr,); | ||||
const LV2_URID uridWindowTitle(uridMap->map(uridMap->handle, LV2_UI__windowTitle)); | |||||
const LV2_URID uridTransientWinId(uridMap->map(uridMap->handle, LV2_KXSTUDIO_PROPERTIES__TransientWindowId)); | |||||
const LV2_URID uridWindowTitle = uridMap->map(uridMap->handle, LV2_UI__windowTitle); | |||||
const LV2_URID uridTransientWinId = uridMap->map(uridMap->handle, LV2_KXSTUDIO_PROPERTIES__TransientWindowId); | |||||
bool hasTitle = false; | bool hasTitle = false; | ||||
@@ -91,7 +117,7 @@ public: | |||||
{ | { | ||||
if (options[i].key == uridTransientWinId) | if (options[i].key == uridTransientWinId) | ||||
{ | { | ||||
if (options[i].type == uridMap->map(uridMap->handle, LV2_ATOM__Long)) | |||||
if (options[i].type == fURIDs.atomLong) | |||||
{ | { | ||||
if (const int64_t transientWinId = *(const int64_t*)options[i].value) | if (const int64_t transientWinId = *(const int64_t*)options[i].value) | ||||
fUI.setWindowTransientWinId(static_cast<intptr_t>(transientWinId)); | fUI.setWindowTransientWinId(static_cast<intptr_t>(transientWinId)); | ||||
@@ -101,7 +127,7 @@ public: | |||||
} | } | ||||
else if (options[i].key == uridWindowTitle) | else if (options[i].key == uridWindowTitle) | ||||
{ | { | ||||
if (options[i].type == uridMap->map(uridMap->handle, LV2_ATOM__String)) | |||||
if (options[i].type == fURIDs.atomString) | |||||
{ | { | ||||
if (const char* const windowTitle = (const char*)options[i].value) | if (const char* const windowTitle = (const char*)options[i].value) | ||||
{ | { | ||||
@@ -124,27 +150,32 @@ public: | |||||
{ | { | ||||
if (format == 0) | if (format == 0) | ||||
{ | { | ||||
const uint32_t parameterOffset(fUI.getParameterOffset()); | |||||
const uint32_t parameterOffset = fUI.getParameterOffset(); | |||||
if (rindex < parameterOffset) | if (rindex < parameterOffset) | ||||
return; | return; | ||||
DISTRHO_SAFE_ASSERT_RETURN(bufferSize == sizeof(float),) | DISTRHO_SAFE_ASSERT_RETURN(bufferSize == sizeof(float),) | ||||
const float value(*(const float*)buffer); | |||||
const float value = *(const float*)buffer; | |||||
fUI.parameterChanged(rindex-parameterOffset, value); | fUI.parameterChanged(rindex-parameterOffset, value); | ||||
} | } | ||||
#if DISTRHO_PLUGIN_WANT_STATE | #if DISTRHO_PLUGIN_WANT_STATE | ||||
else if (format == fEventTransferURID) | |||||
else if (format == fURIDs.atomEventTransfer) | |||||
{ | { | ||||
const LV2_Atom* const atom((const LV2_Atom*)buffer); | |||||
DISTRHO_SAFE_ASSERT_RETURN(atom->type == fKeyValueURID,); | |||||
const LV2_Atom* const atom = (const LV2_Atom*)buffer; | |||||
const char* const key = (const char*)LV2_ATOM_BODY_CONST(atom); | |||||
const char* const value = key+(std::strlen(key)+1); | |||||
if (atom->type == fURIDs.dpfKeyValue) | |||||
{ | |||||
const char* const key = (const char*)LV2_ATOM_BODY_CONST(atom); | |||||
const char* const value = key+(std::strlen(key)+1); | |||||
fUI.stateChanged(key, value); | |||||
fUI.stateChanged(key, value); | |||||
} | |||||
else | |||||
{ | |||||
d_stdout("received atom not dpfKeyValue"); | |||||
} | |||||
} | } | ||||
#endif | #endif | ||||
} | } | ||||
@@ -187,11 +218,11 @@ public: | |||||
{ | { | ||||
for (int i=0; options[i].key != 0; ++i) | for (int i=0; options[i].key != 0; ++i) | ||||
{ | { | ||||
if (options[i].key == fUridMap->map(fUridMap->handle, LV2_PARAMETERS__sampleRate)) | |||||
if (options[i].key == fURIDs.paramSampleRate) | |||||
{ | { | ||||
if (options[i].type == fUridMap->map(fUridMap->handle, LV2_ATOM__Float)) | |||||
if (options[i].type == fURIDs.atomFloat) | |||||
{ | { | ||||
const float sampleRate(*(const float*)options[i].value); | |||||
const float sampleRate = *(const float*)options[i].value; | |||||
fUI.setSampleRate(sampleRate); | fUI.setSampleRate(sampleRate); | ||||
continue; | continue; | ||||
} | } | ||||
@@ -211,7 +242,7 @@ public: | |||||
#if DISTRHO_PLUGIN_WANT_PROGRAMS | #if DISTRHO_PLUGIN_WANT_PROGRAMS | ||||
void lv2ui_select_program(const uint32_t bank, const uint32_t program) | void lv2ui_select_program(const uint32_t bank, const uint32_t program) | ||||
{ | { | ||||
const uint32_t realProgram(bank * 128 + program); | |||||
const uint32_t realProgram = bank * 128 + program; | |||||
fUI.programLoaded(realProgram); | fUI.programLoaded(realProgram); | ||||
} | } | ||||
@@ -237,7 +268,7 @@ protected: | |||||
{ | { | ||||
DISTRHO_SAFE_ASSERT_RETURN(fWriteFunction != nullptr,); | DISTRHO_SAFE_ASSERT_RETURN(fWriteFunction != nullptr,); | ||||
const uint32_t eventInPortIndex(DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS); | |||||
const uint32_t eventInPortIndex = DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS; | |||||
// join key and value | // join key and value | ||||
String tmpStr; | String tmpStr; | ||||
@@ -248,23 +279,23 @@ protected: | |||||
tmpStr[std::strlen(key)] = '\0'; | tmpStr[std::strlen(key)] = '\0'; | ||||
// set msg size (key + separator + value + null terminator) | // set msg size (key + separator + value + null terminator) | ||||
const size_t msgSize(tmpStr.length()+1); | |||||
const size_t msgSize = tmpStr.length() + 1U; | |||||
// reserve atom space | // reserve atom space | ||||
const size_t atomSize(sizeof(LV2_Atom) + msgSize); | |||||
const size_t atomSize = sizeof(LV2_Atom) + msgSize; | |||||
char atomBuf[atomSize]; | char atomBuf[atomSize]; | ||||
std::memset(atomBuf, 0, atomSize); | std::memset(atomBuf, 0, atomSize); | ||||
// set atom info | // set atom info | ||||
LV2_Atom* const atom((LV2_Atom*)atomBuf); | |||||
LV2_Atom* const atom = (LV2_Atom*)atomBuf; | |||||
atom->size = msgSize; | atom->size = msgSize; | ||||
atom->type = fKeyValueURID; | |||||
atom->type = fURIDs.dpfKeyValue; | |||||
// set atom data | // set atom data | ||||
std::memcpy(atomBuf + sizeof(LV2_Atom), tmpStr.buffer(), msgSize); | std::memcpy(atomBuf + sizeof(LV2_Atom), tmpStr.buffer(), msgSize); | ||||
// send to DSP side | // send to DSP side | ||||
fWriteFunction(fController, eventInPortIndex, atomSize, fEventTransferURID, atom); | |||||
fWriteFunction(fController, eventInPortIndex, atomSize, fURIDs.atomEventTransfer, atom); | |||||
} | } | ||||
#if DISTRHO_PLUGIN_WANT_MIDI_INPUT | #if DISTRHO_PLUGIN_WANT_MIDI_INPUT | ||||
@@ -275,7 +306,7 @@ protected: | |||||
if (channel > 0xF) | if (channel > 0xF) | ||||
return; | return; | ||||
const uint32_t eventInPortIndex(DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS); | |||||
const uint32_t eventInPortIndex = DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS; | |||||
LV2_Atom_MidiEvent atomMidiEvent; | LV2_Atom_MidiEvent atomMidiEvent; | ||||
atomMidiEvent.atom.size = 3; | atomMidiEvent.atom.size = 3; | ||||
@@ -286,7 +317,8 @@ protected: | |||||
atomMidiEvent.data[2] = velocity; | atomMidiEvent.data[2] = velocity; | ||||
// send to DSP side | // send to DSP side | ||||
fWriteFunction(fController, eventInPortIndex, lv2_atom_total_size(&atomMidiEvent.atom), fEventTransferURID, &atomMidiEvent); | |||||
fWriteFunction(fController, eventInPortIndex, lv2_atom_total_size(&atomMidiEvent.atom), | |||||
fURIDs.atomEventTransfer, &atomMidiEvent); | |||||
} | } | ||||
#endif | #endif | ||||
@@ -298,22 +330,68 @@ protected: | |||||
fUiResize->ui_resize(fUiResize->handle, width, height); | fUiResize->ui_resize(fUiResize->handle, width, height); | ||||
} | } | ||||
bool fileRequest(const char* const key) | |||||
{ | |||||
d_stdout("UI file request %s %p", key, fUiRequestValue); | |||||
if (fUiRequestValue == nullptr) | |||||
return false; | |||||
String dpf_lv2_key(DISTRHO_PLUGIN_URI "#"); | |||||
dpf_lv2_key += key; | |||||
const int r = fUiRequestValue->request(fUiRequestValue->handle, | |||||
fUridMap->map(fUridMap->handle, dpf_lv2_key.buffer()), | |||||
fURIDs.atomPath, | |||||
nullptr); | |||||
d_stdout("UI file request %s %p => %s %i", key, fUiRequestValue, dpf_lv2_key.buffer(), r); | |||||
return r == LV2UI_REQUEST_VALUE_SUCCESS; | |||||
} | |||||
private: | private: | ||||
UIExporter fUI; | UIExporter fUI; | ||||
// LV2 features | // LV2 features | ||||
const LV2_URID_Map* const fUridMap; | |||||
const LV2UI_Resize* const fUiResize; | |||||
const LV2UI_Touch* const fUiTouch; | |||||
const LV2_URID_Map* const fUridMap; | |||||
const LV2UI_Request_Value* const fUiRequestValue; | |||||
const LV2UI_Resize* const fUiResize; | |||||
const LV2UI_Touch* const fUiTouch; | |||||
// LV2 UI stuff | // LV2 UI stuff | ||||
const LV2UI_Controller fController; | const LV2UI_Controller fController; | ||||
const LV2UI_Write_Function fWriteFunction; | const LV2UI_Write_Function fWriteFunction; | ||||
// Need to save this | |||||
const LV2_URID fEventTransferURID; | |||||
const LV2_URID fMidiEventURID; | |||||
const LV2_URID fKeyValueURID; | |||||
// LV2 URIDs | |||||
const struct URIDs { | |||||
const LV2_URID_Map* _uridMap; | |||||
LV2_URID dpfKeyValue; | |||||
LV2_URID atomEventTransfer; | |||||
LV2_URID atomFloat; | |||||
LV2_URID atomLong; | |||||
LV2_URID atomPath; | |||||
LV2_URID atomString; | |||||
LV2_URID midiEvent; | |||||
LV2_URID paramSampleRate; | |||||
LV2_URID patchSet; | |||||
URIDs(const LV2_URID_Map* const uridMap) | |||||
: _uridMap(uridMap), | |||||
dpfKeyValue(map(DISTRHO_PLUGIN_LV2_STATE_PREFIX "KeyValueState")), | |||||
atomEventTransfer(map(LV2_ATOM__eventTransfer)), | |||||
atomFloat(map(LV2_ATOM__Float)), | |||||
atomLong(map(LV2_ATOM__Long)), | |||||
atomPath(map(LV2_ATOM__Path)), | |||||
atomString(map(LV2_ATOM__String)), | |||||
midiEvent(map(LV2_MIDI__MidiEvent)), | |||||
paramSampleRate(map(LV2_PARAMETERS__sampleRate)), | |||||
patchSet(map(LV2_PATCH__Set)) {} | |||||
inline LV2_URID map(const char* const uri) const | |||||
{ | |||||
return _uridMap->map(_uridMap->handle, uri); | |||||
} | |||||
} fURIDs; | |||||
// using ui:showInterface if true | // using ui:showInterface if true | ||||
bool fWinIdWasNull; | bool fWinIdWasNull; | ||||
@@ -350,13 +428,23 @@ private: | |||||
uiPtr->setSize(width, height); | uiPtr->setSize(width, height); | ||||
} | } | ||||
static bool fileRequestCallback(void* ptr, const char* key) | |||||
{ | |||||
return uiPtr->fileRequest(key); | |||||
} | |||||
#undef uiPtr | #undef uiPtr | ||||
}; | }; | ||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
static LV2UI_Handle lv2ui_instantiate(const LV2UI_Descriptor*, const char* uri, const char* bundlePath, | |||||
LV2UI_Write_Function writeFunction, LV2UI_Controller controller, LV2UI_Widget* widget, const LV2_Feature* const* features) | |||||
static LV2UI_Handle lv2ui_instantiate(const LV2UI_Descriptor*, | |||||
const char* const uri, | |||||
const char* const bundlePath, | |||||
const LV2UI_Write_Function writeFunction, | |||||
const LV2UI_Controller controller, | |||||
LV2UI_Widget* const widget, | |||||
const LV2_Feature* const* const features) | |||||
{ | { | ||||
if (uri == nullptr || std::strcmp(uri, DISTRHO_PLUGIN_URI) != 0) | if (uri == nullptr || std::strcmp(uri, DISTRHO_PLUGIN_URI) != 0) | ||||
{ | { | ||||
@@ -364,12 +452,10 @@ static LV2UI_Handle lv2ui_instantiate(const LV2UI_Descriptor*, const char* uri, | |||||
return nullptr; | return nullptr; | ||||
} | } | ||||
const LV2_Options_Option* options = nullptr; | |||||
const LV2_URID_Map* uridMap = nullptr; | |||||
const LV2UI_Resize* uiResize = nullptr; | |||||
const LV2UI_Touch* uiTouch = nullptr; | |||||
void* parentId = nullptr; | |||||
void* instance = nullptr; | |||||
const LV2_Options_Option* options = nullptr; | |||||
const LV2_URID_Map* uridMap = nullptr; | |||||
void* parentId = nullptr; | |||||
void* instance = nullptr; | |||||
#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | #if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | ||||
struct LV2_DirectAccess_Interface { | struct LV2_DirectAccess_Interface { | ||||
@@ -380,16 +466,12 @@ static LV2UI_Handle lv2ui_instantiate(const LV2UI_Descriptor*, const char* uri, | |||||
for (int i=0; features[i] != nullptr; ++i) | for (int i=0; features[i] != nullptr; ++i) | ||||
{ | { | ||||
if (std::strcmp(features[i]->URI, LV2_OPTIONS__options) == 0) | |||||
/**/ if (std::strcmp(features[i]->URI, LV2_OPTIONS__options) == 0) | |||||
options = (const LV2_Options_Option*)features[i]->data; | options = (const LV2_Options_Option*)features[i]->data; | ||||
else if (std::strcmp(features[i]->URI, LV2_URID__map) == 0) | else if (std::strcmp(features[i]->URI, LV2_URID__map) == 0) | ||||
uridMap = (const LV2_URID_Map*)features[i]->data; | uridMap = (const LV2_URID_Map*)features[i]->data; | ||||
else if (std::strcmp(features[i]->URI, LV2_UI__resize) == 0) | |||||
uiResize = (const LV2UI_Resize*)features[i]->data; | |||||
else if (std::strcmp(features[i]->URI, LV2_UI__parent) == 0) | else if (std::strcmp(features[i]->URI, LV2_UI__parent) == 0) | ||||
parentId = features[i]->data; | parentId = features[i]->data; | ||||
else if (std::strcmp(features[i]->URI, LV2_UI__touch) == 0) | |||||
uiTouch = (const LV2UI_Touch*)features[i]->data; | |||||
#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | #if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | ||||
else if (std::strcmp(features[i]->URI, LV2_DATA_ACCESS_URI) == 0) | else if (std::strcmp(features[i]->URI, LV2_DATA_ACCESS_URI) == 0) | ||||
extData = (const LV2_Extension_Data_Feature*)features[i]->data; | extData = (const LV2_Extension_Data_Feature*)features[i]->data; | ||||
@@ -439,9 +521,9 @@ static LV2UI_Handle lv2ui_instantiate(const LV2UI_Descriptor*, const char* uri, | |||||
if (options != nullptr) | if (options != nullptr) | ||||
{ | { | ||||
const LV2_URID uridAtomFloat(uridMap->map(uridMap->handle, LV2_ATOM__Float)); | |||||
const LV2_URID uridSampleRate(uridMap->map(uridMap->handle, LV2_PARAMETERS__sampleRate)); | |||||
const LV2_URID uridScaleFactor(uridMap->map(uridMap->handle, LV2_UI__scaleFactor)); | |||||
const LV2_URID uridAtomFloat = uridMap->map(uridMap->handle, LV2_ATOM__Float); | |||||
const LV2_URID uridSampleRate = uridMap->map(uridMap->handle, LV2_PARAMETERS__sampleRate); | |||||
const LV2_URID uridScaleFactor = uridMap->map(uridMap->handle, LV2_UI__scaleFactor); | |||||
for (int i=0; options[i].key != 0; ++i) | for (int i=0; options[i].key != 0; ++i) | ||||
{ | { | ||||
@@ -468,7 +550,8 @@ static LV2UI_Handle lv2ui_instantiate(const LV2UI_Descriptor*, const char* uri, | |||||
d_lastUiSampleRate = 44100.0; | d_lastUiSampleRate = 44100.0; | ||||
} | } | ||||
return new UiLv2(bundlePath, winId, options, uridMap, uiResize, uiTouch, controller, writeFunction, scaleFactor, widget, instance); | |||||
return new UiLv2(bundlePath, winId, options, uridMap, features, | |||||
controller, writeFunction, scaleFactor, widget, instance); | |||||
} | } | ||||
#define uiPtr ((UiLv2*)ui) | #define uiPtr ((UiLv2*)ui) | ||||