| @@ -2,17 +2,17 @@ | |||
| * Carla Backend API | |||
| * Copyright (C) 2011-2013 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or modify | |||
| * it under the terms of the GNU General Public License as published by | |||
| * the Free Software Foundation; either version 2 of the License, or | |||
| * any later version. | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU General Public License for more details. | |||
| * | |||
| * For a full copy of the GNU General Public License see the COPYING file | |||
| * For a full copy of the GNU General Public License see the GPL.txt file | |||
| */ | |||
| #ifndef __CARLA_BACKEND_HPP__ | |||
| @@ -69,6 +69,30 @@ const unsigned int PLUGIN_CAN_BALANCE = 0x400; //!< Plugin can make use o | |||
| const unsigned int PLUGIN_CAN_FORCE_STEREO = 0x800; //!< Plugin can be used in forced-stereo mode. | |||
| /**@}*/ | |||
| /*! | |||
| * @defgroup PluginOptions Plugin Options | |||
| * | |||
| * Various plugin options.\n | |||
| * ON or OFF defines the default plugin value. | |||
| * \see CarlaPlugin::options() | |||
| * \note PitchBend is disabled by default on VST plugins | |||
| * @{ | |||
| */ | |||
| const unsigned int PLUGIN_OPTION_FIXED_BUFFER = 0x001; //!< OFF: Use a constant, fixed size audio buffer (128 or lower is used) | |||
| const unsigned int PLUGIN_OPTION_FORCE_STEREO = 0x002; //!< OFF: Force mono plugin as stereo | |||
| const unsigned int PLUGIN_OPTION_SELF_AUTOMATION = 0x004; //!< OFF: Let the plugin handle MIDI-CC automation, not the host | |||
| const unsigned int PLUGIN_OPTION_USE_CHUNKS = 0x008; //!< ON: Use chunks to save data | |||
| const unsigned int PLUGIN_OPTION_SEND_ALL_SOUND_OFF = 0x010; //!< ON: Send MIDI ALL_SOUND_OFF / ALL_NOTES_OFF events | |||
| const unsigned int PLUGIN_OPTION_SEND_NOTE_OFF_VELO = 0x020; //!< OFF: Send MIDI Note-Off events with a velocity value | |||
| const unsigned int PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH = 0x040; //!< ON: Send MIDI Note aftertouch events | |||
| const unsigned int PLUGIN_OPTION_SEND_PITCHBEND = 0x080; //!< ON: Send MIDI Pitchbend events | |||
| #ifdef WANT_VST | |||
| const unsigned int PLUGIN_OPTION_VST_SUPPLY_IDLE = 0x100; //!< ON: Idle Plugin's custom GUI (VST only) | |||
| const unsigned int PLUGIN_OPTION_VST_UPDATE_DISPLAY = 0x200; //!< ON: Recheck plugin properties on updateDisplay message (VST Only) | |||
| #endif | |||
| /**@}*/ | |||
| /*! | |||
| * @defgroup ParameterHints Parameter Hints | |||
| * | |||
| @@ -214,93 +238,85 @@ enum OptionsType { | |||
| */ | |||
| OPTION_PROCESS_MODE = 1, | |||
| /*! | |||
| * High-Precision processing mode.\n | |||
| * When enabled, audio will be processed by blocks of 8 samples at a time, indenpendently of the buffer size.\n | |||
| * Default is off.\n | |||
| * EXPERIMENTAL AND INCOMPLETE! | |||
| */ | |||
| OPTION_PROCESS_HIGH_PRECISION = 2, | |||
| /*! | |||
| * Force mono plugins as stereo, by running 2 instances at the same time. | |||
| * \note Not supported by all plugins. | |||
| */ | |||
| OPTION_FORCE_STEREO = 3, | |||
| OPTION_FORCE_STEREO = 2, | |||
| /*! | |||
| * Use plugin bridges whenever possible.\n | |||
| * Default is no, and not recommended at this point!. | |||
| * EXPERIMENTAL AND INCOMPLETE! | |||
| */ | |||
| OPTION_PREFER_PLUGIN_BRIDGES = 4, | |||
| OPTION_PREFER_PLUGIN_BRIDGES = 3, | |||
| /*! | |||
| * Use OSC-UI bridges whenever possible, otherwise UIs will be handled in the main thread.\n | |||
| * Default is yes. | |||
| */ | |||
| OPTION_PREFER_UI_BRIDGES = 5, | |||
| OPTION_PREFER_UI_BRIDGES = 4, | |||
| #ifdef WANT_DSSI | |||
| /*! | |||
| * Use (unofficial) dssi-vst chunks feature.\n | |||
| * Default is no. | |||
| */ | |||
| OPTION_USE_DSSI_VST_CHUNKS = 6, | |||
| OPTION_USE_DSSI_VST_CHUNKS = 5, | |||
| #endif | |||
| /*! | |||
| * Maximum number of parameters allowed.\n | |||
| * Default is MAX_DEFAULT_PARAMETERS. | |||
| */ | |||
| OPTION_MAX_PARAMETERS = 7, | |||
| OPTION_MAX_PARAMETERS = 6, | |||
| /*! | |||
| * Timeout value in ms for how much to wait for OSC-Bridges to respond.\n | |||
| * Default is 4000 (4 secs). | |||
| */ | |||
| OPTION_OSC_UI_TIMEOUT = 8, | |||
| OPTION_OSC_UI_TIMEOUT = 7, | |||
| /*! | |||
| * Prefered buffer size. | |||
| */ | |||
| OPTION_PREFERRED_BUFFER_SIZE = 9, | |||
| OPTION_PREFERRED_BUFFER_SIZE = 8, | |||
| /*! | |||
| * Prefered sample rate. | |||
| */ | |||
| OPTION_PREFERRED_SAMPLE_RATE = 10, | |||
| OPTION_PREFERRED_SAMPLE_RATE = 9, | |||
| #ifndef BUILD_BRIDGE | |||
| /*! | |||
| * Set path to the native plugin bridge executable.\n | |||
| * Default unset. | |||
| */ | |||
| OPTION_PATH_BRIDGE_NATIVE = 11, | |||
| OPTION_PATH_BRIDGE_NATIVE = 10, | |||
| /*! | |||
| * Set path to the POSIX 32bit plugin bridge executable.\n | |||
| * Default unset. | |||
| */ | |||
| OPTION_PATH_BRIDGE_POSIX32 = 12, | |||
| OPTION_PATH_BRIDGE_POSIX32 = 11, | |||
| /*! | |||
| * Set path to the POSIX 64bit plugin bridge executable.\n | |||
| * Default unset. | |||
| */ | |||
| OPTION_PATH_BRIDGE_POSIX64 = 13, | |||
| OPTION_PATH_BRIDGE_POSIX64 = 12, | |||
| /*! | |||
| * Set path to the Windows 32bit plugin bridge executable.\n | |||
| * Default unset. | |||
| */ | |||
| OPTION_PATH_BRIDGE_WIN32 = 14, | |||
| OPTION_PATH_BRIDGE_WIN32 = 13, | |||
| /*! | |||
| * Set path to the Windows 64bit plugin bridge executable.\n | |||
| * Default unset. | |||
| */ | |||
| OPTION_PATH_BRIDGE_WIN64 = 15, | |||
| OPTION_PATH_BRIDGE_WIN64 = 14, | |||
| #endif | |||
| #ifdef WANT_LV2 | |||
| @@ -308,43 +324,43 @@ enum OptionsType { | |||
| * Set path to the LV2 Gtk2 UI bridge executable.\n | |||
| * Default unset. | |||
| */ | |||
| OPTION_PATH_BRIDGE_LV2_GTK2 = 16, | |||
| OPTION_PATH_BRIDGE_LV2_GTK2 = 15, | |||
| /*! | |||
| * Set path to the LV2 Gtk3 UI bridge executable.\n | |||
| * Default unset. | |||
| */ | |||
| OPTION_PATH_BRIDGE_LV2_GTK3 = 17, | |||
| OPTION_PATH_BRIDGE_LV2_GTK3 = 16, | |||
| /*! | |||
| * Set path to the LV2 Qt4 UI bridge executable.\n | |||
| * Default unset. | |||
| */ | |||
| OPTION_PATH_BRIDGE_LV2_QT4 = 18, | |||
| OPTION_PATH_BRIDGE_LV2_QT4 = 17, | |||
| /*! | |||
| * Set path to the LV2 Qt5 UI bridge executable.\n | |||
| * Default unset. | |||
| */ | |||
| OPTION_PATH_BRIDGE_LV2_QT5 = 19, | |||
| OPTION_PATH_BRIDGE_LV2_QT5 = 18, | |||
| /*! | |||
| * Set path to the LV2 Cocoa UI bridge executable.\n | |||
| * Default unset. | |||
| */ | |||
| OPTION_PATH_BRIDGE_LV2_COCOA = 20, | |||
| OPTION_PATH_BRIDGE_LV2_COCOA = 19, | |||
| /*! | |||
| * Set path to the LV2 Windows UI bridge executable.\n | |||
| * Default unset. | |||
| */ | |||
| OPTION_PATH_BRIDGE_LV2_WINDOWS = 21, | |||
| OPTION_PATH_BRIDGE_LV2_WINDOWS = 20, | |||
| /*! | |||
| * Set path to the LV2 X11 UI bridge executable.\n | |||
| * Default unset. | |||
| */ | |||
| OPTION_PATH_BRIDGE_LV2_X11 = 22, | |||
| OPTION_PATH_BRIDGE_LV2_X11 = 21, | |||
| #endif | |||
| #ifdef WANT_VST | |||
| @@ -352,19 +368,19 @@ enum OptionsType { | |||
| * Set path to the VST Cocoa UI bridge executable.\n | |||
| * Default unset. | |||
| */ | |||
| OPTION_PATH_BRIDGE_VST_COCOA = 23, | |||
| OPTION_PATH_BRIDGE_VST_COCOA = 22, | |||
| /*! | |||
| * Set path to the VST HWND UI bridge executable.\n | |||
| * Default unset. | |||
| */ | |||
| OPTION_PATH_BRIDGE_VST_HWND = 24, | |||
| OPTION_PATH_BRIDGE_VST_HWND = 23, | |||
| /*! | |||
| * Set path to the VST X11 UI bridge executable.\n | |||
| * Default unset. | |||
| */ | |||
| OPTION_PATH_BRIDGE_VST_X11 = 25 | |||
| OPTION_PATH_BRIDGE_VST_X11 = 24 | |||
| #endif | |||
| }; | |||
| @@ -2,17 +2,17 @@ | |||
| * Carla Engine API | |||
| * Copyright (C) 2012-2013 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or modify | |||
| * it under the terms of the GNU General Public License as published by | |||
| * the Free Software Foundation; either version 2 of the License, or | |||
| * any later version. | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU General Public License for more details. | |||
| * | |||
| * For a full copy of the GNU General Public License see the COPYING file | |||
| * For a full copy of the GNU General Public License see the GPL.txt file | |||
| */ | |||
| #ifndef __CARLA_ENGINE_HPP__ | |||
| @@ -31,12 +31,7 @@ CARLA_BACKEND_START_NAMESPACE | |||
| } // Fix editor indentation | |||
| #endif | |||
| /*! | |||
| * @defgroup CarlaEngineAPI Carla Engine API | |||
| * | |||
| * The Carla Engine API | |||
| * @{ | |||
| */ | |||
| // ----------------------------------------------------------------------- | |||
| /*! | |||
| * The type of an engine. | |||
| @@ -45,23 +40,23 @@ enum EngineType { | |||
| /*! | |||
| * Null engine type. | |||
| */ | |||
| EngineTypeNull = 0, | |||
| kEngineTypeNull = 0, | |||
| /*! | |||
| * JACK engine type.\n | |||
| * Provides all processing modes. | |||
| */ | |||
| EngineTypeJack = 1, | |||
| kEngineTypeJack = 1, | |||
| /*! | |||
| * RtAudio engine type, used to provide Native Audio and MIDI support. | |||
| */ | |||
| EngineTypeRtAudio = 2, | |||
| kEngineTypeRtAudio = 2, | |||
| /*! | |||
| * Plugin engine type, used to export the engine as a plugin (DSSI, LV2 and VST) via the DISTRHO Plugin Toolkit. | |||
| */ | |||
| EngineTypePlugin = 3 | |||
| kEngineTypePlugin = 3 | |||
| }; | |||
| /*! | |||
| @@ -71,17 +66,17 @@ enum EnginePortType { | |||
| /*! | |||
| * Null port type. | |||
| */ | |||
| EnginePortTypeNull = 0, | |||
| kEnginePortTypeNull = 0, | |||
| /*! | |||
| * Audio port type. | |||
| */ | |||
| EnginePortTypeAudio = 1, | |||
| kEnginePortTypeAudio = 1, | |||
| /*! | |||
| * Event port type. | |||
| */ | |||
| EnginePortTypeEvent = 2, | |||
| kEnginePortTypeEvent = 2 | |||
| }; | |||
| /*! | |||
| @@ -91,19 +86,19 @@ enum EngineEventType { | |||
| /*! | |||
| * Null port type. | |||
| */ | |||
| EngineEventTypeNull = 0, | |||
| kEngineEventTypeNull = 0, | |||
| /*! | |||
| * Control event type. | |||
| * \see EngineControlEvent | |||
| */ | |||
| EngineEventTypeControl = 1, | |||
| kEngineEventTypeControl = 1, | |||
| /*! | |||
| * MIDI event type. | |||
| * \see EngineMidiEvent | |||
| */ | |||
| EngineEventTypeMidi = 2 | |||
| kEngineEventTypeMidi = 2 | |||
| }; | |||
| /*! | |||
| @@ -113,42 +108,42 @@ enum EngineControlEventType { | |||
| /*! | |||
| * Null event type. | |||
| */ | |||
| EngineControlEventTypeNull = 0, | |||
| kEngineControlEventTypeNull = 0, | |||
| /*! | |||
| * Parameter event type.\n | |||
| * \note Value uses a range of 0.0<->1.0. | |||
| */ | |||
| EngineControlEventTypeParameter = 1, | |||
| kEngineControlEventTypeParameter = 1, | |||
| /*! | |||
| * MIDI Bank event type. | |||
| */ | |||
| EngineControlEventTypeMidiBank = 2, | |||
| kEngineControlEventTypeMidiBank = 2, | |||
| /*! | |||
| * MIDI Program change event type. | |||
| */ | |||
| EngineControlEventTypeMidiProgram = 3, | |||
| kEngineControlEventTypeMidiProgram = 3, | |||
| /*! | |||
| * All sound off event type. | |||
| */ | |||
| EngineControlEventTypeAllSoundOff = 4, | |||
| kEngineControlEventTypeAllSoundOff = 4, | |||
| /*! | |||
| * All notes off event type. | |||
| */ | |||
| EngineControlEventTypeAllNotesOff = 5 | |||
| kEngineControlEventTypeAllNotesOff = 5 | |||
| }; | |||
| /*! | |||
| * Engine control event. | |||
| */ | |||
| struct EngineControlEvent { | |||
| EngineControlEventType type; | |||
| uint16_t parameter; // parameter ID, midi bank & midi program | |||
| double value; // parameter value | |||
| EngineControlEventType type; //!< Control-Event type. | |||
| uint16_t parameter; //!< Parameter ID, midi bank or midi program. | |||
| double value; //!< Parameter value. | |||
| EngineControlEvent() | |||
| { | |||
| @@ -157,7 +152,7 @@ struct EngineControlEvent { | |||
| void clear() | |||
| { | |||
| type = EngineControlEventTypeNull; | |||
| type = kEngineControlEventTypeNull; | |||
| parameter = 0; | |||
| value = 0.0; | |||
| } | |||
| @@ -167,8 +162,9 @@ struct EngineControlEvent { | |||
| * Engine MIDI event. | |||
| */ | |||
| struct EngineMidiEvent { | |||
| uint8_t data[3]; | |||
| uint8_t size; | |||
| uint8_t port; //!< Port offset (usually 0) | |||
| uint8_t data[3]; //!< MIDI data, without channel | |||
| uint8_t size; //!< Number of bytes used | |||
| EngineMidiEvent() | |||
| { | |||
| @@ -177,6 +173,7 @@ struct EngineMidiEvent { | |||
| void clear() | |||
| { | |||
| port = 0; | |||
| data[0] = data[1] = data[2] = 0; | |||
| size = 0; | |||
| } | |||
| @@ -186,9 +183,9 @@ struct EngineMidiEvent { | |||
| * Engine event. | |||
| */ | |||
| struct EngineEvent { | |||
| EngineEventType type; //!< type; either Control or MIDI | |||
| uint32_t time; //!< frame offset | |||
| uint8_t channel; //!< channel, used for MIDI-related events | |||
| EngineEventType type; //!< Event Type; either Control or MIDI | |||
| uint32_t time; //!< Time offset in frames | |||
| uint8_t channel; //!< Channel, used for MIDI-related events | |||
| union { | |||
| EngineControlEvent ctrl; | |||
| @@ -202,7 +199,7 @@ struct EngineEvent { | |||
| void clear() | |||
| { | |||
| type = EngineEventTypeNull; | |||
| type = kEngineEventTypeNull; | |||
| time = 0; | |||
| channel = 0; | |||
| } | |||
| @@ -375,7 +372,7 @@ public: | |||
| */ | |||
| EnginePortType type() const | |||
| { | |||
| return EnginePortTypeAudio; | |||
| return kEnginePortTypeAudio; | |||
| } | |||
| /*! | |||
| @@ -411,7 +408,7 @@ public: | |||
| */ | |||
| EnginePortType type() const | |||
| { | |||
| return EnginePortTypeEvent; | |||
| return kEnginePortTypeEvent; | |||
| } | |||
| /*! | |||
| @@ -432,14 +429,14 @@ public: | |||
| virtual const EngineEvent* getEvent(const uint32_t index); | |||
| /*! | |||
| * Write a control event to the buffer.\n | |||
| * Write a control event into the buffer.\n | |||
| * Arguments are the same as in the EngineControlEvent struct. | |||
| ** \note You must only call this for output ports. | |||
| */ | |||
| virtual void writeControlEvent(const uint32_t time, const uint8_t channel, const EngineControlEventType type, const uint16_t parameter, const double value = 0.0); | |||
| /*! | |||
| * Write a MIDI event to the buffer.\n | |||
| * Write a MIDI event into the buffer.\n | |||
| * Arguments are the same as in the EngineMidiEvent struct. | |||
| ** \note You must only call this for output ports. | |||
| */ | |||
| @@ -527,7 +524,11 @@ private: | |||
| // ----------------------------------------------------------------------- | |||
| struct CarlaEnginePrivateData; | |||
| /*! | |||
| * Private data used in CarlaEngine. | |||
| * No other than CarlaEngine must have direct access to this. | |||
| */ | |||
| struct CarlaEngineProtectedData; | |||
| /*! | |||
| * Carla Engine. | |||
| @@ -549,7 +550,6 @@ public: | |||
| */ | |||
| virtual ~CarlaEngine(); | |||
| #if 0 | |||
| // ------------------------------------------------------------------- | |||
| // Static values and calls | |||
| @@ -583,7 +583,12 @@ public: | |||
| virtual int maxPortNameSize(); | |||
| /*! | |||
| * Maximum number of loadable plugins. | |||
| * Current number of plugins loaded. | |||
| */ | |||
| unsigned int currentPluginCount() const; | |||
| /*! | |||
| * Maximum number of loadable plugins allowed. | |||
| * \note This function returns 0 if engine is not started. | |||
| */ | |||
| unsigned int maxPluginNumber() const; | |||
| @@ -625,13 +630,14 @@ public: | |||
| // ------------------------------------------------------------------- | |||
| // Plugin management | |||
| #if 0 | |||
| /*! | |||
| * Get next available plugin id.\n | |||
| * Returns -1 if no more plugins can be loaded. | |||
| */ | |||
| int getNewPluginId() const; | |||
| #endif | |||
| #if 0 | |||
| /*! | |||
| * Get plugin with id \a id. | |||
| */ | |||
| @@ -641,13 +647,12 @@ public: | |||
| * Get plugin with id \a id, faster unchecked version. | |||
| */ | |||
| CarlaPlugin* getPluginUnchecked(const unsigned short id) const; | |||
| #endif | |||
| /*! | |||
| * Get a unique plugin name within the engine.\n | |||
| * Returned variable must be free'd when no longer needed. | |||
| */ | |||
| const char* getUniquePluginName(const char* const name); | |||
| const char* getNewUniquePluginName(const char* const name); | |||
| /*! | |||
| * Add new plugin.\n | |||
| @@ -681,7 +686,7 @@ public: | |||
| // bridge, internal use only | |||
| // TODO - find a better way for this | |||
| void __bridgePluginRegister(const unsigned short id, CarlaPlugin* const plugin); | |||
| //void __bridgePluginRegister(const unsigned short id, CarlaPlugin* const plugin); | |||
| //{ | |||
| // m_carlaPlugins[id] = plugin; | |||
| //} | |||
| @@ -694,7 +699,7 @@ public: | |||
| */ | |||
| const char* getName() const | |||
| { | |||
| return (const char*)name; | |||
| return (const char*)fName; | |||
| } | |||
| /*! | |||
| @@ -702,7 +707,7 @@ public: | |||
| */ | |||
| uint32_t getBufferSize() const | |||
| { | |||
| return bufferSize; | |||
| return fBufferSize; | |||
| } | |||
| /*! | |||
| @@ -710,31 +715,32 @@ public: | |||
| */ | |||
| double getSampleRate() const | |||
| { | |||
| return sampleRate; | |||
| return fSampleRate; | |||
| } | |||
| /*! | |||
| * Get the engine options (read-only). | |||
| */ | |||
| const CarlaEngineOptions& getOptions() const | |||
| const EngineOptions& getOptions() const | |||
| { | |||
| return options; | |||
| return fOptions; | |||
| } | |||
| /*! | |||
| * Get current Time information (read-only). | |||
| */ | |||
| const CarlaEngineTimeInfo& getTimeInfo() const | |||
| const EngineTimeInfo& getTimeInfo() const | |||
| { | |||
| return timeInfo; | |||
| return fTimeInfo; | |||
| } | |||
| /*! | |||
| * Tell the engine it's about to close.\n | |||
| * This is used to prevent the engine thread from reactivating. | |||
| * This is used to prevent the engine thread(s) from reactivating. | |||
| */ | |||
| void aboutToClose(); | |||
| void setAboutToClose(); | |||
| #if 0 | |||
| // ------------------------------------------------------------------- | |||
| // Information (audio peaks) | |||
| @@ -742,11 +748,19 @@ public: | |||
| double getOutputPeak(const unsigned short pluginId, const unsigned short id) const; | |||
| void setInputPeak(const unsigned short pluginId, const unsigned short id, double value); | |||
| void setOutputPeak(const unsigned short pluginId, const unsigned short id, double value); | |||
| #endif | |||
| // ------------------------------------------------------------------- | |||
| // Callback | |||
| /*! | |||
| * TODO. | |||
| */ | |||
| void callback(const CallbackType action, const unsigned short pluginId, const int value1, const int value2, const double value3, const char* const valueStr); | |||
| /*! | |||
| * TODO. | |||
| */ | |||
| void setCallback(const CallbackFunc func, void* const ptr); | |||
| // ------------------------------------------------------------------- | |||
| @@ -778,73 +792,103 @@ public: | |||
| #endif | |||
| // ------------------------------------------------------------------- | |||
| // Mutex locks | |||
| // OSC Stuff | |||
| #ifdef BUILD_BRIDGE | |||
| /*! | |||
| * Lock processing. | |||
| * Check if OSC bridge is registered. | |||
| */ | |||
| void processLock(); | |||
| bool isOscBridgeRegistered() const; | |||
| #else | |||
| /*! | |||
| * Try Lock processing. | |||
| * Check if OSC controller is registered. | |||
| */ | |||
| void processTryLock(); | |||
| bool isOscControlRegistered() const; | |||
| #endif | |||
| /*! | |||
| * Unlock processing. | |||
| * Idle OSC. | |||
| */ | |||
| void processUnlock(); | |||
| void idleOsc(); | |||
| /*! | |||
| * Lock MIDI. | |||
| * Get OSC TCP server path. | |||
| */ | |||
| void midiLock(); | |||
| const char* getOscServerPathTCP() const; | |||
| /*! | |||
| * Try Lock MIDI. | |||
| * Get OSC UDP server path. | |||
| */ | |||
| void midiTryLock(); | |||
| const char* getOscServerPathUDP() const; | |||
| #ifdef BUILD_BRIDGE | |||
| /*! | |||
| * Unlock MIDI. | |||
| * Set OSC bridge data. | |||
| */ | |||
| void midiUnlock(); | |||
| void setOscBridgeData(const CarlaOscData* const oscData); | |||
| #endif | |||
| // ------------------------------------------------------------------- | |||
| // OSC Stuff | |||
| // ------------------------------------- | |||
| protected: | |||
| CarlaString fName; | |||
| uint32_t fBufferSize; | |||
| double fSampleRate; | |||
| EngineOptions fOptions; | |||
| EngineTimeInfo fTimeInfo; | |||
| ScopedPointer<CarlaEngineProtectedData> const fData; | |||
| #ifndef BUILD_BRIDGE | |||
| // Rack mode data | |||
| //static const unsigned short MAX_EVENTS = 1024; | |||
| //EngineEvent fRackEventsIn[MAX_EVENTS]; | |||
| //EngineEvent fRackEventsOut[MAX_EVENTS]; | |||
| /*! | |||
| * Check if OSC controller is registered. | |||
| * Proccess audio buffer in rack mode. | |||
| */ | |||
| bool isOscControlRegistered() const; | |||
| #else | |||
| void processRack(float* inBuf[2], float* outBuf[2], const uint32_t frames); | |||
| /*! | |||
| * Check if OSC bridge is registered. | |||
| * Proccess audio buffer in patchbay mode. | |||
| * In \a bufCount, [0]=inBufCount and [1]=outBufCount | |||
| */ | |||
| bool isOscBridgeRegistered() const; | |||
| void processPatchbay(float** inBuf, float** outBuf, const uint32_t bufCount[2], const uint32_t frames); | |||
| #endif | |||
| /*! | |||
| * Idle OSC. | |||
| * Report to all plugins about buffer size change. | |||
| */ | |||
| void idleOsc(); | |||
| void bufferSizeChanged(const uint32_t newBufferSize); | |||
| /*! | |||
| * Get OSC TCP server path. | |||
| * Report to all plugins about sample rate change.\n | |||
| * This is not supported on all plugin types, on which case they will be re-initiated.\n | |||
| * TODO: Not implemented yet. | |||
| */ | |||
| const char* getOscServerPathTCP() const; | |||
| void sampleRateChanged(const double newSampleRate); | |||
| /*! | |||
| * Get OSC UDP server path. | |||
| */ | |||
| const char* getOscServerPathUDP() const; | |||
| private: | |||
| #ifdef CARLA_ENGINE_JACK | |||
| static CarlaEngine* newJack(); | |||
| #endif | |||
| #ifdef CARLA_ENGINE_RTAUDIO | |||
| enum RtAudioApi { | |||
| RTAUDIO_DUMMY = 0, | |||
| RTAUDIO_LINUX_ALSA = 1, | |||
| RTAUDIO_LINUX_PULSE = 2, | |||
| RTAUDIO_LINUX_OSS = 3, | |||
| RTAUDIO_UNIX_JACK = 4, | |||
| RTAUDIO_MACOSX_CORE = 5, | |||
| RTAUDIO_WINDOWS_ASIO = 6, | |||
| RTAUDIO_WINDOWS_DS = 7 | |||
| }; | |||
| #ifdef BUILD_BRIDGE | |||
| /*! | |||
| * Set OSC bridge data. | |||
| */ | |||
| void setOscBridgeData(const CarlaOscData* const oscData); | |||
| static CarlaEngine* newRtAudio(const RtAudioApi api); | |||
| static unsigned int getRtAudioApiCount(); | |||
| static const char* getRtAudioApiName(unsigned int index); | |||
| #endif | |||
| #ifdef BUILD_BRIDGE | |||
| @@ -899,112 +943,7 @@ public: | |||
| void osc_send_control_exit(); | |||
| #endif | |||
| #endif | |||
| // ------------------------------------- | |||
| #if 0 | |||
| /*! | |||
| * \class ScopedLocker | |||
| * | |||
| * \brief Carla engine scoped locker | |||
| * | |||
| * This is a handy class that temporarily locks an engine during a function scope. | |||
| */ | |||
| class ScopedLocker | |||
| { | |||
| public: | |||
| /*! | |||
| * Lock the engine \a engine if \a lock is true. | |||
| * The engine is unlocked in the deconstructor of this class if \a lock is true. | |||
| * | |||
| * \param engine The engine to lock | |||
| * \param lock Wherever to lock the engine or not, true by default | |||
| */ | |||
| ScopedLocker(CarlaEngine* const engine, bool lock = true); | |||
| // : mutex(&engine->m_procLock), | |||
| // m_lock(lock) | |||
| //{ | |||
| // if (m_lock) | |||
| // mutex->lock(); | |||
| //} | |||
| ~ScopedLocker() {} | |||
| //{ | |||
| // if (m_lock) | |||
| // mutex->unlock(); | |||
| //} | |||
| private: | |||
| QMutex* const mutex; | |||
| const bool m_lock; | |||
| }; | |||
| #endif | |||
| // ------------------------------------- | |||
| protected: | |||
| CarlaString name; | |||
| uint32_t bufferSize; | |||
| double sampleRate; | |||
| EngineOptions options; | |||
| EngineTimeInfo timeInfo; | |||
| #ifndef BUILD_BRIDGE | |||
| // Rack mode data | |||
| static const unsigned short MAX_EVENTS = 1024; | |||
| EngineEvent rackEventsIn[MAX_EVENTS]; | |||
| EngineEvent rackEventsOut[MAX_EVENTS]; | |||
| /*! | |||
| * Proccess audio buffer in rack mode. | |||
| */ | |||
| //void processRack(float* inBuf[2], float* outBuf[2], const uint32_t frames); | |||
| /*! | |||
| * Proccess audio buffer in patchbay mode. | |||
| * In \a bufCount, [0]=inBufCount and [1]=outBufCount | |||
| */ | |||
| //void processPatchbay(float** inBuf, float** outBuf, const uint32_t bufCount[2], const uint32_t frames); | |||
| #endif | |||
| #if 0 | |||
| /*! | |||
| * Report to all plugins about buffer size change. | |||
| */ | |||
| void bufferSizeChanged(const uint32_t newBufferSize); | |||
| /*! | |||
| * Report to all plugins about sample rate change. | |||
| * This is not supported on all plugin types, on which case they will be re-initiated. | |||
| */ | |||
| void sampleRateChanged(const double newSampleRate); | |||
| private: | |||
| #ifdef CARLA_ENGINE_JACK | |||
| static CarlaEngine* newJack(); | |||
| #endif | |||
| #ifdef CARLA_ENGINE_RTAUDIO | |||
| enum RtAudioApi { | |||
| RTAUDIO_DUMMY = 0, | |||
| RTAUDIO_LINUX_ALSA = 1, | |||
| RTAUDIO_LINUX_PULSE = 2, | |||
| RTAUDIO_LINUX_OSS = 3, | |||
| RTAUDIO_UNIX_JACK = 4, | |||
| RTAUDIO_MACOSX_CORE = 5, | |||
| RTAUDIO_WINDOWS_ASIO = 6, | |||
| RTAUDIO_WINDOWS_DS = 7 | |||
| }; | |||
| static CarlaEngine* newRtAudio(RtAudioApi api); | |||
| static unsigned int getRtAudioApiCount(); | |||
| static const char* getRtAudioApiName(unsigned int index); | |||
| #endif | |||
| #endif | |||
| friend class CarlaEngineEventPort; | |||
| ScopedPointer<CarlaEnginePrivateData> const data; | |||
| CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngine) | |||
| }; | |||
| @@ -2,50 +2,32 @@ | |||
| * Carla Plugin API | |||
| * Copyright (C) 2011-2013 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or modify | |||
| * it under the terms of the GNU General Public License as published by | |||
| * the Free Software Foundation; either version 2 of the License, or | |||
| * any later version. | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU General Public License for more details. | |||
| * | |||
| * For a full copy of the GNU General Public License see the COPYING file | |||
| * For a full copy of the GNU General Public License see the GPL.txt file | |||
| */ | |||
| #ifndef __CARLA_PLUGIN_HPP__ | |||
| #define __CARLA_PLUGIN_HPP__ | |||
| //#include "carla_midi.h" | |||
| //#include "carla_engine.hpp" | |||
| #include "carla_backend.hpp" | |||
| #include "carla_native.h" | |||
| #include "carla_utils.hpp" | |||
| //#include "carla_plugin_thread.hpp" | |||
| # include "carla_backend.hpp" | |||
| #ifdef BUILD_BRIDGE | |||
| # include "carla_bridge_osc.hpp" | |||
| #else | |||
| # include "carla_osc_utils.hpp" | |||
| #ifdef WANT_LADSPA | |||
| # include "ladspa_rdf.hpp" | |||
| #endif | |||
| // common includes | |||
| //#include <cmath> | |||
| //#include <vector> | |||
| //#include <QtCore/QMutex> | |||
| //#include <QtGui/QMainWindow> | |||
| //#ifdef Q_WS_X11 | |||
| //# include <QtGui/QX11EmbedContainer> | |||
| //typedef QX11EmbedContainer GuiContainer; | |||
| //#else | |||
| //# include <QtGui/QWidget> | |||
| //typedef QWidget GuiContainer; | |||
| //#endif | |||
| typedef struct _PluginDescriptor PluginDescriptor; | |||
| // Avoid including liblo here | |||
| typedef void* lo_address; | |||
| CARLA_BACKEND_START_NAMESPACE | |||
| @@ -53,134 +35,48 @@ CARLA_BACKEND_START_NAMESPACE | |||
| } // Fix editor indentation | |||
| #endif | |||
| class CarlaEngineAudioPort; | |||
| class CarlaEngineEventPort; | |||
| /*! | |||
| * @defgroup CarlaPluginAPI Carla Plugin API | |||
| * | |||
| * The Carla Plugin API. | |||
| * @{ | |||
| */ | |||
| #define CARLA_PROCESS_CONTINUE_CHECK if (! m_enabled) { x_engine->callback(CALLBACK_DEBUG, m_id, m_enabled, 0, 0.0, nullptr); return; } | |||
| const unsigned short MAX_MIDI_EVENTS = 512; | |||
| const unsigned short MAX_POST_EVENTS = 152; | |||
| #ifndef BUILD_BRIDGE | |||
| enum PluginBridgeInfoType { | |||
| PluginBridgeAudioCount, | |||
| PluginBridgeMidiCount, | |||
| PluginBridgeParameterCount, | |||
| PluginBridgeProgramCount, | |||
| PluginBridgeMidiProgramCount, | |||
| PluginBridgePluginInfo, | |||
| PluginBridgeParameterInfo, | |||
| PluginBridgeParameterData, | |||
| PluginBridgeParameterRanges, | |||
| PluginBridgeProgramInfo, | |||
| PluginBridgeMidiProgramInfo, | |||
| PluginBridgeConfigure, | |||
| PluginBridgeSetParameterValue, | |||
| PluginBridgeSetDefaultValue, | |||
| PluginBridgeSetProgram, | |||
| PluginBridgeSetMidiProgram, | |||
| PluginBridgeSetCustomData, | |||
| PluginBridgeSetChunkData, | |||
| PluginBridgeUpdateNow, | |||
| PluginBridgeError | |||
| kPluginBridgeAudioCount, | |||
| kPluginBridgeMidiCount, | |||
| kPluginBridgeParameterCount, | |||
| kPluginBridgeProgramCount, | |||
| kPluginBridgeMidiProgramCount, | |||
| kPluginBridgePluginInfo, | |||
| kPluginBridgeParameterInfo, | |||
| kPluginBridgeParameterData, | |||
| kPluginBridgeParameterRanges, | |||
| kPluginBridgeProgramInfo, | |||
| kPluginBridgeMidiProgramInfo, | |||
| kPluginBridgeConfigure, | |||
| kPluginBridgeSetParameterValue, | |||
| kPluginBridgeSetDefaultValue, | |||
| kPluginBridgeSetProgram, | |||
| kPluginBridgeSetMidiProgram, | |||
| kPluginBridgeSetCustomData, | |||
| kPluginBridgeSetChunkData, | |||
| kPluginBridgeUpdateNow, | |||
| kPluginBridgeError | |||
| }; | |||
| #endif | |||
| enum PluginPostEventType { | |||
| PluginPostEventNull, | |||
| PluginPostEventDebug, | |||
| PluginPostEventParameterChange, // param, N, value | |||
| PluginPostEventProgramChange, // index | |||
| PluginPostEventMidiProgramChange, // index | |||
| PluginPostEventNoteOn, // channel, note, velo | |||
| PluginPostEventNoteOff // channel, note | |||
| }; | |||
| struct PluginAudioData { | |||
| uint32_t count; | |||
| uint32_t* rindexes; | |||
| CarlaEngineAudioPort** ports; | |||
| PluginAudioData() | |||
| : count(0), | |||
| rindexes(nullptr), | |||
| ports(nullptr) {} | |||
| }; | |||
| struct PluginEventData { | |||
| CarlaEngineEventPort* portIn; | |||
| CarlaEngineEventPort* portOut; | |||
| PluginEventData() | |||
| : portIn(nullptr), | |||
| portOut(nullptr) {} | |||
| kPluginPostEventNull, | |||
| kPluginPostEventDebug, | |||
| kPluginPostEventParameterChange, // param, N, value | |||
| kPluginPostEventProgramChange, // index | |||
| kPluginPostEventMidiProgramChange, // index | |||
| kPluginPostEventNoteOn, // channel, note, velo | |||
| kPluginPostEventNoteOff // channel, note | |||
| }; | |||
| struct PluginParameterData { | |||
| uint32_t count; | |||
| ParameterData* data; | |||
| ParameterRanges* ranges; | |||
| // ----------------------------------------------------------------------- | |||
| PluginParameterData() | |||
| : count(0), | |||
| data(nullptr), | |||
| ranges(nullptr) {} | |||
| }; | |||
| struct PluginProgramData { | |||
| uint32_t count; | |||
| int32_t current; | |||
| const char** names; | |||
| PluginProgramData() | |||
| : count(0), | |||
| current(-1), | |||
| names(nullptr) {} | |||
| }; | |||
| struct PluginMidiProgramData { | |||
| uint32_t count; | |||
| int32_t current; | |||
| MidiProgramData* data; | |||
| PluginMidiProgramData() | |||
| : count(0), | |||
| current(-1), | |||
| data(nullptr) {} | |||
| }; | |||
| struct PluginPostEvent { | |||
| PluginPostEventType type; | |||
| int32_t value1; | |||
| int32_t value2; | |||
| double value3; | |||
| PluginPostEvent() | |||
| : type(PluginPostEventNull), | |||
| value1(-1), | |||
| value2(-1), | |||
| value3(0.0) {} | |||
| }; | |||
| struct ExternalMidiNote { | |||
| int8_t channel; // invalid = -1 | |||
| uint8_t note; | |||
| uint8_t velo; | |||
| ExternalMidiNote() | |||
| : channel(-1), | |||
| note(0), | |||
| velo(0) {} | |||
| }; | |||
| struct CarlaPluginPrivateData; | |||
| /*! | |||
| * Protected data used in CarlaPlugin and subclasses.\n | |||
| * Non-plugin code MUST NEVER have direct access to this. | |||
| */ | |||
| struct CarlaPluginProtectedData; | |||
| /*! | |||
| * \class CarlaPlugin | |||
| @@ -199,12 +95,12 @@ public: | |||
| * This is the constructor of the base plugin class. | |||
| * | |||
| * \param engine The engine which this plugin belongs to, must not be null | |||
| * \param id The 'id' of this plugin, must between 0 and CarlaEngine::maxPluginNumber() | |||
| * \param id The 'id' of this plugin, must be between 0 and CarlaEngine::maxPluginNumber() | |||
| */ | |||
| CarlaPlugin(CarlaEngine* const engine, const unsigned short id); | |||
| /*! | |||
| * This is the de-constructor of the base plugin class. | |||
| * This is the destructor of the base plugin class. | |||
| */ | |||
| virtual ~CarlaPlugin(); | |||
| @@ -217,11 +113,14 @@ public: | |||
| * \note Plugin bridges will return their respective plugin type, there is no plugin type such as "bridge".\n | |||
| * To check if a plugin is a bridge use: | |||
| * \code | |||
| * if (m_hints & PLUGIN_IS_BRIDGE) | |||
| * if (hints() & PLUGIN_IS_BRIDGE) | |||
| * ... | |||
| * \endcode | |||
| */ | |||
| PluginType type() const; | |||
| virtual PluginType type() const | |||
| { | |||
| return PLUGIN_NONE; | |||
| } | |||
| /*! | |||
| * Get the plugin's id (as passed in the constructor). | |||
| @@ -237,6 +136,13 @@ public: | |||
| */ | |||
| unsigned int hints() const; | |||
| /*! | |||
| * Get the plugin's options. | |||
| * | |||
| * \see PluginOptions | |||
| */ | |||
| unsigned int options() const; | |||
| /*! | |||
| * Check if the plugin is enabled. | |||
| * | |||
| @@ -339,12 +245,12 @@ public: | |||
| /*! | |||
| * Get the parameter data of \a parameterId. | |||
| */ | |||
| const ParameterData* parameterData(const uint32_t parameterId) const; | |||
| const ParameterData& parameterData(const uint32_t parameterId) const; | |||
| /*! | |||
| * Get the parameter ranges of \a parameterId. | |||
| */ | |||
| const ParameterRanges* parameterRanges(const uint32_t parameterId) const; | |||
| const ParameterRanges& parameterRanges(const uint32_t parameterId) const; | |||
| /*! | |||
| * Check if parameter \a parameterId is of output type. | |||
| @@ -356,14 +262,14 @@ public: | |||
| * | |||
| * \see getMidiProgramName() | |||
| */ | |||
| const MidiProgramData* midiProgramData(const uint32_t index) const; | |||
| const MidiProgramData& midiProgramData(const uint32_t index) const; | |||
| /*! | |||
| * Get the custom data set at \a index. | |||
| * | |||
| * \see setCustomData() | |||
| */ | |||
| const CustomData* customData(const size_t index) const; | |||
| const CustomData& customData(const size_t index) const; | |||
| /*! | |||
| * Get the complete plugin chunk data into \a dataPtr. | |||
| @@ -458,11 +364,6 @@ public: | |||
| */ | |||
| void getParameterCountInfo(uint32_t* const ins, uint32_t* const outs, uint32_t* const total); | |||
| /*! | |||
| * Get information about the plugin's custom GUI, if provided. | |||
| */ | |||
| //virtual void getGuiInfo(GuiType* const type, bool* const resizable); | |||
| // ------------------------------------------------------------------- | |||
| // Set data (internal stuff) | |||
| @@ -531,7 +432,7 @@ public: | |||
| /*! | |||
| * BridgePlugin call used to set internal data. | |||
| */ | |||
| virtual int setOscBridgeInfo(const PluginBridgeInfoType type, const int argc, const lo_arg* const* const argv, const char* const types); | |||
| //virtual int setOscBridgeInfo(const PluginBridgeInfoType type, const int argc, const lo_arg* const* const argv, const char* const types); | |||
| #endif | |||
| // ------------------------------------------------------------------- | |||
| @@ -705,7 +606,7 @@ public: | |||
| * Update the plugin's internal OSC data according to \a source and \a url.\n | |||
| * This is used for OSC-GUI bridges. | |||
| */ | |||
| void updateOscData(const lo_address source, const char* const url); | |||
| void updateOscData(const lo_address& source, const char* const url); | |||
| /*! | |||
| * Free the plugin's internal OSC memory data. | |||
| @@ -820,14 +721,6 @@ public: | |||
| */ | |||
| const char* libError(const char* const filename); | |||
| // ------------------------------------------------------------------- | |||
| // Locks | |||
| void engineProcessLock(); | |||
| void engineProcessUnlock(); | |||
| void engineMidiLock(); | |||
| void engineMidiUnlock(); | |||
| // ------------------------------------------------------------------- | |||
| // Plugin initializers | |||
| @@ -857,227 +750,12 @@ public: | |||
| // ------------------------------------------------------------------- | |||
| /*! | |||
| * \class ScopedDisabler | |||
| * | |||
| * \brief Carla plugin scoped disabler | |||
| * | |||
| * This is a handy class that temporarily disables a plugin during a function scope.\n | |||
| * It should be used when the plugin needs reload or state change, something like this: | |||
| * \code | |||
| * { | |||
| * const CarlaPlugin::ScopedDisabler m(plugin); | |||
| * plugin->setChunkData(data); | |||
| * } | |||
| * \endcode | |||
| */ | |||
| class ScopedDisabler | |||
| { | |||
| public: | |||
| /*! | |||
| * Disable plugin \a plugin if \a disable is true. | |||
| * The plugin is re-enabled in the deconstructor of this class if \a disable is true. | |||
| * | |||
| * \param plugin The plugin to disable | |||
| * \param disable Wherever to disable the plugin or not, true by default | |||
| */ | |||
| ScopedDisabler(CarlaPlugin* const plugin, const bool disable = true) | |||
| : m_plugin(plugin), | |||
| m_disable(disable) | |||
| { | |||
| if (m_disable) | |||
| { | |||
| m_plugin->engineProcessLock(); | |||
| m_plugin->setEnabled(false); | |||
| m_plugin->engineProcessUnlock(); | |||
| } | |||
| } | |||
| ~ScopedDisabler() | |||
| { | |||
| if (m_disable) | |||
| { | |||
| m_plugin->engineProcessLock(); | |||
| m_plugin->setEnabled(true); | |||
| m_plugin->engineProcessUnlock(); | |||
| } | |||
| } | |||
| private: | |||
| CarlaPlugin* const m_plugin; | |||
| const bool m_disable; | |||
| }; | |||
| // ------------------------------------------------------------------- | |||
| protected: | |||
| CarlaPluginPrivateData* const data; | |||
| friend class CarlaPluginInternal; | |||
| #if 0 | |||
| unsigned short m_id; | |||
| CarlaEngine* const x_engine; | |||
| CarlaEngineClient* x_client; | |||
| double x_dryWet, x_volume; | |||
| double x_balanceLeft, x_balanceRight; | |||
| PluginType m_type; | |||
| unsigned int m_hints; | |||
| bool m_active; | |||
| bool m_activeBefore; | |||
| bool m_enabled; | |||
| void* m_lib; | |||
| const char* m_name; | |||
| const char* m_filename; | |||
| // options | |||
| int8_t m_ctrlInChannel; | |||
| bool m_fixedBufferSize; | |||
| bool m_processHighPrecision; | |||
| // latency | |||
| uint32_t m_latency; | |||
| float** m_latencyBuffers; | |||
| // ------------------------------------------------------------------- | |||
| // Storage Data | |||
| PluginAudioData aIn; | |||
| PluginAudioData aOut; | |||
| PluginMidiData midi; | |||
| PluginParameterData param; | |||
| PluginProgramData prog; | |||
| PluginMidiProgramData midiprog; | |||
| std::vector<CustomData> custom; | |||
| // ------------------------------------------------------------------- | |||
| // Extra | |||
| struct { | |||
| CarlaOscData data; | |||
| CarlaPluginThread* thread; | |||
| } osc; | |||
| struct { | |||
| QMutex mutex; | |||
| PluginPostEvent data[MAX_POST_EVENTS]; | |||
| } postEvents; | |||
| ExternalMidiNote extMidiNotes[MAX_MIDI_EVENTS]; | |||
| // ------------------------------------------------------------------- | |||
| // Utilities | |||
| static double fixParameterValue(double& value, const ParameterRanges& ranges) | |||
| { | |||
| if (value < ranges.min) | |||
| value = ranges.min; | |||
| else if (value > ranges.max) | |||
| value = ranges.max; | |||
| return value; | |||
| } | |||
| static float fixParameterValue(float& value, const ParameterRanges& ranges) | |||
| { | |||
| if (value < ranges.min) | |||
| value = ranges.min; | |||
| else if (value > ranges.max) | |||
| value = ranges.max; | |||
| return value; | |||
| } | |||
| friend class CarlaEngine; // FIXME | |||
| friend class CarlaEngineJack; | |||
| #endif | |||
| }; | |||
| #if 0 | |||
| /*! | |||
| * \class CarlaPluginGUI | |||
| * | |||
| * \brief Carla Backend gui plugin class | |||
| * | |||
| * \see CarlaPlugin | |||
| */ | |||
| class CarlaPluginGUI : public QMainWindow | |||
| { | |||
| public: | |||
| /*! | |||
| * \class Callback | |||
| * | |||
| * \brief Carla plugin GUI callback | |||
| */ | |||
| class Callback | |||
| { | |||
| public: | |||
| virtual ~Callback() {} | |||
| virtual void guiClosedCallback() = 0; | |||
| }; | |||
| // ------------------------------------------------------------------- | |||
| // Constructor and destructor | |||
| /*! | |||
| * TODO | |||
| */ | |||
| CarlaPluginGUI(QWidget* const parent, Callback* const callback); | |||
| /*! | |||
| * TODO | |||
| */ | |||
| ~CarlaPluginGUI(); | |||
| // ------------------------------------------------------------------- | |||
| // Get data | |||
| /*! | |||
| * TODO | |||
| */ | |||
| GuiContainer* getContainer() const; | |||
| /*! | |||
| * TODO | |||
| */ | |||
| WId getWinId() const; | |||
| // ------------------------------------------------------------------- | |||
| // Set data | |||
| /*! | |||
| * TODO | |||
| */ | |||
| void setNewSize(const int width, const int height); | |||
| /*! | |||
| * TODO | |||
| */ | |||
| void setResizable(const bool resizable); | |||
| /*! | |||
| * TODO | |||
| */ | |||
| void setTitle(const char* const title); | |||
| /*! | |||
| * TODO | |||
| */ | |||
| void setVisible(const bool yesNo); | |||
| // ------------------------------------------------------------------- | |||
| ScopedPointer<CarlaPluginProtectedData> const fData; | |||
| private: | |||
| Callback* const m_callback; | |||
| GuiContainer* m_container; | |||
| QByteArray m_geometry; | |||
| bool m_resizable; | |||
| void hideEvent(QHideEvent* const event); | |||
| void closeEvent(QCloseEvent* const event); | |||
| CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPlugin) | |||
| }; | |||
| #endif | |||
| /**@}*/ | |||
| @@ -8,8 +8,7 @@ include ../../Makefile.mk | |||
| # -------------------------------------------------------------- | |||
| BUILD_CXX_FLAGS += -fvisibility=hidden -fPIC | |||
| BUILD_CXX_FLAGS += -I. -I.. -I../../includes -I../../libs -I../../utils | |||
| BUILD_CXX_FLAGS += -fvisibility=hidden -fPIC -I. -I.. -I../../includes -I../../libs -I../../utils | |||
| BUILD_CXX_FLAGS += $(shell pkg-config --cflags liblo QtCore) | |||
| LINK_FLAGS += -shared | |||
| @@ -33,17 +32,6 @@ LINK_FLAGS += $(shell pkg-config --libs libpulse-simple) | |||
| WANT_RTAUDIO = true | |||
| endif | |||
| OBJS = \ | |||
| carla_engine.cpp.o | |||
| # carla_engine_osc.cpp.o \ | |||
| # carla_engine_thread.cpp.o \ | |||
| # jack.cpp.o \ | |||
| # rtaudio.cpp.o | |||
| TARGET = ../carla_engine.so | |||
| # -------------------------------------------------------------- | |||
| ifeq ($(WANT_JACK),true) | |||
| BUILD_CXX_FLAGS += -DCARLA_ENGINE_JACK | |||
| endif | |||
| @@ -56,12 +44,27 @@ BUILD_CXX_FLAGS += -D__RTAUDIO_DEBUG__ -D__RTMIDI_DEBUG__ | |||
| else | |||
| BUILD_CXX_FLAGS += -D_FORTIFY_SOURCE=2 | |||
| endif | |||
| OBJS += rtaudio-4.0.11/RtAudio.cpp.o | |||
| OBJS += rtmidi-2.0.1/RtMidi.cpp.o | |||
| endif | |||
| # -------------------------------------------------------------- | |||
| OBJS = \ | |||
| carla_engine.cpp.o | |||
| # carla_engine_osc.cpp.o \ | |||
| # carla_engine_thread.cpp.o \ | |||
| # jack.cpp.o \ | |||
| # rtaudio.cpp.o | |||
| ifeq ($(WANT_RTAUDIO),true) | |||
| OBJS += \ | |||
| rtaudio-4.0.11/RtAudio.cpp.o \ | |||
| rtmidi-2.0.1/RtMidi.cpp.o | |||
| endif | |||
| TARGET = ../carla_engine.so | |||
| # -------------------------------------------------------------- | |||
| all: $(TARGET) | |||
| clean: | |||
| @@ -214,7 +214,7 @@ void CarlaEngineEventPort::writeControlEvent(const uint32_t time, const uint8_t | |||
| return; | |||
| } | |||
| qWarning("CarlaEngineEventPort::writeEvent() - buffer full"); | |||
| qWarning("CarlaEngineEventPort::writeControlEvent() - buffer full"); | |||
| } | |||
| #else | |||
| Q_UNUSED(time); | |||
| @@ -265,7 +265,7 @@ void CarlaEngineEventPort::writeMidiEvent(const uint32_t time, const uint8_t cha | |||
| return; | |||
| } | |||
| qWarning("CarlaEngineEventPort::writeEvent() - buffer full"); | |||
| qWarning("CarlaEngineEventPort::writeMidiEvent() - buffer full"); | |||
| } | |||
| #else | |||
| Q_UNUSED(time); | |||
| @@ -351,8 +351,6 @@ CarlaEngine::~CarlaEngine() | |||
| //data = nullptr; | |||
| } | |||
| #if 0 | |||
| // ----------------------------------------------------------------------- | |||
| // Static values and calls | |||
| @@ -449,6 +447,11 @@ int CarlaEngine::maxPortNameSize() | |||
| return STR_MAX; | |||
| } | |||
| unsigned int CarlaEngine::currentPluginCount() const | |||
| { | |||
| return data->curPluginCount; | |||
| } | |||
| unsigned int CarlaEngine::maxPluginNumber() const | |||
| { | |||
| return data->maxPluginNumber; | |||
| @@ -460,12 +463,28 @@ unsigned int CarlaEngine::maxPluginNumber() const | |||
| bool CarlaEngine::init(const char* const clientName) | |||
| { | |||
| qDebug("CarlaEngine::init(\"%s\")", clientName); | |||
| data->osc.init(clientName); | |||
| CARLA_ASSERT(! data->plugins); | |||
| data->aboutToClose = false; | |||
| data->curPluginCount = 0; | |||
| data->maxPluginNumber = 0; | |||
| data->nextPluginId = 0; | |||
| switch (options.processMode) | |||
| { | |||
| case PROCESS_MODE_CONTINUOUS_RACK: | |||
| data->maxPluginNumber = MAX_RACK_PLUGINS; | |||
| break; | |||
| case PROCESS_MODE_PATCHBAY: | |||
| data->maxPluginNumber = MAX_PATCHBAY_PLUGINS; | |||
| break; | |||
| default: | |||
| data->maxPluginNumber = MAX_DEFAULT_PLUGINS; | |||
| break; | |||
| } | |||
| data->plugins = new EnginePluginData[data->maxPluginNumber]; | |||
| data->osc.init(clientName); | |||
| #ifndef BUILD_BRIDGE | |||
| data->oscData = data->osc.getControlData(); | |||
| @@ -478,9 +497,6 @@ bool CarlaEngine::init(const char* const clientName) | |||
| carla_setprocname(clientName); | |||
| #endif | |||
| //data->postEvents.resize(); | |||
| //data->plugins.resize(); | |||
| data->thread.startNow(); | |||
| return true; | |||
| @@ -489,6 +505,7 @@ bool CarlaEngine::init(const char* const clientName) | |||
| bool CarlaEngine::close() | |||
| { | |||
| qDebug("CarlaEngine::close()"); | |||
| CARLA_ASSERT(data->plugins); | |||
| data->thread.stopNow(); | |||
| @@ -497,9 +514,17 @@ bool CarlaEngine::close() | |||
| #endif | |||
| data->osc.close(); | |||
| data->oscData = nullptr; | |||
| data->aboutToClose = true; | |||
| data->curPluginCount = 0; | |||
| data->maxPluginNumber = 0; | |||
| data->oscData = nullptr; | |||
| if (data->plugins) | |||
| { | |||
| delete[] data->plugins; | |||
| data->plugins = nullptr; | |||
| } | |||
| name.clear(); | |||
| @@ -509,6 +534,7 @@ bool CarlaEngine::close() | |||
| // ----------------------------------------------------------------------- | |||
| // Plugin management | |||
| #if 0 | |||
| int CarlaEngine::getNewPluginId() const | |||
| { | |||
| qDebug("CarlaEngine::getNewPluginId()"); | |||
| @@ -516,46 +542,49 @@ int CarlaEngine::getNewPluginId() const | |||
| return data->nextPluginId; | |||
| } | |||
| #endif | |||
| #if 0 | |||
| CarlaPlugin* CarlaEngine::getPlugin(const unsigned short id) const | |||
| { | |||
| qDebug("CarlaEngine::getPlugin(%i) [max:%i]", id, data->maxPluginNumber); | |||
| CARLA_ASSERT(data->maxPluginNumber > 0); | |||
| CARLA_ASSERT(id < data->maxPluginNumber); | |||
| qDebug("CarlaEngine::getPlugin(%i) [count:%i]", id, data->curPluginCount); | |||
| CARLA_ASSERT(data->curPluginCount > 0); | |||
| CARLA_ASSERT(id < data->curPluginCount); | |||
| CARLA_ASSERT(data->plugins); | |||
| if (id < data->maxPluginNumber) | |||
| return data->carlaPlugins[id]; | |||
| if (id < data->curPluginCount && data->plugins) | |||
| return data->plugins[id].plugin; | |||
| return nullptr; | |||
| } | |||
| CarlaPlugin* CarlaEngine::getPluginUnchecked(const unsigned short id) const | |||
| { | |||
| return data->carlaPlugins[id]; | |||
| return data->plugins[id].plugin; | |||
| } | |||
| #endif | |||
| const char* CarlaEngine::getUniquePluginName(const char* const name) | |||
| const char* CarlaEngine::getNewUniquePluginName(const char* const name) | |||
| { | |||
| qDebug("CarlaEngine::getUniquePluginName(\"%s\")", name); | |||
| CARLA_ASSERT(data->maxPluginNumber > 0); | |||
| qDebug("CarlaEngine::getNewUniquePluginName(\"%s\")", name); | |||
| CARLA_ASSERT(data->curPluginCount > 0); | |||
| CARLA_ASSERT(data->plugins); | |||
| CARLA_ASSERT(name); | |||
| CarlaString sname(name); | |||
| if (sname.isEmpty()) | |||
| if (sname.isEmpty() || ! data->plugins) | |||
| return strdup("(No name)"); | |||
| sname.truncate(maxClientNameSize()-5-1); // 5 = strlen(" (10)") | |||
| sname.replace(':', '.'); // ':' is used in JACK1 to split client/port names | |||
| #if 0 | |||
| for (unsigned short i=0; i < data->maxPluginNumber; i++) | |||
| for (unsigned short i=0; i < data->curPluginCount; i++) | |||
| { | |||
| // Check if unique name doesn't exist | |||
| if (data->uniqueNames[i] && sname != data->uniqueNames[i]) | |||
| continue; | |||
| if (const char* const pluginName = data->plugins[i].plugin->name()) | |||
| { | |||
| if (sname != pluginName) | |||
| continue; | |||
| } | |||
| // Check if string has already been modified | |||
| { | |||
| @@ -603,7 +632,6 @@ const char* CarlaEngine::getUniquePluginName(const char* const name) | |||
| // Modify string if not | |||
| sname += " (2)"; | |||
| } | |||
| #endif | |||
| return strdup(sname); | |||
| } | |||
| @@ -616,27 +644,6 @@ short CarlaEngine::addPlugin(const BinaryType btype, const PluginType ptype, con | |||
| CARLA_ASSERT(filename); | |||
| CARLA_ASSERT(label); | |||
| if (QThread::currentThread() != &data->thread) | |||
| { | |||
| EnginePostEvent postEvent; | |||
| data->postEvents.append(postEvent); | |||
| return; | |||
| } | |||
| if (data->maxPluginNumber == 0) | |||
| { | |||
| #ifdef BUILD_BRIDGE | |||
| data->maxPluginNumber = MAX_PLUGINS; // which is 1 | |||
| #else | |||
| if (options.processMode == PROCESS_MODE_CONTINUOUS_RACK) | |||
| data->maxPluginNumber = MAX_RACK_PLUGINS; | |||
| else if (options.processMode == PROCESS_MODE_PATCHBAY) | |||
| data->maxPluginNumber = MAX_PATCHBAY_PLUGINS; | |||
| else | |||
| data->maxPluginNumber = MAX_DEFAULT_PLUGINS; | |||
| #endif | |||
| } | |||
| CarlaPlugin::Initializer init = { | |||
| this, | |||
| filename, | |||
| @@ -646,14 +653,30 @@ short CarlaEngine::addPlugin(const BinaryType btype, const PluginType ptype, con | |||
| CarlaPlugin* plugin = nullptr; | |||
| const char* bridgeBinary = nullptr; // TODO | |||
| #ifndef BUILD_BRIDGE | |||
| const char* bridgeBinary; | |||
| // Can't use bridge plugins without jack multi-client for now | |||
| if (type() != CarlaEngineTypeJack) | |||
| switch (btype) | |||
| { | |||
| case BINARY_POSIX32: | |||
| bridgeBinary = options.bridge_posix32.isNotEmpty() ? (const char*)options.bridge_posix32 : nullptr; | |||
| case BINARY_POSIX64: | |||
| bridgeBinary = options.bridge_posix64.isNotEmpty() ? (const char*)options.bridge_posix64 : nullptr; | |||
| case BINARY_WIN32: | |||
| bridgeBinary = options.bridge_win32.isNotEmpty() ? (const char*)options.bridge_win32 : nullptr; | |||
| case BINARY_WIN64: | |||
| bridgeBinary = options.bridge_win64.isNotEmpty() ? (const char*)options.bridge_win64 : nullptr; | |||
| default: | |||
| bridgeBinary = nullptr; | |||
| break; | |||
| } | |||
| #ifndef BUILD_BRIDGE | |||
| if (btype != BINARY_NATIVE || (options.preferPluginBridges && bridgeBinary)) | |||
| #ifndef Q_OS_WIN | |||
| if (btype == BINARY_NATIVE && options.bridge_native.isNotEmpty()) | |||
| bridgeBinary = (const char*)options.bridge_native; | |||
| #endif | |||
| if (options.preferPluginBridges && bridgeBinary) | |||
| { | |||
| // TODO | |||
| if (options.processMode != PROCESS_MODE_MULTIPLE_CLIENTS) | |||
| @@ -663,7 +686,7 @@ short CarlaEngine::addPlugin(const BinaryType btype, const PluginType ptype, con | |||
| } | |||
| // TODO | |||
| if (type() != CarlaEngineTypeJack) | |||
| if (type() != EngineTypeJack) | |||
| { | |||
| setLastError("Can only use bridged plugins with JACK backend"); | |||
| return -1; | |||
| @@ -672,7 +695,7 @@ short CarlaEngine::addPlugin(const BinaryType btype, const PluginType ptype, con | |||
| plugin = CarlaPlugin::newBridge(init, btype, ptype, bridgeBinary); | |||
| } | |||
| else | |||
| #endif | |||
| #endif // BUILD_BRIDGE | |||
| { | |||
| switch (ptype) | |||
| { | |||
| @@ -712,10 +735,9 @@ short CarlaEngine::addPlugin(const BinaryType btype, const PluginType ptype, con | |||
| if (! plugin) | |||
| return -1; | |||
| const short id = plugin->id(); | |||
| const short id = data->curPluginCount++; | |||
| EnginePluginData pluginData(plugin); | |||
| data->plugins.append(pluginData); | |||
| plugin->setId(id); | |||
| return id; | |||
| } | |||
| @@ -723,10 +745,13 @@ short CarlaEngine::addPlugin(const BinaryType btype, const PluginType ptype, con | |||
| bool CarlaEngine::removePlugin(const unsigned short id) | |||
| { | |||
| qDebug("CarlaEngine::removePlugin(%i)", id); | |||
| CARLA_ASSERT(data->maxPluginNumber > 0); | |||
| CARLA_ASSERT(id < data->maxPluginNumber); | |||
| CARLA_ASSERT(data->curPluginCount > 0); | |||
| CARLA_ASSERT(id < data->curPluginCount); | |||
| CARLA_ASSERT(data->plugins); | |||
| CarlaPlugin* const plugin = data->carlaPlugins[id]; | |||
| CarlaPlugin* plugin = data->plugins[id].plugin; | |||
| CARLA_ASSERT(plugin); | |||
| if (plugin /*&& plugin->id() == id*/) | |||
| { | |||
| @@ -734,34 +759,52 @@ bool CarlaEngine::removePlugin(const unsigned short id) | |||
| data->thread.stopNow(); | |||
| processLock(); | |||
| plugin->setEnabled(false); | |||
| data->carlaPlugins[id] = nullptr; | |||
| data->uniqueNames[id] = nullptr; | |||
| processUnlock(); | |||
| // wait for processing to stop for this plugin | |||
| // TODO | |||
| // clear this plugin | |||
| data->plugins[id].plugin = nullptr; | |||
| data->plugins[id].insPeak[0] = 0.0; | |||
| data->plugins[id].insPeak[1] = 0.0; | |||
| data->plugins[id].outsPeak[0] = 0.0; | |||
| data->plugins[id].outsPeak[1] = 0.0; | |||
| // wait for processing to stop for this plugin | |||
| // TODO | |||
| //processLock(); | |||
| //plugin->setEnabled(false); | |||
| //data->carlaPlugins[id] = nullptr; | |||
| //data->uniqueNames[id] = nullptr; | |||
| //processUnlock(); | |||
| delete plugin; | |||
| #ifndef BUILD_BRIDGE | |||
| osc_send_control_remove_plugin(id); | |||
| if (options.processMode == PROCESS_MODE_CONTINUOUS_RACK) | |||
| // move all plugins 1 spot backwards | |||
| for (unsigned short i=id; i < data->curPluginCount-1; i++) | |||
| { | |||
| // TODO - handle OSC server comm | |||
| plugin = data->plugins[i+1].plugin; | |||
| for (unsigned short i=id; i < data->maxPluginNumber-1; i++) | |||
| { | |||
| data->carlaPlugins[i] = data->carlaPlugins[i+1]; | |||
| data->uniqueNames[i] = data->uniqueNames[i+1]; | |||
| CARLA_ASSERT(plugin); | |||
| if (data->carlaPlugins[i]) | |||
| data->carlaPlugins[i]->setId(i); | |||
| } | |||
| if (plugin) | |||
| plugin->setId(i); | |||
| data->plugins[i].plugin = plugin; | |||
| data->plugins[i].insPeak[0] = 0.0; | |||
| data->plugins[i].insPeak[1] = 0.0; | |||
| data->plugins[i].outsPeak[0] = 0.0; | |||
| data->plugins[i].outsPeak[1] = 0.0; | |||
| } | |||
| #endif | |||
| data->curPluginCount--; | |||
| if (isRunning() && ! data->aboutToClose) | |||
| data->thread.startNow(); | |||
| #endif | |||
| return true; | |||
| } | |||
| @@ -777,28 +820,36 @@ void CarlaEngine::removeAllPlugins() | |||
| data->thread.stopNow(); | |||
| for (unsigned short i=0; i < data->maxPluginNumber; i++) | |||
| const unsigned int oldCount = data->curPluginCount; | |||
| // wait for processing | |||
| // TODO | |||
| data->curPluginCount = 0; | |||
| data->maxPluginNumber = 0; | |||
| for (unsigned short i=0; i < oldCount; i++) | |||
| { | |||
| CarlaPlugin* const plugin = data->carlaPlugins[i]; | |||
| CarlaPlugin* const plugin = data->plugins[i].plugin; | |||
| if (plugin) | |||
| { | |||
| processLock(); | |||
| plugin->setEnabled(false); | |||
| processUnlock(); | |||
| CARLA_ASSERT(plugin); | |||
| if (plugin) | |||
| delete plugin; | |||
| data->carlaPlugins[i] = nullptr; | |||
| data->uniqueNames[i] = nullptr; | |||
| } | |||
| } | |||
| data->maxPluginNumber = 0; | |||
| // clear this plugin | |||
| data->plugins[i].plugin = nullptr; | |||
| data->plugins[i].insPeak[0] = 0.0; | |||
| data->plugins[i].insPeak[1] = 0.0; | |||
| data->plugins[i].outsPeak[0] = 0.0; | |||
| data->plugins[i].outsPeak[1] = 0.0; | |||
| } | |||
| if (isRunning() && ! data->aboutToClose) | |||
| data->thread.startNow(); | |||
| } | |||
| #if 0 | |||
| void CarlaEngine::idlePluginGuis() | |||
| { | |||
| CARLA_ASSERT(data->maxPluginNumber > 0); | |||
| @@ -816,16 +867,18 @@ void CarlaEngine::__bridgePluginRegister(const unsigned short id, CarlaPlugin* c | |||
| { | |||
| data->carlaPlugins[id] = plugin; | |||
| } | |||
| #endif | |||
| // ----------------------------------------------------------------------- | |||
| // Information (base) | |||
| void CarlaEngine::aboutToClose() | |||
| void CarlaEngine::setAboutToClose() | |||
| { | |||
| qDebug("CarlaEngine::aboutToClose()"); | |||
| qDebug("CarlaEngine::setAboutToClose()"); | |||
| data->aboutToClose = true; | |||
| } | |||
| #if 0 | |||
| // ----------------------------------------------------------------------- | |||
| // Information (audio peaks) | |||
| @@ -860,6 +913,7 @@ void CarlaEngine::setOutputPeak(const unsigned short pluginId, const unsigned sh | |||
| data->outsPeak[pluginId*MAX_PEAKS + id] = value; | |||
| } | |||
| #endif | |||
| // ----------------------------------------------------------------------- | |||
| // Callback | |||
| @@ -877,7 +931,7 @@ void CarlaEngine::setCallback(const CallbackFunc func, void* const ptr) | |||
| qDebug("CarlaEngine::setCallback(%p, %p)", func, ptr); | |||
| CARLA_ASSERT(func); | |||
| data->callback = func; | |||
| data->callback = func; | |||
| data->callbackPtr = ptr; | |||
| } | |||
| @@ -927,15 +981,10 @@ void CarlaEngine::setOption(const OptionsType option, const int value, const cha | |||
| options.processMode = static_cast<ProcessMode>(value); | |||
| break; | |||
| case OPTION_PROCESS_HIGH_PRECISION: | |||
| CARLA_ENGINE_SET_OPTION_RUNNING_CHECK | |||
| options.processHighPrecision = value; | |||
| break; | |||
| case OPTION_MAX_PARAMETERS: | |||
| CARLA_ENGINE_SET_OPTION_RUNNING_CHECK | |||
| if (value > 0) | |||
| if (value < 0) | |||
| return; // TODO error here | |||
| options.maxParameters = value; | |||
| @@ -1033,51 +1082,18 @@ void CarlaEngine::setOption(const OptionsType option, const int value, const cha | |||
| } | |||
| #endif | |||
| // ----------------------------------------------------------------------- | |||
| // Mutex locks | |||
| void CarlaEngine::processLock() | |||
| { | |||
| data->procLock.lock(); | |||
| } | |||
| void CarlaEngine::processTryLock() | |||
| { | |||
| data->procLock.tryLock(); | |||
| } | |||
| void CarlaEngine::processUnlock() | |||
| { | |||
| data->procLock.unlock(); | |||
| } | |||
| void CarlaEngine::midiLock() | |||
| { | |||
| data->midiLock.lock(); | |||
| } | |||
| void CarlaEngine::midiTryLock() | |||
| { | |||
| data->midiLock.tryLock(); | |||
| } | |||
| void CarlaEngine::midiUnlock() | |||
| { | |||
| data->midiLock.unlock(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // OSC Stuff | |||
| #ifndef BUILD_BRIDGE | |||
| bool CarlaEngine::isOscControlRegistered() const | |||
| #ifdef BUILD_BRIDGE | |||
| bool CarlaEngine::isOscBridgeRegistered() const | |||
| { | |||
| return data->osc.isControlRegistered(); | |||
| return bool(data->oscData); | |||
| } | |||
| #else | |||
| bool CarlaEngine::isOscBridgeRegistered() const | |||
| bool CarlaEngine::isOscControlRegistered() const | |||
| { | |||
| return bool(data->oscData); | |||
| return data->osc.isControlRegistered(); | |||
| } | |||
| #endif | |||
| @@ -1112,8 +1128,7 @@ void CarlaEngine::processRack(float* inBuf[2], float* outBuf[2], const uint32_t | |||
| // initialize outputs (zero) | |||
| carla_zeroFloat(outBuf[0], frames); | |||
| carla_zeroFloat(outBuf[1], frames); | |||
| memset(rackControlEventsOut, 0, sizeof(CarlaEngineControlEvent)*MAX_CONTROL_EVENTS); | |||
| memset(rackMidiEventsOut, 0, sizeof(CarlaEngineMidiEvent)*MAX_MIDI_EVENTS); | |||
| std::memset(rackEventsOut, 0, sizeof(EngineEvent)*MAX_EVENTS); | |||
| bool processed = false; | |||
| @@ -1213,9 +1228,9 @@ void CarlaEngine::processRack(float* inBuf[2], float* outBuf[2], const uint32_t | |||
| // if no plugins in the rack, copy inputs over outputs | |||
| if (! processed) | |||
| { | |||
| memcpy(outBuf[0], inBuf[0], sizeof(float)*frames); | |||
| memcpy(outBuf[1], inBuf[1], sizeof(float)*frames); | |||
| memcpy(rackMidiEventsOut, rackMidiEventsIn, sizeof(CarlaEngineMidiEvent)*MAX_MIDI_EVENTS); | |||
| std::memcpy(outBuf[0], inBuf[0], sizeof(float)*frames); | |||
| std::memcpy(outBuf[1], inBuf[1], sizeof(float)*frames); | |||
| std::memcpy(rackEventsOut, rackEventsIn, sizeof(EngineEvent)*MAX_EVENTS); | |||
| } | |||
| } | |||
| @@ -1595,6 +1610,7 @@ void CarlaEngine::osc_send_control_note_off(const int32_t pluginId, const int32_ | |||
| } | |||
| } | |||
| #if 0 | |||
| void CarlaEngine::osc_send_control_set_input_peak_value(const int32_t pluginId, const int32_t portId) | |||
| { | |||
| //qDebug("CarlaEngine::osc_send_control_set_input_peak_value(%i, %i)", pluginId, portId); | |||
| @@ -1626,6 +1642,7 @@ void CarlaEngine::osc_send_control_set_output_peak_value(const int32_t pluginId, | |||
| lo_send(data->oscData->target, target_path, "iid", pluginId, portId, data->outsPeak[pluginId*MAX_PEAKS + portId-1]); | |||
| } | |||
| } | |||
| #endif | |||
| void CarlaEngine::osc_send_control_exit() | |||
| { | |||
| @@ -1935,6 +1952,4 @@ void CarlaEngine::osc_send_bridge_set_outpeak(const int32_t portId) | |||
| } | |||
| #endif | |||
| #endif | |||
| CARLA_BACKEND_END_NAMESPACE | |||
| @@ -8,17 +8,21 @@ CONFIG += link_pkgconfig qt shared warn_on | |||
| DEFINES = DEBUG | |||
| DEFINES += QTCREATOR_TEST | |||
| # Misc | |||
| DEFINES += __LINUX_ALSA__ __LINUX_ALSASEQ__ | |||
| DEFINES += __LINUX_PULSE__ | |||
| DEFINES += __UNIX_JACK__ | |||
| # JACK | |||
| DEFINES += CARLA_ENGINE_JACK | |||
| # RtAudio/RtMidi | |||
| DEFINES += CARLA_ENGINE_RTAUDIO HAVE_GETTIMEOFDAY | |||
| DEFINES += __LINUX_ALSA__ __LINUX_ALSASEQ__ __LINUX_PULSE__ __UNIX_JACK__ | |||
| DEFINES += __RTAUDIO_DEBUG__ __RTMIDI_DEBUG__ | |||
| # DISTRHO Plugin | |||
| # DEFINES += CARLA_ENGINE_PLUGIN | |||
| # DEFINES += DISTRHO_PLUGIN_TARGET_STANDALONE | |||
| DEFINES += CARLA_ENGINE_PLUGIN | |||
| DEFINES += DISTRHO_PLUGIN_TARGET_STANDALONE | |||
| # Misc | |||
| DEFINES += WANT_LADSPA WANT_DSSI WANT_LV2 WANT_VST | |||
| @@ -33,9 +37,9 @@ SOURCES = \ | |||
| carla_engine.cpp \ | |||
| # carla_engine_osc.cpp \ | |||
| # carla_engine_thread.cpp \ | |||
| jack.cpp \ | |||
| plugin.cpp \ | |||
| rtaudio.cpp | |||
| jack.cpp \ | |||
| # plugin.cpp \ | |||
| rtaudio.cpp | |||
| HEADERS = \ | |||
| carla_engine_internal.hpp \ | |||
| @@ -48,12 +52,14 @@ HEADERS += \ | |||
| ../carla_plugin.hpp | |||
| HEADERS += \ | |||
| ../../includes/carla_defines.hpp \ | |||
| ../../includes/carla_midi.h \ | |||
| ../../utils/carla_utils.hpp \ | |||
| ../../utils/carla_backend_utils.hpp \ | |||
| ../../utils/carla_juce_utils.hpp | |||
| # HEADERS += \ | |||
| # plugin/DistrhoPluginInfo.h | |||
| HEADERS += \ | |||
| plugin/DistrhoPluginInfo.h | |||
| INCLUDEPATH = . .. \ | |||
| ../../includes \ | |||
| @@ -70,6 +76,6 @@ SOURCES += rtaudio-4.0.11/RtAudio.cpp | |||
| SOURCES += rtmidi-2.0.1/RtMidi.cpp | |||
| # Plugin | |||
| # INCLUDEPATH += ../distrho-plugin-toolkit | |||
| INCLUDEPATH += ../../libs/distrho-plugin-toolkit | |||
| QMAKE_CXXFLAGS *= -std=c++0x | |||
| @@ -24,7 +24,7 @@ | |||
| #include "carla_plugin.hpp" | |||
| #include "rt_list.hpp" | |||
| //#include "rt_list.hpp" | |||
| #ifndef BUILD_BRIDGE | |||
| # include <QtCore/QProcessEnvironment> | |||
| @@ -125,19 +125,17 @@ struct EnginePostEvent { | |||
| #endif | |||
| struct EnginePluginData { | |||
| CarlaPlugin* const plugin; | |||
| CarlaPlugin* plugin; | |||
| double insPeak[MAX_PEAKS]; | |||
| double outsPeak[MAX_PEAKS]; | |||
| EnginePluginData(CarlaPlugin* const plugin_) | |||
| : plugin(plugin_), | |||
| EnginePluginData() | |||
| : plugin(nullptr), | |||
| insPeak{0}, | |||
| outsPeak{0} {} | |||
| EnginePluginData() = delete; | |||
| }; | |||
| struct CarlaEnginePrivateData { | |||
| struct CarlaEngineProtectedData { | |||
| CarlaEngineOsc osc; | |||
| CarlaEngineThread thread; | |||
| @@ -152,32 +150,26 @@ struct CarlaEnginePrivateData { | |||
| QProcessEnvironment procEnv; | |||
| #endif | |||
| // for postEvents | |||
| CarlaMutex eventLock; | |||
| // for external midi input (GUI and OSC) | |||
| CarlaMutex midiLock; | |||
| bool aboutToClose; // don't re-activate thread if true | |||
| unsigned int curPluginCount; // number of plugins loaded (0...max) | |||
| unsigned int maxPluginNumber; // number of plugins allowed (0, 16, 99 or 999) | |||
| //RtList<EnginePostEvent> postEvents; | |||
| RtList<EnginePluginData> plugins; | |||
| EnginePluginData* plugins; | |||
| bool aboutToClose; | |||
| unsigned int maxPluginNumber; | |||
| unsigned int nextPluginId; | |||
| CarlaEnginePrivateData(CarlaEngine* const engine) | |||
| CarlaEngineProtectedData(CarlaEngine* const engine) | |||
| : osc(engine), | |||
| thread(engine), | |||
| oscData(nullptr), | |||
| callback(nullptr), | |||
| callbackPtr(nullptr), | |||
| //postEvents(1, 1), | |||
| plugins(1, 1), | |||
| aboutToClose(false), | |||
| curPluginCount(0), | |||
| maxPluginNumber(0), | |||
| nextPluginId(0) {} | |||
| plugins(nullptr) {} | |||
| CarlaEngineProtectedData() = delete; | |||
| CarlaEnginePrivateData() = delete; | |||
| CARLA_LEAK_DETECTOR(CarlaEngineProtectedData) | |||
| }; | |||
| CARLA_BACKEND_END_NAMESPACE | |||
| @@ -30,7 +30,7 @@ CARLA_BACKEND_START_NAMESPACE | |||
| #endif | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| // Engine port (JackAudio) | |||
| // Carla Engine JACK-Audio port | |||
| class CarlaEngineJackAudioPort : public CarlaEngineAudioPort | |||
| { | |||
| @@ -43,9 +43,13 @@ public: | |||
| qDebug("CarlaEngineJackAudioPort::CarlaEngineJackAudioPort(%s, %s, %p, %p)", bool2str(isInput), ProcessMode2Str(processMode), client, port); | |||
| if (processMode == PROCESS_MODE_SINGLE_CLIENT || processMode == PROCESS_MODE_MULTIPLE_CLIENTS) | |||
| { | |||
| CARLA_ASSERT(m_client && m_port); | |||
| } | |||
| else | |||
| { | |||
| CARLA_ASSERT(! (m_client || m_port)); | |||
| } | |||
| } | |||
| ~CarlaEngineJackAudioPort() | |||
| @@ -69,7 +73,7 @@ public: | |||
| if (! m_port) | |||
| return CarlaEngineAudioPort::initBuffer(engine); | |||
| //buffer = jackbridge_port_get_buffer(m_port, engine->getBufferSize()); | |||
| buffer = jackbridge_port_get_buffer(m_port, engine->getBufferSize()); | |||
| } | |||
| float* getBuffer() const | |||
| @@ -85,27 +89,31 @@ private: | |||
| }; | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| // Engine port (JackControl) | |||
| // Carla Engine JACK-Event port | |||
| class CarlaEngineJackControlPort : public CarlaEngineControlPort | |||
| class CarlaEngineJackEventPort : public CarlaEngineEventPort | |||
| { | |||
| public: | |||
| CarlaEngineJackControlPort(const bool isInput, const ProcessMode processMode, jack_client_t* const client, jack_port_t* const port) | |||
| : CarlaEngineControlPort(isInput, processMode), | |||
| CarlaEngineJackEventPort(const bool isInput, const ProcessMode processMode, jack_client_t* const client, jack_port_t* const port) | |||
| : CarlaEngineEventPort(isInput, processMode), | |||
| m_client(client), | |||
| m_port(port) | |||
| { | |||
| qDebug("CarlaEngineJackControlPort::CarlaEngineJackControlPort(%s, %s, %p, %p)", bool2str(isInput), ProcessMode2Str(processMode), client, port); | |||
| qDebug("CarlaEngineJackEventPort::CarlaEngineJackEventPort(%s, %s, %p, %p)", bool2str(isInput), ProcessMode2Str(processMode), client, port); | |||
| if (processMode == PROCESS_MODE_SINGLE_CLIENT || processMode == PROCESS_MODE_MULTIPLE_CLIENTS) | |||
| { | |||
| CARLA_ASSERT(m_client && m_port); | |||
| } | |||
| else | |||
| { | |||
| CARLA_ASSERT(! (m_client || m_port)); | |||
| } | |||
| } | |||
| ~CarlaEngineJackControlPort() | |||
| ~CarlaEngineJackEventPort() | |||
| { | |||
| qDebug("CarlaEngineJackControlPort::~CarlaEngineJackControlPort()"); | |||
| qDebug("CarlaEngineJackEventPort::~CarlaEngineJackEventPort()"); | |||
| if (m_client && m_port) | |||
| jackbridge_port_unregister(m_client, m_port); | |||
| @@ -122,9 +130,9 @@ public: | |||
| } | |||
| if (! m_port) | |||
| return CarlaEngineControlPort::initBuffer(engine); | |||
| return CarlaEngineEventPort::initBuffer(engine); | |||
| //buffer = jackbridge_port_get_buffer(m_port, engine->getBufferSize()); | |||
| buffer = jackbridge_port_get_buffer(m_port, engine->getBufferSize()); | |||
| if (! isInput) | |||
| jackbridge_midi_clear_buffer(buffer); | |||
| @@ -133,7 +141,7 @@ public: | |||
| uint32_t getEventCount() | |||
| { | |||
| if (! m_port) | |||
| return CarlaEngineControlPort::getEventCount(); | |||
| return CarlaEngineEventPort::getEventCount(); | |||
| if (! isInput) | |||
| return 0; | |||
| @@ -146,10 +154,10 @@ public: | |||
| return jackbridge_midi_get_event_count(buffer); | |||
| } | |||
| const CarlaEngineControlEvent* getEvent(const uint32_t index) | |||
| const EngineEvent* getEvent(const uint32_t index) | |||
| { | |||
| if (! m_port) | |||
| return CarlaEngineControlPort::getEvent(index); | |||
| return CarlaEngineEventPort::getEvent(index); | |||
| if (! isInput) | |||
| return nullptr; | |||
| @@ -161,114 +169,129 @@ public: | |||
| jack_midi_event_t jackEvent; | |||
| if (jackbridge_midi_event_get(&jackEvent, buffer, index) != 0) | |||
| if (jackbridge_midi_event_get(&jackEvent, buffer, index) != 0 || jackEvent.size > 3) | |||
| return nullptr; | |||
| const uint8_t midiStatus = jackEvent.buffer[0]; | |||
| const uint8_t midiChannel = midiStatus & 0x0F; | |||
| m_retEvent.clear(); | |||
| const uint8_t midiStatus = MIDI_GET_STATUS_FROM_DATA(jackEvent.buffer); | |||
| const uint8_t midiChannel = MIDI_GET_CHANNEL_FROM_DATA(jackEvent.buffer); | |||
| m_retEvent.time = jackEvent.time; | |||
| m_retEvent.channel = midiChannel; | |||
| if (MIDI_IS_STATUS_CONTROL_CHANGE(midiStatus)) | |||
| { | |||
| const uint8_t midiControl = jackEvent.buffer[1]; | |||
| m_retEvent.type = EngineEventTypeControl; | |||
| if (MIDI_IS_CONTROL_BANK_SELECT(midiControl)) | |||
| { | |||
| const uint8_t midiBank = jackEvent.buffer[2]; | |||
| m_retEvent.type = CarlaEngineControlEventTypeMidiBankChange; | |||
| m_retEvent.value = midiBank; | |||
| m_retEvent.ctrl.type = EngineControlEventTypeMidiBank; | |||
| m_retEvent.ctrl.parameter = midiBank; | |||
| m_retEvent.ctrl.value = 0.0; | |||
| } | |||
| else if (midiControl == MIDI_CONTROL_ALL_SOUND_OFF) | |||
| { | |||
| m_retEvent.type = CarlaEngineControlEventTypeAllSoundOff; | |||
| m_retEvent.ctrl.type = EngineControlEventTypeAllSoundOff; | |||
| m_retEvent.ctrl.parameter = 0; | |||
| m_retEvent.ctrl.value = 0.0; | |||
| } | |||
| else if (midiControl == MIDI_CONTROL_ALL_NOTES_OFF) | |||
| { | |||
| m_retEvent.type = CarlaEngineControlEventTypeAllNotesOff; | |||
| m_retEvent.ctrl.type = EngineControlEventTypeAllNotesOff; | |||
| m_retEvent.ctrl.parameter = 0; | |||
| m_retEvent.ctrl.value = 0.0; | |||
| } | |||
| else | |||
| { | |||
| const uint8_t midiValue = jackEvent.buffer[2]; | |||
| m_retEvent.type = CarlaEngineControlEventTypeParameterChange; | |||
| m_retEvent.parameter = midiControl; | |||
| m_retEvent.value = double(midiValue)/127; | |||
| m_retEvent.ctrl.type = EngineControlEventTypeParameter; | |||
| m_retEvent.ctrl.parameter = midiControl; | |||
| m_retEvent.ctrl.value = double(midiValue)/127; | |||
| } | |||
| return &m_retEvent; | |||
| } | |||
| if (MIDI_IS_STATUS_PROGRAM_CHANGE(midiStatus)) | |||
| else if (MIDI_IS_STATUS_PROGRAM_CHANGE(midiStatus)) | |||
| { | |||
| const uint8_t midiProgram = jackEvent.buffer[1]; | |||
| m_retEvent.type = EngineEventTypeControl; | |||
| m_retEvent.type = CarlaEngineControlEventTypeMidiProgramChange; | |||
| m_retEvent.value = midiProgram; | |||
| m_retEvent.ctrl.type = EngineControlEventTypeMidiProgram; | |||
| m_retEvent.ctrl.parameter = midiProgram; | |||
| m_retEvent.ctrl.value = 0.0; | |||
| } | |||
| else | |||
| { | |||
| m_retEvent.type = EngineEventTypeMidi; | |||
| return &m_retEvent; | |||
| m_retEvent.midi.data[0] = midiStatus; | |||
| m_retEvent.midi.data[1] = jackEvent.buffer[1]; | |||
| m_retEvent.midi.data[2] = jackEvent.buffer[2]; | |||
| m_retEvent.midi.size = jackEvent.size; | |||
| } | |||
| return nullptr; | |||
| return &m_retEvent; | |||
| } | |||
| void writeEvent(const CarlaEngineControlEventType type, const uint32_t time, const uint8_t channel, const uint16_t parameter, const double value) | |||
| void writeControlEvent(const uint32_t time, const uint8_t channel, const EngineControlEventType type, const uint16_t parameter, const double value) | |||
| { | |||
| if (! m_port) | |||
| return CarlaEngineControlPort::writeEvent(type, time, channel, parameter, value); | |||
| return CarlaEngineEventPort::writeControlEvent(time, channel, type, parameter, value); | |||
| if (isInput) | |||
| return; | |||
| CARLA_ASSERT(buffer); | |||
| CARLA_ASSERT(type != CarlaEngineControlEventTypeNull); | |||
| CARLA_ASSERT(channel < 16); | |||
| CARLA_ASSERT(type != EngineControlEventTypeNull); | |||
| CARLA_ASSERT(channel < MAX_MIDI_CHANNELS); | |||
| if (! buffer) | |||
| return; | |||
| if (type == CarlaEngineControlEventTypeNull) | |||
| if (type == EngineControlEventTypeNull) | |||
| return; | |||
| if (type == CarlaEngineControlEventTypeParameterChange) | |||
| CARLA_ASSERT(! MIDI_IS_CONTROL_BANK_SELECT(parameter)); | |||
| if (channel >= 16) | |||
| if (channel >= MAX_MIDI_CHANNELS) | |||
| return; | |||
| if (type == EngineControlEventTypeParameter) | |||
| { | |||
| CARLA_ASSERT(! MIDI_IS_CONTROL_BANK_SELECT(parameter)); | |||
| } | |||
| uint8_t data[3] = { 0 }; | |||
| uint8_t size = 0; | |||
| switch (type) | |||
| { | |||
| case CarlaEngineControlEventTypeNull: | |||
| case EngineControlEventTypeNull: | |||
| break; | |||
| case CarlaEngineControlEventTypeParameterChange: | |||
| case EngineControlEventTypeParameter: | |||
| data[0] = MIDI_STATUS_CONTROL_CHANGE + channel; | |||
| data[1] = parameter; | |||
| data[2] = value * 127; | |||
| size = 3; | |||
| size = 3; | |||
| break; | |||
| case CarlaEngineControlEventTypeMidiBankChange: | |||
| case EngineControlEventTypeMidiBank: | |||
| data[0] = MIDI_STATUS_CONTROL_CHANGE + channel; | |||
| data[1] = MIDI_CONTROL_BANK_SELECT; | |||
| data[2] = value; | |||
| size = 3; | |||
| break; | |||
| case CarlaEngineControlEventTypeMidiProgramChange: | |||
| case EngineControlEventTypeMidiProgram: | |||
| data[0] = MIDI_STATUS_PROGRAM_CHANGE + channel; | |||
| data[1] = value; | |||
| size = 2; | |||
| size = 2; | |||
| break; | |||
| case CarlaEngineControlEventTypeAllSoundOff: | |||
| case EngineControlEventTypeAllSoundOff: | |||
| data[0] = MIDI_STATUS_CONTROL_CHANGE + channel; | |||
| data[1] = MIDI_CONTROL_ALL_SOUND_OFF; | |||
| size = 2; | |||
| size = 2; | |||
| break; | |||
| case CarlaEngineControlEventTypeAllNotesOff: | |||
| case EngineControlEventTypeAllNotesOff: | |||
| data[0] = MIDI_STATUS_CONTROL_CHANGE + channel; | |||
| data[1] = MIDI_CONTROL_ALL_NOTES_OFF; | |||
| size = 2; | |||
| size = 2; | |||
| break; | |||
| } | |||
| @@ -276,125 +299,41 @@ public: | |||
| jackbridge_midi_event_write(buffer, time, data, size); | |||
| } | |||
| private: | |||
| jack_client_t* const m_client; | |||
| jack_port_t* const m_port; | |||
| CarlaEngineControlEvent m_retEvent; | |||
| CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineJackControlPort) | |||
| }; | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| // Engine port (JackMIDI) | |||
| class CarlaEngineJackMidiPort : public CarlaEngineMidiPort | |||
| { | |||
| public: | |||
| CarlaEngineJackMidiPort(const bool isInput, const ProcessMode processMode, jack_client_t* const client, jack_port_t* const port) | |||
| : CarlaEngineMidiPort(isInput, processMode), | |||
| m_client(client), | |||
| m_port(port) | |||
| { | |||
| qDebug("CarlaEngineJackMidiPort::CarlaEngineJackMidiPort(%s, %s, %p, %p)", bool2str(isInput), ProcessMode2Str(processMode), client, port); | |||
| if (processMode == PROCESS_MODE_SINGLE_CLIENT || processMode == PROCESS_MODE_MULTIPLE_CLIENTS) | |||
| CARLA_ASSERT(m_client && m_port); | |||
| else | |||
| CARLA_ASSERT(! (m_client || m_port)); | |||
| } | |||
| ~CarlaEngineJackMidiPort() | |||
| void writeMidiEvent(const uint32_t time, const uint8_t channel, const uint8_t* const data, const uint8_t size) | |||
| { | |||
| qDebug("CarlaEngineJackMidiPort::~CarlaEngineJackMidiPort()"); | |||
| if (m_client && m_port) | |||
| jackbridge_port_unregister(m_client, m_port); | |||
| } | |||
| void initBuffer(CarlaEngine* const engine) | |||
| { | |||
| CARLA_ASSERT(engine); | |||
| if (! engine) | |||
| { | |||
| buffer = nullptr; | |||
| return; | |||
| } | |||
| if (! m_port) | |||
| return CarlaEngineMidiPort::initBuffer(engine); | |||
| //buffer = jackbridge_port_get_buffer(m_port, engine->getBufferSize()); | |||
| if (! isInput) | |||
| jackbridge_midi_clear_buffer(buffer); | |||
| } | |||
| uint32_t getEventCount() | |||
| { | |||
| if (! m_port) | |||
| return CarlaEngineMidiPort::getEventCount(); | |||
| if (! isInput) | |||
| return 0; | |||
| CARLA_ASSERT(buffer); | |||
| return jackbridge_midi_get_event_count(buffer); | |||
| } | |||
| const CarlaEngineMidiEvent* getEvent(const uint32_t index) | |||
| { | |||
| if (! m_port) | |||
| return CarlaEngineMidiPort::getEvent(index); | |||
| if (! isInput) | |||
| return nullptr; | |||
| CARLA_ASSERT(buffer); | |||
| if (! buffer) | |||
| return nullptr; | |||
| jack_midi_event_t jackEvent; | |||
| if (jackbridge_midi_event_get(&jackEvent, buffer, index) != 0 || jackEvent.size > 3) | |||
| return nullptr; | |||
| m_retEvent.clear(); | |||
| m_retEvent.time = jackEvent.time; | |||
| m_retEvent.size = jackEvent.size; | |||
| memcpy(m_retEvent.data, jackEvent.buffer, jackEvent.size); | |||
| return &m_retEvent; | |||
| } | |||
| void writeEvent(const uint32_t time, const uint8_t* const data, const uint8_t size) | |||
| { | |||
| if (! m_port) | |||
| return CarlaEngineMidiPort::writeEvent(time, data, size); | |||
| return CarlaEngineEventPort::writeMidiEvent(time, channel, data, size); | |||
| if (isInput) | |||
| return; | |||
| CARLA_ASSERT(buffer); | |||
| CARLA_ASSERT(channel < MAX_MIDI_CHANNELS); | |||
| CARLA_ASSERT(data); | |||
| CARLA_ASSERT(size > 0); | |||
| if (! (buffer && data && size > 0)) | |||
| if (! buffer) | |||
| return; | |||
| if (channel >= MAX_MIDI_CHANNELS) | |||
| return; | |||
| if (! (data && size > 0)) | |||
| return; | |||
| uint8_t jdata[size]; | |||
| std::memcpy(jdata, data, sizeof(uint8_t)*size); | |||
| jdata[0] = data[0] + channel; | |||
| jackbridge_midi_event_write(buffer, time, data, size); | |||
| jackbridge_midi_event_write(buffer, time, jdata, size); | |||
| } | |||
| private: | |||
| jack_client_t* const m_client; | |||
| jack_port_t* const m_port; | |||
| CarlaEngineMidiEvent m_retEvent; | |||
| EngineEvent m_retEvent; | |||
| CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineJackMidiPort) | |||
| CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineJackEventPort) | |||
| }; | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| @@ -403,12 +342,12 @@ private: | |||
| class CarlaEngineJackClient : public CarlaEngineClient | |||
| { | |||
| public: | |||
| CarlaEngineJackClient(const CarlaEngineType engineType, const ProcessMode processMode, jack_client_t* const client) | |||
| CarlaEngineJackClient(const EngineType engineType, const ProcessMode processMode, jack_client_t* const client) | |||
| : CarlaEngineClient(engineType, processMode), | |||
| m_client(client), | |||
| m_usesClient(processMode == PROCESS_MODE_SINGLE_CLIENT || processMode == PROCESS_MODE_MULTIPLE_CLIENTS) | |||
| { | |||
| qDebug("CarlaEngineJackClient::CarlaEngineJackClient(%s, %s, %p)", CarlaEngineType2Str(engineType), ProcessMode2Str(processMode), client); | |||
| qDebug("CarlaEngineJackClient::CarlaEngineJackClient(%s, %s, %p)", EngineType2Str(engineType), ProcessMode2Str(processMode), client); | |||
| if (m_usesClient) | |||
| CARLA_ASSERT(m_client); | |||
| @@ -433,6 +372,8 @@ public: | |||
| if (processMode == PROCESS_MODE_MULTIPLE_CLIENTS) | |||
| { | |||
| CARLA_ASSERT(m_client && ! isActive()); | |||
| if (m_client && ! isActive()) | |||
| jackbridge_activate(m_client); | |||
| } | |||
| @@ -446,6 +387,8 @@ public: | |||
| if (processMode == PROCESS_MODE_MULTIPLE_CLIENTS) | |||
| { | |||
| CARLA_ASSERT(m_client && isActive()); | |||
| if (m_client && isActive()) | |||
| jackbridge_deactivate(m_client); | |||
| } | |||
| @@ -471,9 +414,9 @@ public: | |||
| jackbridge_recompute_total_latencies(m_client); | |||
| } | |||
| const CarlaEnginePort* addPort(const CarlaEnginePortType portType, const char* const name, const bool isInput) | |||
| const CarlaEnginePort* addPort(const EnginePortType portType, const char* const name, const bool isInput) | |||
| { | |||
| qDebug("CarlaJackEngineClient::addPort(%s, \"%s\", %s)", CarlaEnginePortType2Str(portType), name, bool2str(isInput)); | |||
| qDebug("CarlaJackEngineClient::addPort(%s, \"%s\", %s)", EnginePortType2Str(portType), name, bool2str(isInput)); | |||
| jack_port_t* port = nullptr; | |||
| @@ -482,13 +425,12 @@ public: | |||
| { | |||
| switch (portType) | |||
| { | |||
| case CarlaEnginePortTypeNull: | |||
| case EnginePortTypeNull: | |||
| break; | |||
| case CarlaEnginePortTypeAudio: | |||
| case EnginePortTypeAudio: | |||
| port = jackbridge_port_register(m_client, name, JACK_DEFAULT_AUDIO_TYPE, isInput ? JackPortIsInput : JackPortIsOutput, 0); | |||
| break; | |||
| case CarlaEnginePortTypeControl: | |||
| case CarlaEnginePortTypeMIDI: | |||
| case EnginePortTypeEvent: | |||
| port = jackbridge_port_register(m_client, name, JACK_DEFAULT_MIDI_TYPE, isInput ? JackPortIsInput : JackPortIsOutput, 0); | |||
| break; | |||
| } | |||
| @@ -497,17 +439,15 @@ public: | |||
| // Create Engine port | |||
| switch (portType) | |||
| { | |||
| case CarlaEnginePortTypeNull: | |||
| case EnginePortTypeNull: | |||
| break; | |||
| case CarlaEnginePortTypeAudio: | |||
| case EnginePortTypeAudio: | |||
| return new CarlaEngineJackAudioPort(isInput, processMode, m_client, port); | |||
| case CarlaEnginePortTypeControl: | |||
| return new CarlaEngineJackControlPort(isInput, processMode, m_client, port); | |||
| case CarlaEnginePortTypeMIDI: | |||
| return new CarlaEngineJackMidiPort(isInput, processMode, m_client, port); | |||
| case EnginePortTypeEvent: | |||
| return new CarlaEngineJackEventPort(isInput, processMode, m_client, port); | |||
| } | |||
| qCritical("CarlaJackEngineClient::addPort(%i, \"%s\", %s) - invalid type", portType, name, bool2str(isInput)); | |||
| qCritical("CarlaJackEngineClient::addPort(%s, \"%s\", %s) - invalid type", EnginePortType2Str(portType), name, bool2str(isInput)); | |||
| return nullptr; | |||
| } | |||
| @@ -539,7 +479,7 @@ public: | |||
| memset(&m_pos, 0, sizeof(jack_position_t)); | |||
| #ifdef BUILD_BRIDGE | |||
| hasQuit = false; | |||
| m_hasQuit = false; | |||
| #endif | |||
| } | |||
| @@ -579,7 +519,6 @@ public: | |||
| { | |||
| qDebug("CarlaEngineJack::init(\"%s\")", clientName); | |||
| #if 0 | |||
| m_state = JackTransportStopped; | |||
| m_freewheel = false; | |||
| @@ -600,14 +539,12 @@ public: | |||
| if (options.processMode == PROCESS_MODE_CONTINUOUS_RACK) | |||
| { | |||
| m_rackPorts[rackPortAudioIn1] = jackbridge_port_register(m_client, "in1", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); | |||
| m_rackPorts[rackPortAudioIn2] = jackbridge_port_register(m_client, "in2", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); | |||
| m_rackPorts[rackPortAudioOut1] = jackbridge_port_register(m_client, "out1", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); | |||
| m_rackPorts[rackPortAudioOut2] = jackbridge_port_register(m_client, "out2", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); | |||
| m_rackPorts[rackPortControlIn] = jackbridge_port_register(m_client, "control-in", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0); | |||
| m_rackPorts[rackPortControlOut] = jackbridge_port_register(m_client, "control-out", JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0); | |||
| m_rackPorts[rackPortMidiIn] = jackbridge_port_register(m_client, "midi-in", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0); | |||
| m_rackPorts[rackPortMidiOut] = jackbridge_port_register(m_client, "midi-out", JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0); | |||
| m_rackPorts[rackPortAudioIn1] = jackbridge_port_register(m_client, "audio-in1", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); | |||
| m_rackPorts[rackPortAudioIn2] = jackbridge_port_register(m_client, "audio-in2", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); | |||
| m_rackPorts[rackPortAudioOut1] = jackbridge_port_register(m_client, "audio-out1", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); | |||
| m_rackPorts[rackPortAudioOut2] = jackbridge_port_register(m_client, "audio-out2", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); | |||
| m_rackPorts[rackPortEventIn] = jackbridge_port_register(m_client, "events-in", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0); | |||
| m_rackPorts[rackPortEventOut] = jackbridge_port_register(m_client, "events-out", JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0); | |||
| } | |||
| if (jackbridge_activate(m_client) == 0) | |||
| @@ -650,8 +587,6 @@ public: | |||
| CarlaEngine::init(name); | |||
| return true; | |||
| #endif | |||
| #endif | |||
| return false; | |||
| } | |||
| bool close() | |||
| @@ -659,10 +594,9 @@ public: | |||
| qDebug("CarlaEngineJack::close()"); | |||
| CarlaEngine::close(); | |||
| #if 0 | |||
| #ifdef BUILD_BRIDGE | |||
| hasQuit = true; | |||
| m_client = nullptr; | |||
| m_client = nullptr; | |||
| m_hasQuit = true; | |||
| return true; | |||
| #else | |||
| if (jackbridge_deactivate(m_client) == 0) | |||
| @@ -673,10 +607,8 @@ public: | |||
| jackbridge_port_unregister(m_client, m_rackPorts[rackPortAudioIn2]); | |||
| jackbridge_port_unregister(m_client, m_rackPorts[rackPortAudioOut1]); | |||
| jackbridge_port_unregister(m_client, m_rackPorts[rackPortAudioOut2]); | |||
| jackbridge_port_unregister(m_client, m_rackPorts[rackPortControlIn]); | |||
| jackbridge_port_unregister(m_client, m_rackPorts[rackPortControlOut]); | |||
| jackbridge_port_unregister(m_client, m_rackPorts[rackPortMidiIn]); | |||
| jackbridge_port_unregister(m_client, m_rackPorts[rackPortMidiOut]); | |||
| jackbridge_port_unregister(m_client, m_rackPorts[rackPortEventIn]); | |||
| jackbridge_port_unregister(m_client, m_rackPorts[rackPortEventOut]); | |||
| } | |||
| if (jackbridge_client_close(m_client) == 0) | |||
| @@ -691,7 +623,6 @@ public: | |||
| setLastError("Failed to deactivate the JACK client"); | |||
| m_client = nullptr; | |||
| #endif | |||
| #endif | |||
| return false; | |||
| } | |||
| @@ -710,16 +641,15 @@ public: | |||
| return m_freewheel; | |||
| } | |||
| CarlaEngineType type() const | |||
| EngineType type() const | |||
| { | |||
| return CarlaEngineTypeJack; | |||
| return EngineTypeJack; | |||
| } | |||
| CarlaEngineClient* addClient(CarlaPlugin* const plugin) | |||
| { | |||
| jack_client_t* client = nullptr; | |||
| #if 0 | |||
| #ifdef BUILD_BRIDGE | |||
| client = m_client = jackbridge_client_open(plugin->name(), JackNullOption, nullptr); | |||
| @@ -744,17 +674,14 @@ public: | |||
| jackbridge_set_latency_callback(client, carla_jack_latency_callback_plugin, plugin); | |||
| } | |||
| #endif | |||
| #endif | |||
| #ifdef BUILD_BRIDGE | |||
| return new CarlaEngineJackClient(CarlaEngineTypeJack, PROCESS_MODE_MULTIPLE_CLIENTS, client); | |||
| return new CarlaEngineJackClient(EngineTypeJack, PROCESS_MODE_MULTIPLE_CLIENTS, client); | |||
| #else | |||
| return new CarlaEngineJackClient(CarlaEngineTypeJack, options.processMode, client); | |||
| return new CarlaEngineJackClient(EngineTypeJack, options.processMode, client); | |||
| #endif | |||
| } | |||
| #if 0 | |||
| // ------------------------------------- | |||
| protected: | |||
| @@ -818,6 +745,7 @@ protected: | |||
| timeInfo.valid = 0; | |||
| } | |||
| #if 0 | |||
| #ifndef BUILD_BRIDGE | |||
| if (options.processMode == PROCESS_MODE_SINGLE_CLIENT) | |||
| { | |||
| @@ -1005,6 +933,7 @@ protected: | |||
| } | |||
| } | |||
| } | |||
| #endif | |||
| #endif | |||
| } | |||
| @@ -1015,6 +944,7 @@ protected: | |||
| return; | |||
| #endif | |||
| #if 0 | |||
| for (unsigned short i=0, max=maxPluginNumber(); i < max; i++) | |||
| { | |||
| CarlaPlugin* const plugin = getPluginUnchecked(i); | |||
| @@ -1022,6 +952,7 @@ protected: | |||
| if (plugin && plugin->enabled()) | |||
| latencyPlugin(plugin, mode); | |||
| } | |||
| #endif | |||
| } | |||
| void handleJackShutdownCallback() | |||
| @@ -1039,7 +970,6 @@ protected: | |||
| } | |||
| // ------------------------------------- | |||
| #endif | |||
| private: | |||
| jack_client_t* m_client; | |||
| @@ -1050,24 +980,21 @@ private: | |||
| // ------------------------------------- | |||
| #ifdef BUILD_BRIDGE | |||
| bool hasQuit; | |||
| bool m_hasQuit; | |||
| #else | |||
| enum RackPorts { | |||
| rackPortAudioIn1 = 0, | |||
| rackPortAudioIn2 = 1, | |||
| rackPortAudioOut1 = 2, | |||
| rackPortAudioOut2 = 3, | |||
| rackPortControlIn = 4, | |||
| rackPortControlOut = 5, | |||
| rackPortMidiIn = 6, | |||
| rackPortMidiOut = 7, | |||
| rackPortCount = 8 | |||
| rackPortAudioIn1 = 0, | |||
| rackPortAudioIn2 = 1, | |||
| rackPortAudioOut1 = 2, | |||
| rackPortAudioOut2 = 3, | |||
| rackPortEventIn = 4, | |||
| rackPortEventOut = 5, | |||
| rackPortCount = 8 | |||
| }; | |||
| jack_port_t* m_rackPorts[rackPortCount]; | |||
| #endif | |||
| #if 0 | |||
| // ------------------------------------- | |||
| static void processPlugin(CarlaPlugin* const p, const uint32_t nframes) | |||
| @@ -1147,41 +1074,41 @@ private: | |||
| static int carla_jack_srate_callback(jack_nframes_t newSampleRate, void* arg) | |||
| { | |||
| CarlaEngineJack* const _this_ = (CarlaEngineJack*)arg; | |||
| _this_->handleJackSampleRateCallback(newSampleRate); | |||
| if (CarlaEngineJack* const _this_ = (CarlaEngineJack*)arg) | |||
| _this_->handleJackSampleRateCallback(newSampleRate); | |||
| return 0; | |||
| } | |||
| static int carla_jack_bufsize_callback(jack_nframes_t newBufferSize, void* arg) | |||
| { | |||
| CarlaEngineJack* const _this_ = (CarlaEngineJack*)arg; | |||
| _this_->handleJackBufferSizeCallback(newBufferSize); | |||
| if (CarlaEngineJack* const _this_ = (CarlaEngineJack*)arg) | |||
| _this_->handleJackBufferSizeCallback(newBufferSize); | |||
| return 0; | |||
| } | |||
| static void carla_jack_freewheel_callback(int starting, void* arg) | |||
| { | |||
| CarlaEngineJack* const _this_ = (CarlaEngineJack*)arg; | |||
| _this_->handleJackFreewheelCallback(bool(starting)); | |||
| if (CarlaEngineJack* const _this_ = (CarlaEngineJack*)arg) | |||
| _this_->handleJackFreewheelCallback(bool(starting)); | |||
| } | |||
| static int carla_jack_process_callback(jack_nframes_t nframes, void* arg) | |||
| { | |||
| CarlaEngineJack* const _this_ = (CarlaEngineJack*)arg; | |||
| _this_->handleJackProcessCallback(nframes); | |||
| if (CarlaEngineJack* const _this_ = (CarlaEngineJack*)arg) | |||
| _this_->handleJackProcessCallback(nframes); | |||
| return 0; | |||
| } | |||
| static void carla_jack_latency_callback(jack_latency_callback_mode_t mode, void* arg) | |||
| { | |||
| CarlaEngineJack* const _this_ = (CarlaEngineJack*)arg; | |||
| _this_->handleJackLatencyCallback(mode); | |||
| if (CarlaEngineJack* const _this_ = (CarlaEngineJack*)arg) | |||
| _this_->handleJackLatencyCallback(mode); | |||
| } | |||
| static void carla_jack_shutdown_callback(void* arg) | |||
| { | |||
| CarlaEngineJack* const _this_ = (CarlaEngineJack*)arg; | |||
| _this_->handleJackShutdownCallback(); | |||
| if (CarlaEngineJack* const _this_ = (CarlaEngineJack*)arg) | |||
| _this_->handleJackShutdownCallback(); | |||
| } | |||
| // ------------------------------------- | |||
| @@ -1208,7 +1135,6 @@ private: | |||
| if (plugin && plugin->enabled()) | |||
| latencyPlugin(plugin, mode); | |||
| } | |||
| #endif | |||
| CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineJack) | |||
| }; | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * Carla RtAudio Engine | |||
| * Copyright (C) 2012 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2012-2013 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or modify | |||
| * it under the terms of the GNU General Public License as published by | |||
| @@ -9,7 +9,7 @@ | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU General Public License for more details. | |||
| * | |||
| * For a full copy of the GNU General Public License see the COPYING file | |||
| @@ -36,32 +36,32 @@ CARLA_BACKEND_START_NAMESPACE | |||
| class CarlaEngineRtAudioClient : public CarlaEngineClient | |||
| { | |||
| public: | |||
| CarlaEngineRtAudioClient(const CarlaEngineType engineType, const ProcessMode processMode) | |||
| CarlaEngineRtAudioClient(const EngineType engineType, const ProcessMode processMode) | |||
| : CarlaEngineClient(engineType, processMode) | |||
| { | |||
| qDebug("CarlaEngineRtAudioClient::CarlaEngineRtAudioClient(%s, %s)", EngineType2Str(engineType), ProcessMode2Str(processMode)); | |||
| } | |||
| ~CarlaEngineRtAudioClient() | |||
| { | |||
| qDebug("CarlaEngineRtAudioClient::~CarlaEngineRtAudioClient()"); | |||
| } | |||
| const CarlaEnginePort* addPort(const CarlaEnginePortType portType, const char* const name, const bool isInput) | |||
| const CarlaEnginePort* addPort(const EnginePortType portType, const char* const name, const bool isInput) | |||
| { | |||
| qDebug("CarlaEngineRtAudioClient::addPort(%s, \"%s\", %s)", CarlaEnginePortType2Str(portType), name, bool2str(isInput)); | |||
| qDebug("CarlaEngineRtAudioClient::addPort(%s, \"%s\", %s)", EnginePortType2Str(portType), name, bool2str(isInput)); | |||
| switch (portType) | |||
| { | |||
| case CarlaEnginePortTypeNull: | |||
| case EnginePortTypeNull: | |||
| break; | |||
| case CarlaEnginePortTypeAudio: | |||
| case EnginePortTypeAudio: | |||
| return new CarlaEngineAudioPort(isInput, processMode); | |||
| case CarlaEnginePortTypeControl: | |||
| return new CarlaEngineControlPort(isInput, processMode); | |||
| case CarlaEnginePortTypeMIDI: | |||
| return new CarlaEngineMidiPort(isInput, processMode); | |||
| case EnginePortTypeEvent: | |||
| return new CarlaEngineEventPort(isInput, processMode); | |||
| } | |||
| qCritical("CarlaEngineRtAudioClient::addPort(%i, \"%s\", %s) - invalid type", portType, name, bool2str(isInput)); | |||
| qCritical("CarlaEngineRtAudioClient::addPort(%s, \"%s\", %s) - invalid type", EnginePortType2Str(portType), name, bool2str(isInput)); | |||
| return nullptr; | |||
| } | |||
| @@ -72,8 +72,6 @@ private: | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| // RtAudio Engine | |||
| #if 0 | |||
| class CarlaEngineRtAudio : public CarlaEngine | |||
| { | |||
| public: | |||
| @@ -81,10 +79,10 @@ public: | |||
| : CarlaEngine(), | |||
| audio(api) | |||
| { | |||
| qDebug("CarlaEngineRtAudio::CarlaEngineRtAudio()"); | |||
| qDebug("CarlaEngineRtAudio::CarlaEngineRtAudio(%i)", api); | |||
| midiIn = nullptr; | |||
| midiOut = nullptr; | |||
| evIn = nullptr; | |||
| evOut = nullptr; | |||
| m_audioInterleaved = false; | |||
| m_inBuf1 = nullptr; | |||
| @@ -245,14 +243,14 @@ public: | |||
| return false; | |||
| } | |||
| CarlaEngineType type() const | |||
| EngineType type() const | |||
| { | |||
| return CarlaEngineTypeRtAudio; | |||
| return EngineTypeRtAudio; | |||
| } | |||
| CarlaEngineClient* addClient(CarlaPlugin* const) | |||
| { | |||
| return new CarlaEngineRtAudioClient(CarlaEngineTypeRtAudio, options.processMode); | |||
| return new CarlaEngineRtAudioClient(EngineTypeRtAudio, options.processMode); | |||
| } | |||
| // ------------------------------------- | |||
| @@ -295,14 +293,8 @@ protected: | |||
| float* inBuf[2] = { m_inBuf1, m_inBuf2 }; | |||
| float* outBuf[2] = { m_outBuf1, m_outBuf2 }; | |||
| // initialize control input | |||
| memset(rackControlEventsIn, 0, sizeof(CarlaEngineControlEvent)*MAX_CONTROL_EVENTS); | |||
| { | |||
| // TODO | |||
| } | |||
| // initialize midi input | |||
| memset(rackMidiEventsIn, 0, sizeof(CarlaEngineMidiEvent)*MAX_MIDI_EVENTS); | |||
| // initialize events input | |||
| memset(rackEventsIn, 0, sizeof(EngineEvent)*MAX_EVENTS); | |||
| { | |||
| // TODO | |||
| } | |||
| @@ -347,8 +339,8 @@ protected: | |||
| private: | |||
| RtAudio audio; | |||
| MidiInApi* midiIn; | |||
| MidiOutApi* midiOut; | |||
| ScopedPointer<MidiInApi> evIn; | |||
| ScopedPointer<MidiOutApi> evOut; | |||
| bool m_audioInterleaved; | |||
| float* m_inBuf1; | |||
| @@ -362,10 +354,26 @@ private: | |||
| _this_->handleProcessCallback(outputBuffer, inputBuffer, nframes, streamTime, status); | |||
| return 0; | |||
| } | |||
| CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineRtAudio) | |||
| }; | |||
| // ----------------------------------------- | |||
| static std::vector<RtAudio::Api> rtApis; | |||
| static void initRtApis() | |||
| { | |||
| static bool initiated = false; | |||
| if (! initiated) | |||
| { | |||
| initiated = true; | |||
| RtAudio::getCompiledApi(rtApis); | |||
| } | |||
| } | |||
| CarlaEngine* CarlaEngine::newRtAudio(RtAudioApi api) | |||
| { | |||
| RtAudio::Api rtApi = RtAudio::UNSPECIFIED; | |||
| @@ -403,19 +411,18 @@ CarlaEngine* CarlaEngine::newRtAudio(RtAudioApi api) | |||
| unsigned int CarlaEngine::getRtAudioApiCount() | |||
| { | |||
| std::vector<RtAudio::Api> apis; | |||
| RtAudio::getCompiledApi(apis); | |||
| return apis.size(); | |||
| initRtApis(); | |||
| return rtApis.size(); | |||
| } | |||
| const char* CarlaEngine::getRtAudioApiName(unsigned int index) | |||
| { | |||
| std::vector<RtAudio::Api> apis; | |||
| RtAudio::getCompiledApi(apis); | |||
| initRtApis(); | |||
| if (index < apis.size()) | |||
| if (index < rtApis.size()) | |||
| { | |||
| const RtAudio::Api& api(apis[index]); | |||
| const RtAudio::Api& api(rtApis[index]); | |||
| switch (api) | |||
| { | |||
| @@ -442,7 +449,8 @@ const char* CarlaEngine::getRtAudioApiName(unsigned int index) | |||
| return nullptr; | |||
| } | |||
| #endif | |||
| // ----------------------------------------- | |||
| CARLA_BACKEND_END_NAMESPACE | |||
| @@ -13,7 +13,7 @@ BUILD_CXX_FLAGS += -fvisibility=hidden -fPIC -I. -I.. -I../../includes -I../../u | |||
| BUILD_CXX_FLAGS += $(shell pkg-config --cflags QtCore QtGui) | |||
| LINK_FLAGS += -shared | |||
| LINK_FLAGS += $(shell pkg-config --libs QtCore QtGui) | |||
| LINK_FLAGS += $(shell pkg-config --libs QtCore QtGui) -lGL | |||
| ifeq ($(HAVE_ZYN_DEPS),true) | |||
| ZYN_CXX_FLAGS = $(BUILD_CXX_FLAGS) | |||
| @@ -1,9 +1,7 @@ | |||
| [Project] | |||
| Manager=KDevGenericManager | |||
| Name=Carla | |||
| [Filters] | |||
| Excludes=*/.*,*/*~,*/*.pyc,*/ui_*.py,*/__pycache__/ | |||
| [Project] | |||
| Manager= | |||
| Name=source | |||
| VersionControlSupport=kdevgit | |||
| @@ -2,17 +2,17 @@ | |||
| * Carla common defines | |||
| * Copyright (C) 2011-2013 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or modify | |||
| * it under the terms of the GNU General Public License as published by | |||
| * the Free Software Foundation; either version 2 of the License, or | |||
| * any later version. | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU General Public License for more details. | |||
| * | |||
| * For a full copy of the GNU General Public License see the COPYING file | |||
| * For a full copy of the GNU General Public License see the GPL.txt file | |||
| */ | |||
| #ifndef __CARLA_DEFINES_HPP__ | |||
| @@ -2,17 +2,17 @@ | |||
| * Carla Backend utils | |||
| * Copyright (C) 2011-2013 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or modify | |||
| * it under the terms of the GNU General Public License as published by | |||
| * the Free Software Foundation; either version 2 of the License, or | |||
| * any later version. | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU General Public License for more details. | |||
| * | |||
| * For a full copy of the GNU General Public License see the COPYING file | |||
| * For a full copy of the GNU General Public License see the GPL.txt file | |||
| */ | |||
| #ifndef __CARLA_BACKEND_UTILS_HPP__ | |||
| @@ -167,8 +167,6 @@ const char* OptionsType2Str(const OptionsType& type) | |||
| return "OPTION_PROCESS_NAME"; | |||
| case OPTION_PROCESS_MODE: | |||
| return "OPTION_PROCESS_MODE"; | |||
| case OPTION_PROCESS_HIGH_PRECISION: | |||
| return "OPTION_PROCESS_HIGH_PRECISION"; | |||
| case OPTION_FORCE_STEREO: | |||
| return "OPTION_FORCE_STEREO"; | |||
| case OPTION_PREFER_PLUGIN_BRIDGES: | |||
| @@ -1,19 +1,19 @@ | |||
| /* | |||
| * Carla misc utils imported from Juce source code | |||
| * Copyright (C) 2013 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2004-11 Raw Material Software Ltd. | |||
| * Copyright (C) 2013 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or modify | |||
| * it under the terms of the GNU General Public License as published by | |||
| * the Free Software Foundation; either version 2 of the License, or | |||
| * any later version. | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU General Public License for more details. | |||
| * | |||
| * For a full copy of the GNU General Public License see the COPYING file | |||
| * For a full copy of the GNU General Public License see the GPL.txt file | |||
| */ | |||
| #ifndef __CARLA_JUCE_UTILS_HPP__ | |||
| @@ -26,195 +26,327 @@ extern "C" { | |||
| #include <cassert> | |||
| #include <cstring> | |||
| // Declare non copyable and prevent heap allocation | |||
| #define LIST_DECLARATIONS(className) \ | |||
| className(const className&); \ | |||
| className& operator= (const className&); \ | |||
| static void* operator new (size_t); \ | |||
| static void operator delete (void*); \ | |||
| typedef struct list_head k_list_head; | |||
| // ----------------------------------------------------------------------- | |||
| template<typename T> | |||
| class RtList | |||
| class List | |||
| { | |||
| public: | |||
| RtList(const size_t minPreallocated, const size_t maxPreallocated) | |||
| protected: | |||
| List() | |||
| : fDataSize(sizeof(Data)) | |||
| { | |||
| qcount = 0; | |||
| ::INIT_LIST_HEAD(&queue); | |||
| ::rtsafe_memory_pool_create(&mempool, nullptr, sizeof(RtListData), minPreallocated, maxPreallocated); | |||
| assert(mempool); | |||
| _init(); | |||
| } | |||
| ~RtList() | |||
| { | |||
| clear(); | |||
| ::rtsafe_memory_pool_destroy(mempool); | |||
| } | |||
| void resize(const size_t minPreallocated, const size_t maxPreallocated) | |||
| public: | |||
| virtual ~List() | |||
| { | |||
| clear(); | |||
| ::rtsafe_memory_pool_destroy(mempool); | |||
| ::rtsafe_memory_pool_create(&mempool, nullptr, sizeof(RtListData), minPreallocated, maxPreallocated); | |||
| assert(mempool); | |||
| } | |||
| void clear() | |||
| { | |||
| if (! isEmpty()) | |||
| if (fCount != 0) | |||
| { | |||
| RtListData* data; | |||
| Data* data; | |||
| k_list_head* entry; | |||
| list_for_each(entry, &queue) | |||
| list_for_each(entry, &fQueue) | |||
| { | |||
| data = list_entry(entry, RtListData, siblings); | |||
| ::rtsafe_memory_pool_deallocate(mempool, data); | |||
| data = list_entry(entry, Data, siblings); | |||
| _deallocate(data); | |||
| } | |||
| } | |||
| qcount = 0; | |||
| ::INIT_LIST_HEAD(&queue); | |||
| _init(); | |||
| } | |||
| size_t count() const | |||
| { | |||
| return qcount; | |||
| return fCount; | |||
| } | |||
| bool isEmpty() const | |||
| { | |||
| return (qcount == 0); | |||
| //return (list_empty(&queue) != 0); | |||
| return (fCount == 0); | |||
| } | |||
| void append(const T& value, const bool sleepy = false) | |||
| void append(const T& value) | |||
| { | |||
| RtListData* data; | |||
| if (sleepy) | |||
| data = (RtListData*)::rtsafe_memory_pool_allocate_sleepy(mempool); | |||
| else | |||
| data = (RtListData*)::rtsafe_memory_pool_allocate_atomic(mempool); | |||
| if (data) | |||
| if (Data* const data = _allocate()) | |||
| { | |||
| ::memcpy(&data->value, &value, sizeof(T)); | |||
| ::list_add_tail(&data->siblings, &queue); | |||
| qcount++; | |||
| std::memcpy(&data->value, &value, sizeof(T)); | |||
| list_add_tail(&data->siblings, &fQueue); | |||
| fCount++; | |||
| } | |||
| } | |||
| T& getFirst() | |||
| T& getAt(const size_t index, const bool remove = false) | |||
| { | |||
| return __get(true, false); | |||
| } | |||
| if (fCount == 0 || index >= fCount) | |||
| return _retEmpty(); | |||
| T& getFirstAndRemove() | |||
| { | |||
| return __get(true, true); | |||
| Data* data = nullptr; | |||
| k_list_head* entry; | |||
| size_t i = 0; | |||
| list_for_each(entry, &fQueue) | |||
| { | |||
| if (index != i++) | |||
| continue; | |||
| data = list_entry(entry, Data, siblings); | |||
| assert(data); | |||
| if (remove) | |||
| { | |||
| fCount--; | |||
| list_del(entry); | |||
| _deallocate(data); | |||
| } | |||
| break; | |||
| } | |||
| assert(data); | |||
| return data->value; | |||
| } | |||
| T& getLast() | |||
| T& getFirst(const bool remove = false) | |||
| { | |||
| return __get(false, false); | |||
| return _getFirstOrLast(true, remove); | |||
| } | |||
| T& getLastAndRemove() | |||
| T& getLast(const bool remove = false) | |||
| { | |||
| return __get(false, true); | |||
| return _getFirstOrLast(false, remove); | |||
| } | |||
| bool removeOne(const T& value) | |||
| { | |||
| RtListData* data; | |||
| Data* data = nullptr; | |||
| k_list_head* entry; | |||
| list_for_each(entry, &queue) | |||
| list_for_each(entry, &fQueue) | |||
| { | |||
| data = list_entry(entry, RtListData, siblings); | |||
| data = list_entry(entry, Data, siblings); | |||
| assert(data); | |||
| if (data->value == value) | |||
| { | |||
| qcount--; | |||
| ::list_del(entry); | |||
| ::rtsafe_memory_pool_deallocate(mempool, data); | |||
| return true; | |||
| fCount--; | |||
| list_del(entry); | |||
| _deallocate(data); | |||
| break; | |||
| } | |||
| } | |||
| return false; | |||
| return (data != nullptr); | |||
| } | |||
| void removeAll(const T& value) | |||
| { | |||
| RtListData* data; | |||
| Data* data; | |||
| k_list_head* entry; | |||
| k_list_head* tmp; | |||
| list_for_each_safe(entry, tmp, &queue) | |||
| list_for_each_safe(entry, tmp, &fQueue) | |||
| { | |||
| data = list_entry(entry, RtListData, siblings); | |||
| data = list_entry(entry, Data, siblings); | |||
| assert(data); | |||
| if (data->value == value) | |||
| { | |||
| qcount--; | |||
| ::list_del(entry); | |||
| ::rtsafe_memory_pool_deallocate(mempool, data); | |||
| fCount--; | |||
| list_del(entry); | |||
| _deallocate(data); | |||
| } | |||
| } | |||
| } | |||
| private: | |||
| size_t qcount; | |||
| k_list_head queue; | |||
| RtMemPool_Handle mempool; | |||
| protected: | |||
| const size_t fDataSize; | |||
| size_t fCount; | |||
| k_list_head fQueue; | |||
| struct RtListData { | |||
| struct Data { | |||
| T value; | |||
| k_list_head siblings; | |||
| }; | |||
| T& __get(const bool first, const bool doDelete) | |||
| virtual Data* _allocate() = 0; | |||
| virtual void _deallocate(Data* const dataPtr) = 0; | |||
| private: | |||
| void _init() | |||
| { | |||
| if (isEmpty()) | |||
| { | |||
| // FIXME ? | |||
| static T value; | |||
| static bool reset = true; | |||
| fCount = 0; | |||
| INIT_LIST_HEAD(&fQueue); | |||
| } | |||
| if (reset) | |||
| { | |||
| reset = false; | |||
| ::memset(&value, 0, sizeof(T)); | |||
| } | |||
| T& _getFirstOrLast(const bool first, const bool remove) | |||
| { | |||
| if (fCount == 0) | |||
| return _retEmpty(); | |||
| return value; | |||
| } | |||
| k_list_head* const entry = first ? fQueue.next : fQueue.prev; | |||
| Data* const data = list_entry(entry, Data, siblings); | |||
| k_list_head* entry = first ? queue.next : queue.prev; | |||
| RtListData* data = list_entry(entry, RtListData, siblings); | |||
| if (data == nullptr) | |||
| return _retEmpty(); | |||
| T& ret = data->value; | |||
| if (data && doDelete) | |||
| if (data && remove) | |||
| { | |||
| qcount--; | |||
| ::list_del(entry); | |||
| ::rtsafe_memory_pool_deallocate(mempool, data); | |||
| fCount--; | |||
| list_del(entry); | |||
| _deallocate(data); | |||
| } | |||
| return ret; | |||
| } | |||
| // Non-copyable | |||
| RtList(const RtList&); | |||
| RtList& operator= (const RtList&); | |||
| T& _retEmpty() | |||
| { | |||
| // FIXME ? | |||
| static T value; | |||
| static bool reset = true; | |||
| if (reset) | |||
| { | |||
| reset = false; | |||
| std::memset(&value, 0, sizeof(T)); | |||
| } | |||
| return value; | |||
| } | |||
| LIST_DECLARATIONS(List) | |||
| }; | |||
| template<typename T> | |||
| class RtList : public List<T> | |||
| { | |||
| public: | |||
| RtList(const size_t minPreallocated, const size_t maxPreallocated) | |||
| { | |||
| rtsafe_memory_pool_create(&fMemPool, nullptr, this->fDataSize, minPreallocated, maxPreallocated); | |||
| assert(fMemPool); | |||
| } | |||
| ~RtList() | |||
| { | |||
| if (fMemPool != nullptr) | |||
| rtsafe_memory_pool_destroy(fMemPool); | |||
| } | |||
| void append_sleepy(const T& value) | |||
| { | |||
| if (typename List<T>::Data* const data = _allocate_sleepy()) | |||
| { | |||
| std::memcpy(&data->value, &value, sizeof(T)); | |||
| list_add_tail(&data->siblings, &this->fQueue); | |||
| this->fCount++; | |||
| } | |||
| } | |||
| void resize(const size_t minPreallocated, const size_t maxPreallocated) | |||
| { | |||
| this->clear(); | |||
| rtsafe_memory_pool_destroy(fMemPool); | |||
| rtsafe_memory_pool_create(&fMemPool, nullptr, this->fDataSize, minPreallocated, maxPreallocated); | |||
| assert(fMemPool); | |||
| } | |||
| private: | |||
| RtMemPool_Handle fMemPool; | |||
| typename List<T>::Data* _allocate() | |||
| { | |||
| return _allocate_atomic(); | |||
| } | |||
| typename List<T>::Data* _allocate_atomic() | |||
| { | |||
| return (typename List<T>::Data*)rtsafe_memory_pool_allocate_atomic(fMemPool); | |||
| } | |||
| typename List<T>::Data* _allocate_sleepy() | |||
| { | |||
| return (typename List<T>::Data*)rtsafe_memory_pool_allocate_sleepy(fMemPool); | |||
| } | |||
| void _deallocate(typename List<T>::Data* const dataPtr) | |||
| { | |||
| rtsafe_memory_pool_deallocate(fMemPool, dataPtr); | |||
| } | |||
| LIST_DECLARATIONS(RtList) | |||
| }; | |||
| template<typename T> | |||
| class NonRtList : public List<T> | |||
| { | |||
| public: | |||
| NonRtList() | |||
| { | |||
| } | |||
| ~NonRtList() | |||
| { | |||
| } | |||
| private: | |||
| typename List<T>::Data* _allocate() | |||
| { | |||
| return (typename List<T>::Data*)malloc(this->fDataSize); | |||
| } | |||
| void _deallocate(typename List<T>::Data* const dataPtr) | |||
| { | |||
| free(dataPtr); | |||
| } | |||
| LIST_DECLARATIONS(NonRtList) | |||
| }; | |||
| template<typename T> | |||
| class NonRtListNew : public List<T> | |||
| { | |||
| public: | |||
| NonRtListNew() | |||
| { | |||
| } | |||
| // Prevent heap allocation | |||
| static void* operator new (size_t); | |||
| static void operator delete (void*); | |||
| ~NonRtListNew() | |||
| { | |||
| } | |||
| private: | |||
| typename List<T>::Data* _allocate() | |||
| { | |||
| return new typename List<T>::Data; | |||
| } | |||
| void _deallocate(typename List<T>::Data* const dataPtr) | |||
| { | |||
| delete dataPtr; | |||
| } | |||
| LIST_DECLARATIONS(NonRtListNew) | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| #endif // __RT_LIST_HPP__ | |||