Browse Source

Export internal audio and midi players as LV2 plugins

Signed-off-by: falkTX <falktx@falktx.com>
tags/v2.1-rc1
falkTX 5 years ago
parent
commit
9bee2ff784
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
4 changed files with 124 additions and 17 deletions
  1. +4
    -2
      source/plugin/carla-base.cpp
  2. +28
    -12
      source/plugin/carla-lv2-export.cpp
  3. +71
    -3
      source/plugin/carla-lv2.cpp
  4. +21
    -0
      source/utils/CarlaLv2Utils.hpp

+ 4
- 2
source/plugin/carla-base.cpp View File

@@ -59,8 +59,10 @@ struct PluginListManager {
std::strcmp(desc->label, "carlapatchbay3s" ) == 0 ||
std::strcmp(desc->label, "carlapatchbay16" ) == 0 ||
std::strcmp(desc->label, "carlapatchbay32" ) == 0 ||
std::strcmp(desc->label, "bigmeter" ) == 0 /*||
std::strcmp(desc->label, "notes" ) == 0*/)
std::strcmp(desc->label, "bigmeter" ) == 0 ||
/*std::strcmp(desc->label, "notes" ) == 0*/
std::strcmp(desc->label, "audiofile" ) == 0 ||
std::strcmp(desc->label, "midifile" ) == 0)
{
descs.append(desc);
}


+ 28
- 12
source/plugin/carla-lv2-export.cpp View File

@@ -24,6 +24,7 @@
#include "lv2/midi.h"
#include "lv2/options.h"
#include "lv2/parameters.h"
#include "lv2/patch.h"
#include "lv2/port-props.h"
#include "lv2/state.h"
#include "lv2/time.h"
@@ -111,6 +112,7 @@ static void writeManifestFile(PluginListManager& plm)
// -------------------------------------------------------------------
// Header

text += "@prefix atom: <" LV2_ATOM_PREFIX "> .\n";
text += "@prefix lv2: <" LV2_CORE_PREFIX "> .\n";
text += "@prefix opts: <" LV2_OPTIONS_PREFIX "> .\n";
text += "@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n";
@@ -158,6 +160,15 @@ static void writeManifestFile(PluginListManager& plm)
# endif
#endif

// -------------------------------------------------------------------
// File handling

text += "<http://kxstudio.sf.net/carla/file>\n";
text += " a lv2:Parameter ;\n";
text += " rdfs:label \"file\" ;\n";
text += " rdfs:range atom:Path .\n";
text += "\n";

// -------------------------------------------------------------------
// Write file now

@@ -216,15 +227,16 @@ static void writePluginFile(const NativePluginDescriptor* const pluginDesc)
// -------------------------------------------------------------------
// Header

text += "@prefix atom: <" LV2_ATOM_PREFIX "> .\n";
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 opts: <" LV2_OPTIONS_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 += "@prefix atom: <" LV2_ATOM_PREFIX "> .\n";
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 opts: <" LV2_OPTIONS_PREFIX "> .\n";
text += "@prefix patch: <" LV2_PATCH_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";

// -------------------------------------------------------------------
@@ -287,7 +299,7 @@ static void writePluginFile(const NativePluginDescriptor* const pluginDesc)

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

if (pluginDesc->hints & NATIVE_PLUGIN_USES_STATE)
if ((pluginDesc->hints & NATIVE_PLUGIN_USES_STATE) || (pluginDesc->hints & NATIVE_PLUGIN_NEEDS_UI_OPEN_SAVE))
text += " lv2:extensionData <" LV2_STATE__interface "> ;\n";

if (pluginDesc->category != NATIVE_PLUGIN_CATEGORY_SYNTH)
@@ -310,7 +322,7 @@ static void writePluginFile(const NativePluginDescriptor* const pluginDesc)
// UIs

