Browse Source

LV2 plugin fixes, implement state save&restore

tags/1.9.4
falkTX 11 years ago
parent
commit
dfd0c8aaff
2 changed files with 158 additions and 30 deletions
  1. +88
    -22
      source/plugin/carla-native-export.cpp
  2. +70
    -8
      source/plugin/carla-native-plugin.cpp

+ 88
- 22
source/plugin/carla-native-export.cpp View File

@@ -123,7 +123,34 @@ void writeManifestFile()
else
text += "<http://kxstudio.sf.net/carla/plugins/" + label + ">\n";

text += " a lv2:Plugin ;\n";
switch (pluginDesc->category)
{
case PLUGIN_CATEGORY_SYNTH:
text += " a lv2:InstrumentPlugin, lv2:Plugin ;\n";
break;
case PLUGIN_CATEGORY_DELAY:
text += " a lv2:DelayPlugin, lv2:Plugin ;\n";
break;
case PLUGIN_CATEGORY_EQ:
text += " a lv2:EQPlugin, lv2:Plugin ;\n";
break;
case PLUGIN_CATEGORY_FILTER:
text += " a lv2:FilterPlugin, lv2:Plugin ;\n";
break;
case PLUGIN_CATEGORY_DYNAMICS:
text += " a lv2:DynamicsPlugin, lv2:Plugin ;\n";
break;
case PLUGIN_CATEGORY_MODULATOR:
text += " a lv2:ModulatorPlugin, lv2:Plugin ;\n";
break;
case PLUGIN_CATEGORY_UTILITY:
text += " a lv2:UtilityPlugin, lv2:Plugin ;\n";
break;
default:
text += " a lv2:Plugin ;\n";
break;
}

text += " lv2:binary <carla-native" PLUGIN_EXT "> ;\n";
text += " rdfs:seeAlso <" + label + ".ttl> .\n";
text += "\n";
@@ -202,26 +229,61 @@ void writePluginFile(const PluginDescriptor* const pluginDesc)
text += "@prefix doap: <http://usefulinc.com/ns/doap#> .\n";
text += "@prefix foaf: <http://xmlns.com/foaf/0.1/> .\n";
text += "@prefix lv2: <" LV2_CORE_PREFIX "> .\n";
text += "@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .\n";
text += "@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n";
text += "@prefix ui: <" LV2_UI_PREFIX "> .\n";
text += "@prefix unit: <" LV2_UNITS_PREFIX "> .\n";
text += "\n";

// -------------------------------------------------------------------
// Plugin
// Plugin URI

if (pluginLabel == "carla")
text += "<http://kxstudio.sf.net/carla>\n";
else
text += "<http://kxstudio.sf.net/carla/plugins/" + pluginLabel + ">\n";

//text += " a " + getPluginType() + " ;\n";
// -------------------------------------------------------------------
// Features

if (pluginDesc->hints & PLUGIN_IS_RTSAFE)
text += " lv2:optionalFeature <" LV2_CORE__hardRTCapable "> ;\n\n";

text += " lv2:requiredFeature <" LV2_BUF_SIZE__boundedBlockLength "> ,\n";

if (pluginDesc->hints & PLUGIN_USES_STATIC_BUFFERS)
text += " <" LV2_BUF_SIZE__fixedBlockLength "> ,\n";

text += " <" LV2_OPTIONS__options "> ,\n";
text += " <" LV2_URID__map "> ;\n";
text += " lv2:extensionData <" LV2_OPTIONS__interface "> ,\n";
text += " <" LV2_STATE__interface "> ,\n";
text += " <" LV2_PROGRAMS__Interface "> ;\n";
text += "\n";

// -------------------------------------------------------------------
// Extensions

text += " lv2:extensionData <" LV2_OPTIONS__interface ">";

if (pluginDesc->hints & PLUGIN_USES_STATE)
{
text += " ,\n";
text += " <" LV2_STATE__interface ">";

if ((pluginDesc->hints & PLUGIN_IS_SYNTH) == 0)
{
text += " ,\n";
text += " <" LV2_PROGRAMS__Interface "> ;\n";
}
else
text += " ;\n";
}
else if ((pluginDesc->hints & PLUGIN_IS_SYNTH) == 0)
{
text += " ,\n";
text += " <" LV2_PROGRAMS__Interface "> ;\n";
}
else
text += " ;\n";

text += "\n";

