From 278e1972d89a984a01f6b2618f1063bdfd9e7086 Mon Sep 17 00:00:00 2001 From: falkTX Date: Thu, 31 Oct 2019 21:41:35 +0100 Subject: [PATCH] Add lv2 midnam support; Cleanup CarlaEngine.hpp const usage --- source/backend/CarlaEngine.hpp | 190 +++++++++++---------- source/backend/engine/CarlaEngineJack.cpp | 38 ++++- source/backend/engine/CarlaEnginePorts.cpp | 4 + source/backend/plugin/CarlaPluginLV2.cpp | 68 +++++++- source/includes/lv2/midnam.h | 63 +++++++ source/utils/CarlaLv2Utils.hpp | 1 + 6 files changed, 266 insertions(+), 98 deletions(-) create mode 100644 source/includes/lv2/midnam.h diff --git a/source/backend/CarlaEngine.hpp b/source/backend/CarlaEngine.hpp index 8167d5b4b..d9e8d4b9b 100644 --- a/source/backend/CarlaEngine.hpp +++ b/source/backend/CarlaEngine.hpp @@ -177,7 +177,7 @@ struct CARLA_API EngineControlEvent { * Convert this control event into MIDI data. * Returns size. */ - uint8_t convertToMidiData(const uint8_t channel, uint8_t data[3]) const noexcept; + uint8_t convertToMidiData(uint8_t channel, uint8_t data[3]) const noexcept; }; /*! @@ -216,7 +216,7 @@ struct CARLA_API EngineEvent { /*! * Fill this event from MIDI data. */ - void fillFromMidiData(const uint8_t size, const uint8_t* const data, const uint8_t midiPortOffset) noexcept; + void fillFromMidiData(uint8_t size, const uint8_t* data, uint8_t midiPortOffset) noexcept; }; // ----------------------------------------------------------------------- @@ -335,7 +335,7 @@ struct CARLA_API EngineTimeInfo { EngineTimeInfo& operator=(const EngineTimeInfo&) noexcept; // fast comparison, doesn't check all values - bool compareIgnoringRollingFrames(const EngineTimeInfo& timeInfo, const uint32_t maxFrames) const noexcept; + bool compareIgnoringRollingFrames(const EngineTimeInfo& timeInfo, uint32_t maxFrames) const noexcept; // quick operator, doesn't check all values bool operator==(const EngineTimeInfo& timeInfo) const noexcept; @@ -356,7 +356,7 @@ protected: * The constructor. * All constructor parameters are constant and will never change in the lifetime of the port. */ - CarlaEnginePort(const CarlaEngineClient& client, const bool isInputPort, const uint32_t indexOffset) noexcept; + CarlaEnginePort(const CarlaEngineClient& client, bool isInputPort, uint32_t indexOffset) noexcept; public: /*! @@ -390,6 +390,11 @@ public: return kClient; } + /*! + * Set a meta-data property on this port. + */ + virtual void setMetaData(const char* key, const char* value, const char* type); + #ifndef DOXYGEN protected: const CarlaEngineClient& kClient; @@ -410,7 +415,7 @@ public: * The constructor. * All constructor parameters are constant and will never change in the lifetime of the port. */ - CarlaEngineAudioPort(const CarlaEngineClient& client, const bool isInputPort, const uint32_t indexOffset) noexcept; + CarlaEngineAudioPort(const CarlaEngineClient& client, bool isInputPort, uint32_t indexOffset) noexcept; /*! * The destructor. @@ -457,7 +462,7 @@ public: * The constructor. * All constructor parameters are constant and will never change in the lifetime of the port. */ - CarlaEngineCVPort(const CarlaEngineClient& client, const bool isInputPort, const uint32_t indexOffset) noexcept; + CarlaEngineCVPort(const CarlaEngineClient& client, bool isInputPort, uint32_t indexOffset) noexcept; /*! * The destructor. @@ -504,7 +509,7 @@ public: * The constructor. * All constructor parameters are constant and will never change in the lifetime of the port. */ - CarlaEngineEventPort(const CarlaEngineClient& client, const bool isInputPort, const uint32_t indexOffset) noexcept; + CarlaEngineEventPort(const CarlaEngineClient& client, bool isInputPort, uint32_t indexOffset) noexcept; /*! * The destructor. @@ -534,44 +539,44 @@ public: * Get the event at @a index. * @note You must only call this for input ports. */ - virtual const EngineEvent& getEvent(const uint32_t index) const noexcept; + virtual const EngineEvent& getEvent(uint32_t index) const noexcept; /*! * Get the event at @a index, faster unchecked version. */ - virtual const EngineEvent& getEventUnchecked(const uint32_t index) const noexcept; + virtual const EngineEvent& getEventUnchecked(uint32_t index) const noexcept; /*! * Write a control event into the buffer. * @note You must only call this for output ports. */ - bool writeControlEvent(const uint32_t time, const uint8_t channel, const EngineControlEvent& ctrl) noexcept; + bool writeControlEvent(uint32_t time, uint8_t channel, const EngineControlEvent& ctrl) noexcept; /*! * Write a control event into the buffer. * Arguments are the same as in the EngineControlEvent struct. * @note You must only call this for output ports. */ - virtual bool writeControlEvent(const uint32_t time, const uint8_t channel, const EngineControlEventType type, const uint16_t param, const float value = 0.0f) noexcept; + virtual bool writeControlEvent(uint32_t time, uint8_t channel, EngineControlEventType type, uint16_t param, float value = 0.0f) noexcept; /*! * Write a MIDI event into the buffer. * @note You must only call this for output ports. */ - bool writeMidiEvent(const uint32_t time, const uint8_t size, const uint8_t* const data) noexcept; + bool writeMidiEvent(uint32_t time, uint8_t size, const uint8_t* data) noexcept; /*! * Write a MIDI event into the buffer. * @note You must only call this for output ports. */ - bool writeMidiEvent(const uint32_t time, const uint8_t channel, const EngineMidiEvent& midi) noexcept; + bool writeMidiEvent(uint32_t time, uint8_t channel, const EngineMidiEvent& midi) noexcept; /*! * Write a MIDI event into the buffer. * Arguments are the same as in the EngineMidiEvent struct. * @note You must only call this for output ports. */ - virtual bool writeMidiEvent(const uint32_t time, const uint8_t channel, const uint8_t size, const uint8_t* const data) noexcept; + virtual bool writeMidiEvent(uint32_t time, uint8_t channel, uint8_t size, const uint8_t* data) noexcept; #ifndef DOXYGEN protected: @@ -637,13 +642,13 @@ public: /*! * Change the client's latency. */ - virtual void setLatency(const uint32_t samples) noexcept; + virtual void setLatency(uint32_t samples) noexcept; /*! * Add a new port of type @a portType. * @note This function does nothing in rack processing mode since ports are static there. */ - virtual CarlaEnginePort* addPort(const EnginePortType portType, const char* const name, const bool isInput, const uint32_t indexOffset); + virtual CarlaEnginePort* addPort(EnginePortType portType, const char* name, bool isInput, uint32_t indexOffset); /*! * Get this client's engine. @@ -658,17 +663,17 @@ public: /*! * Get an audio port name. */ - const char* getAudioPortName(const bool isInput, const uint index) const noexcept; + const char* getAudioPortName(bool isInput, uint index) const noexcept; /*! * Get a CV port name. */ - const char* getCVPortName(const bool isInput, const uint index) const noexcept; + const char* getCVPortName(bool isInput, uint index) const noexcept; /*! * Get an event port name. */ - const char* getEventPortName(const bool isInput, const uint index) const noexcept; + const char* getEventPortName(bool isInput, uint index) const noexcept; #ifndef DOXYGEN protected: @@ -678,10 +683,10 @@ protected: struct ProtectedData; ProtectedData* const pData; - void _addAudioPortName(const bool, const char* const); - void _addCVPortName(const bool, const char* const); - void _addEventPortName(const bool, const char* const); - const char* _getUniquePortName(const char* const); + void _addAudioPortName(bool, const char*); + void _addCVPortName(bool, const char*); + void _addEventPortName(bool, const char*); + const char* _getUniquePortName(const char*); void _clearPorts(); CARLA_DECLARE_NON_COPY_CLASS(CarlaEngineClient) @@ -721,30 +726,30 @@ public: /*! * Get the name of the engine driver at @a index. */ - static const char* getDriverName(const uint index); + static const char* getDriverName(uint index); /*! * Get the device names of the driver at @a index. */ - static const char* const* getDriverDeviceNames(const uint index); + static const char* const* getDriverDeviceNames(uint index); /*! * Get device information about the driver at @a index and name @a driverName. */ - static const EngineDriverDeviceInfo* getDriverDeviceInfo(const uint index, const char* const driverName); + static const EngineDriverDeviceInfo* getDriverDeviceInfo(uint index, const char* driverName); /*! * Show a device custom control panel. * @see ENGINE_DRIVER_DEVICE_HAS_CONTROL_PANEL */ - static bool showDriverDeviceControlPanel(const uint index, const char* const deviceName); + static bool showDriverDeviceControlPanel(uint index, const char* deviceName); /*! * Create a new engine, using driver @a driverName. * Returned value must be deleted when no longer needed. * @note This only initializes engine data, it doesn't actually start the engine. */ - static CarlaEngine* newDriverByName(const char* const driverName); + static CarlaEngine* newDriverByName(const char* driverName); // ------------------------------------------------------------------- // Constant values @@ -777,7 +782,7 @@ public: * Initialize/start the engine, using @a clientName. * When the engine is initialized, you need to call idle() at regular intervals. */ - virtual bool init(const char* const clientName) = 0; + virtual bool init(const char* clientName) = 0; /*! * Close engine. @@ -821,7 +826,7 @@ public: * Add new engine client. * @note This function must only be called within a plugin class. */ - virtual CarlaEngineClient* addClient(CarlaPlugin* const plugin); + virtual CarlaEngineClient* addClient(CarlaPlugin* plugin); /*! * Get the current CPU load estimated by the engine. @@ -843,7 +848,7 @@ public: * @see ENGINE_DRIVER_DEVICE_VARIABLE_BUFFER_SIZE * @see ENGINE_DRIVER_DEVICE_VARIABLE_SAMPLE_RATE */ - virtual bool setBufferSizeAndSampleRate(const uint bufferSize, const double sampleRate); + virtual bool setBufferSizeAndSampleRate(uint bufferSize, double sampleRate); /*! * Show the custom control panel for the current engine device. @@ -858,23 +863,23 @@ public: * Add new plugin. * @see ENGINE_CALLBACK_PLUGIN_ADDED */ - bool addPlugin(const BinaryType btype, const PluginType ptype, - const char* const filename, const char* const name, const char* const label, const int64_t uniqueId, - const void* const extra, const uint options); + bool addPlugin(BinaryType btype, PluginType ptype, + const char* filename, const char* name, const char* label, int64_t uniqueId, + const void* extra, uint options); /*! * Add new plugin, using native binary type and default options. * @see ENGINE_CALLBACK_PLUGIN_ADDED */ - bool addPlugin(const PluginType ptype, - const char* const filename, const char* const name, const char* const label, const int64_t uniqueId, - const void* const extra); + bool addPlugin(PluginType ptype, + const char* filename, const char* name, const char* label, int64_t uniqueId, + const void* extra); /*! * Remove plugin with id @a id. * @see ENGINE_CALLBACK_PLUGIN_REMOVED */ - bool removePlugin(const uint id); + bool removePlugin(uint id); /*! * Remove all plugins. @@ -888,24 +893,24 @@ public: * Returned variable must be deleted if non-null. * @see ENGINE_CALLBACK_PLUGIN_RENAMED */ - virtual bool renamePlugin(const uint id, const char* const newName); + virtual bool renamePlugin(uint id, const char* newName); /*! * Clone plugin with id @a id. */ - bool clonePlugin(const uint id); + bool clonePlugin(uint id); /*! * Prepare replace of plugin with id @a id. * The next call to addPlugin() will use this id, replacing the selected plugin. * @note This function requires addPlugin() to be called afterwards, as soon as possible. */ - bool replacePlugin(const uint id) noexcept; + bool replacePlugin(uint id) noexcept; /*! * Switch plugins with id @a idA and @a idB. */ - bool switchPlugins(const uint idA, const uint idB) noexcept; + bool switchPlugins(uint idA, uint idB) noexcept; #endif /*! @@ -915,23 +920,23 @@ public: * @param parameterId The parameter to update * @param touch The new state for the parameter */ - virtual void touchPluginParameter(const uint id, const uint32_t parameterId, const bool touch) noexcept; + virtual void touchPluginParameter(uint id, uint32_t parameterId, bool touch) noexcept; /*! * Get plugin with id @a id. */ - CarlaPlugin* getPlugin(const uint id) const noexcept; + CarlaPlugin* getPlugin(uint id) const noexcept; /*! * Get plugin with id @a id, faster unchecked version. */ - CarlaPlugin* getPluginUnchecked(const uint id) const noexcept; + CarlaPlugin* getPluginUnchecked(uint id) const noexcept; /*! * Get a unique plugin name within the engine. * Returned variable must be deleted if non-null. */ - const char* getUniquePluginName(const char* const name) const; + const char* getUniquePluginName(const char* name) const; // ------------------------------------------------------------------- // Project management @@ -941,18 +946,18 @@ public: * This will try to load a generic file as a plugin, * either by direct handling (SF2 and SFZ) or by using an internal plugin (like Audio and MIDI). */ - bool loadFile(const char* const filename); + bool loadFile(const char* filename); /*! * Load a project file. * @note Already loaded plugins are not removed; call removeAllPlugins() first if needed. */ - bool loadProject(const char* const filename, const bool setAsCurrentProject); + bool loadProject(const char* filename, bool setAsCurrentProject); /*! * Save current project to a file. */ - bool saveProject(const char* const filename, const bool setAsCurrentProject); + bool saveProject(const char* filename, bool setAsCurrentProject); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH /*! @@ -1006,17 +1011,17 @@ public: * Get a plugin's peak values. * @note not thread-safe if pluginId == MAIN_CARLA_PLUGIN_ID */ - const float* getPeaks(const uint pluginId) const noexcept; + const float* getPeaks(uint pluginId) const noexcept; /*! * Get a plugin's input peak value. */ - float getInputPeak(const uint pluginId, const bool isLeft) const noexcept; + float getInputPeak(uint pluginId, bool isLeft) const noexcept; /*! * Get a plugin's output peak value. */ - float getOutputPeak(const uint pluginId, const bool isLeft) const noexcept; + float getOutputPeak(uint pluginId, bool isLeft) const noexcept; // ------------------------------------------------------------------- // Callback @@ -1025,15 +1030,14 @@ public: * Call the main engine callback, if set. * May be called by plugins. */ - virtual void callback(const bool sendHost, const bool sendOsc, - const EngineCallbackOpcode action, const uint pluginId, - const int value1, const int value2, const int value3, - const float valuef, const char* const valueStr) noexcept; + virtual void callback(bool sendHost, bool sendOsc, + EngineCallbackOpcode action, uint pluginId, + int value1, int value2, int value3, float valuef, const char* valueStr) noexcept; /*! * Set the main engine callback to @a func. */ - void setCallback(const EngineCallbackFunc func, void* const ptr) noexcept; + void setCallback(EngineCallbackFunc func, void* ptr) noexcept; // ------------------------------------------------------------------- // Callback @@ -1042,12 +1046,12 @@ public: * Call the file callback, if set. * May be called by plugins. */ - const char* runFileCallback(const FileCallbackOpcode action, const bool isDir, const char* const title, const char* const filter) noexcept; + const char* runFileCallback(FileCallbackOpcode action, bool isDir, const char* title, const char* filter) noexcept; /*! * Set the file callback to @a func. */ - void setFileCallback(const FileCallbackFunc func, void* const ptr) noexcept; + void setFileCallback(FileCallbackFunc func, void* ptr) noexcept; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH // ------------------------------------------------------------------- @@ -1056,19 +1060,19 @@ public: /*! * Connect two patchbay ports. */ - virtual bool patchbayConnect(const bool external, - const uint groupA, const uint portA, - const uint groupB, const uint portB); + virtual bool patchbayConnect(bool external, + uint groupA, uint portA, + uint groupB, uint portB); /*! * Remove a patchbay connection. */ - virtual bool patchbayDisconnect(const bool external, const uint connectionId); + virtual bool patchbayDisconnect(bool external, uint connectionId); /*! * Force the engine to resend all patchbay clients, ports and connections again. */ - virtual bool patchbayRefresh(const bool sendHost, const bool sendOsc, const bool external); + virtual bool patchbayRefresh(bool sendHost, bool sendOsc, bool external); #endif // ------------------------------------------------------------------- @@ -1087,12 +1091,12 @@ public: /*! * Set the engine transport bpm to @a bpm. */ - virtual void transportBPM(const double bpm) noexcept; + virtual void transportBPM(double bpm) noexcept; /*! * Relocate the engine transport to @a frames. */ - virtual void transportRelocate(const uint64_t frame) noexcept; + virtual void transportRelocate(uint64_t frame) noexcept; // ------------------------------------------------------------------- // Error handling @@ -1105,7 +1109,7 @@ public: /*! * Set last error. */ - void setLastError(const char* const error) const noexcept; + void setLastError(const char* error) const noexcept; // ------------------------------------------------------------------- // Misc @@ -1133,7 +1137,7 @@ public: * Tell the engine to stop the current cancelable action. * @see ENGINE_CALLBACK_CANCELABLE_ACTION */ - void setActionCanceled(const bool canceled) noexcept; + void setActionCanceled(bool canceled) noexcept; /*! * Check wherever the last cancelable action was indeed canceled or not. @@ -1146,7 +1150,7 @@ public: /*! * Set the engine option @a option to @a value or @a valueStr. */ - virtual void setOption(const EngineOption option, const int value, const char* const valueStr) noexcept; + virtual void setOption(EngineOption option, int value, const char* valueStr) noexcept; // ------------------------------------------------------------------- // OSC Stuff @@ -1175,14 +1179,14 @@ public: * Return internal data, needed for EventPorts when used in Rack, Patchbay and Bridge modes. * @note RT call */ - EngineEvent* getInternalEventBuffer(const bool isInput) const noexcept; + EngineEvent* getInternalEventBuffer(bool isInput) const noexcept; #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH /*! * Virtual functions for handling external graph ports. */ - virtual bool connectExternalGraphPort(const uint, const uint, const char* const); - virtual bool disconnectExternalGraphPort(const uint, const uint, const char* const); + virtual bool connectExternalGraphPort(uint, uint, const char*); + virtual bool disconnectExternalGraphPort(uint, uint, const char*); #endif // ------------------------------------------------------------------- @@ -1214,24 +1218,24 @@ protected: /*! * Report to all plugins about buffer size change. */ - void bufferSizeChanged(const uint32_t newBufferSize); + void bufferSizeChanged(uint32_t newBufferSize); /*! * Report to all plugins about sample rate change. * This is not supported on all plugin types, in which case they will have to be re-initiated. */ - void sampleRateChanged(const double newSampleRate); + void sampleRateChanged(double newSampleRate); /*! * Report to all plugins about offline mode change. */ - void offlineModeChanged(const bool isOffline); + void offlineModeChanged(bool isOffline); /*! * Set a plugin (stereo) peak values. * @note RT call */ - void setPluginPeaksRT(const uint pluginId, float const inPeaks[2], float const outPeaks[2]) noexcept; + void setPluginPeaksRT(uint pluginId, float const inPeaks[2], float const outPeaks[2]) noexcept; /*! * Common save project function for main engine and plugin. @@ -1251,10 +1255,10 @@ protected: * Virtual functions for handling patchbay state. * Do not free returned data. */ - virtual const char* const* getPatchbayConnections(const bool external) const; - virtual void restorePatchbayConnection(const bool external, - const char* const sourcePort, - const char* const targetPort); + virtual const char* const* getPatchbayConnections(bool external) const; + virtual void restorePatchbayConnection(bool external, + const char* sourcePort, + const char* targetPort); #endif // ------------------------------------------------------------------- @@ -1292,26 +1296,26 @@ public: #ifdef BUILD_BRIDGE // Bridge - static CarlaEngine* newBridge(const char* const audioPoolBaseName, - const char* const rtClientBaseName, - const char* const nonRtClientBaseName, - const char* const nonRtServerBaseName); + static CarlaEngine* newBridge(const char* audioPoolBaseName, + const char* rtClientBaseName, + const char* nonRtClientBaseName, + const char* nonRtServerBaseName); #else # ifdef USING_JUCE // Juce - static CarlaEngine* newJuce(const AudioApi api); + static CarlaEngine* newJuce(AudioApi api); static uint getJuceApiCount(); - static const char* getJuceApiName(const uint index); - static const char* const* getJuceApiDeviceNames(const uint index); - static const EngineDriverDeviceInfo* getJuceDeviceInfo(const uint index, const char* const deviceName); - static bool showJuceDeviceControlPanel(const uint index, const char* const deviceName); + static const char* getJuceApiName(uint index); + static const char* const* getJuceApiDeviceNames(uint index); + static const EngineDriverDeviceInfo* getJuceDeviceInfo(uint index, const char* deviceName); + static bool showJuceDeviceControlPanel(uint index, const char* deviceName); # else // RtAudio - static CarlaEngine* newRtAudio(const AudioApi api); + static CarlaEngine* newRtAudio(AudioApi api); static uint getRtAudioApiCount(); - static const char* getRtAudioApiName(const uint index); - static const char* const* getRtAudioApiDeviceNames(const uint index); - static const EngineDriverDeviceInfo* getRtAudioDeviceInfo(const uint index, const char* const deviceName); + static const char* getRtAudioApiName(uint index); + static const char* const* getRtAudioApiDeviceNames(uint index); + static const EngineDriverDeviceInfo* getRtAudioDeviceInfo(uint index, const char* deviceName); # endif #endif diff --git a/source/backend/engine/CarlaEngineJack.cpp b/source/backend/engine/CarlaEngineJack.cpp index ec36c24e7..29b597de2 100644 --- a/source/backend/engine/CarlaEngineJack.cpp +++ b/source/backend/engine/CarlaEngineJack.cpp @@ -96,7 +96,7 @@ public: case ENGINE_PROCESS_MODE_SINGLE_CLIENT: case ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS: CARLA_SAFE_ASSERT_RETURN(jackClient != nullptr && jackPort != nullptr,); -#ifndef BUILD_BRIDGE +#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH if (const jack_uuid_t uuid = jackbridge_port_uuid(jackPort)) jackbridge_set_property(jackClient, uuid, JACKEY_SIGNAL_TYPE, "AUDIO", "text/plain"); #endif @@ -114,7 +114,7 @@ public: if (fJackClient != nullptr && fJackPort != nullptr) { -#ifndef BUILD_BRIDGE +#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH try { if (const jack_uuid_t uuid = jackbridge_port_uuid(fJackPort)) jackbridge_remove_property(fJackClient, uuid, JACKEY_SIGNAL_TYPE); @@ -158,6 +158,16 @@ public: fJackPort = nullptr; } +#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH + void setMetaData(const char* const key, const char* const value, const char* const type) override + { + try { + if (const jack_uuid_t uuid = jackbridge_port_uuid(fJackPort)) + jackbridge_set_property(fJackClient, uuid, key, value, type); + } CARLA_SAFE_EXCEPTION("Port setMetaData"); + } +#endif + private: jack_client_t* fJackClient; jack_port_t* fJackPort; @@ -188,7 +198,7 @@ public: case ENGINE_PROCESS_MODE_SINGLE_CLIENT: case ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS: CARLA_SAFE_ASSERT_RETURN(jackClient != nullptr && jackPort != nullptr,); -#ifndef BUILD_BRIDGE +#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH if (const jack_uuid_t uuid = jackbridge_port_uuid(jackPort)) jackbridge_set_property(jackClient, uuid, JACKEY_SIGNAL_TYPE, "CV", "text/plain"); #endif @@ -206,7 +216,7 @@ public: if (fJackClient != nullptr && fJackPort != nullptr) { -#ifndef BUILD_BRIDGE +#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH try { if (const jack_uuid_t uuid = jackbridge_port_uuid(fJackPort)) jackbridge_remove_property(fJackClient, uuid, JACKEY_SIGNAL_TYPE); @@ -250,6 +260,16 @@ public: fJackPort = nullptr; } +#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH + void setMetaData(const char* const key, const char* const value, const char* const type) override + { + try { + if (const jack_uuid_t uuid = jackbridge_port_uuid(fJackPort)) + jackbridge_set_property(fJackClient, uuid, key, value, type); + } CARLA_SAFE_EXCEPTION("Port setMetaData"); + } +#endif + private: jack_client_t* fJackClient; jack_port_t* fJackPort; @@ -439,6 +459,16 @@ public: fJackPort = nullptr; } +#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH + void setMetaData(const char* const key, const char* const value, const char* const type) override + { + try { + if (const jack_uuid_t uuid = jackbridge_port_uuid(fJackPort)) + jackbridge_set_property(fJackClient, uuid, key, value, type); + } CARLA_SAFE_EXCEPTION("Port setMetaData"); + } +#endif + private: jack_client_t* fJackClient; jack_port_t* fJackPort; diff --git a/source/backend/engine/CarlaEnginePorts.cpp b/source/backend/engine/CarlaEnginePorts.cpp index 8465da5ac..0eaeded29 100644 --- a/source/backend/engine/CarlaEnginePorts.cpp +++ b/source/backend/engine/CarlaEnginePorts.cpp @@ -42,6 +42,10 @@ CarlaEnginePort::~CarlaEnginePort() noexcept carla_debug("CarlaEnginePort::~CarlaEnginePort()"); } +void CarlaEnginePort::setMetaData(const char*, const char*, const char*) +{ +} + // ----------------------------------------------------------------------- // Carla Engine Audio port diff --git a/source/backend/plugin/CarlaPluginLV2.cpp b/source/backend/plugin/CarlaPluginLV2.cpp index e8a2b8279..0b455742b 100644 --- a/source/backend/plugin/CarlaPluginLV2.cpp +++ b/source/backend/plugin/CarlaPluginLV2.cpp @@ -68,6 +68,7 @@ const uint PLUGIN_HAS_EXTENSION_PROGRAMS = 0x02000; const uint PLUGIN_HAS_EXTENSION_STATE = 0x04000; const uint PLUGIN_HAS_EXTENSION_WORKER = 0x08000; const uint PLUGIN_HAS_EXTENSION_INLINE_DISPLAY = 0x10000; +const uint PLUGIN_HAS_EXTENSION_MIDNAM = 0x20000; // Extra Parameter Hints const uint PARAMETER_IS_STRICT_BOUNDS = 0x1000; @@ -165,6 +166,7 @@ enum CarlaLv2Features { kFeatureIdUridUnmap, kFeatureIdWorker, kFeatureIdInlineDisplay, + kFeatureIdMidnam, kFeatureCountPlugin, // UI features kFeatureIdUiDataAccess = kFeatureCountPlugin, @@ -2835,6 +2837,17 @@ public: if (fEventsOut.ctrl != nullptr && fEventsOut.ctrl->port == nullptr) fEventsOut.ctrl->port = pData->event.portOut; + if (fEventsIn.ctrl != nullptr && fExt.midnam != nullptr) + { + if (char* const midnam = fExt.midnam->midnam(fHandle)) + { + fEventsIn.ctrl->port->setMetaData("http://www.midi.org/dtds/MIDINameDocument10.dtd", + midnam, "text/xml"); + if (fExt.midnam->free != nullptr) + fExt.midnam->free(midnam); + } + } + if (forcedStereoIn || forcedStereoOut) pData->options |= PLUGIN_OPTION_FORCE_STEREO; else @@ -4812,6 +4825,8 @@ public: pData->hints |= PLUGIN_HAS_EXTENSION_WORKER; else if (std::strcmp(extension, LV2_INLINEDISPLAY__interface) == 0) pData->hints |= PLUGIN_HAS_EXTENSION_INLINE_DISPLAY; + else if (std::strcmp(extension, LV2_MIDNAM__interface) == 0) + pData->hints |= PLUGIN_HAS_EXTENSION_MIDNAM; else carla_stdout("Plugin '%s' has non-supported extension: '%s'", fRdfDescriptor->URI, extension); } @@ -4828,7 +4843,14 @@ public: carla_stdout("Plugin '%s' uses inline-display but does not set extension data, nasty!", fRdfDescriptor->URI); pData->hints |= PLUGIN_HAS_EXTENSION_INLINE_DISPLAY; - break; + } + else if (std::strcmp(feature.URI, LV2_MIDNAM__update) == 0) + { + if (pData->hints & PLUGIN_HAS_EXTENSION_MIDNAM) + break; + + carla_stdout("Plugin '%s' uses midnam but does not set extension data, nasty!", fRdfDescriptor->URI); + pData->hints |= PLUGIN_HAS_EXTENSION_MIDNAM; } } @@ -4849,6 +4871,9 @@ public: if (pData->hints & PLUGIN_HAS_EXTENSION_INLINE_DISPLAY) fExt.inlineDisplay = (const LV2_Inline_Display_Interface*)fDescriptor->extension_data(LV2_INLINEDISPLAY__interface); + if (pData->hints & PLUGIN_HAS_EXTENSION_MIDNAM) + fExt.midnam = (const LV2_Midnam_Interface*)fDescriptor->extension_data(LV2_MIDNAM__interface); + // check if invalid if (fExt.options != nullptr && fExt.options->get == nullptr && fExt.options->set == nullptr) fExt.options = nullptr; @@ -4874,6 +4899,9 @@ public: fExt.inlineDisplay = nullptr; } } + + if (fExt.midnam != nullptr && fExt.midnam->midnam == nullptr) + fExt.midnam = nullptr; } CARLA_SAFE_ASSERT_RETURN(fLatencyIndex == -1,); @@ -5185,6 +5213,24 @@ public: // ------------------------------------------------------------------- + void handleMidnamUpdate() + { + CARLA_SAFE_ASSERT_RETURN(fExt.midnam != nullptr,); + + if (fEventsIn.ctrl == nullptr) + return; + + char* const midnam = fExt.midnam->midnam(fHandle); + CARLA_SAFE_ASSERT_RETURN(midnam != nullptr,); + + fEventsIn.ctrl->port->setMetaData("http://www.midi.org/dtds/MIDINameDocument10.dtd", midnam, "text/xml"); + + if (fExt.midnam->free != nullptr) + fExt.midnam->free(midnam); + } + + // ------------------------------------------------------------------- + void handleExternalUIClosed() { CARLA_SAFE_ASSERT_RETURN(fUI.type == UI::TYPE_EXTERNAL,); @@ -5717,6 +5763,10 @@ public: inlineDisplay->handle = this; inlineDisplay->queue_draw = carla_lv2_inline_display_queue_draw; + LV2_Midnam* const midnam = new LV2_Midnam; + midnam->handle = this; + midnam->update = carla_lv2_midnam_update; + // --------------------------------------------------------------- // initialize features (part 2) @@ -5788,6 +5838,9 @@ public: fFeatures[kFeatureIdInlineDisplay]->URI = LV2_INLINEDISPLAY__queue_draw; fFeatures[kFeatureIdInlineDisplay]->data = inlineDisplay; + fFeatures[kFeatureIdMidnam]->URI = LV2_MIDNAM__update; + fFeatures[kFeatureIdMidnam]->data = midnam; + // --------------------------------------------------------------- // initialize plugin @@ -6368,6 +6421,7 @@ private: const LV2_State_Interface* state; const LV2_Worker_Interface* worker; const LV2_Inline_Display_Interface* inlineDisplay; + const LV2_Midnam_Interface* midnam; const LV2_Programs_Interface* programs; const LV2UI_Idle_Interface* uiidle; const LV2UI_Show_Interface* uishow; @@ -6379,6 +6433,7 @@ private: state(nullptr), worker(nullptr), inlineDisplay(nullptr), + midnam(nullptr), programs(nullptr), uiidle(nullptr), uishow(nullptr), @@ -6896,6 +6951,17 @@ private: ((CarlaPluginLV2*)handle)->handleInlineDisplayQueueRedraw(); } + // ------------------------------------------------------------------- + // Midnam Feature + + static void carla_lv2_midnam_update(LV2_Midnam_Handle handle) + { + CARLA_SAFE_ASSERT_RETURN(handle != nullptr,); + carla_stdout("carla_lv2_midnam_update(%p)", handle); + + ((CarlaPluginLV2*)handle)->handleMidnamUpdate(); + } + // ------------------------------------------------------------------- // External UI Feature diff --git a/source/includes/lv2/midnam.h b/source/includes/lv2/midnam.h new file mode 100644 index 000000000..4c2d9988e --- /dev/null +++ b/source/includes/lv2/midnam.h @@ -0,0 +1,63 @@ +/* + Copyright 2016 Robin Gareus + 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 permission notice appear in all copies. + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#ifndef LV2_MIDNAM_H +#define LV2_MIDNAM_H + +#include "lv2.h" + +/** + @defgroup lv2midnam MIDI Naming + @{ +*/ + +#define LV2_MIDNAM_URI "http://ardour.org/lv2/midnam" +#define LV2_MIDNAM_PREFIX LV2_MIDNAM_URI "#" +#define LV2_MIDNAM__interface LV2_MIDNAM_PREFIX "interface" +#define LV2_MIDNAM__update LV2_MIDNAM_PREFIX "update" + +typedef void* LV2_Midnam_Handle; + +/** a LV2 Feature provided by the Host to the plugin */ +typedef struct { + /** Opaque host data */ + LV2_Midnam_Handle handle; + /** Request from run() that the host should re-read the midnam */ + void (*update)(LV2_Midnam_Handle handle); +} LV2_Midnam; + +typedef struct { + /** Query midnam document. The plugin + * is expected to return a null-terminated XML + * text which is a valid midnam desciption + * (or NULL in case of error). + * + * The midnam \ must be unique and + * specific for the given plugin-instance. + */ + char* (*midnam)(LV2_Handle instance); + + /** The unique model id used ith the midnam, + * (or NULL). + */ + char* (*model)(LV2_Handle instance); + + /** free allocated strings. The host + * calls this for every value returned by + * \ref midnam and \ref model. + */ + void (*free)(char*); +} LV2_Midnam_Interface; + +#endif diff --git a/source/utils/CarlaLv2Utils.hpp b/source/utils/CarlaLv2Utils.hpp index 5bf3724d7..5349c32fc 100644 --- a/source/utils/CarlaLv2Utils.hpp +++ b/source/utils/CarlaLv2Utils.hpp @@ -47,6 +47,7 @@ #include "lv2/log.h" // logger #include "lv2/midi.h" +#include "lv2/midnam.h" // morph #include "lv2/options.h" #include "lv2/parameters.h"