| @@ -60,7 +60,7 @@ const unsigned int PLUGIN_USES_SINGLE_THREAD = 0x0040; //!< Plugin needs a singl | |||
| const unsigned int PLUGIN_CAN_DRYWET = 0x0100; //!< Plugin can make use of Dry/Wet controls. | |||
| const unsigned int PLUGIN_CAN_VOLUME = 0x0200; //!< Plugin can make use of Volume controls. | |||
| const unsigned int PLUGIN_CAN_BALANCE = 0x0400; //!< Plugin can make use of Left & Right Balance controls. | |||
| const unsigned int PLUGIN_CAN_BALANCE = 0x0800; //!< Plugin can make use of Panning controls. | |||
| const unsigned int PLUGIN_CAN_PANNING = 0x0800; //!< Plugin can make use of Panning controls. | |||
| const unsigned int PLUGIN_CAN_FORCE_STEREO = 0x1000; //!< Plugin can be used in forced-stereo mode. | |||
| /**@}*/ | |||
| @@ -146,7 +146,7 @@ enum EngineControlEventType { | |||
| */ | |||
| struct EngineControlEvent { | |||
| EngineControlEventType type; //!< Control-Event type. | |||
| uint16_t parameter; //!< Parameter ID, midi bank or midi program. | |||
| uint16_t param; //!< Parameter ID, midi bank or midi program. | |||
| double value; //!< Parameter value, normalized to 0.0<->1.0. | |||
| EngineControlEvent() | |||
| @@ -156,8 +156,8 @@ struct EngineControlEvent { | |||
| void clear() | |||
| { | |||
| type = kEngineControlEventTypeNull; | |||
| parameter = 0; | |||
| type = kEngineControlEventTypeNull; | |||
| param = 0; | |||
| value = 0.0; | |||
| } | |||
| }; | |||
| @@ -213,6 +213,42 @@ struct EngineEvent { | |||
| // ----------------------------------------------------------------------- | |||
| /*! | |||
| * Engine devices | |||
| */ | |||
| struct EngineDevices { | |||
| struct Audio { | |||
| uint32_t count; | |||
| int32_t current; | |||
| const char** names; | |||
| } audio; | |||
| struct Midi { | |||
| uint32_t count; | |||
| const char** names; | |||
| bool* selected; | |||
| } midi; | |||
| struct Info { | |||
| unsigned int* bufferSizes; // valid until 0 value reached | |||
| unsigned int* sampleRates; // valid until 0 value reached | |||
| } info; | |||
| EngineDevices() | |||
| { | |||
| audio.count = 0; | |||
| audio.current = -1; | |||
| audio.names = nullptr; | |||
| midi.count = 0; | |||
| midi.names = nullptr; | |||
| midi.selected = nullptr; | |||
| info.bufferSizes = nullptr; | |||
| info.sampleRates = nullptr; | |||
| } | |||
| }; | |||
| /*! | |||
| * Engine options. | |||
| */ | |||
| @@ -226,10 +262,10 @@ struct EngineOptions { | |||
| bool useDssiVstChunks; | |||
| #endif | |||
| uint maxParameters; | |||
| uint oscUiTimeout; | |||
| uint preferredBufferSize; | |||
| uint preferredSampleRate; | |||
| unsigned int maxParameters; | |||
| unsigned int oscUiTimeout; | |||
| unsigned int preferredBufferSize; | |||
| unsigned int preferredSampleRate; | |||
| #ifndef BUILD_BRIDGE | |||
| CarlaString bridge_native; | |||
| @@ -301,15 +337,14 @@ struct EngineTimeInfo { | |||
| bool playing; | |||
| uint32_t frame; | |||
| uint32_t time; | |||
| uint64_t time; | |||
| uint32_t valid; | |||
| EngineTimeInfoBBT bbt; | |||
| EngineTimeInfo() | |||
| : playing(false), | |||
| frame(0), | |||
| time(0), | |||
| valid(0x0) {} | |||
| { | |||
| clear(); | |||
| } | |||
| void clear() | |||
| { | |||
| @@ -337,7 +372,7 @@ public: | |||
| CarlaEnginePort(const bool isInput, const ProcessMode processMode); | |||
| /*! | |||
| * The decontructor. | |||
| * The destructor. | |||
| */ | |||
| virtual ~CarlaEnginePort(); | |||
| @@ -374,7 +409,7 @@ public: | |||
| CarlaEngineAudioPort(const bool isInput, const ProcessMode processMode); | |||
| /*! | |||
| * The decontructor. | |||
| * The destructor. | |||
| */ | |||
| virtual ~CarlaEngineAudioPort(); | |||
| @@ -421,7 +456,7 @@ public: | |||
| CarlaEngineEventPort(const bool isInput, const ProcessMode processMode); | |||
| /*! | |||
| * The decontructor. | |||
| * The destructor. | |||
| */ | |||
| virtual ~CarlaEngineEventPort(); | |||
| @@ -446,23 +481,39 @@ public: | |||
| /*! | |||
| * Get the event at \a index. | |||
| ** \note You must only call this for input ports. | |||
| * \note You must only call this for input ports. | |||
| */ | |||
| virtual const EngineEvent* getEvent(const uint32_t index); | |||
| virtual const EngineEvent& getEvent(const uint32_t index); | |||
| /*! | |||
| * 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. | |||
| * \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); | |||
| virtual void writeControlEvent(const uint32_t time, const uint8_t channel, const EngineControlEventType type, const uint16_t param, const double value = 0.0); | |||
| /*! | |||
| * Write a control event into the buffer, overloaded call. | |||
| */ | |||
| void writeControlEvent(const uint32_t time, const uint8_t channel, const EngineControlEvent& ctrl) | |||
| { | |||
| writeControlEvent(time, channel, ctrl.type, ctrl.param, ctrl.value); | |||
| } | |||
| /*! | |||
| * 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. | |||
| */ | |||
| virtual void writeMidiEvent(const uint32_t time, const uint8_t channel, const uint8_t* const data, const uint8_t size); | |||
| virtual void writeMidiEvent(const uint32_t time, const uint8_t channel, const uint8_t port, const uint8_t* const data, const uint8_t size); | |||
| /*! | |||
| * Write a MIDI event into the buffer, overloaded call. | |||
| */ | |||
| void writeMidiEvent(const uint32_t time, const uint8_t channel, const EngineMidiEvent& midi) | |||
| { | |||
| writeMidiEvent(time, channel, midi.port, midi.data, midi.size); | |||
| } | |||
| private: | |||
| const uint32_t kMaxEventCount; | |||
| @@ -480,7 +531,7 @@ private: | |||
| */ | |||
| class CarlaEngineClient | |||
| { | |||
| protected: | |||
| public: | |||
| /*! | |||
| * The constructor, protected.\n | |||
| * All constructor parameters are constant and will never change in the lifetime of the client.\n | |||
| @@ -488,7 +539,6 @@ protected: | |||
| */ | |||
| CarlaEngineClient(const CarlaBackend::EngineType engineType, const CarlaBackend::ProcessMode processMode); | |||
| public: | |||
| /*! | |||
| * The destructor. | |||
| */ | |||
| @@ -532,23 +582,23 @@ public: | |||
| * Add a new port of type \a portType. | |||
| * \note This function does nothing in rack processing mode since ports are static there (2 audio + 1 event for both input and output). | |||
| */ | |||
| virtual const CarlaEnginePort* addPort(const EnginePortType portType, const char* const name, const bool isInput) = 0; | |||
| virtual const CarlaEnginePort* addPort(const EnginePortType portType, const char* const name, const bool isInput); | |||
| protected: | |||
| const EngineType kEngineType; | |||
| const ProcessMode kProcessMode; | |||
| private: | |||
| bool fActive; | |||
| uint32_t fLatency; | |||
| private: | |||
| CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineClient) | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| /*! | |||
| * Private data used in CarlaEngine. | |||
| * Protected data used in CarlaEngine. | |||
| * Non-engine code MUST NEVER have direct access to this. | |||
| */ | |||
| struct CarlaEngineProtectedData; | |||
| @@ -630,7 +680,7 @@ public: | |||
| virtual bool close(); | |||
| /*! | |||
| * Idle. | |||
| * Idle engine. | |||
| */ | |||
| virtual void idle(); | |||
| @@ -653,36 +703,18 @@ public: | |||
| * Add new engine client. | |||
| * \note This must only be called within a plugin class. | |||
| */ | |||
| virtual CarlaEngineClient* addClient(CarlaPlugin* const plugin) = 0; | |||
| virtual CarlaEngineClient* addClient(CarlaPlugin* const plugin); | |||
| // ------------------------------------------------------------------- | |||
| // Plugin management | |||
| /*! | |||
| * Get plugin with id \a id. | |||
| */ | |||
| CarlaPlugin* getPlugin(const unsigned int id) const; | |||
| /*! | |||
| * Get plugin with id \a id, faster unchecked version. | |||
| */ | |||
| CarlaPlugin* getPluginUnchecked(const unsigned int id) const; | |||
| /*! | |||
| * Get a unique plugin name within the engine.\n | |||
| * Returned variable must NOT be free'd. | |||
| */ | |||
| const char* getNewUniquePluginName(const char* const name); | |||
| /*! | |||
| * Add new plugin.\n | |||
| * Returns the id of the plugin, or -1 if the operation failed. | |||
| * Add new plugin. | |||
| */ | |||
| bool addPlugin(const BinaryType btype, const PluginType ptype, const char* const filename, const char* const name, const char* const label, const void* const extra = nullptr); | |||
| /*! | |||
| * Add new plugin, using native binary type.\n | |||
| * Returns the id of the plugin, or -1 if the operation failed. | |||
| * Add new plugin, using native binary type. | |||
| */ | |||
| bool addPlugin(const PluginType ptype, const char* const filename, const char* const name, const char* const label, const void* const extra = nullptr) | |||
| { | |||
| @@ -699,6 +731,22 @@ public: | |||
| */ | |||
| void removeAllPlugins(); | |||
| /*! | |||
| * Get plugin with id \a id. | |||
| */ | |||
| CarlaPlugin* getPlugin(const unsigned int id) const; | |||
| /*! | |||
| * Get plugin with id \a id, faster unchecked version. | |||
| */ | |||
| CarlaPlugin* getPluginUnchecked(const unsigned int id) const; | |||
| /*! | |||
| * Get a unique plugin name within the engine.\n | |||
| * Returned variable must NOT be free'd. | |||
| */ | |||
| const char* getNewUniquePluginName(const char* const name); | |||
| // bridge, internal use only | |||
| // TODO - find a better way for this | |||
| //void __bridgePluginRegister(const unsigned short id, CarlaPlugin* const plugin); | |||
| @@ -711,8 +759,7 @@ public: | |||
| /*! | |||
| * Load \a filename session. | |||
| * \note Already loaded plugins are not removed, but added afterwards.\n | |||
| * Call removeAllPlugins() first if needed. | |||
| * \note Already loaded plugins are not removed; call removeAllPlugins() first if needed. | |||
| */ | |||
| void loadProject(const char* const filename); | |||
| @@ -769,6 +816,9 @@ public: | |||
| return fTimeInfo; | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // Information (peaks) | |||
| /*! | |||
| * TODO. | |||
| */ | |||
| @@ -779,17 +829,6 @@ public: | |||
| */ | |||
| float getOutputPeak(const unsigned int pluginId, const unsigned short id) const; | |||
| /*! | |||
| * Tell the engine it's about to close.\n | |||
| * This is used to prevent the engine thread(s) from reactivating. | |||
| */ | |||
| void setAboutToClose(); | |||
| /*! | |||
| * Safely block wait until the current proccessing callback ends. | |||
| */ | |||
| void waitForProccessEnd(); | |||
| // ------------------------------------------------------------------- | |||
| // Callback | |||
| @@ -816,6 +855,20 @@ public: | |||
| */ | |||
| void setLastError(const char* const error); | |||
| // ------------------------------------------------------------------- | |||
| // Misc | |||
| /*! | |||
| * Tell the engine it's about to close.\n | |||
| * This is used to prevent the engine thread(s) from reactivating. | |||
| */ | |||
| void setAboutToClose(); | |||
| /*! | |||
| * Safely block wait until the current proccessing callback ends. | |||
| */ | |||
| void waitForProccessEnd(); | |||
| // ------------------------------------------------------------------- | |||
| // Options | |||
| @@ -879,7 +932,7 @@ protected: | |||
| EngineOptions fOptions; | |||
| EngineTimeInfo fTimeInfo; | |||
| ScopedPointer<CarlaEngineProtectedData> const fData; | |||
| CarlaEngineProtectedData* const fData; | |||
| /*! | |||
| * Report to all plugins about buffer size change. | |||
| @@ -898,20 +951,19 @@ protected: | |||
| */ | |||
| void proccessPendingEvents(); | |||
| public: | |||
| /*! | |||
| * TODO. | |||
| */ | |||
| void setPeaks(const unsigned int pluginId, float* inPeaks, float* outPeaks); | |||
| #ifndef BUILD_BRIDGE | |||
| // Rack mode data | |||
| EngineEvent* getRackEventBuffer(const bool isInput); | |||
| //static const unsigned short MAX_EVENTS = 1024; | |||
| //EngineEvent fRackEventsIn[MAX_EVENTS]; | |||
| //EngineEvent fRackEventsOut[MAX_EVENTS]; | |||
| // Rack mode data | |||
| EngineEvent* getRackEventBuffer(const bool isInput); | |||
| /*! | |||
| * Proccess audio buffer in rack mode. | |||
| */ | |||
| @@ -48,38 +48,34 @@ CarlaEngineAudioPort::CarlaEngineAudioPort(const bool isInput, const ProcessMode | |||
| { | |||
| qDebug("CarlaEngineAudioPort::CarlaEngineAudioPort(%s, %s)", bool2str(isInput), ProcessMode2Str(processMode)); | |||
| #ifndef BUILD_BRIDGE | |||
| if (kProcessMode == PROCESS_MODE_PATCHBAY) | |||
| fBuffer = new float[PATCHBAY_BUFFER_SIZE]; | |||
| #endif | |||
| } | |||
| CarlaEngineAudioPort::~CarlaEngineAudioPort() | |||
| { | |||
| qDebug("CarlaEngineAudioPort::~CarlaEngineAudioPort()"); | |||
| #ifndef BUILD_BRIDGE | |||
| if (kProcessMode == PROCESS_MODE_PATCHBAY) | |||
| { | |||
| CARLA_ASSERT(fBuffer); | |||
| CARLA_ASSERT(fBuffer != nullptr); | |||
| if (fBuffer) | |||
| if (fBuffer != nullptr) | |||
| delete[] fBuffer; | |||
| } | |||
| #endif | |||
| } | |||
| void CarlaEngineAudioPort::initBuffer(CarlaEngine* const) | |||
| { | |||
| #ifndef BUILD_BRIDGE | |||
| if (kProcessMode == PROCESS_MODE_PATCHBAY && ! kIsInput) | |||
| carla_zeroFloat(fBuffer, PATCHBAY_BUFFER_SIZE); | |||
| #endif | |||
| } | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| // Carla Engine Event port | |||
| static const EngineEvent kFallbackEngineEvent; | |||
| CarlaEngineEventPort::CarlaEngineEventPort(const bool isInput, const ProcessMode processMode) | |||
| : CarlaEnginePort(isInput, processMode), | |||
| kMaxEventCount(processMode == PROCESS_MODE_CONTINUOUS_RACK ? RACK_EVENT_COUNT : PATCHBAY_EVENT_COUNT), | |||
| @@ -87,25 +83,21 @@ CarlaEngineEventPort::CarlaEngineEventPort(const bool isInput, const ProcessMode | |||
| { | |||
| qDebug("CarlaEngineEventPort::CarlaEngineEventPort(%s, %s)", bool2str(isInput), ProcessMode2Str(processMode)); | |||
| #ifndef BUILD_BRIDGE | |||
| if (kProcessMode == PROCESS_MODE_PATCHBAY) | |||
| fBuffer = new EngineEvent[PATCHBAY_EVENT_COUNT]; | |||
| #endif | |||
| } | |||
| CarlaEngineEventPort::~CarlaEngineEventPort() | |||
| { | |||
| qDebug("CarlaEngineEventPort::~CarlaEngineEventPort()"); | |||
| #ifndef BUILD_BRIDGE | |||
| if (kProcessMode == PROCESS_MODE_PATCHBAY) | |||
| { | |||
| CARLA_ASSERT(fBuffer); | |||
| CARLA_ASSERT(fBuffer != nullptr); | |||
| if (fBuffer) | |||
| if (fBuffer != nullptr) | |||
| delete[] fBuffer; | |||
| } | |||
| #endif | |||
| } | |||
| void CarlaEngineEventPort::initBuffer(CarlaEngine* const engine) | |||
| @@ -115,31 +107,28 @@ void CarlaEngineEventPort::initBuffer(CarlaEngine* const engine) | |||
| if (engine == nullptr) | |||
| return; | |||
| #ifndef BUILD_BRIDGE | |||
| if (kProcessMode == PROCESS_MODE_CONTINUOUS_RACK) | |||
| fBuffer = engine->getRackEventBuffer(kIsInput); | |||
| else if (kProcessMode == PROCESS_MODE_PATCHBAY && ! kIsInput) | |||
| carla_zeroMem(fBuffer, sizeof(EngineEvent)*PATCHBAY_EVENT_COUNT); | |||
| #endif | |||
| } | |||
| uint32_t CarlaEngineEventPort::getEventCount() | |||
| { | |||
| if (! kIsInput) | |||
| return 0; | |||
| CARLA_ASSERT(kIsInput); | |||
| CARLA_ASSERT(fBuffer != nullptr); | |||
| if (! kIsInput) | |||
| return 0; | |||
| if (fBuffer == nullptr) | |||
| return 0; | |||
| #ifndef BUILD_BRIDGE | |||
| if (kProcessMode == PROCESS_MODE_CONTINUOUS_RACK || kProcessMode == PROCESS_MODE_PATCHBAY) | |||
| { | |||
| uint32_t count = 0; | |||
| const EngineEvent* const events = fBuffer; | |||
| for (unsigned short i=0; i < kMaxEventCount; i++, count++) | |||
| for (uint32_t i=0; i < kMaxEventCount; i++, count++) | |||
| { | |||
| if (events[i].type == kEngineEventTypeNull) | |||
| break; | |||
| @@ -147,46 +136,43 @@ uint32_t CarlaEngineEventPort::getEventCount() | |||
| return count; | |||
| } | |||
| #endif | |||
| return 0; | |||
| } | |||
| const EngineEvent* CarlaEngineEventPort::getEvent(const uint32_t index) | |||
| const EngineEvent& CarlaEngineEventPort::getEvent(const uint32_t index) | |||
| { | |||
| if (! kIsInput) | |||
| return nullptr; | |||
| CARLA_ASSERT(kIsInput); | |||
| CARLA_ASSERT(fBuffer != nullptr); | |||
| CARLA_ASSERT(index < kMaxEventCount); | |||
| if (! kIsInput) | |||
| return kFallbackEngineEvent; | |||
| if (fBuffer == nullptr) | |||
| return nullptr; | |||
| return kFallbackEngineEvent; | |||
| if (index >= kMaxEventCount) | |||
| return nullptr; | |||
| return kFallbackEngineEvent; | |||
| #ifndef BUILD_BRIDGE | |||
| if (kProcessMode == PROCESS_MODE_CONTINUOUS_RACK || kProcessMode == PROCESS_MODE_PATCHBAY) | |||
| { | |||
| const EngineEvent* const events = fBuffer; | |||
| return &events[index]; | |||
| return events[index]; | |||
| } | |||
| #endif | |||
| return nullptr; | |||
| return kFallbackEngineEvent; | |||
| } | |||
| void CarlaEngineEventPort::writeControlEvent(const uint32_t time, const uint8_t channel, const EngineControlEventType type, const uint16_t parameter, const double value) | |||
| void CarlaEngineEventPort::writeControlEvent(const uint32_t time, const uint8_t channel, const EngineControlEventType type, const uint16_t param, const double value) | |||
| { | |||
| if (kIsInput) | |||
| return; | |||
| CARLA_ASSERT(! kIsInput); | |||
| CARLA_ASSERT(fBuffer != nullptr); | |||
| CARLA_ASSERT(type != kEngineControlEventTypeNull); | |||
| CARLA_ASSERT(channel < MAX_MIDI_CHANNELS); | |||
| CARLA_ASSERT(value >= 0.0 && value <= 1.0); | |||
| if (kIsInput) | |||
| return; | |||
| if (fBuffer == nullptr) | |||
| return; | |||
| if (type == kEngineControlEventTypeNull) | |||
| @@ -195,15 +181,14 @@ void CarlaEngineEventPort::writeControlEvent(const uint32_t time, const uint8_t | |||
| return; | |||
| if (type == kEngineControlEventTypeParameter) | |||
| { | |||
| CARLA_ASSERT(! MIDI_IS_CONTROL_BANK_SELECT(parameter)); | |||
| CARLA_ASSERT(! MIDI_IS_CONTROL_BANK_SELECT(param)); | |||
| } | |||
| #ifndef BUILD_BRIDGE | |||
| if (kProcessMode == PROCESS_MODE_CONTINUOUS_RACK || kProcessMode == PROCESS_MODE_PATCHBAY) | |||
| { | |||
| EngineEvent* const events = fBuffer; | |||
| for (unsigned short i=0; i < kMaxEventCount; i++) | |||
| for (uint32_t i=0; i < kMaxEventCount; i++) | |||
| { | |||
| if (events[i].type != kEngineEventTypeNull) | |||
| continue; | |||
| @@ -212,32 +197,27 @@ void CarlaEngineEventPort::writeControlEvent(const uint32_t time, const uint8_t | |||
| events[i].time = time; | |||
| events[i].channel = channel; | |||
| events[i].ctrl.type = type; | |||
| events[i].ctrl.parameter = parameter; | |||
| events[i].ctrl.value = value; | |||
| events[i].ctrl.type = type; | |||
| events[i].ctrl.param = param; | |||
| events[i].ctrl.value = value; | |||
| return; | |||
| } | |||
| qWarning("CarlaEngineEventPort::writeControlEvent() - buffer full"); | |||
| } | |||
| #else | |||
| Q_UNUSED(time); | |||
| Q_UNUSED(parameter); | |||
| Q_UNUSED(value); | |||
| #endif | |||
| } | |||
| void CarlaEngineEventPort::writeMidiEvent(const uint32_t time, const uint8_t channel, const uint8_t* const data, const uint8_t size) | |||
| void CarlaEngineEventPort::writeMidiEvent(const uint32_t time, const uint8_t channel, const uint8_t port, const uint8_t* const data, const uint8_t size) | |||
| { | |||
| if (kIsInput) | |||
| return; | |||
| CARLA_ASSERT(! kIsInput); | |||
| CARLA_ASSERT(fBuffer != nullptr); | |||
| CARLA_ASSERT(channel < MAX_MIDI_CHANNELS); | |||
| CARLA_ASSERT(data != nullptr); | |||
| CARLA_ASSERT(size > 0); | |||
| if (kIsInput) | |||
| return; | |||
| if (fBuffer == nullptr) | |||
| return; | |||
| if (channel >= MAX_MIDI_CHANNELS) | |||
| @@ -247,7 +227,6 @@ void CarlaEngineEventPort::writeMidiEvent(const uint32_t time, const uint8_t cha | |||
| if (size == 0) | |||
| return; | |||
| #ifndef BUILD_BRIDGE | |||
| if (kProcessMode == PROCESS_MODE_CONTINUOUS_RACK || kProcessMode == PROCESS_MODE_PATCHBAY) | |||
| { | |||
| if (size > 3) | |||
| @@ -255,7 +234,7 @@ void CarlaEngineEventPort::writeMidiEvent(const uint32_t time, const uint8_t cha | |||
| EngineEvent* const events = fBuffer; | |||
| for (unsigned short i=0; i < kMaxEventCount; i++) | |||
| for (uint32_t i=0; i < kMaxEventCount; i++) | |||
| { | |||
| if (events[i].type != kEngineEventTypeNull) | |||
| continue; | |||
| @@ -264,6 +243,7 @@ void CarlaEngineEventPort::writeMidiEvent(const uint32_t time, const uint8_t cha | |||
| events[i].time = time; | |||
| events[i].channel = channel; | |||
| events[i].midi.port = port; | |||
| events[i].midi.data[0] = data[0]; | |||
| events[i].midi.data[1] = data[1]; | |||
| events[i].midi.data[2] = data[2]; | |||
| @@ -274,9 +254,6 @@ void CarlaEngineEventPort::writeMidiEvent(const uint32_t time, const uint8_t cha | |||
| qWarning("CarlaEngineEventPort::writeMidiEvent() - buffer full"); | |||
| } | |||
| #else | |||
| Q_UNUSED(time); | |||
| #endif | |||
| } | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| @@ -338,6 +315,24 @@ void CarlaEngineClient::setLatency(const uint32_t samples) | |||
| fLatency = samples; | |||
| } | |||
| const CarlaEnginePort* CarlaEngineClient::addPort(const EnginePortType portType, const char* const name, const bool isInput) | |||
| { | |||
| qDebug("CarlaEngineClient::addPort(%s, \"%s\", %s)", EnginePortType2Str(portType), name, bool2str(isInput)); | |||
| switch (portType) | |||
| { | |||
| case kEnginePortTypeNull: | |||
| break; | |||
| case kEnginePortTypeAudio: | |||
| return new CarlaEngineAudioPort(isInput, kProcessMode); | |||
| case kEnginePortTypeEvent: | |||
| return new CarlaEngineEventPort(isInput, kProcessMode); | |||
| } | |||
| qCritical("CarlaEngineClient::addPort(%s, \"%s\", %s) - invalid type", EnginePortType2Str(portType), name, bool2str(isInput)); | |||
| return nullptr; | |||
| } | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| // Carla Engine | |||
| @@ -353,7 +348,7 @@ CarlaEngine::~CarlaEngine() | |||
| { | |||
| qDebug("CarlaEngine::~CarlaEngine()"); | |||
| //data = nullptr; | |||
| delete fData; | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| @@ -610,102 +605,15 @@ void CarlaEngine::idle() | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Plugin management | |||
| CarlaPlugin* CarlaEngine::getPlugin(const unsigned int id) const | |||
| { | |||
| qDebug("CarlaEngine::getPlugin(%i) [count:%i]", id, fData->curPluginCount); | |||
| CARLA_ASSERT(fData->curPluginCount > 0); | |||
| CARLA_ASSERT(id < fData->curPluginCount); | |||
| CARLA_ASSERT(fData->plugins != nullptr); | |||
| if (id < fData->curPluginCount && fData->plugins != nullptr) | |||
| return fData->plugins[id].plugin; | |||
| return nullptr; | |||
| } | |||
| // Virtual, per-engine type calls | |||
| CarlaPlugin* CarlaEngine::getPluginUnchecked(const unsigned int id) const | |||
| CarlaEngineClient* CarlaEngine::addClient(CarlaPlugin* const) | |||
| { | |||
| return fData->plugins[id].plugin; | |||
| return new CarlaEngineClient(type(), fOptions.processMode); | |||
| } | |||
| const char* CarlaEngine::getNewUniquePluginName(const char* const name) | |||
| { | |||
| qDebug("CarlaEngine::getNewUniquePluginName(\"%s\")", name); | |||
| CARLA_ASSERT(fData->maxPluginNumber > 0); | |||
| CARLA_ASSERT(fData->plugins != nullptr); | |||
| CARLA_ASSERT(name != nullptr); | |||
| static CarlaString sname; | |||
| sname = name; | |||
| if (sname.isEmpty() || fData->plugins == nullptr) | |||
| return strdup("(No name)"); | |||
| sname.truncate(maxClientNameSize()-5-1); // 5 = strlen(" (10)") | |||
| sname.replace(':', '.'); // ':' is used in JACK1 to split client/port names | |||
| for (unsigned short i=0; i < fData->curPluginCount; i++) | |||
| { | |||
| CARLA_ASSERT(fData->plugins[i].plugin); | |||
| // Check if unique name doesn't exist | |||
| if (const char* const pluginName = fData->plugins[i].plugin->name()) | |||
| { | |||
| if (sname != pluginName) | |||
| continue; | |||
| } | |||
| // Check if string has already been modified | |||
| { | |||
| const size_t len = sname.length(); | |||
| // 1 digit, ex: " (2)" | |||
| if (sname[len-4] == ' ' && sname[len-3] == '(' && sname.isDigit(len-2) && sname[len-1] == ')') | |||
| { | |||
| int number = sname[len-2] - '0'; | |||
| if (number == 9) | |||
| { | |||
| // next number is 10, 2 digits | |||
| sname.truncate(len-4); | |||
| sname += " (10)"; | |||
| //sname.replace(" (9)", " (10)"); | |||
| } | |||
| else | |||
| sname[len-2] = char('0' + number + 1); | |||
| continue; | |||
| } | |||
| // 2 digits, ex: " (11)" | |||
| if (sname[len-5] == ' ' && sname[len-4] == '(' && sname.isDigit(len-3) && sname.isDigit(len-2) && sname[len-1] == ')') | |||
| { | |||
| char n2 = sname[len-2]; | |||
| char n3 = sname[len-3]; | |||
| if (n2 == '9') | |||
| { | |||
| n2 = '0'; | |||
| n3 = char(n3 + 1); | |||
| } | |||
| else | |||
| n2 = char(n2 + 1); | |||
| sname[len-2] = n2; | |||
| sname[len-3] = n3; | |||
| continue; | |||
| } | |||
| } | |||
| // Modify string if not | |||
| sname += " (2)"; | |||
| } | |||
| return (const char*)sname; | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Plugin management | |||
| bool CarlaEngine::addPlugin(const BinaryType btype, const PluginType ptype, const char* const filename, const char* const name, const char* const label, const void* const extra) | |||
| { | |||
| @@ -938,6 +846,101 @@ void CarlaEngine::removeAllPlugins() | |||
| fData->thread.startNow(); | |||
| } | |||
| CarlaPlugin* CarlaEngine::getPlugin(const unsigned int id) const | |||
| { | |||
| qDebug("CarlaEngine::getPlugin(%i) [count:%i]", id, fData->curPluginCount); | |||
| CARLA_ASSERT(fData->curPluginCount > 0); | |||
| CARLA_ASSERT(id < fData->curPluginCount); | |||
| CARLA_ASSERT(fData->plugins != nullptr); | |||
| if (id < fData->curPluginCount && fData->plugins != nullptr) | |||
| return fData->plugins[id].plugin; | |||
| return nullptr; | |||
| } | |||
| CarlaPlugin* CarlaEngine::getPluginUnchecked(const unsigned int id) const | |||
| { | |||
| return fData->plugins[id].plugin; | |||
| } | |||
| const char* CarlaEngine::getNewUniquePluginName(const char* const name) | |||
| { | |||
| qDebug("CarlaEngine::getNewUniquePluginName(\"%s\")", name); | |||
| CARLA_ASSERT(fData->maxPluginNumber > 0); | |||
| CARLA_ASSERT(fData->plugins != nullptr); | |||
| CARLA_ASSERT(name != nullptr); | |||
| static CarlaString sname; | |||
| sname = name; | |||
| if (sname.isEmpty() || fData->plugins == nullptr) | |||
| return strdup("(No name)"); | |||
| sname.truncate(maxClientNameSize()-5-1); // 5 = strlen(" (10)") | |||
| sname.replace(':', '.'); // ':' is used in JACK1 to split client/port names | |||
| for (unsigned short i=0; i < fData->curPluginCount; i++) | |||
| { | |||
| CARLA_ASSERT(fData->plugins[i].plugin); | |||
| // Check if unique name doesn't exist | |||
| if (const char* const pluginName = fData->plugins[i].plugin->name()) | |||
| { | |||
| if (sname != pluginName) | |||
| continue; | |||
| } | |||
| // Check if string has already been modified | |||
| { | |||
| const size_t len = sname.length(); | |||
| // 1 digit, ex: " (2)" | |||
| if (sname[len-4] == ' ' && sname[len-3] == '(' && sname.isDigit(len-2) && sname[len-1] == ')') | |||
| { | |||
| int number = sname[len-2] - '0'; | |||
| if (number == 9) | |||
| { | |||
| // next number is 10, 2 digits | |||
| sname.truncate(len-4); | |||
| sname += " (10)"; | |||
| //sname.replace(" (9)", " (10)"); | |||
| } | |||
| else | |||
| sname[len-2] = char('0' + number + 1); | |||
| continue; | |||
| } | |||
| // 2 digits, ex: " (11)" | |||
| if (sname[len-5] == ' ' && sname[len-4] == '(' && sname.isDigit(len-3) && sname.isDigit(len-2) && sname[len-1] == ')') | |||
| { | |||
| char n2 = sname[len-2]; | |||
| char n3 = sname[len-3]; | |||
| if (n2 == '9') | |||
| { | |||
| n2 = '0'; | |||
| n3 = char(n3 + 1); | |||
| } | |||
| else | |||
| n2 = char(n2 + 1); | |||
| sname[len-2] = n2; | |||
| sname[len-3] = n3; | |||
| continue; | |||
| } | |||
| } | |||
| // Modify string if not | |||
| sname += " (2)"; | |||
| } | |||
| return (const char*)sname; | |||
| } | |||
| #if 0 | |||
| void CarlaEngine::__bridgePluginRegister(const unsigned short id, CarlaPlugin* const plugin) | |||
| { | |||
| @@ -989,7 +992,7 @@ void CarlaEngine::saveProject(const char* const filename) | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Information (base) | |||
| // Information (peaks) | |||
| float CarlaEngine::getInputPeak(const unsigned int pluginId, const unsigned short id) const | |||
| { | |||
| @@ -1007,34 +1010,6 @@ float CarlaEngine::getOutputPeak(const unsigned int pluginId, const unsigned sho | |||
| return fData->plugins[pluginId].outsPeak[id]; | |||
| } | |||
| void CarlaEngine::setAboutToClose() | |||
| { | |||
| qDebug("CarlaEngine::setAboutToClose()"); | |||
| fData->aboutToClose = true; | |||
| } | |||
| void CarlaEngine::waitForProccessEnd() | |||
| { | |||
| qDebug("CarlaEngine::waitForProccessEnd()"); | |||
| fData->nextAction.pluginId = 0; | |||
| fData->nextAction.opcode = EnginePostActionIdle; | |||
| fData->nextAction.mutex.lock(); | |||
| if (isRunning()) | |||
| { | |||
| // block wait for unlock on proccessing side | |||
| fData->nextAction.mutex.lock(); | |||
| } | |||
| else | |||
| { | |||
| doIdle(fData, false); | |||
| } | |||
| fData->nextAction.mutex.unlock(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Callback | |||
| @@ -1068,6 +1043,37 @@ void CarlaEngine::setLastError(const char* const error) | |||
| fData->lastError = error; | |||
| } | |||
| void CarlaEngine::setAboutToClose() | |||
| { | |||
| qDebug("CarlaEngine::setAboutToClose()"); | |||
| fData->aboutToClose = true; | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Misc | |||
| void CarlaEngine::waitForProccessEnd() | |||
| { | |||
| qDebug("CarlaEngine::waitForProccessEnd()"); | |||
| fData->nextAction.pluginId = 0; | |||
| fData->nextAction.opcode = EnginePostActionIdle; | |||
| fData->nextAction.mutex.lock(); | |||
| if (isRunning()) | |||
| { | |||
| // block wait for unlock on proccessing side | |||
| fData->nextAction.mutex.lock(); | |||
| } | |||
| else | |||
| { | |||
| doIdle(fData, false); | |||
| } | |||
| fData->nextAction.mutex.unlock(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Global options | |||
| @@ -1433,7 +1439,6 @@ void CarlaEngine::osc_send_peaks(CarlaPlugin* const /*plugin*/) | |||
| void CarlaEngine::osc_send_peaks(CarlaPlugin* const plugin, const unsigned short& id) | |||
| #endif | |||
| { | |||
| #if 0 | |||
| // Peak values | |||
| if (plugin->audioInCount() > 0) | |||
| { | |||
| @@ -1455,7 +1460,6 @@ void CarlaEngine::osc_send_peaks(CarlaPlugin* const plugin, const unsigned short | |||
| osc_send_control_set_output_peak_value(id, 2); | |||
| #endif | |||
| } | |||
| #endif | |||
| } | |||
| #ifndef BUILD_BRIDGE | |||
| @@ -1772,7 +1776,6 @@ 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); | |||
| @@ -1785,7 +1788,7 @@ void CarlaEngine::osc_send_control_set_input_peak_value(const int32_t pluginId, | |||
| char target_path[strlen(fData->oscData->path)+22]; | |||
| strcpy(target_path, fData->oscData->path); | |||
| strcat(target_path, "/set_input_peak_value"); | |||
| lo_send(fData->oscData->target, target_path, "iid", pluginId, portId, data->insPeak[pluginId*MAX_PEAKS + portId-1]); | |||
| lo_send(fData->oscData->target, target_path, "iid", pluginId, portId, fData->plugins[pluginId].insPeak[portId-1]); | |||
| } | |||
| } | |||
| @@ -1801,10 +1804,9 @@ void CarlaEngine::osc_send_control_set_output_peak_value(const int32_t pluginId, | |||
| char target_path[strlen(fData->oscData->path)+23]; | |||
| strcpy(target_path, fData->oscData->path); | |||
| strcat(target_path, "/set_output_peak_value"); | |||
| lo_send(fData->oscData->target, target_path, "iid", pluginId, portId, data->outsPeak[pluginId*MAX_PEAKS + portId-1]); | |||
| lo_send(fData->oscData->target, target_path, "iid", pluginId, portId, fData->plugins[pluginId].outsPeak[portId-1]); | |||
| } | |||
| } | |||
| #endif | |||
| void CarlaEngine::osc_send_control_exit() | |||
| { | |||
| @@ -86,6 +86,8 @@ private: | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| // Carla Engine JACK-Event port | |||
| static const EngineEvent kFallbackJackEngineEvent; | |||
| class CarlaEngineJackEventPort : public CarlaEngineEventPort | |||
| { | |||
| public: | |||
| @@ -139,34 +141,34 @@ public: | |||
| if (kPort == nullptr) | |||
| return CarlaEngineEventPort::getEventCount(); | |||
| if (! kIsInput) | |||
| return 0; | |||
| CARLA_ASSERT(kIsInput); | |||
| CARLA_ASSERT(fJackBuffer != nullptr); | |||
| if (! kIsInput) | |||
| return 0; | |||
| if (fJackBuffer != nullptr) | |||
| return 0; | |||
| return jackbridge_midi_get_event_count(fJackBuffer); | |||
| } | |||
| const EngineEvent* getEvent(const uint32_t index) | |||
| const EngineEvent& getEvent(const uint32_t index) | |||
| { | |||
| if (kPort == nullptr) | |||
| return CarlaEngineEventPort::getEvent(index); | |||
| if (! kIsInput) | |||
| return nullptr; | |||
| CARLA_ASSERT(kIsInput); | |||
| CARLA_ASSERT(fJackBuffer != nullptr); | |||
| if (fJackBuffer != nullptr) | |||
| return nullptr; | |||
| if (! kIsInput) | |||
| return kFallbackJackEngineEvent; | |||
| if (fJackBuffer == nullptr) | |||
| return kFallbackJackEngineEvent; | |||
| jack_midi_event_t jackEvent; | |||
| if (jackbridge_midi_event_get(&jackEvent, fJackBuffer, index) != 0 || jackEvent.size > 3) | |||
| return nullptr; | |||
| return kFallbackJackEngineEvent; | |||
| fRetEvent.clear(); | |||
| @@ -179,45 +181,45 @@ public: | |||
| if (MIDI_IS_STATUS_CONTROL_CHANGE(midiStatus)) | |||
| { | |||
| const uint8_t midiControl = jackEvent.buffer[1]; | |||
| fRetEvent.type = kEngineEventTypeControl; | |||
| fRetEvent.type = kEngineEventTypeControl; | |||
| if (MIDI_IS_CONTROL_BANK_SELECT(midiControl)) | |||
| { | |||
| const uint8_t midiBank = jackEvent.buffer[2]; | |||
| fRetEvent.ctrl.type = kEngineControlEventTypeMidiBank; | |||
| fRetEvent.ctrl.parameter = midiBank; | |||
| fRetEvent.ctrl.value = 0.0; | |||
| fRetEvent.ctrl.type = kEngineControlEventTypeMidiBank; | |||
| fRetEvent.ctrl.param = midiBank; | |||
| fRetEvent.ctrl.value = 0.0; | |||
| } | |||
| else if (midiControl == MIDI_CONTROL_ALL_SOUND_OFF) | |||
| { | |||
| fRetEvent.ctrl.type = kEngineControlEventTypeAllSoundOff; | |||
| fRetEvent.ctrl.parameter = 0; | |||
| fRetEvent.ctrl.value = 0.0; | |||
| fRetEvent.ctrl.type = kEngineControlEventTypeAllSoundOff; | |||
| fRetEvent.ctrl.param = 0; | |||
| fRetEvent.ctrl.value = 0.0; | |||
| } | |||
| else if (midiControl == MIDI_CONTROL_ALL_NOTES_OFF) | |||
| { | |||
| fRetEvent.ctrl.type = kEngineControlEventTypeAllNotesOff; | |||
| fRetEvent.ctrl.parameter = 0; | |||
| fRetEvent.ctrl.value = 0.0; | |||
| fRetEvent.ctrl.type = kEngineControlEventTypeAllNotesOff; | |||
| fRetEvent.ctrl.param = 0; | |||
| fRetEvent.ctrl.value = 0.0; | |||
| } | |||
| else | |||
| { | |||
| const uint8_t midiValue = jackEvent.buffer[2]; | |||
| fRetEvent.ctrl.type = kEngineControlEventTypeParameter; | |||
| fRetEvent.ctrl.parameter = midiControl; | |||
| fRetEvent.ctrl.value = double(midiValue)/127; | |||
| fRetEvent.ctrl.type = kEngineControlEventTypeParameter; | |||
| fRetEvent.ctrl.param = midiControl; | |||
| fRetEvent.ctrl.value = double(midiValue)/127.0; | |||
| } | |||
| } | |||
| else if (MIDI_IS_STATUS_PROGRAM_CHANGE(midiStatus)) | |||
| { | |||
| const uint8_t midiProgram = jackEvent.buffer[1]; | |||
| fRetEvent.type = kEngineEventTypeControl; | |||
| fRetEvent.type = kEngineEventTypeControl; | |||
| fRetEvent.ctrl.type = kEngineControlEventTypeMidiProgram; | |||
| fRetEvent.ctrl.parameter = midiProgram; | |||
| fRetEvent.ctrl.value = 0.0; | |||
| fRetEvent.ctrl.type = kEngineControlEventTypeMidiProgram; | |||
| fRetEvent.ctrl.param = midiProgram; | |||
| fRetEvent.ctrl.value = 0.0; | |||
| } | |||
| else | |||
| { | |||
| @@ -229,22 +231,22 @@ public: | |||
| fRetEvent.midi.size = jackEvent.size; | |||
| } | |||
| return &fRetEvent; | |||
| return fRetEvent; | |||
| } | |||
| void writeControlEvent(const uint32_t time, const uint8_t channel, const EngineControlEventType type, const uint16_t parameter, const double value) | |||
| void writeControlEvent(const uint32_t time, const uint8_t channel, const EngineControlEventType type, const uint16_t param, const double value) | |||
| { | |||
| if (kPort == nullptr) | |||
| return CarlaEngineEventPort::writeControlEvent(time, channel, type, parameter, value); | |||
| if (kIsInput) | |||
| return; | |||
| return CarlaEngineEventPort::writeControlEvent(time, channel, type, param, value); | |||
| CARLA_ASSERT(! kIsInput); | |||
| CARLA_ASSERT(fJackBuffer != nullptr); | |||
| CARLA_ASSERT(type != kEngineControlEventTypeNull); | |||
| CARLA_ASSERT(channel < MAX_MIDI_CHANNELS); | |||
| CARLA_ASSERT(value >= 0.0 && value <= 1.0); | |||
| if (kIsInput) | |||
| return; | |||
| if (fJackBuffer == nullptr) | |||
| return; | |||
| if (type == kEngineControlEventTypeNull) | |||
| @@ -253,7 +255,7 @@ public: | |||
| return; | |||
| if (type == kEngineControlEventTypeParameter) | |||
| { | |||
| CARLA_ASSERT(! MIDI_IS_CONTROL_BANK_SELECT(parameter)); | |||
| CARLA_ASSERT(! MIDI_IS_CONTROL_BANK_SELECT(param)); | |||
| } | |||
| uint8_t data[3] = { 0 }; | |||
| @@ -265,19 +267,19 @@ public: | |||
| break; | |||
| case kEngineControlEventTypeParameter: | |||
| data[0] = MIDI_STATUS_CONTROL_CHANGE + channel; | |||
| data[1] = parameter; | |||
| data[1] = param; | |||
| data[2] = value * 127; | |||
| size = 3; | |||
| break; | |||
| case kEngineControlEventTypeMidiBank: | |||
| data[0] = MIDI_STATUS_CONTROL_CHANGE + channel; | |||
| data[1] = MIDI_CONTROL_BANK_SELECT; | |||
| data[2] = value; | |||
| size = 3; | |||
| data[2] = param; | |||
| size = 3; | |||
| break; | |||
| case kEngineControlEventTypeMidiProgram: | |||
| data[0] = MIDI_STATUS_PROGRAM_CHANGE + channel; | |||
| data[1] = value; | |||
| data[1] = param; | |||
| size = 2; | |||
| break; | |||
| case kEngineControlEventTypeAllSoundOff: | |||
| @@ -296,24 +298,26 @@ public: | |||
| jackbridge_midi_event_write(fJackBuffer, time, data, size); | |||
| } | |||
| void writeMidiEvent(const uint32_t time, const uint8_t channel, const uint8_t* const data, const uint8_t size) | |||
| void writeMidiEvent(const uint32_t time, const uint8_t channel, const uint8_t port, const uint8_t* const data, const uint8_t size) | |||
| { | |||
| if (kPort == nullptr) | |||
| return CarlaEngineEventPort::writeMidiEvent(time, channel, data, size); | |||
| if (kIsInput) | |||
| return; | |||
| return CarlaEngineEventPort::writeMidiEvent(time, channel, port, data, size); | |||
| CARLA_ASSERT(! kIsInput); | |||
| CARLA_ASSERT(fJackBuffer != nullptr); | |||
| CARLA_ASSERT(channel < MAX_MIDI_CHANNELS); | |||
| CARLA_ASSERT(data); | |||
| CARLA_ASSERT(data != nullptr); | |||
| CARLA_ASSERT(size > 0); | |||
| if (kIsInput) | |||
| return; | |||
| if (fJackBuffer == nullptr) | |||
| return; | |||
| if (channel >= MAX_MIDI_CHANNELS) | |||
| return; | |||
| if (! (data && size > 0)) | |||
| if (data == nullptr) | |||
| return; | |||
| if (size == 0) | |||
| return; | |||
| uint8_t jdata[size]; | |||
| @@ -370,13 +374,13 @@ public: | |||
| void activate() | |||
| { | |||
| qDebug("CarlaEngineClient::activate()"); | |||
| qDebug("CarlaEngineJackClient::activate()"); | |||
| if (kProcessMode == PROCESS_MODE_MULTIPLE_CLIENTS) | |||
| { | |||
| CARLA_ASSERT(kClient && ! isActive()); | |||
| CARLA_ASSERT(kClient && ! fActive); | |||
| if (kClient && ! isActive()) | |||
| if (kClient && ! fActive) | |||
| jackbridge_activate(kClient); | |||
| } | |||
| @@ -385,13 +389,13 @@ public: | |||
| void deactivate() | |||
| { | |||
| qDebug("CarlaEngineClient::deactivate()"); | |||
| qDebug("CarlaEngineJackClient::deactivate()"); | |||
| if (kProcessMode == PROCESS_MODE_MULTIPLE_CLIENTS) | |||
| { | |||
| CARLA_ASSERT(kClient && isActive()); | |||
| CARLA_ASSERT(kClient && fActive); | |||
| if (kClient && isActive()) | |||
| if (kClient && fActive) | |||
| jackbridge_deactivate(kClient); | |||
| } | |||
| @@ -400,7 +404,7 @@ public: | |||
| bool isOk() const | |||
| { | |||
| qDebug("CarlaEngineClient::isOk()"); | |||
| qDebug("CarlaEngineJackClient::isOk()"); | |||
| if (kUseClient) | |||
| return bool(kClient); | |||
| @@ -418,11 +422,11 @@ public: | |||
| const CarlaEnginePort* addPort(const EnginePortType portType, const char* const name, const bool isInput) | |||
| { | |||
| qDebug("CarlaJackEngineClient::addPort(%s, \"%s\", %s)", EnginePortType2Str(portType), name, bool2str(isInput)); | |||
| qDebug("CarlaEngineJackClient::addPort(%s, \"%s\", %s)", EnginePortType2Str(portType), name, bool2str(isInput)); | |||
| jack_port_t* port = nullptr; | |||
| // Create Jack port if needed | |||
| // Create JACK port first, if needed | |||
| if (kUseClient) | |||
| { | |||
| switch (portType) | |||
| @@ -449,7 +453,7 @@ public: | |||
| return new CarlaEngineJackEventPort(isInput, kProcessMode, kClient, port); | |||
| } | |||
| qCritical("CarlaJackEngineClient::addPort(%s, \"%s\", %s) - invalid type", EnginePortType2Str(portType), name, bool2str(isInput)); | |||
| qCritical("CarlaEngineJackClient::addPort(%s, \"%s\", %s) - invalid type", EnginePortType2Str(portType), name, bool2str(isInput)); | |||
| return nullptr; | |||
| } | |||
| @@ -1047,7 +1051,7 @@ private: | |||
| } | |||
| } | |||
| if (CarlaEngine* const engine = p->getEngine()) | |||
| if (CarlaEngineJack* const engine = (CarlaEngineJack*)p->getEngine()) | |||
| engine->setPeaks(p->id(), inPeaks, outPeaks); | |||
| } | |||
| @@ -42,40 +42,6 @@ static const unsigned int paramPan = 8; | |||
| static const unsigned int paramCount = sizeof(paramMap); | |||
| static const unsigned int programCount = 128; | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| // Plugin Engine client | |||
| class CarlaEnginePluginClient : public CarlaEngineClient | |||
| { | |||
| public: | |||
| CarlaEnginePluginClient(const EngineType engineType, const ProcessMode processMode) | |||
| : CarlaEngineClient(engineType, processMode) | |||
| { | |||
| } | |||
| ~CarlaEnginePluginClient() | |||
| { | |||
| } | |||
| const CarlaEnginePort* addPort(const EnginePortType portType, const char* const name, const bool isInput) | |||
| { | |||
| qDebug("CarlaEnginePluginClient::addPort(%s, \"%s\", %s)", EnginePortType2Str(portType), name, bool2str(isInput)); | |||
| switch (portType) | |||
| { | |||
| case kEnginePortTypeNull: | |||
| break; | |||
| case kEnginePortTypeAudio: | |||
| return new CarlaEngineAudioPort(isInput, kProcessMode); | |||
| case kEnginePortTypeEvent: | |||
| return new CarlaEngineEventPort(isInput, kProcessMode); | |||
| } | |||
| qCritical("CarlaEnginePluginClient::addPort(%s, \"%s\", %s) - invalid type", EnginePortType2Str(portType), name, bool2str(isInput)); | |||
| return nullptr; | |||
| } | |||
| }; | |||
| // ----------------------------------------- | |||
| class CarlaEnginePlugin : public CarlaEngine, | |||
| @@ -163,11 +129,6 @@ public: | |||
| return kEngineTypeRtAudio; | |||
| } | |||
| CarlaEngineClient* addClient(CarlaPlugin* const) | |||
| { | |||
| return new CarlaEnginePluginClient(kEngineTypePlugin, fOptions.processMode); | |||
| } | |||
| protected: | |||
| // --------------------------------------------- | |||
| // DISTRHO Plugin Information | |||
| @@ -30,45 +30,6 @@ CARLA_BACKEND_START_NAMESPACE | |||
| } // Fix editor indentation | |||
| #endif | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| // RtAudio Engine client | |||
| class CarlaEngineRtAudioClient : public CarlaEngineClient | |||
| { | |||
| public: | |||
| 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 EnginePortType portType, const char* const name, const bool isInput) | |||
| { | |||
| qDebug("CarlaEngineRtAudioClient::addPort(%s, \"%s\", %s)", EnginePortType2Str(portType), name, bool2str(isInput)); | |||
| switch (portType) | |||
| { | |||
| case kEnginePortTypeNull: | |||
| break; | |||
| case kEnginePortTypeAudio: | |||
| return new CarlaEngineAudioPort(isInput, kProcessMode); | |||
| case kEnginePortTypeEvent: | |||
| return new CarlaEngineEventPort(isInput, kProcessMode); | |||
| } | |||
| qCritical("CarlaEngineRtAudioClient::addPort(%s, \"%s\", %s) - invalid type", EnginePortType2Str(portType), name, bool2str(isInput)); | |||
| return nullptr; | |||
| } | |||
| private: | |||
| CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineRtAudioClient) | |||
| }; | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| // RtAudio Engine | |||
| @@ -248,11 +209,6 @@ public: | |||
| return kEngineTypeRtAudio; | |||
| } | |||
| CarlaEngineClient* addClient(CarlaPlugin* const) | |||
| { | |||
| return new CarlaEngineRtAudioClient(kEngineTypeRtAudio, fOptions.processMode); | |||
| } | |||
| // ------------------------------------- | |||
| protected: | |||
| @@ -1,9 +1,7 @@ | |||
| # QtCreator project file | |||
| QT = core gui | |||
| CONFIG = debug | |||
| CONFIG += link_pkgconfig qt shared warn_on | |||
| CONFIG += link_pkgconfig shared warn_on | |||
| DEFINES = DEBUG | |||
| DEFINES += QTCREATOR_TEST | |||
| @@ -27,7 +25,7 @@ TARGET = carla_plugin | |||
| TEMPLATE = lib | |||
| VERSION = 0.5.0 | |||
| SOURCES = \ | |||
| SOURCES = \ | |||
| carla_plugin.cpp \ | |||
| carla_plugin_thread.cpp \ | |||
| carla_bridge.cpp \ | |||
| @@ -39,7 +37,7 @@ SOURCES = \ | |||
| fluidsynth.cpp \ | |||
| linuxsampler.cpp | |||
| HEADERS = \ | |||
| HEADERS = \ | |||
| carla_plugin_internal.hpp \ | |||
| carla_plugin_thread.hpp | |||
| @@ -47,6 +45,7 @@ HEADERS += \ | |||
| ../carla_backend.hpp \ | |||
| ../carla_engine.hpp \ | |||
| ../carla_native.h \ | |||
| ../carla_native.hpp \ | |||
| ../carla_plugin.hpp | |||
| INCLUDEPATH = . .. \ | |||
| @@ -54,8 +53,24 @@ INCLUDEPATH = . .. \ | |||
| ../../libs \ | |||
| ../../utils | |||
| # FIXME | |||
| # --------------------------------------------------------------------------------------- | |||
| PKGCONFIG += QtCore QtGui | |||
| # Fake includes | |||
| INCLUDEPATH += \ | |||
| /opt/kxstudio/include | |||
| /usr/include/qt4/ \ | |||
| /opt/kxstudio/include/ | |||
| # System includes | |||
| QMAKE_CXXFLAGS += -isystem /usr/include/qt4/ | |||
| QMAKE_CXXFLAGS += -isystem /opt/kxstudio/include/ | |||
| WARN_FLAGS = \ | |||
| -ansi -pedantic -pedantic-errors -Wall -Wextra -Wformat=2 -Wunused-parameter -Wuninitialized \ | |||
| -Wcast-qual -Wconversion -Wsign-conversion -Wlogical-op -Waggregate-return -Wno-vla \ | |||
| -fipa-pure-const -Wsuggest-attribute=const #pure,const,noreturn | |||
| QMAKE_CXXFLAGS *= -std=c++0x | |||
| QMAKE_CFLAGS += $${WARN_FLAGS} -std=c99 -Wc++-compat -Wunsuffixed-float-constants -Wwrite-strings | |||
| # QMAKE_CXXFLAGS += $${WARN_FLAGS} -std=c++0x -fPIC | |||
| QMAKE_CXXFLAGS += $${WARN_FLAGS} -std=c++11 -Wzero-as-null-pointer-constant | |||
| @@ -1595,7 +1595,7 @@ private: | |||
| CARLA_BACKEND_END_NAMESPACE | |||
| #else // WANT_DSSI | |||
| # warning Building without DSSI support | |||
| //# warning Building without DSSI support | |||
| #endif | |||
| CARLA_BACKEND_START_NAMESPACE | |||
| @@ -1318,7 +1318,7 @@ private: | |||
| CARLA_BACKEND_END_NAMESPACE | |||
| #else // WANT_FLUIDSYNTH | |||
| # warning fluidsynth not available (no SF2 support) | |||
| //# warning fluidsynth not available (no SF2 support) | |||
| #endif | |||
| CARLA_BACKEND_START_NAMESPACE | |||
| @@ -768,30 +768,26 @@ public: | |||
| if (fData->event.portIn != nullptr && fData->activeBefore) | |||
| { | |||
| const EngineEvent* event = nullptr; | |||
| uint32_t time, nEvents = fData->event.portIn->getEventCount(); | |||
| for (i=0; i < nEvents; i++) | |||
| { | |||
| event = fData->event.portIn->getEvent(i); | |||
| const EngineEvent& event = fData->event.portIn->getEvent(i); | |||
| if (event == nullptr) | |||
| continue; | |||
| time = event->time - framesOffset; | |||
| time = event.time - framesOffset; | |||
| if (time >= frames) | |||
| continue; | |||
| // Control change | |||
| switch (event->type) | |||
| switch (event.type) | |||
| { | |||
| case kEngineEventTypeNull: | |||
| break; | |||
| case kEngineEventTypeControl: | |||
| { | |||
| const EngineControlEvent& ctrlEvent = event->ctrl; | |||
| const EngineControlEvent& ctrlEvent = event.ctrl; | |||
| switch (ctrlEvent.type) | |||
| { | |||
| @@ -801,11 +797,11 @@ public: | |||
| case kEngineControlEventTypeParameter: | |||
| { | |||
| // Control backend stuff | |||
| if (event->channel == fData->ctrlInChannel) | |||
| if (event.channel == fData->ctrlInChannel) | |||
| { | |||
| double value; | |||
| if (MIDI_IS_CONTROL_BREATH_CONTROLLER(ctrlEvent.parameter) && (fData->hints & PLUGIN_CAN_DRYWET) > 0) | |||
| if (MIDI_IS_CONTROL_BREATH_CONTROLLER(ctrlEvent.param) && (fData->hints & PLUGIN_CAN_DRYWET) > 0) | |||
| { | |||
| value = ctrlEvent.value; | |||
| setDryWet(value, false, false); | |||
| @@ -813,7 +809,7 @@ public: | |||
| continue; | |||
| } | |||
| if (MIDI_IS_CONTROL_CHANNEL_VOLUME(ctrlEvent.parameter) && (fData->hints & PLUGIN_CAN_VOLUME) > 0) | |||
| if (MIDI_IS_CONTROL_CHANNEL_VOLUME(ctrlEvent.param) && (fData->hints & PLUGIN_CAN_VOLUME) > 0) | |||
| { | |||
| value = ctrlEvent.value*127/100; | |||
| setVolume(value, false, false); | |||
| @@ -821,7 +817,7 @@ public: | |||
| continue; | |||
| } | |||
| if (MIDI_IS_CONTROL_BALANCE(ctrlEvent.parameter) && (fData->hints & PLUGIN_CAN_BALANCE) > 0) | |||
| if (MIDI_IS_CONTROL_BALANCE(ctrlEvent.param) && (fData->hints & PLUGIN_CAN_BALANCE) > 0) | |||
| { | |||
| double left, right; | |||
| value = ctrlEvent.value/0.5 - 1.0; | |||
| @@ -853,9 +849,9 @@ public: | |||
| // Control plugin parameters | |||
| for (k=0; k < fData->param.count; k++) | |||
| { | |||
| if (fData->param.data[k].midiChannel != event->channel) | |||
| if (fData->param.data[k].midiChannel != event.channel) | |||
| continue; | |||
| if (fData->param.data[k].midiCC != ctrlEvent.parameter) | |||
| if (fData->param.data[k].midiCC != ctrlEvent.param) | |||
| continue; | |||
| if (fData->param.data[k].type != PARAMETER_INPUT) | |||
| continue; | |||
| @@ -889,7 +885,7 @@ public: | |||
| break; | |||
| case kEngineControlEventTypeAllSoundOff: | |||
| if (event->channel == fData->ctrlInChannel) | |||
| if (event.channel == fData->ctrlInChannel) | |||
| { | |||
| if (fDescriptor->deactivate != nullptr) | |||
| { | |||
| @@ -1078,7 +1074,7 @@ public: | |||
| if (fData->param.data[k].midiCC > 0) | |||
| { | |||
| value = fData->param.ranges[k].Value(fParamBuffers[k]); // FIXME - range 0.0-1.0 new name | |||
| value = fData->param.ranges[k].normalizeValue(fParamBuffers[k]); | |||
| fData->event.portOut->writeControlEvent(framesOffset, fData->param.data[k].midiChannel, kEngineControlEventTypeParameter, fData->param.data[k].midiCC, value); | |||
| } | |||
| } | |||
| @@ -957,7 +957,7 @@ CarlaPlugin* LinuxSamplerPlugin::newLinuxSampler(const Initializer& init, bool i | |||
| CARLA_BACKEND_END_NAMESPACE | |||
| #else // WANT_LINUXSAMPLER | |||
| # warning linuxsampler not available (no GIG and SFZ support) | |||
| //# warning linuxsampler not available (no GIG and SFZ support) | |||
| #endif | |||
| CARLA_BACKEND_START_NAMESPACE | |||
| @@ -4635,7 +4635,7 @@ int CarlaEngineOsc::handleMsgLv2EventTransfer(CARLA_ENGINE_OSC_HANDLE_ARGS2) | |||
| CARLA_BACKEND_END_NAMESPACE | |||
| #else // WANT_LV2 | |||
| # warning Building without LV2 support | |||
| //# warning Building without LV2 support | |||
| #endif | |||
| CARLA_BACKEND_START_NAMESPACE | |||
| @@ -2381,7 +2381,7 @@ VstPlugin* VstPlugin::lastVstPlugin = nullptr; | |||
| CARLA_BACKEND_END_NAMESPACE | |||
| #else // WANT_VST | |||
| # warning Building without VST support | |||
| //# warning Building without VST support | |||
| #endif | |||
| CARLA_BACKEND_START_NAMESPACE | |||
| @@ -732,6 +732,8 @@ class CarlaMainW(QMainWindow): | |||
| while (self.ui.w_plugins.layout().takeAt(0)): | |||
| pass | |||
| self.ui.act_plugin_remove_all.setEnabled(False) | |||
| for i in range(self.fPluginCount): | |||
| pwidget = self.fPluginList[i] | |||
| @@ -508,7 +508,7 @@ public: | |||
| for (size_t i=0; i < bufferLen; i++) | |||
| { | |||
| if (buffer[i] >= 'A' && buffer[i] <= 'Z') | |||
| buffer[i] = char(buffer[i] + charDiff); | |||
| buffer[i] += charDiff; | |||
| } | |||
| } | |||
| @@ -519,7 +519,7 @@ public: | |||
| for (size_t i=0; i < bufferLen; i++) | |||
| { | |||
| if (buffer[i] >= 'a' && buffer[i] <= 'z') | |||
| buffer[i] = char(buffer[i] + charDiff); | |||
| buffer[i] -= charDiff; | |||
| } | |||
| } | |||