// -------------------------------------------------------------------
@@ -274,8 +336,6 @@ void writePluginFile(const PluginDescriptor* const pluginDesc)
{
if (i == 1)
text += " lv2:port [\n";
else
text += " [\n";

text += " a lv2:InputPort, atom:AtomPort ;\n";
text += " atom:bufferType atom:Sequence ;\n";
@@ -296,7 +356,7 @@ void writePluginFile(const PluginDescriptor* const pluginDesc)
if (i+1 == pluginDesc->midiIns)
text += " ] ;\n\n";
else
text += " ] ,\n";
text += " ] , [\n";
}

// -------------------------------------------------------------------
@@ -306,8 +366,6 @@ void writePluginFile(const PluginDescriptor* const pluginDesc)
{
if (i == 0)
text += " lv2:port [\n";
else
text += " [\n";

text += " a lv2:OutputPort, atom:AtomPort ;\n";
text += " atom:bufferType atom:Sequence ;\n";
@@ -328,7 +386,7 @@ void writePluginFile(const PluginDescriptor* const pluginDesc)
if (i+1 == pluginDesc->midiOuts)
text += " ] ;\n\n";
else
text += " ] ,\n";
text += " ] , [\n";
}

// -------------------------------------------------------------------
@@ -354,8 +412,6 @@ void writePluginFile(const PluginDescriptor* const pluginDesc)
{
if (i == 0)
text += " lv2:port [\n";
else
text += " [\n";

text += " a lv2:InputPort, lv2:AudioPort ;\n";
text += " lv2:index " + String(portIndex++) + " ;\n";
@@ -365,7 +421,7 @@ void writePluginFile(const PluginDescriptor* const pluginDesc)
if (i+1 == pluginDesc->audioIns)
text += " ] ;\n\n";
else
text += " ] ,\n";
text += " ] , [\n";
}

// -------------------------------------------------------------------
@@ -375,8 +431,6 @@ void writePluginFile(const PluginDescriptor* const pluginDesc)
{
if (i == 0)
text += " lv2:port [\n";
else
text += " [\n";

text += " a lv2:OutputPort, lv2:AudioPort ;\n";
text += " lv2:index " + String(portIndex++) + " ;\n";
@@ -386,7 +440,7 @@ void writePluginFile(const PluginDescriptor* const pluginDesc)
if (i+1 == pluginDesc->audioOuts)
text += " ] ;\n\n";
else
text += " ] ,\n";
text += " ] , [\n";
}

// -------------------------------------------------------------------
@@ -410,8 +464,6 @@ void writePluginFile(const PluginDescriptor* const pluginDesc)

if (i == 0)
text += " lv2:port [\n";
else
text += " [\n";

if (paramInfo->hints & PARAMETER_IS_OUTPUT)
text += " a lv2:OutputPort, lv2:ControlPort ;\n";
@@ -452,8 +504,22 @@ void writePluginFile(const PluginDescriptor* const pluginDesc)
text += " lv2:portProperty <" LV2_PORT_PROPS__notOnGUI "> ;\n";
}

if (paramInfo->scalePointCount > 0)
for (uint32_t j=0; j < paramInfo->scalePointCount; ++j)
{
const ParameterScalePoint* const scalePoint(&paramInfo->scalePoints[j]);

if (j == 0)
text += " lv2:scalePoint [ ";
else
text += " [ ";

text += "rdfs:label \"" + String(scalePoint->label) + "\" ;\n";
text += " rdf:value " + String::formatted("%f", scalePoint->value) + " ";

if (j+1 == paramInfo->scalePointCount)
text += "] ;\n";
else
text += "] ,\n";
}

if (paramUnit.isNotEmpty())
@@ -469,7 +535,7 @@ void writePluginFile(const PluginDescriptor* const pluginDesc)
if (i+1 == paramCount)
text += " ] ;\n\n";
else
text += " ] ,\n";
text += " ] , [\n";
}

text += " doap:name \"" + String(pluginDesc->name) + "\" ;\n";


+ 70
- 8
source/plugin/carla-native-plugin.cpp View File

@@ -85,7 +85,7 @@ public:

if (options == nullptr || uridMap == nullptr)
{
carla_stderr("Host don't provides option or urid-map features");
carla_stderr("Host doesn't provides option or urid-map features");
return;
}

@@ -353,12 +353,41 @@ public:

uint32_t lv2_get_options(LV2_Options_Option* const /*options*/) const
{
return 0;
// currently unused
return LV2_OPTIONS_SUCCESS;
}