#ifdef HAVE_PYQT
if (pluginDesc->hints & NATIVE_PLUGIN_HAS_UI)
if ((pluginDesc->hints & NATIVE_PLUGIN_HAS_UI) != 0 && (pluginDesc->hints & NATIVE_PLUGIN_NEEDS_UI_OPEN_SAVE) == 0)
{
text += " ui:ui <http://kxstudio.sf.net/carla/ui-ext> ;\n";
text += "\n";
@@ -320,7 +332,8 @@ static void writePluginFile(const NativePluginDescriptor* const pluginDesc)
// -------------------------------------------------------------------
// First input MIDI/Time/UI port

const bool hasEventInPort = (pluginDesc->hints & NATIVE_PLUGIN_USES_TIME) != 0 || (pluginDesc->hints & NATIVE_PLUGIN_HAS_UI) != 0;
const bool hasEventInPort = (pluginDesc->hints & NATIVE_PLUGIN_USES_TIME) != 0
|| (pluginDesc->hints & NATIVE_PLUGIN_HAS_UI) != 0;

if (pluginDesc->midiIns > 0 || hasEventInPort)
{
@@ -375,6 +388,9 @@ static void writePluginFile(const NativePluginDescriptor* const pluginDesc)
text += " ] ;\n\n";
}

if (pluginDesc->hints & NATIVE_PLUGIN_NEEDS_UI_OPEN_SAVE)
text += " patch:writable <http://kxstudio.sf.net/carla/file> ;\n\n";

// -------------------------------------------------------------------
// MIDI inputs



+ 71
- 3
source/plugin/carla-lv2.cpp View File

@@ -71,6 +71,7 @@ public:
#ifdef USING_JUCE
fJuceInitialiser(),
#endif
fLoadedFile(),
fWorkerUISignal(0)
{
carla_zeroStruct(fHost);
@@ -244,6 +245,8 @@ public:

if (event->body.type == fURIs.uiEvents && fWorkerUISignal != -1)
{
CARLA_SAFE_ASSERT_CONTINUE((fDescriptor->hints & NATIVE_PLUGIN_NEEDS_UI_OPEN_SAVE) == 0);

if (fWorker != nullptr)
{
// worker is supported by the host, we can continue
@@ -260,6 +263,34 @@ public:
continue;
}

if (event->body.type == fURIs.atomObject)
{
const LV2_Atom_Object* const obj = (const LV2_Atom_Object*)(&event->body);

if (obj->body.otype == fURIs.patchSet) {
// Get property URI.
const LV2_Atom* property = NULL;
lv2_atom_object_get(obj, fURIs.patchProperty, &property, 0);
CARLA_SAFE_ASSERT_CONTINUE(property != nullptr);
CARLA_SAFE_ASSERT_CONTINUE(property->type == fURIs.atomURID);
CARLA_SAFE_ASSERT_CONTINUE(((const LV2_Atom_URID*)property)->body == fURIs.carlaFile);

// Get value.
const LV2_Atom* fileobj = NULL;
lv2_atom_object_get(obj, fURIs.patchValue, &fileobj, 0);
CARLA_SAFE_ASSERT_CONTINUE(fileobj != nullptr);
CARLA_SAFE_ASSERT_CONTINUE(fileobj->type == fURIs.atomPath);

const char* const filepath((const char*)(fileobj + 1));

fWorker->schedule_work(fWorker->handle,
static_cast<uint32_t>(std::strlen(filepath) + 1U),
filepath);
}

continue;
}

if (event->body.type != fURIs.midiEvent)
continue;
if (event->body.size > 4)
@@ -366,6 +397,17 @@ public:
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 & NATIVE_PLUGIN_NEEDS_UI_OPEN_SAVE)
{
store(handle,
fUridMap->map(fUridMap->handle, "http://kxstudio.sf.net/ns/carla/file"),
fLoadedFile.buffer(),
fLoadedFile.length()+1,
fURIs.atomPath,
LV2_STATE_IS_POD);
return LV2_STATE_SUCCESS;
}

if ((fDescriptor->hints & NATIVE_PLUGIN_USES_STATE) == 0 || fDescriptor->get_state == nullptr)
return LV2_STATE_ERR_NO_FEATURE;

@@ -380,13 +422,31 @@ public:
}

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
uint32_t flags, const LV2_Feature* const* const /*features*/)
{
size_t size = 0;
uint32_t type = 0;

if (fDescriptor->hints & NATIVE_PLUGIN_NEEDS_UI_OPEN_SAVE)
{
size = type = 0;
const void* const data = retrieve(handle,
fUridMap->map(fUridMap->handle, "http://kxstudio.sf.net/ns/carla/file"),
&size, &type, &flags);

CARLA_SAFE_ASSERT_RETURN(type == fURIs.atomPath, LV2_STATE_ERR_UNKNOWN);

const char* const filename = (const char*)data;

fLoadedFile = filename;
fDescriptor->set_custom_data(fHandle, "file", filename);
return LV2_STATE_SUCCESS;
}

if ((fDescriptor->hints & NATIVE_PLUGIN_USES_STATE) == 0 || fDescriptor->set_state == nullptr)
return LV2_STATE_ERR_NO_FEATURE;

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

if (size == 0)
@@ -409,6 +469,13 @@ public:
{
const char* const msg = (const char*)data;

if (fDescriptor->hints & NATIVE_PLUGIN_NEEDS_UI_OPEN_SAVE)
{
fLoadedFile = msg;
fDescriptor->set_custom_data(fHandle, "file", msg);
return LV2_WORKER_SUCCESS;
}

/**/ if (std::strncmp(msg, "control ", 8) == 0)
{
if (fDescriptor->ui_set_parameter_value == nullptr)
@@ -767,6 +834,7 @@ private:
juce::SharedResourcePointer<juce::ScopedJuceInitialiser_GUI> fJuceInitialiser;
#endif

CarlaString fLoadedFile;
int fWorkerUISignal;

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


+ 21
- 0
source/utils/CarlaLv2Utils.hpp View File

@@ -569,6 +569,7 @@ public:
fBufferSize(0),
fSampleRate(sampleRate),
fUridMap(nullptr),
fUridUnmap(nullptr),
fWorker(nullptr),
fTimeInfo(),
fLastPositionData(),
@@ -660,6 +661,7 @@ public:
fUridMap = uridMap;
fURIs.map(uridMap);

fUridUnmap = uridUnmap;
fWorker = worker;

clearTimeData();
@@ -1175,6 +1177,7 @@ protected:

// LV2 host features
const LV2_URID_Map* fUridMap;
const LV2_URID_Unmap* fUridUnmap;
const LV2_Worker_Schedule* fWorker;

// Time info stuff
@@ -1475,9 +1478,15 @@ protected:
LV2_URID atomFloat;
LV2_URID atomInt;
LV2_URID atomLong;
LV2_URID atomPath;
LV2_URID atomSequence;
LV2_URID atomString;
LV2_URID atomURID;
LV2_URID carlaFile;
LV2_URID midiEvent;
LV2_URID patchProperty;
LV2_URID patchSet;
LV2_URID patchValue;
LV2_URID timePos;
LV2_URID timeBar;
LV2_URID timeBarBeat;
@@ -1496,9 +1505,15 @@ protected:
atomFloat(0),
atomInt(0),
atomLong(0),
atomPath(0),
atomSequence(0),
atomString(0),
atomURID(0),
carlaFile(0),
midiEvent(0),
patchProperty(0),
patchSet(0),
patchValue(0),
timePos(0),
timeBar(0),
timeBarBeat(0),
@@ -1518,9 +1533,15 @@ protected:
atomFloat = uridMap->map(uridMap->handle, LV2_ATOM__Float);
atomInt = uridMap->map(uridMap->handle, LV2_ATOM__Int);
atomLong = uridMap->map(uridMap->handle, LV2_ATOM__Long);
atomPath = uridMap->map(uridMap->handle, LV2_ATOM__Path);
atomSequence = uridMap->map(uridMap->handle, LV2_ATOM__Sequence);
atomString = uridMap->map(uridMap->handle, LV2_ATOM__String);
atomURID = uridMap->map(uridMap->handle, LV2_ATOM__URID);
carlaFile = uridMap->map(uridMap->handle, "http://kxstudio.sf.net/carla/file");
midiEvent = uridMap->map(uridMap->handle, LV2_MIDI__MidiEvent);
patchProperty = uridMap->map(uridMap->handle, LV2_PATCH__property);
patchSet = uridMap->map(uridMap->handle, LV2_PATCH__Set);
patchValue = uridMap->map(uridMap->handle, LV2_PATCH__value);
timePos = uridMap->map(uridMap->handle, LV2_TIME__Position);
timeBar = uridMap->map(uridMap->handle, LV2_TIME__bar);
timeBarBeat = uridMap->map(uridMap->handle, LV2_TIME__barBeat);


Loading…
Cancel
Save