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); | |||