Signed-off-by: falkTX <falktx@falktx.com>tags/v2.1-rc1
@@ -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); | |||
} | |||
@@ -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,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; | |||
// ------------------------------------------------------------------- | |||
@@ -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); | |||