uint32_t lv2_set_options(const LV2_Options_Option* const /*options*/)
uint32_t lv2_set_options(const LV2_Options_Option* const options)
{
return 0;
for (int i=0; options[i].key != 0; ++i)
{
if (options[i].key == fUridMap->map(fUridMap->handle, LV2_BUF_SIZE__maxBlockLength))
{
if (options[i].type == fUridMap->map(fUridMap->handle, LV2_ATOM__Int))
{
fBufferSize = *(const int*)options[i].value;

if (fDescriptor->dispatcher != nullptr)
fDescriptor->dispatcher(fHandle, PLUGIN_OPCODE_BUFFER_SIZE_CHANGED, 0, fBufferSize, nullptr, 0.0f);
}
else
carla_stderr("Host changed maxBlockLength but with wrong value type");
}
else if (options[i].key == fUridMap->map(fUridMap->handle, LV2_CORE__sampleRate))
{
if (options[i].type == fUridMap->map(fUridMap->handle, LV2_ATOM__Double))
{
fSampleRate = *(const double*)options[i].value;

if (fDescriptor->dispatcher != nullptr)
fDescriptor->dispatcher(fHandle, PLUGIN_OPCODE_SAMPLE_RATE_CHANGED, 0, 0, nullptr, fSampleRate);
}
else
carla_stderr("Host changed sampleRate but with wrong value type");
}
}

return LV2_OPTIONS_SUCCESS;
}

const LV2_Program_Descriptor* lv2_get_program(const uint32_t index) const
@@ -384,7 +413,7 @@ public:
return &progDesc;
}

void lv2_select_program(uint32_t bank, uint32_t program) const
void lv2_select_program(uint32_t bank, uint32_t program)
{
if (fDescriptor->set_midi_program == nullptr)
return;
@@ -392,14 +421,47 @@ public:
fDescriptor->set_midi_program(fHandle, 0, bank, program);
}

LV2_State_Status lv2_save(const LV2_State_Store_Function /*store*/, const LV2_State_Handle /*handle*/, const uint32_t /*flags*/, const LV2_Feature* const* const /*features*/) const
LV2_State_Status lv2_save(const LV2_State_Store_Function store, const LV2_State_Handle handle, const uint32_t /*flags*/, const LV2_Feature* const* const /*features*/) const
{
if ((fDescriptor->hints & PLUGIN_USES_STATE) == 0 || fDescriptor->get_state == nullptr)
return LV2_STATE_ERR_UNKNOWN;

if (char* const state = fDescriptor->get_state(fHandle))
{
store(handle,
fUridMap->map(fUridMap->handle, "http://kxstudio.sf.net/ns/carla/chunk"),
state,
std::strlen(state),
fUridMap->map(fUridMap->handle, LV2_ATOM__String),
LV2_STATE_IS_POD|LV2_STATE_IS_PORTABLE);

return LV2_STATE_SUCCESS;
}

return LV2_STATE_ERR_UNKNOWN;
}

LV2_State_Status lv2_restore(const LV2_State_Retrieve_Function /*retrieve*/, const LV2_State_Handle /*handle*/, const uint32_t /*flags*/, const LV2_Feature* const* const /*features*/) const
LV2_State_Status lv2_restore(const LV2_State_Retrieve_Function retrieve, const LV2_State_Handle handle, uint32_t flags, const LV2_Feature* const* const /*features*/) const
{
return LV2_STATE_ERR_UNKNOWN;
if ((fDescriptor->hints & PLUGIN_USES_STATE) == 0 || fDescriptor->set_state == nullptr)
return LV2_STATE_ERR_UNKNOWN;

size_t size = 0;
uint32_t type = 0;
const void* data = retrieve(handle, fUridMap->map(fUridMap->handle, "http://kxstudio.sf.net/ns/carla/chunk"), &size, &type, &flags);

if (size == 0)
return LV2_STATE_ERR_UNKNOWN;
if (type == 0)
return LV2_STATE_ERR_UNKNOWN;
if (data == nullptr)
return LV2_STATE_ERR_UNKNOWN;
if (type != fUridMap->map(fUridMap->handle, LV2_ATOM__String))
return LV2_STATE_ERR_BAD_TYPE;

fDescriptor->set_state(fHandle, (const char*)data);

return LV2_STATE_SUCCESS;
}

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


Loading…
Cancel
Save