| @@ -83,63 +83,14 @@ unsigned int get_engine_driver_count() | |||||
| { | { | ||||
| qDebug("CarlaBackendStandalone::get_engine_driver_count()"); | qDebug("CarlaBackendStandalone::get_engine_driver_count()"); | ||||
| unsigned int count = 0; | |||||
| #ifdef CARLA_ENGINE_JACK | |||||
| count += 1; | |||||
| #endif | |||||
| #ifdef CARLA_ENGINE_RTAUDIO | |||||
| std::vector<RtAudio::Api> apis; | |||||
| RtAudio::getCompiledApi(apis); | |||||
| count += apis.size(); | |||||
| #endif | |||||
| return count; | |||||
| return CarlaBackend::CarlaEngine::getDriverCount(); | |||||
| } | } | ||||
| const char* get_engine_driver_name(unsigned int index) | const char* get_engine_driver_name(unsigned int index) | ||||
| { | { | ||||
| qDebug("CarlaBackendStandalone::get_engine_driver_name(%i)", index); | qDebug("CarlaBackendStandalone::get_engine_driver_name(%i)", index); | ||||
| #ifdef CARLA_ENGINE_JACK | |||||
| if (index == 0) | |||||
| return "JACK"; | |||||
| else | |||||
| index -= 1; | |||||
| #endif | |||||
| #ifdef CARLA_ENGINE_RTAUDIO | |||||
| std::vector<RtAudio::Api> apis; | |||||
| RtAudio::getCompiledApi(apis); | |||||
| if (index < apis.size()) | |||||
| { | |||||
| RtAudio::Api api = apis[index]; | |||||
| switch (api) | |||||
| { | |||||
| case RtAudio::UNSPECIFIED: | |||||
| return "Unspecified"; | |||||
| case RtAudio::LINUX_ALSA: | |||||
| return "ALSA"; | |||||
| case RtAudio::LINUX_PULSE: | |||||
| return "PulseAudio"; | |||||
| case RtAudio::LINUX_OSS: | |||||
| return "OSS"; | |||||
| case RtAudio::UNIX_JACK: | |||||
| return "JACK (RtAudio)"; | |||||
| case RtAudio::MACOSX_CORE: | |||||
| return "CoreAudio"; | |||||
| case RtAudio::WINDOWS_ASIO: | |||||
| return "ASIO"; | |||||
| case RtAudio::WINDOWS_DS: | |||||
| return "DirectSound"; | |||||
| case RtAudio::RTAUDIO_DUMMY: | |||||
| return "Dummy"; | |||||
| } | |||||
| } | |||||
| #endif | |||||
| qWarning("CarlaBackendStandalone::get_engine_driver_name(%i) - invalid index", index); | |||||
| return nullptr; | |||||
| return CarlaBackend::CarlaEngine::getDriverName(index); | |||||
| } | } | ||||
| // ------------------------------------------------------------------------------------------------------------------- | // ------------------------------------------------------------------------------------------------------------------- | ||||
| @@ -183,49 +134,9 @@ bool engine_init(const char* driver_name, const char* client_name) | |||||
| qDebug("CarlaBackendStandalone::engine_init(\"%s\", \"%s\")", driver_name, client_name); | qDebug("CarlaBackendStandalone::engine_init(\"%s\", \"%s\")", driver_name, client_name); | ||||
| CARLA_ASSERT(! carlaEngine); | CARLA_ASSERT(! carlaEngine); | ||||
| #ifdef CARLA_ENGINE_JACK | |||||
| if (strcmp(driver_name, "JACK") == 0) | |||||
| carlaEngine = new CarlaBackend::CarlaEngineJack; | |||||
| #else | |||||
| if (false) | |||||
| pass(); | |||||
| #endif | |||||
| carlaEngine = CarlaBackend::CarlaEngine::newDriverByName(driver_name); | |||||
| #ifdef CARLA_ENGINE_RTAUDIO | |||||
| #ifdef __LINUX_ALSA__ | |||||
| else if (strcmp(driver_name, "ALSA") == 0) | |||||
| carlaEngine = new CarlaBackend::CarlaEngineRtAudio(RtAudio::LINUX_ALSA); | |||||
| #endif | |||||
| #ifdef __LINUX_PULSE__ | |||||
| else if (strcmp(driver_name, "PulseAudio") == 0) | |||||
| carlaEngine = new CarlaBackend::CarlaEngineRtAudio(RtAudio::LINUX_PULSE); | |||||
| #endif | |||||
| #ifdef __LINUX_OSS__ | |||||
| else if (strcmp(driver_name, "OSS") == 0) | |||||
| carlaEngine = new CarlaBackend::CarlaEngineRtAudio(RtAudio::LINUX_OSS); | |||||
| #endif | |||||
| #ifdef __UNIX_JACK__ | |||||
| else if (strcmp(driver_name, "JACK (RtAudio)") == 0) | |||||
| carlaEngine = new CarlaBackend::CarlaEngineRtAudio(RtAudio::UNIX_JACK); | |||||
| #endif | |||||
| #ifdef __MACOSX_CORE__ | |||||
| else if (strcmp(driver_name, "CoreAudio") == 0) | |||||
| carlaEngine = new CarlaBackend::CarlaEngineRtAudio(RtAudio::MACOSX_CORE); | |||||
| #endif | |||||
| #ifdef __WINDOWS_ASIO__ | |||||
| else if (strcmp(driver_name, "ASIO") == 0) | |||||
| carlaEngine = new CarlaBackend::CarlaEngineRtAudio(RtAudio::WINDOWS_ASIO); | |||||
| #endif | |||||
| #ifdef __WINDOWS_DS__ | |||||
| else if (strcmp(driver_name, "DirectSound") == 0) | |||||
| carlaEngine = new CarlaBackend::CarlaEngineRtAudio(RtAudio::WINDOWS_DS); | |||||
| #endif | |||||
| #ifdef __RTAUDIO_DUMMY__ | |||||
| else if (strcmp(driver_name, "Dummy") == 0) | |||||
| carlaEngine = new CarlaBackend::CarlaEngineRtAudio(RtAudio::RTAUDIO_DUMMY); | |||||
| #endif | |||||
| #endif | |||||
| else | |||||
| if (! carlaEngine) | |||||
| { | { | ||||
| CarlaBackend::setLastError("The seleted audio driver is not available!"); | CarlaBackend::setLastError("The seleted audio driver is not available!"); | ||||
| return false; | return false; | ||||
| @@ -245,7 +156,14 @@ bool engine_init(const char* driver_name, const char* client_name) | |||||
| carlaEngineStarted = carlaEngine->init(client_name); | carlaEngineStarted = carlaEngine->init(client_name); | ||||
| if (carlaEngineStarted) | if (carlaEngineStarted) | ||||
| { | |||||
| CarlaBackend::setLastError("no error"); | CarlaBackend::setLastError("no error"); | ||||
| } | |||||
| else if (carlaEngine) | |||||
| { | |||||
| delete carlaEngine; | |||||
| carlaEngine = nullptr; | |||||
| } | |||||
| return carlaEngineStarted; | return carlaEngineStarted; | ||||
| } | } | ||||
| @@ -427,7 +427,7 @@ public: | |||||
| info.copyright = strdup(copyright); | info.copyright = strdup(copyright); | ||||
| if (! m_name) | if (! m_name) | ||||
| m_name = x_engine->getUniqueName(name); | |||||
| m_name = x_engine->getUniquePluginName(name); | |||||
| break; | break; | ||||
| } | } | ||||
| @@ -936,7 +936,7 @@ public: | |||||
| m_filename = strdup(filename); | m_filename = strdup(filename); | ||||
| if (name) | if (name) | ||||
| m_name = x_engine->getUniqueName(name); | |||||
| m_name = x_engine->getUniquePluginName(name); | |||||
| // register plugin now so we can receive OSC (and wait for it) | // register plugin now so we can receive OSC (and wait for it) | ||||
| x_engine->__bridgePluginRegister(m_id, this); | x_engine->__bridgePluginRegister(m_id, this); | ||||
| @@ -102,6 +102,127 @@ unsigned short CarlaEngine::maxPluginNumber() | |||||
| return m_maxPluginNumber; | return m_maxPluginNumber; | ||||
| } | } | ||||
| const char* CarlaEngine::getFixedClientName(const char* const clientName) | |||||
| { | |||||
| char* fixedName = strdup(clientName); | |||||
| for (size_t i=0; i < strlen(fixedName); i++) | |||||
| { | |||||
| if (! (std::isalpha(fixedName[i]) || std::isdigit(fixedName[i]))) | |||||
| fixedName[i] = '_'; | |||||
| } | |||||
| return fixedName; | |||||
| } | |||||
| unsigned int CarlaEngine::getDriverCount() | |||||
| { | |||||
| unsigned int count = 0; | |||||
| #ifdef CARLA_ENGINE_JACK | |||||
| count += 1; | |||||
| #endif | |||||
| #ifdef CARLA_ENGINE_RTAUDIO | |||||
| std::vector<RtAudio::Api> apis; | |||||
| RtAudio::getCompiledApi(apis); | |||||
| count += apis.size(); | |||||
| #endif | |||||
| return count; | |||||
| } | |||||
| const char* CarlaEngine::getDriverName(unsigned int index) | |||||
| { | |||||
| #ifdef CARLA_ENGINE_JACK | |||||
| if (index == 0) | |||||
| return "JACK"; | |||||
| else | |||||
| index -= 1; | |||||
| #endif | |||||
| #ifdef CARLA_ENGINE_RTAUDIO | |||||
| std::vector<RtAudio::Api> apis; | |||||
| RtAudio::getCompiledApi(apis); | |||||
| if (index < apis.size()) | |||||
| { | |||||
| RtAudio::Api api = apis[index]; | |||||
| switch (api) | |||||
| { | |||||
| case RtAudio::UNSPECIFIED: | |||||
| return "Unspecified"; | |||||
| case RtAudio::LINUX_ALSA: | |||||
| return "ALSA"; | |||||
| case RtAudio::LINUX_PULSE: | |||||
| return "PulseAudio"; | |||||
| case RtAudio::LINUX_OSS: | |||||
| return "OSS"; | |||||
| case RtAudio::UNIX_JACK: | |||||
| return "JACK (RtAudio)"; | |||||
| case RtAudio::MACOSX_CORE: | |||||
| return "CoreAudio"; | |||||
| case RtAudio::WINDOWS_ASIO: | |||||
| return "ASIO"; | |||||
| case RtAudio::WINDOWS_DS: | |||||
| return "DirectSound"; | |||||
| case RtAudio::RTAUDIO_DUMMY: | |||||
| return "Dummy"; | |||||
| } | |||||
| } | |||||
| #endif | |||||
| qWarning("CarlaEngine::getDriverName(%i) - invalid index", index); | |||||
| return nullptr; | |||||
| } | |||||
| CarlaEngine* CarlaEngine::newDriverByName(const char* driverName) | |||||
| { | |||||
| #ifdef CARLA_ENGINE_JACK | |||||
| if (strcmp(driverName, "JACK") == 0) | |||||
| return newJack(); | |||||
| #else | |||||
| if (false) | |||||
| pass(); | |||||
| #endif | |||||
| #ifdef CARLA_ENGINE_RTAUDIO | |||||
| #ifdef __LINUX_ALSA__ | |||||
| else if (strcmp(driverName, "ALSA") == 0) | |||||
| return newRtAudio(RtAudio::LINUX_ALSA); | |||||
| #endif | |||||
| #ifdef __LINUX_PULSE__ | |||||
| else if (strcmp(driverName, "PulseAudio") == 0) | |||||
| return newRtAudio(RtAudio::LINUX_PULSE); | |||||
| #endif | |||||
| #ifdef __LINUX_OSS__ | |||||
| else if (strcmp(driverName, "OSS") == 0) | |||||
| return newRtAudio(RtAudio::LINUX_OSS); | |||||
| #endif | |||||
| #ifdef __UNIX_JACK__ | |||||
| else if (strcmp(driverName, "JACK (RtAudio)") == 0) | |||||
| return newRtAudio(RtAudio::UNIX_JACK); | |||||
| #endif | |||||
| #ifdef __MACOSX_CORE__ | |||||
| else if (strcmp(driverName, "CoreAudio") == 0) | |||||
| return newRtAudio(RtAudio::MACOSX_CORE); | |||||
| #endif | |||||
| #ifdef __WINDOWS_ASIO__ | |||||
| else if (strcmp(driverName, "ASIO") == 0) | |||||
| return newRtAudio(RtAudio::WINDOWS_ASIO); | |||||
| #endif | |||||
| #ifdef __WINDOWS_DS__ | |||||
| else if (strcmp(driverName, "DirectSound") == 0) | |||||
| return newRtAudio(RtAudio::WINDOWS_DS); | |||||
| #endif | |||||
| #ifdef __RTAUDIO_DUMMY__ | |||||
| else if (strcmp(driverName, "Dummy") == 0) | |||||
| return newRtAudio(RtAudio::RTAUDIO_DUMMY); | |||||
| #endif | |||||
| #endif | |||||
| return nullptr; | |||||
| } | |||||
| // ----------------------------------------------------------------------- | |||||
| // Virtual, per-engine type calls | |||||
| bool CarlaEngine::init(const char* const clientName) | bool CarlaEngine::init(const char* const clientName) | ||||
| { | { | ||||
| qDebug("CarlaEngine::init(\"%s\")", clientName); | qDebug("CarlaEngine::init(\"%s\")", clientName); | ||||
| @@ -169,9 +290,10 @@ CarlaPlugin* CarlaEngine::getPluginUnchecked(const unsigned short id) const | |||||
| return m_carlaPlugins[id]; | return m_carlaPlugins[id]; | ||||
| } | } | ||||
| const char* CarlaEngine::getUniqueName(const char* const name) | |||||
| const char* CarlaEngine::getUniquePluginName(const char* const name) | |||||
| { | { | ||||
| qDebug("CarlaEngine::getUniqueName(\"%s\")", name); | |||||
| qDebug("CarlaEngine::getUniquePluginName(\"%s\")", name); | |||||
| CARLA_ASSERT(name); | |||||
| QString qname(name); | QString qname(name); | ||||
| @@ -695,10 +817,6 @@ CarlaEngineClient::~CarlaEngineClient() | |||||
| #ifdef CARLA_ENGINE_JACK | #ifdef CARLA_ENGINE_JACK | ||||
| if (handle.jackClient) | if (handle.jackClient) | ||||
| jackbridge_client_close(handle.jackClient); | jackbridge_client_close(handle.jackClient); | ||||
| #endif | |||||
| #ifdef CARLA_ENGINE_RTAUDIO | |||||
| if (handle.rtAudioPtr) | |||||
| delete handle.rtAudioPtr; | |||||
| #endif | #endif | ||||
| } | } | ||||
| } | } | ||||
| @@ -717,10 +835,6 @@ void CarlaEngineClient::activate() | |||||
| #ifdef CARLA_ENGINE_JACK | #ifdef CARLA_ENGINE_JACK | ||||
| if (handle.jackClient) | if (handle.jackClient) | ||||
| jackbridge_activate(handle.jackClient); | jackbridge_activate(handle.jackClient); | ||||
| #endif | |||||
| #ifdef CARLA_ENGINE_RTAUDIO | |||||
| if (handle.rtAudioPtr) | |||||
| handle.rtAudioPtr->startStream(); | |||||
| #endif | #endif | ||||
| } | } | ||||
| } | } | ||||
| @@ -742,10 +856,6 @@ void CarlaEngineClient::deactivate() | |||||
| #ifdef CARLA_ENGINE_JACK | #ifdef CARLA_ENGINE_JACK | ||||
| if (handle.jackClient) | if (handle.jackClient) | ||||
| jackbridge_deactivate(handle.jackClient); | jackbridge_deactivate(handle.jackClient); | ||||
| #endif | |||||
| #ifdef CARLA_ENGINE_RTAUDIO | |||||
| if (handle.rtAudioPtr) | |||||
| handle.rtAudioPtr->stopStream(); | |||||
| #endif | #endif | ||||
| } | } | ||||
| } | } | ||||
| @@ -771,10 +881,6 @@ bool CarlaEngineClient::isOk() const | |||||
| #ifdef CARLA_ENGINE_JACK | #ifdef CARLA_ENGINE_JACK | ||||
| if (handle.type == CarlaEngineTypeJack) | if (handle.type == CarlaEngineTypeJack) | ||||
| return bool(handle.jackClient); | return bool(handle.jackClient); | ||||
| #endif | |||||
| #ifdef CARLA_ENGINE_RTAUDIO | |||||
| if (handle.type == CarlaEngineTypeRtAudio) | |||||
| return bool(handle.rtAudioPtr); | |||||
| #endif | #endif | ||||
| } | } | ||||
| @@ -809,13 +915,6 @@ const CarlaEngineBasePort* CarlaEngineClient::addPort(const CarlaEnginePortType | |||||
| } | } | ||||
| } | } | ||||
| #endif | #endif | ||||
| #ifdef CARLA_ENGINE_RTAUDIO | |||||
| if (handle.type == CarlaEngineTypeRtAudio) | |||||
| { | |||||
| // TODO | |||||
| } | |||||
| #endif | |||||
| } | } | ||||
| switch (portType) | switch (portType) | ||||
| @@ -857,10 +956,6 @@ CarlaEngineBasePort::~CarlaEngineBasePort() | |||||
| if (handle.jackClient && handle.jackPort) | if (handle.jackClient && handle.jackPort) | ||||
| jackbridge_port_unregister(handle.jackClient, handle.jackPort); | jackbridge_port_unregister(handle.jackClient, handle.jackPort); | ||||
| #endif | #endif | ||||
| #ifdef CARLA_ENGINE_RTAUDIO | |||||
| // TODO | |||||
| #endif | |||||
| } | } | ||||
| // ------------------------------------------------------------------------------------------------------------------- | // ------------------------------------------------------------------------------------------------------------------- | ||||
| @@ -918,10 +1013,6 @@ void CarlaEngineControlPort::initBuffer(CarlaEngine* const engine) | |||||
| jackbridge_midi_clear_buffer(buffer); | jackbridge_midi_clear_buffer(buffer); | ||||
| } | } | ||||
| #endif | #endif | ||||
| #ifdef CARLA_ENGINE_RTAUDIO | |||||
| // TODO | |||||
| #endif | |||||
| } | } | ||||
| uint32_t CarlaEngineControlPort::getEventCount() | uint32_t CarlaEngineControlPort::getEventCount() | ||||
| @@ -954,10 +1045,6 @@ uint32_t CarlaEngineControlPort::getEventCount() | |||||
| return jackbridge_midi_get_event_count(buffer); | return jackbridge_midi_get_event_count(buffer); | ||||
| #endif | #endif | ||||
| #ifdef CARLA_ENGINE_RTAUDIO | |||||
| // TODO | |||||
| #endif | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| @@ -1037,10 +1124,6 @@ const CarlaEngineControlEvent* CarlaEngineControlPort::getEvent(uint32_t index) | |||||
| } | } | ||||
| #endif | #endif | ||||
| #ifdef CARLA_ENGINE_RTAUDIO | |||||
| // TODO | |||||
| #endif | |||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| @@ -1116,10 +1199,6 @@ void CarlaEngineControlPort::writeEvent(CarlaEngineControlEventType type, uint32 | |||||
| } | } | ||||
| } | } | ||||
| #endif | #endif | ||||
| #ifdef CARLA_ENGINE_RTAUDIO | |||||
| // TODO | |||||
| #endif | |||||
| } | } | ||||
| // ------------------------------------------------------------------------------------------------------------------- | // ------------------------------------------------------------------------------------------------------------------- | ||||
| @@ -1152,10 +1231,6 @@ void CarlaEngineMidiPort::initBuffer(CarlaEngine* const engine) | |||||
| jackbridge_midi_clear_buffer(buffer); | jackbridge_midi_clear_buffer(buffer); | ||||
| } | } | ||||
| #endif | #endif | ||||
| #ifdef CARLA_ENGINE_RTAUDIO | |||||
| // TODO | |||||
| #endif | |||||
| } | } | ||||
| uint32_t CarlaEngineMidiPort::getEventCount() | uint32_t CarlaEngineMidiPort::getEventCount() | ||||
| @@ -1188,10 +1263,6 @@ uint32_t CarlaEngineMidiPort::getEventCount() | |||||
| return jackbridge_midi_get_event_count(buffer); | return jackbridge_midi_get_event_count(buffer); | ||||
| #endif | #endif | ||||
| #ifdef CARLA_ENGINE_RTAUDIO | |||||
| // TODO | |||||
| #endif | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| @@ -1232,10 +1303,6 @@ const CarlaEngineMidiEvent* CarlaEngineMidiPort::getEvent(uint32_t index) | |||||
| } | } | ||||
| #endif | #endif | ||||
| #ifdef CARLA_ENGINE_RTAUDIO | |||||
| // TODO | |||||
| #endif | |||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| @@ -1275,10 +1342,6 @@ void CarlaEngineMidiPort::writeEvent(uint32_t time, const uint8_t* data, uint8_t | |||||
| if (handle.jackPort) | if (handle.jackPort) | ||||
| jackbridge_midi_event_write(buffer, time, data, size); | jackbridge_midi_event_write(buffer, time, data, size); | ||||
| #endif | #endif | ||||
| #ifdef CARLA_ENGINE_RTAUDIO | |||||
| // TODO | |||||
| #endif | |||||
| } | } | ||||
| // ------------------------------------------------------------------------------------------------------------------- | // ------------------------------------------------------------------------------------------------------------------- | ||||
| @@ -142,18 +142,12 @@ struct CarlaEngineClientNativeHandle { | |||||
| #ifdef CARLA_ENGINE_JACK | #ifdef CARLA_ENGINE_JACK | ||||
| jack_client_t* jackClient; | jack_client_t* jackClient; | ||||
| #endif | #endif | ||||
| #ifdef CARLA_ENGINE_RTAUDIO | |||||
| RtAudio* rtAudioPtr; | |||||
| #endif | |||||
| CarlaEngineClientNativeHandle() | CarlaEngineClientNativeHandle() | ||||
| { | { | ||||
| type = CarlaEngineTypeNull; | type = CarlaEngineTypeNull; | ||||
| #ifdef CARLA_ENGINE_JACK | #ifdef CARLA_ENGINE_JACK | ||||
| jackClient = nullptr; | jackClient = nullptr; | ||||
| #endif | |||||
| #ifdef CARLA_ENGINE_RTAUDIO | |||||
| rtAudioPtr = nullptr; | |||||
| #endif | #endif | ||||
| } | } | ||||
| }; | }; | ||||
| @@ -199,6 +193,11 @@ public: | |||||
| static int maxClientNameSize(); | static int maxClientNameSize(); | ||||
| static int maxPortNameSize(); | static int maxPortNameSize(); | ||||
| static unsigned short maxPluginNumber(); | static unsigned short maxPluginNumber(); | ||||
| static const char* getFixedClientName(const char* const clientName); | |||||
| static unsigned int getDriverCount(); | |||||
| static const char* getDriverName(unsigned int index); | |||||
| static CarlaEngine* newDriverByName(const char* driverName); | |||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| // Virtual, per-engine type calls | // Virtual, per-engine type calls | ||||
| @@ -216,7 +215,7 @@ public: | |||||
| short getNewPluginId() const; | short getNewPluginId() const; | ||||
| CarlaPlugin* getPlugin(const unsigned short id) const; | CarlaPlugin* getPlugin(const unsigned short id) const; | ||||
| CarlaPlugin* getPluginUnchecked(const unsigned short id) const; | CarlaPlugin* getPluginUnchecked(const unsigned short id) const; | ||||
| const char* getUniqueName(const char* const name); | |||||
| const char* getUniquePluginName(const char* const name); | |||||
| short addPlugin(const BinaryType btype, const PluginType ptype, const char* const filename, const char* const name, const char* const label, void* const extra = nullptr); | short addPlugin(const BinaryType btype, const PluginType ptype, const char* const filename, const char* const name, const char* const label, void* const extra = nullptr); | ||||
| short addPlugin(const PluginType ptype, const char* const filename, const char* const name, const char* const label, void* const extra = nullptr); | short addPlugin(const PluginType ptype, const char* const filename, const char* const name, const char* const label, void* const extra = nullptr); | ||||
| @@ -404,6 +403,13 @@ private: | |||||
| double m_outsPeak[MAX_PLUGINS * MAX_PEAKS]; | double m_outsPeak[MAX_PLUGINS * MAX_PEAKS]; | ||||
| static unsigned short m_maxPluginNumber; | static unsigned short m_maxPluginNumber; | ||||
| #ifdef CARLA_ENGINE_JACK | |||||
| static CarlaEngine* newJack(); | |||||
| #endif | |||||
| #ifdef CARLA_ENGINE_RTAUDIO | |||||
| static CarlaEngine* newRtAudio(RtAudio::Api api); | |||||
| #endif | |||||
| }; | }; | ||||
| // ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
| @@ -429,6 +435,7 @@ private: | |||||
| // ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
| // base | |||||
| class CarlaEngineBasePort | class CarlaEngineBasePort | ||||
| { | { | ||||
| public: | public: | ||||
| @@ -443,6 +450,7 @@ protected: | |||||
| const CarlaEnginePortNativeHandle handle; | const CarlaEnginePortNativeHandle handle; | ||||
| }; | }; | ||||
| // audio | |||||
| class CarlaEngineAudioPort : public CarlaEngineBasePort | class CarlaEngineAudioPort : public CarlaEngineBasePort | ||||
| { | { | ||||
| public: | public: | ||||
| @@ -455,6 +463,7 @@ public: | |||||
| #endif | #endif | ||||
| }; | }; | ||||
| // control | |||||
| class CarlaEngineControlPort : public CarlaEngineBasePort | class CarlaEngineControlPort : public CarlaEngineBasePort | ||||
| { | { | ||||
| public: | public: | ||||
| @@ -468,6 +477,7 @@ public: | |||||
| void writeEvent(CarlaEngineControlEventType type, uint32_t time, uint8_t channel, uint8_t controller, double value); | void writeEvent(CarlaEngineControlEventType type, uint32_t time, uint8_t channel, uint8_t controller, double value); | ||||
| }; | }; | ||||
| // midi | |||||
| class CarlaEngineMidiPort : public CarlaEngineBasePort | class CarlaEngineMidiPort : public CarlaEngineBasePort | ||||
| { | { | ||||
| public: | public: | ||||
| @@ -483,84 +493,6 @@ public: | |||||
| // ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
| #ifdef CARLA_ENGINE_JACK | |||||
| class CarlaEngineJack : public CarlaEngine | |||||
| { | |||||
| public: | |||||
| CarlaEngineJack(); | |||||
| ~CarlaEngineJack(); | |||||
| // ------------------------------------- | |||||
| bool init(const char* const clientName); | |||||
| bool close(); | |||||
| bool isOffline(); | |||||
| bool isRunning(); | |||||
| CarlaEngineClient* addClient(CarlaPlugin* const plugin); | |||||
| // ------------------------------------- | |||||
| void handleSampleRateCallback(double newSampleRate); | |||||
| void handleBufferSizeCallback(uint32_t newBufferSize); | |||||
| void handleFreewheelCallback(bool isFreewheel); | |||||
| void handleProcessCallback(uint32_t nframes); | |||||
| void handleShutdownCallback(); | |||||
| // ------------------------------------- | |||||
| private: | |||||
| jack_client_t* client; | |||||
| jack_transport_state_t state; | |||||
| jack_position_t pos; | |||||
| bool freewheel; | |||||
| // ------------------------------------- | |||||
| #ifndef BUILD_BRIDGE | |||||
| static const unsigned short rackPortAudioIn1 = 0; | |||||
| static const unsigned short rackPortAudioIn2 = 1; | |||||
| static const unsigned short rackPortAudioOut1 = 2; | |||||
| static const unsigned short rackPortAudioOut2 = 3; | |||||
| static const unsigned short rackPortControlIn = 4; | |||||
| static const unsigned short rackPortControlOut = 5; | |||||
| static const unsigned short rackPortMidiIn = 6; | |||||
| static const unsigned short rackPortMidiOut = 7; | |||||
| static const unsigned short rackPortCount = 8; | |||||
| jack_port_t* rackJackPorts[rackPortCount]; | |||||
| #endif | |||||
| }; | |||||
| #endif | |||||
| // ----------------------------------------------------------------------- | |||||
| #ifdef CARLA_ENGINE_RTAUDIO | |||||
| class CarlaEngineRtAudio : public CarlaEngine | |||||
| { | |||||
| public: | |||||
| CarlaEngineRtAudio(RtAudio::Api api); | |||||
| ~CarlaEngineRtAudio(); | |||||
| // ------------------------------------- | |||||
| bool init(const char* const clientName); | |||||
| bool close(); | |||||
| bool isOffline(); | |||||
| bool isRunning(); | |||||
| CarlaEngineClient* addClient(CarlaPlugin* const plugin); | |||||
| // ------------------------------------- | |||||
| void handleProcessCallback(void* outputBuffer, void* inputBuffer, unsigned int nframes, double streamTime, RtAudioStreamStatus status); | |||||
| private: | |||||
| RtAudio adac; | |||||
| }; | |||||
| #endif | |||||
| /**@}*/ | /**@}*/ | ||||
| CARLA_BACKEND_END_NAMESPACE | CARLA_BACKEND_END_NAMESPACE | ||||
| @@ -20,492 +20,546 @@ | |||||
| #include "carla_engine.h" | #include "carla_engine.h" | ||||
| #include "carla_plugin.h" | #include "carla_plugin.h" | ||||
| #include <iostream> | |||||
| CARLA_BACKEND_START_NAMESPACE | CARLA_BACKEND_START_NAMESPACE | ||||
| // ------------------------------------------------------------------------------------------------------------------- | |||||
| // static JACK<->Engine calls | |||||
| static int carla_jack_srate_callback(jack_nframes_t newSampleRate, void* arg) | |||||
| { | |||||
| CarlaEngineJack* const engine = (CarlaEngineJack*)arg; | |||||
| engine->handleSampleRateCallback(newSampleRate); | |||||
| return 0; | |||||
| } | |||||
| static int carla_jack_bufsize_callback(jack_nframes_t newBufferSize, void* arg) | |||||
| { | |||||
| CarlaEngineJack* const engine = (CarlaEngineJack*)arg; | |||||
| engine->handleBufferSizeCallback(newBufferSize); | |||||
| return 0; | |||||
| } | |||||
| static void carla_jack_freewheel_callback(int starting, void* arg) | |||||
| { | |||||
| CarlaEngineJack* const engine = (CarlaEngineJack*)arg; | |||||
| engine->handleFreewheelCallback(bool(starting)); | |||||
| } | |||||
| static int carla_jack_process_callback(jack_nframes_t nframes, void* arg) | |||||
| { | |||||
| CarlaEngineJack* const engine = (CarlaEngineJack*)arg; | |||||
| engine->handleProcessCallback(nframes); | |||||
| return 0; | |||||
| } | |||||
| // ----------------------------------------- | |||||
| static int carla_jack_process_callback_plugin(jack_nframes_t nframes, void* arg) | |||||
| class CarlaEngineJack : public CarlaEngine | |||||
| { | { | ||||
| CarlaPlugin* const plugin = (CarlaPlugin*)arg; | |||||
| if (plugin && plugin->enabled()) | |||||
| { | |||||
| plugin->engineProcessLock(); | |||||
| plugin->initBuffers(); | |||||
| plugin->process_jack(nframes); | |||||
| plugin->engineProcessUnlock(); | |||||
| } | |||||
| return 0; | |||||
| } | |||||
| static void carla_jack_shutdown_callback(void* arg) | |||||
| { | |||||
| CarlaEngineJack* const engine = (CarlaEngineJack*)arg; | |||||
| engine->handleShutdownCallback(); | |||||
| } | |||||
| // ------------------------------------------------------------------------------------------------------------------- | |||||
| // Carla Engine (JACK) | |||||
| CarlaEngineJack::CarlaEngineJack() | |||||
| : CarlaEngine() | |||||
| public: | |||||
| CarlaEngineJack() | |||||
| : CarlaEngine() | |||||
| #ifndef BUILD_BRIDGE | #ifndef BUILD_BRIDGE | ||||
| # ifdef Q_COMPILER_INITIALIZER_LISTS | # ifdef Q_COMPILER_INITIALIZER_LISTS | ||||
| , rackJackPorts{nullptr} | |||||
| , rackJackPorts{nullptr} | |||||
| # endif | # endif | ||||
| #endif | #endif | ||||
| { | |||||
| qDebug("CarlaEngineJack::CarlaEngineJack()"); | |||||
| { | |||||
| qDebug("CarlaEngineJack::CarlaEngineJack()"); | |||||
| type = CarlaEngineTypeJack; | |||||
| type = CarlaEngineTypeJack; | |||||
| client = nullptr; | |||||
| state = JackTransportStopped; | |||||
| freewheel = false; | |||||
| client = nullptr; | |||||
| state = JackTransportStopped; | |||||
| freewheel = false; | |||||
| memset(&pos, 0, sizeof(jack_position_t)); | |||||
| memset(&pos, 0, sizeof(jack_position_t)); | |||||
| #ifndef BUILD_BRIDGE | #ifndef BUILD_BRIDGE | ||||
| # ifndef Q_COMPILER_INITIALIZER_LISTS | # ifndef Q_COMPILER_INITIALIZER_LISTS | ||||
| for (unsigned short i=0; i < rackPortCount; i++) | |||||
| rackJackPorts[i] = nullptr; | |||||
| for (unsigned short i=0; i < rackPortCount; i++) | |||||
| rackJackPorts[i] = nullptr; | |||||
| # endif | # endif | ||||
| #endif | #endif | ||||
| } | |||||
| } | |||||
| CarlaEngineJack::~CarlaEngineJack() | |||||
| { | |||||
| qDebug("CarlaEngineJack::~CarlaEngineJack()"); | |||||
| } | |||||
| ~CarlaEngineJack() | |||||
| { | |||||
| qDebug("CarlaEngineJack::~CarlaEngineJack()"); | |||||
| } | |||||
| // ------------------------------------------------------------------------------------------------------------------- | |||||
| // ------------------------------------- | |||||
| bool CarlaEngineJack::init(const char* const clientName) | |||||
| { | |||||
| qDebug("CarlaEngineJack::init(\"%s\")", clientName); | |||||
| bool init(const char* const clientName) | |||||
| { | |||||
| qDebug("CarlaEngineJack::init(\"%s\")", clientName); | |||||
| client = jackbridge_client_open(clientName, JackNullOption, nullptr); | |||||
| state = JackTransportStopped; | |||||
| freewheel = false; | |||||
| client = jackbridge_client_open(clientName, JackNullOption, nullptr); | |||||
| state = JackTransportStopped; | |||||
| freewheel = false; | |||||
| if (client) | |||||
| { | |||||
| sampleRate = jackbridge_get_sample_rate(client); | |||||
| bufferSize = jackbridge_get_buffer_size(client); | |||||
| if (client) | |||||
| { | |||||
| sampleRate = jackbridge_get_sample_rate(client); | |||||
| bufferSize = jackbridge_get_buffer_size(client); | |||||
| jackbridge_set_sample_rate_callback(client, carla_jack_srate_callback, this); | |||||
| jackbridge_set_buffer_size_callback(client, carla_jack_bufsize_callback, this); | |||||
| jackbridge_set_freewheel_callback(client, carla_jack_freewheel_callback, this); | |||||
| jackbridge_set_process_callback(client, carla_jack_process_callback, this); | |||||
| jackbridge_on_shutdown(client, carla_jack_shutdown_callback, this); | |||||
| jackbridge_set_sample_rate_callback(client, carla_jack_srate_callback, this); | |||||
| jackbridge_set_buffer_size_callback(client, carla_jack_bufsize_callback, this); | |||||
| jackbridge_set_freewheel_callback(client, carla_jack_freewheel_callback, this); | |||||
| jackbridge_set_process_callback(client, carla_jack_process_callback, this); | |||||
| jackbridge_on_shutdown(client, carla_jack_shutdown_callback, this); | |||||
| #ifndef BUILD_BRIDGE | #ifndef BUILD_BRIDGE | ||||
| if (carlaOptions.processMode == PROCESS_MODE_CONTINUOUS_RACK) | |||||
| { | |||||
| rackJackPorts[rackPortAudioIn1] = jackbridge_port_register(client, "in1", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); | |||||
| rackJackPorts[rackPortAudioIn2] = jackbridge_port_register(client, "in2", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); | |||||
| rackJackPorts[rackPortAudioOut1] = jackbridge_port_register(client, "out1", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); | |||||
| rackJackPorts[rackPortAudioOut2] = jackbridge_port_register(client, "out2", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); | |||||
| rackJackPorts[rackPortControlIn] = jackbridge_port_register(client, "control-in", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0); | |||||
| rackJackPorts[rackPortControlOut] = jackbridge_port_register(client, "control-out", JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0); | |||||
| rackJackPorts[rackPortMidiIn] = jackbridge_port_register(client, "midi-in", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0); | |||||
| rackJackPorts[rackPortMidiOut] = jackbridge_port_register(client, "midi-out", JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0); | |||||
| } | |||||
| if (carlaOptions.processMode == PROCESS_MODE_CONTINUOUS_RACK) | |||||
| { | |||||
| rackJackPorts[rackPortAudioIn1] = jackbridge_port_register(client, "in1", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); | |||||
| rackJackPorts[rackPortAudioIn2] = jackbridge_port_register(client, "in2", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); | |||||
| rackJackPorts[rackPortAudioOut1] = jackbridge_port_register(client, "out1", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); | |||||
| rackJackPorts[rackPortAudioOut2] = jackbridge_port_register(client, "out2", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); | |||||
| rackJackPorts[rackPortControlIn] = jackbridge_port_register(client, "control-in", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0); | |||||
| rackJackPorts[rackPortControlOut] = jackbridge_port_register(client, "control-out", JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0); | |||||
| rackJackPorts[rackPortMidiIn] = jackbridge_port_register(client, "midi-in", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0); | |||||
| rackJackPorts[rackPortMidiOut] = jackbridge_port_register(client, "midi-out", JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0); | |||||
| } | |||||
| #endif | #endif | ||||
| if (jackbridge_activate(client) == 0) | |||||
| { | |||||
| // set client name, fixed for OSC usage | |||||
| // FIXME - put this in shared? | |||||
| char* fixedName = strdup(jackbridge_get_client_name(client)); | |||||
| for (size_t i=0; i < strlen(fixedName); i++) | |||||
| if (jackbridge_activate(client) == 0) | |||||
| { | |||||
| name = getFixedClientName(jackbridge_get_client_name(client)); | |||||
| CarlaEngine::init(name); | |||||
| return true; | |||||
| } | |||||
| else | |||||
| { | { | ||||
| if (! (std::isalpha(fixedName[i]) || std::isdigit(fixedName[i]))) | |||||
| fixedName[i] = '_'; | |||||
| setLastError("Failed to activate the JACK client"); | |||||
| client = nullptr; | |||||
| } | } | ||||
| } | |||||
| else | |||||
| setLastError("Failed to create new JACK client"); | |||||
| name = strdup(fixedName); | |||||
| free((void*)fixedName); | |||||
| return false; | |||||
| } | |||||
| CarlaEngine::init(name); | |||||
| bool close() | |||||
| { | |||||
| qDebug("CarlaEngineJack::close()"); | |||||
| CarlaEngine::close(); | |||||
| return true; | |||||
| if (name) | |||||
| { | |||||
| free((void*)name); | |||||
| name = nullptr; | |||||
| } | } | ||||
| else | |||||
| if (jackbridge_deactivate(client) == 0) | |||||
| { | { | ||||
| setLastError("Failed to activate the JACK client"); | |||||
| client = nullptr; | |||||
| #ifndef BUILD_BRIDGE | |||||
| if (carlaOptions.processMode == PROCESS_MODE_CONTINUOUS_RACK) | |||||
| { | |||||
| jackbridge_port_unregister(client, rackJackPorts[rackPortAudioIn1]); | |||||
| jackbridge_port_unregister(client, rackJackPorts[rackPortAudioIn2]); | |||||
| jackbridge_port_unregister(client, rackJackPorts[rackPortAudioOut1]); | |||||
| jackbridge_port_unregister(client, rackJackPorts[rackPortAudioOut2]); | |||||
| jackbridge_port_unregister(client, rackJackPorts[rackPortControlIn]); | |||||
| jackbridge_port_unregister(client, rackJackPorts[rackPortControlOut]); | |||||
| jackbridge_port_unregister(client, rackJackPorts[rackPortMidiIn]); | |||||
| jackbridge_port_unregister(client, rackJackPorts[rackPortMidiOut]); | |||||
| } | |||||
| #endif | |||||
| if (jackbridge_client_close(client) == 0) | |||||
| { | |||||
| client = nullptr; | |||||
| return true; | |||||
| } | |||||
| else | |||||
| setLastError("Failed to close the JACK client"); | |||||
| } | } | ||||
| } | |||||
| else | |||||
| setLastError("Failed to create new JACK client"); | |||||
| else | |||||
| setLastError("Failed to deactivate the JACK client"); | |||||
| return false; | |||||
| } | |||||
| client = nullptr; | |||||
| return false; | |||||
| } | |||||
| bool CarlaEngineJack::close() | |||||
| { | |||||
| qDebug("CarlaEngineJack::close()"); | |||||
| CarlaEngine::close(); | |||||
| bool isOffline() | |||||
| { | |||||
| return freewheel; | |||||
| } | |||||
| if (name) | |||||
| bool isRunning() | |||||
| { | { | ||||
| free((void*)name); | |||||
| name = nullptr; | |||||
| return bool(client); | |||||
| } | } | ||||
| if (jackbridge_deactivate(client) == 0) | |||||
| CarlaEngineClient* addClient(CarlaPlugin* const plugin) | |||||
| { | { | ||||
| CarlaEngineClientNativeHandle handle; | |||||
| handle.type = CarlaEngineTypeJack; | |||||
| #ifndef BUILD_BRIDGE | #ifndef BUILD_BRIDGE | ||||
| if (carlaOptions.processMode == PROCESS_MODE_CONTINUOUS_RACK) | |||||
| if (carlaOptions.processMode == PROCESS_MODE_SINGLE_CLIENT) | |||||
| { | { | ||||
| jackbridge_port_unregister(client, rackJackPorts[rackPortAudioIn1]); | |||||
| jackbridge_port_unregister(client, rackJackPorts[rackPortAudioIn2]); | |||||
| jackbridge_port_unregister(client, rackJackPorts[rackPortAudioOut1]); | |||||
| jackbridge_port_unregister(client, rackJackPorts[rackPortAudioOut2]); | |||||
| jackbridge_port_unregister(client, rackJackPorts[rackPortControlIn]); | |||||
| jackbridge_port_unregister(client, rackJackPorts[rackPortControlOut]); | |||||
| jackbridge_port_unregister(client, rackJackPorts[rackPortMidiIn]); | |||||
| jackbridge_port_unregister(client, rackJackPorts[rackPortMidiOut]); | |||||
| handle.jackClient = client; | |||||
| } | } | ||||
| else if (carlaOptions.processMode == PROCESS_MODE_MULTIPLE_CLIENTS) | |||||
| #endif | #endif | ||||
| if (jackbridge_client_close(client) == 0) | |||||
| { | { | ||||
| client = nullptr; | |||||
| return true; | |||||
| handle.jackClient = jackbridge_client_open(plugin->name(), JackNullOption, nullptr); | |||||
| jackbridge_set_process_callback(handle.jackClient, carla_jack_process_callback_plugin, plugin); | |||||
| } | } | ||||
| else | |||||
| setLastError("Failed to close the JACK client"); | |||||
| } | |||||
| else | |||||
| setLastError("Failed to deactivate the JACK client"); | |||||
| client = nullptr; | |||||
| return false; | |||||
| } | |||||
| bool CarlaEngineJack::isOffline() | |||||
| { | |||||
| return freewheel; | |||||
| } | |||||
| bool CarlaEngineJack::isRunning() | |||||
| { | |||||
| return bool(client); | |||||
| } | |||||
| return new CarlaEngineClient(handle); | |||||
| } | |||||
| CarlaEngineClient* CarlaEngineJack::addClient(CarlaPlugin* const plugin) | |||||
| { | |||||
| CarlaEngineClientNativeHandle handle; | |||||
| handle.type = type; | |||||
| // ------------------------------------- | |||||
| #ifndef BUILD_BRIDGE | |||||
| if (carlaOptions.processMode == PROCESS_MODE_SINGLE_CLIENT) | |||||
| { | |||||
| handle.jackClient = client; | |||||
| } | |||||
| else if (carlaOptions.processMode == PROCESS_MODE_MULTIPLE_CLIENTS) | |||||
| #endif | |||||
| protected: | |||||
| void handleSampleRateCallback(double newSampleRate) | |||||
| { | { | ||||
| handle.jackClient = jackbridge_client_open(plugin->name(), JackNullOption, nullptr); | |||||
| jackbridge_set_process_callback(handle.jackClient, carla_jack_process_callback_plugin, plugin); | |||||
| sampleRate = newSampleRate; | |||||
| } | } | ||||
| //else if (carla_options.process_mode == PROCESS_MODE_CONTINUOUS_RACK) | |||||
| //{ | |||||
| //} | |||||
| return new CarlaEngineClient(handle); | |||||
| } | |||||
| // ------------------------------------------------------------------------------------------------------------------- | |||||
| void CarlaEngineJack::handleSampleRateCallback(double newSampleRate) | |||||
| { | |||||
| sampleRate = newSampleRate; | |||||
| } | |||||
| void CarlaEngineJack::handleBufferSizeCallback(uint32_t newBufferSize) | |||||
| { | |||||
| void handleBufferSizeCallback(uint32_t newBufferSize) | |||||
| { | |||||
| #ifndef BUILD_BRIDGE | #ifndef BUILD_BRIDGE | ||||
| if (carlaOptions.processHighPrecision) | |||||
| return; | |||||
| if (carlaOptions.processHighPrecision) | |||||
| return; | |||||
| #endif | #endif | ||||
| bufferSizeChanged(newBufferSize); | |||||
| } | |||||
| bufferSizeChanged(newBufferSize); | |||||
| } | |||||
| void CarlaEngineJack::handleFreewheelCallback(bool isFreewheel) | |||||
| { | |||||
| freewheel = isFreewheel; | |||||
| } | |||||
| void handleFreewheelCallback(bool isFreewheel) | |||||
| { | |||||
| freewheel = isFreewheel; | |||||
| } | |||||
| void CarlaEngineJack::handleProcessCallback(uint32_t nframes) | |||||
| { | |||||
| void handleProcessCallback(uint32_t nframes) | |||||
| { | |||||
| #ifndef BUILD_BRIDGE | #ifndef BUILD_BRIDGE | ||||
| if (maxPluginNumber() == 0) | |||||
| return; | |||||
| if (maxPluginNumber() == 0) | |||||
| return; | |||||
| #endif | #endif | ||||
| state = jackbridge_transport_query(client, &pos); | |||||
| state = jackbridge_transport_query(client, &pos); | |||||
| timeInfo.playing = (state != JackTransportStopped); | |||||
| timeInfo.playing = (state != JackTransportStopped); | |||||
| if (pos.unique_1 == pos.unique_2) | |||||
| { | |||||
| timeInfo.frame = pos.frame; | |||||
| timeInfo.time = pos.usecs; | |||||
| if (pos.valid & JackPositionBBT) | |||||
| if (pos.unique_1 == pos.unique_2) | |||||
| { | { | ||||
| timeInfo.valid = CarlaEngineTimeBBT; | |||||
| timeInfo.bbt.bar = pos.bar; | |||||
| timeInfo.bbt.beat = pos.beat; | |||||
| timeInfo.bbt.tick = pos.tick; | |||||
| timeInfo.bbt.bar_start_tick = pos.bar_start_tick; | |||||
| timeInfo.bbt.beats_per_bar = pos.beats_per_bar; | |||||
| timeInfo.bbt.beat_type = pos.beat_type; | |||||
| timeInfo.bbt.ticks_per_beat = pos.ticks_per_beat; | |||||
| timeInfo.bbt.beats_per_minute = pos.beats_per_minute; | |||||
| timeInfo.frame = pos.frame; | |||||
| timeInfo.time = pos.usecs; | |||||
| if (pos.valid & JackPositionBBT) | |||||
| { | |||||
| timeInfo.valid = CarlaEngineTimeBBT; | |||||
| timeInfo.bbt.bar = pos.bar; | |||||
| timeInfo.bbt.beat = pos.beat; | |||||
| timeInfo.bbt.tick = pos.tick; | |||||
| timeInfo.bbt.bar_start_tick = pos.bar_start_tick; | |||||
| timeInfo.bbt.beats_per_bar = pos.beats_per_bar; | |||||
| timeInfo.bbt.beat_type = pos.beat_type; | |||||
| timeInfo.bbt.ticks_per_beat = pos.ticks_per_beat; | |||||
| timeInfo.bbt.beats_per_minute = pos.beats_per_minute; | |||||
| } | |||||
| else | |||||
| timeInfo.valid = 0; | |||||
| } | } | ||||
| else | else | ||||
| { | |||||
| timeInfo.frame = 0; | |||||
| timeInfo.valid = 0; | timeInfo.valid = 0; | ||||
| } | |||||
| else | |||||
| { | |||||
| timeInfo.frame = 0; | |||||
| timeInfo.valid = 0; | |||||
| } | |||||
| } | |||||
| #ifndef BUILD_BRIDGE | #ifndef BUILD_BRIDGE | ||||
| if (carlaOptions.processMode == PROCESS_MODE_SINGLE_CLIENT) | |||||
| { | |||||
| for (unsigned short i=0, max=maxPluginNumber(); i < max; i++) | |||||
| if (carlaOptions.processMode == PROCESS_MODE_SINGLE_CLIENT) | |||||
| { | { | ||||
| CarlaPlugin* const plugin = getPluginUnchecked(i); | |||||
| if (plugin && plugin->enabled()) | |||||
| for (unsigned short i=0, max=maxPluginNumber(); i < max; i++) | |||||
| { | { | ||||
| plugin->engineProcessLock(); | |||||
| plugin->initBuffers(); | |||||
| plugin->process_jack(nframes); | |||||
| plugin->engineProcessUnlock(); | |||||
| CarlaPlugin* const plugin = getPluginUnchecked(i); | |||||
| if (plugin && plugin->enabled()) | |||||
| { | |||||
| plugin->engineProcessLock(); | |||||
| plugin->initBuffers(); | |||||
| processPlugin(plugin, nframes); | |||||
| plugin->engineProcessUnlock(); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| } | |||||
| else if (carlaOptions.processMode == PROCESS_MODE_CONTINUOUS_RACK) | |||||
| { | |||||
| // get buffers from jack | |||||
| float* audioIn1 = (float*)jackbridge_port_get_buffer(rackJackPorts[rackPortAudioIn1], nframes); | |||||
| float* audioIn2 = (float*)jackbridge_port_get_buffer(rackJackPorts[rackPortAudioIn2], nframes); | |||||
| float* audioOut1 = (float*)jackbridge_port_get_buffer(rackJackPorts[rackPortAudioOut1], nframes); | |||||
| float* audioOut2 = (float*)jackbridge_port_get_buffer(rackJackPorts[rackPortAudioOut2], nframes); | |||||
| void* controlIn = jackbridge_port_get_buffer(rackJackPorts[rackPortControlIn], nframes); | |||||
| void* controlOut = jackbridge_port_get_buffer(rackJackPorts[rackPortControlOut], nframes); | |||||
| void* midiIn = jackbridge_port_get_buffer(rackJackPorts[rackPortMidiIn], nframes); | |||||
| void* midiOut = jackbridge_port_get_buffer(rackJackPorts[rackPortMidiOut], nframes); | |||||
| // assert buffers | |||||
| CARLA_ASSERT(audioIn1); | |||||
| CARLA_ASSERT(audioIn2); | |||||
| CARLA_ASSERT(audioOut1); | |||||
| CARLA_ASSERT(audioOut2); | |||||
| CARLA_ASSERT(controlIn); | |||||
| CARLA_ASSERT(controlOut); | |||||
| CARLA_ASSERT(midiIn); | |||||
| CARLA_ASSERT(midiOut); | |||||
| // create audio buffers | |||||
| float* inBuf[2] = { audioIn1, audioIn2 }; | |||||
| float* outBuf[2] = { audioOut1, audioOut2 }; | |||||
| // initialize control input | |||||
| memset(rackControlEventsIn, 0, sizeof(CarlaEngineControlEvent)*MAX_ENGINE_CONTROL_EVENTS); | |||||
| else if (carlaOptions.processMode == PROCESS_MODE_CONTINUOUS_RACK) | |||||
| { | { | ||||
| jackbridge_midi_event_t jackEvent; | |||||
| const uint32_t jackEventCount = jackbridge_midi_get_event_count(controlIn); | |||||
| uint32_t carlaEventIndex = 0; | |||||
| for (uint32_t jackEventIndex=0; jackEventIndex < jackEventCount; jackEventIndex++) | |||||
| // get buffers from jack | |||||
| float* audioIn1 = (float*)jackbridge_port_get_buffer(rackJackPorts[rackPortAudioIn1], nframes); | |||||
| float* audioIn2 = (float*)jackbridge_port_get_buffer(rackJackPorts[rackPortAudioIn2], nframes); | |||||
| float* audioOut1 = (float*)jackbridge_port_get_buffer(rackJackPorts[rackPortAudioOut1], nframes); | |||||
| float* audioOut2 = (float*)jackbridge_port_get_buffer(rackJackPorts[rackPortAudioOut2], nframes); | |||||
| void* controlIn = jackbridge_port_get_buffer(rackJackPorts[rackPortControlIn], nframes); | |||||
| void* controlOut = jackbridge_port_get_buffer(rackJackPorts[rackPortControlOut], nframes); | |||||
| void* midiIn = jackbridge_port_get_buffer(rackJackPorts[rackPortMidiIn], nframes); | |||||
| void* midiOut = jackbridge_port_get_buffer(rackJackPorts[rackPortMidiOut], nframes); | |||||
| // assert buffers | |||||
| CARLA_ASSERT(audioIn1); | |||||
| CARLA_ASSERT(audioIn2); | |||||
| CARLA_ASSERT(audioOut1); | |||||
| CARLA_ASSERT(audioOut2); | |||||
| CARLA_ASSERT(controlIn); | |||||
| CARLA_ASSERT(controlOut); | |||||
| CARLA_ASSERT(midiIn); | |||||
| CARLA_ASSERT(midiOut); | |||||
| // create audio buffers | |||||
| float* inBuf[2] = { audioIn1, audioIn2 }; | |||||
| float* outBuf[2] = { audioOut1, audioOut2 }; | |||||
| // initialize control input | |||||
| memset(rackControlEventsIn, 0, sizeof(CarlaEngineControlEvent)*MAX_ENGINE_CONTROL_EVENTS); | |||||
| { | { | ||||
| if (jackbridge_midi_event_get(&jackEvent, controlIn, jackEventIndex) != 0) | |||||
| continue; | |||||
| jackbridge_midi_event_t jackEvent; | |||||
| const uint32_t jackEventCount = jackbridge_midi_get_event_count(controlIn); | |||||
| CarlaEngineControlEvent* const carlaEvent = &rackControlEventsIn[carlaEventIndex++]; | |||||
| uint32_t carlaEventIndex = 0; | |||||
| uint8_t midiStatus = jackEvent.buffer[0]; | |||||
| uint8_t midiChannel = midiStatus & 0x0F; | |||||
| for (uint32_t jackEventIndex=0; jackEventIndex < jackEventCount; jackEventIndex++) | |||||
| { | |||||
| if (jackbridge_midi_event_get(&jackEvent, controlIn, jackEventIndex) != 0) | |||||
| continue; | |||||
| carlaEvent->time = jackEvent.time; | |||||
| carlaEvent->channel = midiChannel; | |||||
| CarlaEngineControlEvent* const carlaEvent = &rackControlEventsIn[carlaEventIndex++]; | |||||
| if (MIDI_IS_STATUS_CONTROL_CHANGE(midiStatus)) | |||||
| { | |||||
| uint8_t midiControl = jackEvent.buffer[1]; | |||||
| uint8_t midiStatus = jackEvent.buffer[0]; | |||||
| uint8_t midiChannel = midiStatus & 0x0F; | |||||
| if (MIDI_IS_CONTROL_BANK_SELECT(midiControl)) | |||||
| { | |||||
| uint8_t midiBank = jackEvent.buffer[2]; | |||||
| carlaEvent->type = CarlaEngineEventMidiBankChange; | |||||
| carlaEvent->value = midiBank; | |||||
| } | |||||
| else if (midiControl == MIDI_CONTROL_ALL_SOUND_OFF) | |||||
| carlaEvent->time = jackEvent.time; | |||||
| carlaEvent->channel = midiChannel; | |||||
| if (MIDI_IS_STATUS_CONTROL_CHANGE(midiStatus)) | |||||
| { | { | ||||
| carlaEvent->type = CarlaEngineEventAllSoundOff; | |||||
| uint8_t midiControl = jackEvent.buffer[1]; | |||||
| if (MIDI_IS_CONTROL_BANK_SELECT(midiControl)) | |||||
| { | |||||
| uint8_t midiBank = jackEvent.buffer[2]; | |||||
| carlaEvent->type = CarlaEngineEventMidiBankChange; | |||||
| carlaEvent->value = midiBank; | |||||
| } | |||||
| else if (midiControl == MIDI_CONTROL_ALL_SOUND_OFF) | |||||
| { | |||||
| carlaEvent->type = CarlaEngineEventAllSoundOff; | |||||
| } | |||||
| else if (midiControl == MIDI_CONTROL_ALL_NOTES_OFF) | |||||
| { | |||||
| carlaEvent->type = CarlaEngineEventAllNotesOff; | |||||
| } | |||||
| else | |||||
| { | |||||
| uint8_t midiValue = jackEvent.buffer[2]; | |||||
| carlaEvent->type = CarlaEngineEventControlChange; | |||||
| carlaEvent->controller = midiControl; | |||||
| carlaEvent->value = double(midiValue)/127; | |||||
| } | |||||
| } | } | ||||
| else if (midiControl == MIDI_CONTROL_ALL_NOTES_OFF) | |||||
| else if (MIDI_IS_STATUS_PROGRAM_CHANGE(midiStatus)) | |||||
| { | { | ||||
| carlaEvent->type = CarlaEngineEventAllNotesOff; | |||||
| uint8_t midiProgram = jackEvent.buffer[1]; | |||||
| carlaEvent->type = CarlaEngineEventMidiProgramChange; | |||||
| carlaEvent->value = midiProgram; | |||||
| } | } | ||||
| else | |||||
| } | |||||
| } | |||||
| // initialize midi input | |||||
| memset(rackMidiEventsIn, 0, sizeof(CarlaEngineMidiEvent)*MAX_ENGINE_MIDI_EVENTS); | |||||
| { | |||||
| uint32_t i = 0, j = 0; | |||||
| jackbridge_midi_event_t jackEvent; | |||||
| while (jackbridge_midi_event_get(&jackEvent, midiIn, j++) == 0) | |||||
| { | |||||
| if (i == MAX_ENGINE_MIDI_EVENTS) | |||||
| break; | |||||
| if (jackEvent.size < 4) | |||||
| { | { | ||||
| uint8_t midiValue = jackEvent.buffer[2]; | |||||
| carlaEvent->type = CarlaEngineEventControlChange; | |||||
| carlaEvent->controller = midiControl; | |||||
| carlaEvent->value = double(midiValue)/127; | |||||
| rackMidiEventsIn[i].time = jackEvent.time; | |||||
| rackMidiEventsIn[i].size = jackEvent.size; | |||||
| memcpy(rackMidiEventsIn[i].data, jackEvent.buffer, jackEvent.size); | |||||
| i += 1; | |||||
| } | } | ||||
| } | } | ||||
| else if (MIDI_IS_STATUS_PROGRAM_CHANGE(midiStatus)) | |||||
| } | |||||
| // process rack | |||||
| processRack(inBuf, outBuf, nframes); | |||||
| // output control | |||||
| { | |||||
| jackbridge_midi_clear_buffer(controlOut); | |||||
| for (unsigned short i=0; i < MAX_ENGINE_CONTROL_EVENTS; i++) | |||||
| { | { | ||||
| uint8_t midiProgram = jackEvent.buffer[1]; | |||||
| carlaEvent->type = CarlaEngineEventMidiProgramChange; | |||||
| carlaEvent->value = midiProgram; | |||||
| CarlaEngineControlEvent* const event = &rackControlEventsOut[i]; | |||||
| if (event->type == CarlaEngineEventControlChange && MIDI_IS_CONTROL_BANK_SELECT(event->controller)) | |||||
| event->type = CarlaEngineEventMidiBankChange; | |||||
| uint8_t data[4] = { 0 }; | |||||
| switch (event->type) | |||||
| { | |||||
| case CarlaEngineEventNull: | |||||
| break; | |||||
| case CarlaEngineEventControlChange: | |||||
| data[0] = MIDI_STATUS_CONTROL_CHANGE + event->channel; | |||||
| data[1] = event->controller; | |||||
| data[2] = event->value * 127; | |||||
| jackbridge_midi_event_write(controlOut, event->time, data, 3); | |||||
| break; | |||||
| case CarlaEngineEventMidiBankChange: | |||||
| data[0] = MIDI_STATUS_CONTROL_CHANGE + event->channel; | |||||
| data[1] = MIDI_CONTROL_BANK_SELECT; | |||||
| data[2] = event->value; | |||||
| jackbridge_midi_event_write(controlOut, event->time, data, 3); | |||||
| break; | |||||
| case CarlaEngineEventMidiProgramChange: | |||||
| data[0] = MIDI_STATUS_PROGRAM_CHANGE + event->channel; | |||||
| data[1] = event->value; | |||||
| jackbridge_midi_event_write(controlOut, event->time, data, 2); | |||||
| break; | |||||
| case CarlaEngineEventAllSoundOff: | |||||
| data[0] = MIDI_STATUS_CONTROL_CHANGE + event->channel; | |||||
| data[1] = MIDI_CONTROL_ALL_SOUND_OFF; | |||||
| jackbridge_midi_event_write(controlOut, event->time, data, 2); | |||||
| break; | |||||
| case CarlaEngineEventAllNotesOff: | |||||
| data[0] = MIDI_STATUS_CONTROL_CHANGE + event->channel; | |||||
| data[1] = MIDI_CONTROL_ALL_NOTES_OFF; | |||||
| jackbridge_midi_event_write(controlOut, event->time, data, 2); | |||||
| break; | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| } | |||||
| // initialize midi input | |||||
| memset(rackMidiEventsIn, 0, sizeof(CarlaEngineMidiEvent)*MAX_ENGINE_MIDI_EVENTS); | |||||
| { | |||||
| uint32_t i = 0, j = 0; | |||||
| jackbridge_midi_event_t jackEvent; | |||||
| while (jackbridge_midi_event_get(&jackEvent, midiIn, j++) == 0) | |||||
| // output midi | |||||
| { | { | ||||
| if (i == MAX_ENGINE_MIDI_EVENTS) | |||||
| break; | |||||
| jackbridge_midi_clear_buffer(midiOut); | |||||
| if (jackEvent.size < 4) | |||||
| for (unsigned short i=0; i < MAX_ENGINE_MIDI_EVENTS; i++) | |||||
| { | { | ||||
| rackMidiEventsIn[i].time = jackEvent.time; | |||||
| rackMidiEventsIn[i].size = jackEvent.size; | |||||
| memcpy(rackMidiEventsIn[i].data, jackEvent.buffer, jackEvent.size); | |||||
| i += 1; | |||||
| if (rackMidiEventsOut[i].size == 0) | |||||
| break; | |||||
| jackbridge_midi_event_write(midiOut, rackMidiEventsOut[i].time, rackMidiEventsOut[i].data, rackMidiEventsOut[i].size); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| #else | |||||
| Q_UNUSED(nframes); | |||||
| #endif | |||||
| } | |||||
| // process rack | |||||
| processRack(inBuf, outBuf, nframes); | |||||
| // output control | |||||
| void handleShutdownCallback() | |||||
| { | |||||
| for (unsigned short i=0, max=maxPluginNumber(); i < max; i++) | |||||
| { | { | ||||
| jackbridge_midi_clear_buffer(controlOut); | |||||
| CarlaPlugin* const plugin = getPluginUnchecked(i); | |||||
| plugin->x_client = nullptr; | |||||
| } | |||||
| for (unsigned short i=0; i < MAX_ENGINE_CONTROL_EVENTS; i++) | |||||
| { | |||||
| CarlaEngineControlEvent* const event = &rackControlEventsOut[i]; | |||||
| client = nullptr; | |||||
| callback(CALLBACK_QUIT, 0, 0, 0, 0.0); | |||||
| } | |||||
| if (event->type == CarlaEngineEventControlChange && MIDI_IS_CONTROL_BANK_SELECT(event->controller)) | |||||
| event->type = CarlaEngineEventMidiBankChange; | |||||
| // ------------------------------------- | |||||
| uint8_t data[4] = { 0 }; | |||||
| private: | |||||
| jack_client_t* client; | |||||
| jack_transport_state_t state; | |||||
| jack_position_t pos; | |||||
| bool freewheel; | |||||
| switch (event->type) | |||||
| { | |||||
| case CarlaEngineEventNull: | |||||
| break; | |||||
| case CarlaEngineEventControlChange: | |||||
| data[0] = MIDI_STATUS_CONTROL_CHANGE + event->channel; | |||||
| data[1] = event->controller; | |||||
| data[2] = event->value * 127; | |||||
| jackbridge_midi_event_write(controlOut, event->time, data, 3); | |||||
| break; | |||||
| case CarlaEngineEventMidiBankChange: | |||||
| data[0] = MIDI_STATUS_CONTROL_CHANGE + event->channel; | |||||
| data[1] = MIDI_CONTROL_BANK_SELECT; | |||||
| data[2] = event->value; | |||||
| jackbridge_midi_event_write(controlOut, event->time, data, 3); | |||||
| break; | |||||
| case CarlaEngineEventMidiProgramChange: | |||||
| data[0] = MIDI_STATUS_PROGRAM_CHANGE + event->channel; | |||||
| data[1] = event->value; | |||||
| jackbridge_midi_event_write(controlOut, event->time, data, 2); | |||||
| break; | |||||
| case CarlaEngineEventAllSoundOff: | |||||
| data[0] = MIDI_STATUS_CONTROL_CHANGE + event->channel; | |||||
| data[1] = MIDI_CONTROL_ALL_SOUND_OFF; | |||||
| jackbridge_midi_event_write(controlOut, event->time, data, 2); | |||||
| break; | |||||
| case CarlaEngineEventAllNotesOff: | |||||
| data[0] = MIDI_STATUS_CONTROL_CHANGE + event->channel; | |||||
| data[1] = MIDI_CONTROL_ALL_NOTES_OFF; | |||||
| jackbridge_midi_event_write(controlOut, event->time, data, 2); | |||||
| break; | |||||
| } | |||||
| } | |||||
| } | |||||
| // ------------------------------------- | |||||
| #ifndef BUILD_BRIDGE | |||||
| enum RackPorts { | |||||
| rackPortAudioIn1 = 0, | |||||
| rackPortAudioIn2 = 1, | |||||
| rackPortAudioOut1 = 2, | |||||
| rackPortAudioOut2 = 3, | |||||
| rackPortControlIn = 4, | |||||
| rackPortControlOut = 5, | |||||
| rackPortMidiIn = 6, | |||||
| rackPortMidiOut = 7, | |||||
| rackPortCount = 8 | |||||
| }; | |||||
| jack_port_t* rackJackPorts[rackPortCount]; | |||||
| #endif | |||||
| static void processPlugin(CarlaPlugin* const p, const uint32_t nframes) | |||||
| { | |||||
| float* inBuffer[p->aIn.count]; | |||||
| float* outBuffer[p->aOut.count]; | |||||
| // output midi | |||||
| for (uint32_t i=0; i < p->aIn.count; i++) | |||||
| inBuffer[i] = p->aIn.ports[i]->getJackAudioBuffer(nframes); | |||||
| for (uint32_t i=0; i < p->aOut.count; i++) | |||||
| outBuffer[i] = p->aOut.ports[i]->getJackAudioBuffer(nframes); | |||||
| #ifndef BUILD_BRIDGE | |||||
| if (carlaOptions.processHighPrecision) | |||||
| { | { | ||||
| jackbridge_midi_clear_buffer(midiOut); | |||||
| float* inBuffer2[p->aIn.count]; | |||||
| float* outBuffer2[p->aOut.count]; | |||||
| for (unsigned short i=0; i < MAX_ENGINE_MIDI_EVENTS; i++) | |||||
| for (uint32_t i=0, j; i < nframes; i += 8) | |||||
| { | { | ||||
| if (rackMidiEventsOut[i].size == 0) | |||||
| break; | |||||
| for (j=0; j < p->aIn.count; j++) | |||||
| inBuffer2[j] = inBuffer[j] + i; | |||||
| jackbridge_midi_event_write(midiOut, rackMidiEventsOut[i].time, rackMidiEventsOut[i].data, rackMidiEventsOut[i].size); | |||||
| for (j=0; j < p->aOut.count; j++) | |||||
| outBuffer2[j] = outBuffer[j] + i; | |||||
| p->process(inBuffer2, outBuffer2, 8, i); | |||||
| } | } | ||||
| } | } | ||||
| } | |||||
| #else | |||||
| Q_UNUSED(nframes); | |||||
| else | |||||
| #endif | #endif | ||||
| } | |||||
| p->process(inBuffer, outBuffer, nframes); | |||||
| } | |||||
| void CarlaEngineJack::handleShutdownCallback() | |||||
| static int carla_jack_srate_callback(jack_nframes_t newSampleRate, void* arg) | |||||
| { | |||||
| CarlaEngineJack* const _this_ = (CarlaEngineJack*)arg; | |||||
| _this_->handleSampleRateCallback(newSampleRate); | |||||
| return 0; | |||||
| } | |||||
| static int carla_jack_bufsize_callback(jack_nframes_t newBufferSize, void* arg) | |||||
| { | |||||
| CarlaEngineJack* const _this_ = (CarlaEngineJack*)arg; | |||||
| _this_->handleBufferSizeCallback(newBufferSize); | |||||
| return 0; | |||||
| } | |||||
| static void carla_jack_freewheel_callback(int starting, void* arg) | |||||
| { | |||||
| CarlaEngineJack* const _this_ = (CarlaEngineJack*)arg; | |||||
| _this_->handleFreewheelCallback(bool(starting)); | |||||
| } | |||||
| static int carla_jack_process_callback(jack_nframes_t nframes, void* arg) | |||||
| { | |||||
| CarlaEngineJack* const _this_ = (CarlaEngineJack*)arg; | |||||
| _this_->handleProcessCallback(nframes); | |||||
| return 0; | |||||
| } | |||||
| static int carla_jack_process_callback_plugin(jack_nframes_t nframes, void* arg) | |||||
| { | |||||
| CarlaPlugin* const plugin = (CarlaPlugin*)arg; | |||||
| if (plugin && plugin->enabled()) | |||||
| { | |||||
| plugin->engineProcessLock(); | |||||
| plugin->initBuffers(); | |||||
| processPlugin(plugin, nframes); | |||||
| plugin->engineProcessUnlock(); | |||||
| } | |||||
| return 0; | |||||
| } | |||||
| static void carla_jack_shutdown_callback(void* arg) | |||||
| { | |||||
| CarlaEngineJack* const _this_ = (CarlaEngineJack*)arg; | |||||
| _this_->handleShutdownCallback(); | |||||
| } | |||||
| }; | |||||
| // ----------------------------------------- | |||||
| CarlaEngine* CarlaEngine::newJack() | |||||
| { | { | ||||
| //for (unsigned short i=0, max=maxPluginNumber(); i < max; i++) | |||||
| //{ | |||||
| //CarlaPlugin* const plugin = getPluginUnchecked(i); | |||||
| //plugin->x_client | |||||
| //} | |||||
| client = nullptr; | |||||
| callback(CALLBACK_QUIT, 0, 0, 0, 0.0); | |||||
| return new CarlaEngineJack(); | |||||
| } | } | ||||
| // ----------------------------------------- | |||||
| CARLA_BACKEND_END_NAMESPACE | CARLA_BACKEND_END_NAMESPACE | ||||
| #endif // CARLA_ENGINE_JACK | #endif // CARLA_ENGINE_JACK | ||||
| @@ -22,223 +22,239 @@ | |||||
| CARLA_BACKEND_START_NAMESPACE | CARLA_BACKEND_START_NAMESPACE | ||||
| // ------------------------------------------------------------------------------------------------------------------- | |||||
| // static RtAudio<->Engine calls | |||||
| // ----------------------------------------- | |||||
| static int carla_rtaudio_process_callback(void* outputBuffer, void* inputBuffer, unsigned int nframes, double streamTime, RtAudioStreamStatus status, void* userData) | |||||
| class CarlaEngineRtAudio : public CarlaEngine | |||||
| { | { | ||||
| CarlaEngineRtAudio* const engine = (CarlaEngineRtAudio*)userData; | |||||
| engine->handleProcessCallback(outputBuffer, inputBuffer, nframes, streamTime, status); | |||||
| return 0; | |||||
| } | |||||
| public: | |||||
| CarlaEngineRtAudio(RtAudio::Api api) | |||||
| : CarlaEngine(), | |||||
| audio(api) | |||||
| { | |||||
| qDebug("CarlaEngineRtAudio::CarlaEngineRtAudio()"); | |||||
| // ------------------------------------------------------------------------------------------------------------------- | |||||
| // Carla Engine (RtAudio) | |||||
| type = CarlaEngineTypeRtAudio; | |||||
| CarlaEngineRtAudio::CarlaEngineRtAudio(RtAudio::Api api) | |||||
| : CarlaEngine(), | |||||
| adac(api) | |||||
| { | |||||
| qDebug("CarlaEngineRtAudio::CarlaEngineRtAudio()"); | |||||
| midiIn = nullptr; | |||||
| midiOut = nullptr; | |||||
| type = CarlaEngineTypeRtAudio; | |||||
| } | |||||
| CarlaEngineRtAudio::~CarlaEngineRtAudio() | |||||
| { | |||||
| qDebug("CarlaEngineRtAudio::~CarlaEngineRtAudio()"); | |||||
| } | |||||
| bool CarlaEngineRtAudio::init(const char* const clientName) | |||||
| { | |||||
| qDebug("CarlaEngineRtAudio::init(\"%s\")", clientName); | |||||
| if (adac.getDeviceCount() < 1) | |||||
| { | |||||
| setLastError("No audio devices available"); | |||||
| return false; | |||||
| // just to make sure | |||||
| carlaOptions.forceStereo = true; | |||||
| carlaOptions.processMode = PROCESS_MODE_CONTINUOUS_RACK; | |||||
| } | } | ||||
| sampleRate = 48000; | |||||
| unsigned int rtBufferFrames = 512; | |||||
| RtAudio::StreamParameters iParams, oParams; | |||||
| //iParams.deviceId = 3; | |||||
| //oParams.deviceId = 2; | |||||
| iParams.nChannels = 2; | |||||
| oParams.nChannels = 2; | |||||
| RtAudio::StreamOptions options; | |||||
| options.flags = /*RTAUDIO_NONINTERLEAVED |*/ RTAUDIO_MINIMIZE_LATENCY /*| RTAUDIO_HOG_DEVICE*/ | RTAUDIO_SCHEDULE_REALTIME | RTAUDIO_ALSA_USE_DEFAULT; | |||||
| options.streamName = clientName; | |||||
| options.priority = 85; | |||||
| try { | |||||
| adac.openStream(&oParams, &iParams, RTAUDIO_FLOAT32, sampleRate, &rtBufferFrames, carla_rtaudio_process_callback, this, &options); | |||||
| } | |||||
| catch (RtError& e) | |||||
| ~CarlaEngineRtAudio() | |||||
| { | { | ||||
| setLastError(e.what()); | |||||
| return false; | |||||
| qDebug("CarlaEngineRtAudio::~CarlaEngineRtAudio()"); | |||||
| } | } | ||||
| bufferSize = rtBufferFrames; | |||||
| // ------------------------------------- | |||||
| // set client name, fixed for OSC usage | |||||
| // FIXME - put this in shared? | |||||
| char* fixedName = strdup(clientName); | |||||
| for (size_t i=0; i < strlen(fixedName); i++) | |||||
| bool init(const char* const clientName) | |||||
| { | { | ||||
| if (! (std::isalpha(fixedName[i]) || std::isdigit(fixedName[i]))) | |||||
| fixedName[i] = '_'; | |||||
| qDebug("CarlaEngineRtAudio::init(\"%s\")", clientName); | |||||
| if (audio.getDeviceCount() < 1) | |||||
| { | |||||
| setLastError("No audio devices available for this driver"); | |||||
| return false; | |||||
| } | |||||
| bufferSize = carlaOptions.preferredBufferSize; | |||||
| sampleRate = carlaOptions.preferredSampleRate; | |||||
| RtAudio::StreamParameters iParams, oParams; | |||||
| //iParams.deviceId = 3; | |||||
| //oParams.deviceId = 2; | |||||
| iParams.nChannels = 2; | |||||
| oParams.nChannels = 2; | |||||
| RtAudio::StreamOptions options; | |||||
| options.flags = /*RTAUDIO_NONINTERLEAVED |*/ RTAUDIO_MINIMIZE_LATENCY /*| RTAUDIO_HOG_DEVICE*/ | RTAUDIO_SCHEDULE_REALTIME | RTAUDIO_ALSA_USE_DEFAULT; | |||||
| options.streamName = clientName; | |||||
| options.priority = 85; | |||||
| try { | |||||
| audio.openStream(&oParams, &iParams, RTAUDIO_FLOAT32, sampleRate, &bufferSize, carla_rtaudio_process_callback, this, &options); | |||||
| } | |||||
| catch (RtError& e) | |||||
| { | |||||
| setLastError(e.what()); | |||||
| return false; | |||||
| } | |||||
| try { | |||||
| audio.startStream(); | |||||
| } | |||||
| catch (RtError& e) | |||||
| { | |||||
| setLastError(e.what()); | |||||
| return false; | |||||
| } | |||||
| midiIn = new MidiInAlsa(clientName, 512); | |||||
| midiIn->openVirtualPort("control-in"); | |||||
| midiIn->openVirtualPort("midi-in"); | |||||
| midiOut = new MidiOutAlsa(clientName); | |||||
| midiOut->openVirtualPort("control-out"); | |||||
| midiOut->openVirtualPort("midi-out"); | |||||
| name = getFixedClientName(clientName); | |||||
| CarlaEngine::init(name); | |||||
| return true; | |||||
| } | } | ||||
| name = strdup(fixedName); | |||||
| free((void*)fixedName); | |||||
| qDebug("RtAudio bufferSize = %i", bufferSize); | |||||
| try { | |||||
| adac.startStream(); | |||||
| } | |||||
| catch (RtError& e) | |||||
| bool close() | |||||
| { | { | ||||
| setLastError(e.what()); | |||||
| return false; | |||||
| qDebug("CarlaEngineRtAudio::close()"); | |||||
| CarlaEngine::close(); | |||||
| if (name) | |||||
| { | |||||
| free((void*)name); | |||||
| name = nullptr; | |||||
| } | |||||
| if (audio.isStreamRunning()) | |||||
| audio.stopStream(); | |||||
| if (audio.isStreamOpen()) | |||||
| audio.closeStream(); | |||||
| if (midiIn) | |||||
| { | |||||
| midiIn->cancelCallback(); | |||||
| midiIn->closePort(); | |||||
| delete midiIn; | |||||
| midiIn = nullptr; | |||||
| } | |||||
| if (midiOut) | |||||
| { | |||||
| midiOut->closePort(); | |||||
| delete midiOut; | |||||
| midiOut = nullptr; | |||||
| } | |||||
| return true; | |||||
| } | } | ||||
| CarlaEngine::init(name); | |||||
| return true; | |||||
| } | |||||
| bool CarlaEngineRtAudio::close() | |||||
| { | |||||
| qDebug("CarlaEngineRtAudio::close()"); | |||||
| CarlaEngine::close(); | |||||
| if (name) | |||||
| bool isOffline() | |||||
| { | { | ||||
| free((void*)name); | |||||
| name = nullptr; | |||||
| return false; | |||||
| } | } | ||||
| if (adac.isStreamRunning()) | |||||
| adac.stopStream(); | |||||
| if (adac.isStreamOpen()) | |||||
| adac.closeStream(); | |||||
| return true; | |||||
| } | |||||
| bool CarlaEngineRtAudio::isOffline() | |||||
| { | |||||
| return false; | |||||
| } | |||||
| bool CarlaEngineRtAudio::isRunning() | |||||
| { | |||||
| return adac.isStreamRunning(); | |||||
| } | |||||
| CarlaEngineClient* CarlaEngineRtAudio::addClient(CarlaPlugin* const plugin) | |||||
| { | |||||
| CarlaEngineClientNativeHandle handle; | |||||
| handle.type = type; | |||||
| // unsigned int rtBufferFrames = getBufferSize(); | |||||
| // RtAudio::StreamParameters iParams, oParams; | |||||
| // iParams.nChannels = plugin->audioInCount(); | |||||
| // oParams.nChannels = plugin->audioOutCount(); | |||||
| // RtAudio::StreamOptions options; | |||||
| // options.flags = /*RTAUDIO_NONINTERLEAVED |*/ RTAUDIO_MINIMIZE_LATENCY /*| RTAUDIO_HOG_DEVICE*/ | RTAUDIO_SCHEDULE_REALTIME | RTAUDIO_ALSA_USE_DEFAULT; | |||||
| // options.streamName = plugin->name(); | |||||
| // options.priority = 85; | |||||
| // try { | |||||
| // adac.openStream(&oParams, &iParams, RTAUDIO_FLOAT32, getSampleRate(), &rtBufferFrames, carla_rtaudio_process_callback, this, &options); | |||||
| // } | |||||
| // catch (RtError& e) | |||||
| // { | |||||
| // setLastError(e.what()); | |||||
| // return false; | |||||
| // } | |||||
| return new CarlaEngineClient(handle); | |||||
| Q_UNUSED(plugin); | |||||
| } | |||||
| // ------------------------------------------------------------------------------------------------------------------- | |||||
| void CarlaEngineRtAudio::handleProcessCallback(void* outputBuffer, void* inputBuffer, unsigned int nframes, double streamTime, RtAudioStreamStatus status) | |||||
| { | |||||
| if (maxPluginNumber() == 0) | |||||
| return; | |||||
| // get buffers from RtAudio | |||||
| float* insPtr = (float*)inputBuffer; | |||||
| float* outsPtr = (float*)outputBuffer; | |||||
| // assert buffers | |||||
| CARLA_ASSERT(insPtr); | |||||
| CARLA_ASSERT(outsPtr); | |||||
| // create temporary audio buffers | |||||
| float inBuf1[nframes]; | |||||
| float inBuf2[nframes]; | |||||
| float outBuf1[nframes]; | |||||
| float outBuf2[nframes]; | |||||
| // initialize audio input | |||||
| for (unsigned int i=0; i < nframes*2; i++) | |||||
| bool isRunning() | |||||
| { | { | ||||
| if (i % 2) | |||||
| inBuf2[i/2] = insPtr[i]; | |||||
| else | |||||
| inBuf1[i/2] = insPtr[i]; | |||||
| return audio.isStreamRunning(); | |||||
| } | } | ||||
| // create (real) audio buffers | |||||
| float* inBuf[2] = { inBuf1, inBuf2 }; | |||||
| float* outBuf[2] = { outBuf1, outBuf2 }; | |||||
| // initialize control input | |||||
| memset(rackControlEventsIn, 0, sizeof(CarlaEngineControlEvent)*MAX_ENGINE_CONTROL_EVENTS); | |||||
| CarlaEngineClient* addClient(CarlaPlugin* const plugin) | |||||
| { | { | ||||
| // TODO | |||||
| } | |||||
| CarlaEngineClientNativeHandle handle; | |||||
| handle.type = CarlaEngineTypeRtAudio; | |||||
| // initialize midi input | |||||
| memset(rackMidiEventsIn, 0, sizeof(CarlaEngineMidiEvent)*MAX_ENGINE_MIDI_EVENTS); | |||||
| { | |||||
| // TODO | |||||
| return new CarlaEngineClient(handle); | |||||
| Q_UNUSED(plugin); | |||||
| } | } | ||||
| processRack(inBuf, outBuf, nframes); | |||||
| // ------------------------------------- | |||||
| // output audio | |||||
| for (unsigned int i=0; i < nframes*2; i++) | |||||
| protected: | |||||
| void handleProcessCallback(void* outputBuffer, void* inputBuffer, unsigned int nframes, double streamTime, RtAudioStreamStatus status) | |||||
| { | { | ||||
| if (i % 2) | |||||
| outsPtr[i] = outBuf2[i/2]; | |||||
| else | |||||
| outsPtr[i] = outBuf1[i/2]; | |||||
| if (maxPluginNumber() == 0) | |||||
| return; | |||||
| // get buffers from RtAudio | |||||
| float* insPtr = (float*)inputBuffer; | |||||
| float* outsPtr = (float*)outputBuffer; | |||||
| // assert buffers | |||||
| CARLA_ASSERT(insPtr); | |||||
| CARLA_ASSERT(outsPtr); | |||||
| // create temporary audio buffers | |||||
| float inBuf1[nframes]; | |||||
| float inBuf2[nframes]; | |||||
| float outBuf1[nframes]; | |||||
| float outBuf2[nframes]; | |||||
| // initialize audio input | |||||
| for (unsigned int i=0; i < nframes*2; i++) | |||||
| { | |||||
| if (i % 2) | |||||
| inBuf2[i/2] = insPtr[i]; | |||||
| else | |||||
| inBuf1[i/2] = insPtr[i]; | |||||
| } | |||||
| // create (real) audio buffers | |||||
| float* inBuf[2] = { inBuf1, inBuf2 }; | |||||
| float* outBuf[2] = { outBuf1, outBuf2 }; | |||||
| // initialize control input | |||||
| memset(rackControlEventsIn, 0, sizeof(CarlaEngineControlEvent)*MAX_ENGINE_CONTROL_EVENTS); | |||||
| { | |||||
| // TODO | |||||
| } | |||||
| // initialize midi input | |||||
| memset(rackMidiEventsIn, 0, sizeof(CarlaEngineMidiEvent)*MAX_ENGINE_MIDI_EVENTS); | |||||
| { | |||||
| // TODO | |||||
| } | |||||
| processRack(inBuf, outBuf, nframes); | |||||
| // output audio | |||||
| for (unsigned int i=0; i < nframes*2; i++) | |||||
| { | |||||
| if (i % 2) | |||||
| outsPtr[i] = outBuf2[i/2]; | |||||
| else | |||||
| outsPtr[i] = outBuf1[i/2]; | |||||
| } | |||||
| // output control | |||||
| { | |||||
| // TODO | |||||
| } | |||||
| // output midi | |||||
| { | |||||
| // TODO | |||||
| } | |||||
| Q_UNUSED(streamTime); | |||||
| Q_UNUSED(status); | |||||
| } | } | ||||
| // output control | |||||
| { | |||||
| // TODO | |||||
| } | |||||
| // ------------------------------------- | |||||
| private: | |||||
| RtAudio audio; | |||||
| MidiInApi* midiIn; | |||||
| MidiOutApi* midiOut; | |||||
| // output midi | |||||
| static int carla_rtaudio_process_callback(void* outputBuffer, void* inputBuffer, unsigned int nframes, double streamTime, RtAudioStreamStatus status, void* userData) | |||||
| { | { | ||||
| // TODO | |||||
| CarlaEngineRtAudio* const _this_ = (CarlaEngineRtAudio*)userData; | |||||
| _this_->handleProcessCallback(outputBuffer, inputBuffer, nframes, streamTime, status); | |||||
| return 0; | |||||
| } | } | ||||
| }; | |||||
| Q_UNUSED(streamTime); | |||||
| Q_UNUSED(status); | |||||
| // ----------------------------------------- | |||||
| CarlaEngine* CarlaEngine::newRtAudio(RtAudio::Api api) | |||||
| { | |||||
| return new CarlaEngineRtAudio(api); | |||||
| } | } | ||||
| // ----------------------------------------- | |||||
| CARLA_BACKEND_END_NAMESPACE | CARLA_BACKEND_END_NAMESPACE | ||||
| #endif // CARLA_ENGINE_RTAUDIO | #endif // CARLA_ENGINE_RTAUDIO | ||||
| @@ -18,6 +18,14 @@ | |||||
| #include "carla_plugin.h" | #include "carla_plugin.h" | ||||
| #include "plugins/carla_native.h" | #include "plugins/carla_native.h" | ||||
| // Internal C plugins | |||||
| extern "C" { | |||||
| extern void carla_register_native_plugin_bypass(); | |||||
| } | |||||
| // Internal C++ plugins | |||||
| extern void carla_register_native_plugin_midiSplit(); | |||||
| CARLA_BACKEND_START_NAMESPACE | CARLA_BACKEND_START_NAMESPACE | ||||
| struct NativePluginMidiData { | struct NativePluginMidiData { | ||||
| @@ -36,6 +44,7 @@ class NativePluginScopedInitiliazer | |||||
| public: | public: | ||||
| NativePluginScopedInitiliazer() | NativePluginScopedInitiliazer() | ||||
| { | { | ||||
| firstInit = true; | |||||
| } | } | ||||
| ~NativePluginScopedInitiliazer() | ~NativePluginScopedInitiliazer() | ||||
| @@ -51,6 +60,16 @@ public: | |||||
| descriptors.clear(); | descriptors.clear(); | ||||
| } | } | ||||
| void maybeFirstInit() | |||||
| { | |||||
| if (firstInit) | |||||
| { | |||||
| firstInit = false; | |||||
| carla_register_native_plugin_bypass(); | |||||
| carla_register_native_plugin_midiSplit(); | |||||
| } | |||||
| } | |||||
| void initializeIfNeeded(const PluginDescriptor* const desc) | void initializeIfNeeded(const PluginDescriptor* const desc) | ||||
| { | { | ||||
| if (descriptors.empty() || std::find(descriptors.begin(), descriptors.end(), desc) == descriptors.end()) | if (descriptors.empty() || std::find(descriptors.begin(), descriptors.end(), desc) == descriptors.end()) | ||||
| @@ -63,6 +82,7 @@ public: | |||||
| } | } | ||||
| private: | private: | ||||
| bool firstInit; | |||||
| std::vector<const PluginDescriptor*> descriptors; | std::vector<const PluginDescriptor*> descriptors; | ||||
| }; | }; | ||||
| @@ -1541,6 +1561,7 @@ public: | |||||
| static size_t getPluginCount() | static size_t getPluginCount() | ||||
| { | { | ||||
| scopedInitliazer.maybeFirstInit(); | |||||
| return pluginDescriptors.size(); | return pluginDescriptors.size(); | ||||
| } | } | ||||
| @@ -1601,9 +1622,9 @@ public: | |||||
| // get info | // get info | ||||
| if (name) | if (name) | ||||
| m_name = x_engine->getUniqueName(name); | |||||
| m_name = x_engine->getUniquePluginName(name); | |||||
| else | else | ||||
| m_name = x_engine->getUniqueName(descriptor->name); | |||||
| m_name = x_engine->getUniquePluginName(descriptor->name); | |||||
| // --------------------------------------------------------------- | // --------------------------------------------------------------- | ||||
| // register client | // register client | ||||
| @@ -1358,44 +1358,6 @@ public: | |||||
| Q_UNUSED(framesOffset); | Q_UNUSED(framesOffset); | ||||
| } | } | ||||
| #ifdef CARLA_ENGINE_JACK | |||||
| /*! | |||||
| * Plugin process callback, JACK helper version. | |||||
| */ | |||||
| void process_jack(const uint32_t nframes) | |||||
| { | |||||
| float* inBuffer[aIn.count]; | |||||
| float* outBuffer[aOut.count]; | |||||
| for (uint32_t i=0; i < aIn.count; i++) | |||||
| inBuffer[i] = aIn.ports[i]->getJackAudioBuffer(nframes); | |||||
| for (uint32_t i=0; i < aOut.count; i++) | |||||
| outBuffer[i] = aOut.ports[i]->getJackAudioBuffer(nframes); | |||||
| #ifndef BUILD_BRIDGE | |||||
| if (carlaOptions.processHighPrecision) | |||||
| { | |||||
| float* inBuffer2[aIn.count]; | |||||
| float* outBuffer2[aOut.count]; | |||||
| for (uint32_t i=0, j; i < nframes; i += 8) | |||||
| { | |||||
| for (j=0; j < aIn.count; j++) | |||||
| inBuffer2[j] = inBuffer[j] + i; | |||||
| for (j=0; j < aOut.count; j++) | |||||
| outBuffer2[j] = outBuffer[j] + i; | |||||
| process(inBuffer2, outBuffer2, 8, i); | |||||
| } | |||||
| } | |||||
| else | |||||
| #endif | |||||
| process(inBuffer, outBuffer, nframes); | |||||
| } | |||||
| #endif | |||||
| /*! | /*! | ||||
| * Tell the plugin the current buffer size has changed. | * Tell the plugin the current buffer size has changed. | ||||
| */ | */ | ||||
| @@ -2266,6 +2228,8 @@ protected: | |||||
| { | { | ||||
| return (value < 0.0) ? -value : value; | return (value < 0.0) ? -value : value; | ||||
| } | } | ||||
| friend class CarlaEngineJack; | |||||
| }; | }; | ||||
| /**@}*/ | /**@}*/ | ||||
| @@ -1483,9 +1483,9 @@ public: | |||||
| m_filename = strdup(filename); | m_filename = strdup(filename); | ||||
| if (name) | if (name) | ||||
| m_name = x_engine->getUniqueName(name); | |||||
| m_name = x_engine->getUniquePluginName(name); | |||||
| else | else | ||||
| m_name = x_engine->getUniqueName(ldescriptor->Name); | |||||
| m_name = x_engine->getUniquePluginName(ldescriptor->Name); | |||||
| // --------------------------------------------------------------- | // --------------------------------------------------------------- | ||||
| // register client | // register client | ||||
| @@ -1251,9 +1251,9 @@ public: | |||||
| m_label = strdup(label); | m_label = strdup(label); | ||||
| if (name) | if (name) | ||||
| m_name = x_engine->getUniqueName(name); | |||||
| m_name = x_engine->getUniquePluginName(name); | |||||
| else | else | ||||
| m_name = x_engine->getUniqueName(label); | |||||
| m_name = x_engine->getUniquePluginName(label); | |||||
| // --------------------------------------------------------------- | // --------------------------------------------------------------- | ||||
| // register client | // register client | ||||
| @@ -1102,11 +1102,11 @@ public: | |||||
| rdf_descriptor = ladspa_rdf_dup(rdf_descriptor_); | rdf_descriptor = ladspa_rdf_dup(rdf_descriptor_); | ||||
| if (name) | if (name) | ||||
| m_name = x_engine->getUniqueName(name); | |||||
| m_name = x_engine->getUniquePluginName(name); | |||||
| else if (rdf_descriptor && rdf_descriptor->Title) | else if (rdf_descriptor && rdf_descriptor->Title) | ||||
| m_name = x_engine->getUniqueName(rdf_descriptor->Title); | |||||
| m_name = x_engine->getUniquePluginName(rdf_descriptor->Title); | |||||
| else | else | ||||
| m_name = x_engine->getUniqueName(descriptor->Name); | |||||
| m_name = x_engine->getUniquePluginName(descriptor->Name); | |||||
| // --------------------------------------------------------------- | // --------------------------------------------------------------- | ||||
| // register client | // register client | ||||
| @@ -721,9 +721,9 @@ public: | |||||
| m_filename = strdup(filename); | m_filename = strdup(filename); | ||||
| if (name) | if (name) | ||||
| m_name = x_engine->getUniqueName(name); | |||||
| m_name = x_engine->getUniquePluginName(name); | |||||
| else | else | ||||
| m_name = x_engine->getUniqueName(label && label[0] ? label : info.InstrumentName.c_str()); | |||||
| m_name = x_engine->getUniquePluginName(label && label[0] ? label : info.InstrumentName.c_str()); | |||||
| sampler_channel = sampler->AddSamplerChannel(); | sampler_channel = sampler->AddSamplerChannel(); | ||||
| sampler_channel->SetEngineType(stype); | sampler_channel->SetEngineType(stype); | ||||
| @@ -4031,9 +4031,9 @@ public: | |||||
| m_filename = strdup(bundle); | m_filename = strdup(bundle); | ||||
| if (name) | if (name) | ||||
| m_name = x_engine->getUniqueName(name); | |||||
| m_name = x_engine->getUniquePluginName(name); | |||||
| else | else | ||||
| m_name = x_engine->getUniqueName(rdf_descriptor->Name); | |||||
| m_name = x_engine->getUniquePluginName(rdf_descriptor->Name); | |||||
| // --------------------------------------------------------------- | // --------------------------------------------------------------- | ||||
| // register client | // register client | ||||
| @@ -170,8 +170,7 @@ typedef struct _PluginDescriptor { | |||||
| void carla_register_native_plugin(const PluginDescriptor* desc); | void carla_register_native_plugin(const PluginDescriptor* desc); | ||||
| #define CARLA_REGISTER_NATIVE_PLUGIN(label, desc) \ | |||||
| void carla_register_native_plugin_##label () __attribute__((constructor)); \ | |||||
| #define CARLA_REGISTER_NATIVE_PLUGIN(label, desc) \ | |||||
| void carla_register_native_plugin_##label () { carla_register_native_plugin(&desc); } | void carla_register_native_plugin_##label () { carla_register_native_plugin(&desc); } | ||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||
| @@ -436,8 +436,7 @@ private: | |||||
| // ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
| #define CARLA_REGISTER_NATIVE_PLUGIN_MM(label, descMM) \ | |||||
| void carla_register_native_plugin_##label () __attribute__((constructor)); \ | |||||
| #define CARLA_REGISTER_NATIVE_PLUGIN_MM(label, descMM) \ | |||||
| void carla_register_native_plugin_##label () { carla_register_native_plugin(descMM.descriptorInit()); } | void carla_register_native_plugin_##label () { carla_register_native_plugin(descMM.descriptorInit()); } | ||||
| #endif // CARLA_NATIVE_MM_H | #endif // CARLA_NATIVE_MM_H | ||||
| @@ -2163,7 +2163,7 @@ public: | |||||
| if (name) | if (name) | ||||
| { | { | ||||
| m_name = x_engine->getUniqueName(name); | |||||
| m_name = x_engine->getUniquePluginName(name); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| @@ -2171,9 +2171,9 @@ public: | |||||
| effect->dispatcher(effect, effGetEffectName, 0, 0, strBuf, 0.0f); | effect->dispatcher(effect, effGetEffectName, 0, 0, strBuf, 0.0f); | ||||
| if (strBuf[0] != 0) | if (strBuf[0] != 0) | ||||
| m_name = x_engine->getUniqueName(strBuf); | |||||
| m_name = x_engine->getUniquePluginName(strBuf); | |||||
| else | else | ||||
| m_name = x_engine->getUniqueName(label); | |||||
| m_name = x_engine->getUniquePluginName(label); | |||||
| } | } | ||||
| // --------------------------------------------------------------- | // --------------------------------------------------------------- | ||||