| @@ -308,6 +308,14 @@ struct EngineTimeInfo { | |||
| frame(0), | |||
| time(0), | |||
| valid(0x0) {} | |||
| void clear() | |||
| { | |||
| playing = false; | |||
| frame = 0; | |||
| time = 0; | |||
| valid = 0x0; | |||
| } | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| @@ -539,9 +547,9 @@ private: | |||
| /*! | |||
| * Private data used in CarlaEngine. | |||
| * No other than CarlaEngine must have direct access to this. | |||
| * Non-engine code MUST NEVER have direct access to this. | |||
| */ | |||
| struct CarlaEnginePrivateData; | |||
| struct CarlaEngineProtectedData; | |||
| /*! | |||
| * Carla Engine. | |||
| @@ -857,6 +865,25 @@ protected: | |||
| EngineOptions fOptions; | |||
| EngineTimeInfo fTimeInfo; | |||
| ScopedPointer<CarlaEngineProtectedData> const fData; | |||
| /*! | |||
| * Report to all plugins about buffer size change. | |||
| */ | |||
| void bufferSizeChanged(const uint32_t newBufferSize); | |||
| /*! | |||
| * 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. | |||
| */ | |||
| void sampleRateChanged(const double newSampleRate); | |||
| /*! | |||
| * TODO. | |||
| */ | |||
| void proccessPendingEvents(); | |||
| #ifndef BUILD_BRIDGE | |||
| // Rack mode data | |||
| EngineEvent* getRackEventBuffer(const bool isInput); | |||
| @@ -877,26 +904,7 @@ protected: | |||
| void processPatchbay(float** inBuf, float** outBuf, const uint32_t bufCount[2], const uint32_t frames); | |||
| #endif | |||
| /*! | |||
| * TODO. | |||
| */ | |||
| void proccessPendingEvents(); | |||
| /*! | |||
| * Report to all plugins about buffer size change. | |||
| */ | |||
| void bufferSizeChanged(const uint32_t newBufferSize); | |||
| /*! | |||
| * 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. | |||
| */ | |||
| void sampleRateChanged(const double newSampleRate); | |||
| private: | |||
| ScopedPointer<CarlaEnginePrivateData> const fData; | |||
| #ifdef WANT_JACK | |||
| static CarlaEngine* newJack(); | |||
| #endif | |||
| @@ -182,6 +182,7 @@ void CarlaEngineEventPort::writeControlEvent(const uint32_t time, const uint8_t | |||
| CARLA_ASSERT(fBuffer != nullptr); | |||
| CARLA_ASSERT(type != kEngineControlEventTypeNull); | |||
| CARLA_ASSERT(channel < MAX_MIDI_CHANNELS); | |||
| CARLA_ASSERT(value >= 0.0 && value <= 1.0); | |||
| if (fBuffer == nullptr) | |||
| return; | |||
| @@ -340,7 +341,7 @@ void CarlaEngineClient::setLatency(const uint32_t samples) | |||
| CarlaEngine::CarlaEngine() | |||
| : fBufferSize(0), | |||
| fSampleRate(0.0), | |||
| fData(new CarlaEnginePrivateData(this)) | |||
| fData(new CarlaEngineProtectedData(this)) | |||
| { | |||
| qDebug("CarlaEngine::CarlaEngine()"); | |||
| } | |||
| @@ -355,7 +356,7 @@ CarlaEngine::~CarlaEngine() | |||
| // ----------------------------------------------------------------------- | |||
| // Helpers | |||
| void doPluginRemove(CarlaEnginePrivateData* const fData, const bool unlock) | |||
| void doPluginRemove(CarlaEngineProtectedData* const fData, const bool unlock) | |||
| { | |||
| CARLA_ASSERT(fData->curPluginCount > 0); | |||
| fData->curPluginCount--; | |||
| @@ -511,6 +512,8 @@ bool CarlaEngine::init(const char* const clientName) | |||
| fName = clientName; | |||
| fName.toBasic(); | |||
| fTimeInfo.clear(); | |||
| fData->aboutToClose = false; | |||
| fData->curPluginCount = 0; | |||
| @@ -1198,6 +1201,40 @@ void CarlaEngine::setOscBridgeData(const CarlaOscData* const oscData) | |||
| // ----------------------------------------------------------------------- | |||
| // protected calls | |||
| void CarlaEngine::bufferSizeChanged(const uint32_t newBufferSize) | |||
| { | |||
| qDebug("CarlaEngine::bufferSizeChanged(%i)", newBufferSize); | |||
| #if 0 | |||
| for (unsigned short i=0; i < data->maxPluginNumber; i++) | |||
| { | |||
| if (data->carlaPlugins[i] && data->carlaPlugins[i]->enabled() /*&& ! data->carlaPlugins[i]->data->processHighPrecision*/) | |||
| data->carlaPlugins[i]->bufferSizeChanged(newBufferSize); | |||
| } | |||
| #endif | |||
| } | |||
| void CarlaEngine::sampleRateChanged(const double newSampleRate) | |||
| { | |||
| qDebug("CarlaEngine::sampleRateChanged(%g)", newSampleRate); | |||
| // TODO | |||
| } | |||
| void CarlaEngine::proccessPendingEvents() | |||
| { | |||
| switch (fData->nextAction.opcode) | |||
| { | |||
| case EnginePostActionNull: | |||
| break; | |||
| case EnginePostActionRemovePlugin: | |||
| doPluginRemove(fData, true); | |||
| break; | |||
| } | |||
| // TODO - peak values | |||
| } | |||
| #ifndef BUILD_BRIDGE | |||
| EngineEvent* CarlaEngine::getRackEventBuffer(const bool isInput) | |||
| { | |||
| @@ -1210,19 +1247,19 @@ 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); | |||
| #if 0 | |||
| std::memset(rackEventsOut, 0, sizeof(EngineEvent)*MAX_EVENTS); | |||
| bool processed = false; | |||
| //std::memset(rackEventsOut, 0, sizeof(EngineEvent)*MAX_EVENTS); | |||
| bool processed = false; | |||
| // process plugins | |||
| for (unsigned short i=0, max=maxPluginNumber(); i < max; i++) | |||
| for (unsigned int i=0; i < fData->curPluginCount; i++) | |||
| { | |||
| CarlaPlugin* const plugin = getPluginUnchecked(i); | |||
| if (! (plugin && plugin->enabled())) | |||
| if (plugin == nullptr || ! plugin->enabled()) | |||
| continue; | |||
| #if 0 | |||
| if (processed) | |||
| { | |||
| // initialize inputs (from previous outputs) | |||
| @@ -1302,6 +1339,7 @@ void CarlaEngine::processRack(float* inBuf[2], float* outBuf[2], const uint32_t | |||
| data->outsPeak[i*MAX_PEAKS + 0] = outPeak1; | |||
| data->outsPeak[i*MAX_PEAKS + 1] = outPeak2; | |||
| } | |||
| #endif | |||
| processed = true; | |||
| } | |||
| @@ -1311,9 +1349,8 @@ void CarlaEngine::processRack(float* inBuf[2], float* outBuf[2], const uint32_t | |||
| { | |||
| 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); | |||
| //std::memcpy(rackEventsOut, rackEventsIn, sizeof(EngineEvent)*MAX_EVENTS); | |||
| } | |||
| #endif | |||
| } | |||
| void CarlaEngine::processPatchbay(float** inBuf, float** outBuf, const uint32_t bufCount[2], const uint32_t frames) | |||
| @@ -1326,40 +1363,6 @@ void CarlaEngine::processPatchbay(float** inBuf, float** outBuf, const uint32_t | |||
| } | |||
| #endif | |||
| void CarlaEngine::proccessPendingEvents() | |||
| { | |||
| switch (fData->nextAction.opcode) | |||
| { | |||
| case EnginePostActionNull: | |||
| break; | |||
| case EnginePostActionRemovePlugin: | |||
| doPluginRemove(fData, true); | |||
| break; | |||
| } | |||
| // TODO - peak values | |||
| } | |||
| void CarlaEngine::bufferSizeChanged(const uint32_t newBufferSize) | |||
| { | |||
| qDebug("CarlaEngine::bufferSizeChanged(%i)", newBufferSize); | |||
| #if 0 | |||
| for (unsigned short i=0; i < data->maxPluginNumber; i++) | |||
| { | |||
| if (data->carlaPlugins[i] && data->carlaPlugins[i]->enabled() /*&& ! data->carlaPlugins[i]->data->processHighPrecision*/) | |||
| data->carlaPlugins[i]->bufferSizeChanged(newBufferSize); | |||
| } | |||
| #endif | |||
| } | |||
| void CarlaEngine::sampleRateChanged(const double newSampleRate) | |||
| { | |||
| qDebug("CarlaEngine::sampleRateChanged(%g)", newSampleRate); | |||
| // TODO | |||
| } | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| // Carla Engine OSC stuff | |||
| @@ -1,10 +1,9 @@ | |||
| # QtCreator project file | |||
| # QT = core | |||
| QT = core | |||
| CONFIG = debug | |||
| CONFIG += link_pkgconfig shared warn_on | |||
| # qt | |||
| CONFIG += link_pkgconfig qt shared warn_on | |||
| DEFINES = DEBUG | |||
| DEFINES += QTCREATOR_TEST | |||
| @@ -30,7 +29,7 @@ DEFINES += WANT_JACK WANT_RTAUDIO | |||
| PKGCONFIG = liblo jack alsa libpulse-simple | |||
| TARGET = carla_engine | |||
| TEMPLATE = app | |||
| TEMPLATE = lib | |||
| VERSION = 0.5.0 | |||
| SOURCES = \ | |||
| @@ -92,4 +91,5 @@ WARN_FLAGS = \ | |||
| -fipa-pure-const -Wsuggest-attribute=const #pure,const,noreturn | |||
| QMAKE_CFLAGS *= $${WARN_FLAGS} -std=c99 -Wc++-compat -Wunsuffixed-float-constants -Wwrite-strings | |||
| QMAKE_CXXFLAGS *= $${WARN_FLAGS} -std=c++11 -Wzero-as-null-pointer-constant | |||
| QMAKE_CXXFLAGS *= $${WARN_FLAGS} -std=c++0x -fPIC | |||
| #QMAKE_CXXFLAGS *= $${WARN_FLAGS} -std=c++11 -Wzero-as-null-pointer-constant | |||
| @@ -135,7 +135,7 @@ struct EnginePluginData { | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| struct CarlaEnginePrivateData { | |||
| struct CarlaEngineProtectedData { | |||
| CarlaEngineOsc osc; | |||
| CarlaEngineThread thread; | |||
| @@ -172,7 +172,7 @@ struct CarlaEnginePrivateData { | |||
| EnginePluginData* plugins; | |||
| CarlaEnginePrivateData(CarlaEngine* const engine) | |||
| CarlaEngineProtectedData(CarlaEngine* const engine) | |||
| : osc(engine), | |||
| thread(engine), | |||
| oscData(nullptr), | |||
| @@ -183,9 +183,9 @@ struct CarlaEnginePrivateData { | |||
| maxPluginNumber(0), | |||
| plugins(nullptr) {} | |||
| CarlaEnginePrivateData() = delete; | |||
| CarlaEngineProtectedData() = delete; | |||
| CARLA_LEAK_DETECTOR(CarlaEnginePrivateData) | |||
| CARLA_LEAK_DETECTOR(CarlaEngineProtectedData) | |||
| }; | |||
| CARLA_BACKEND_END_NAMESPACE | |||
| @@ -361,9 +361,9 @@ int CarlaEngineOsc::handleMsgRegister(const int argc, const lo_arg* const* const | |||
| qDebug("CarlaEngineOsc::handleMsgRegister()"); | |||
| CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "s"); | |||
| if (m_controlData.path) | |||
| if (fControlData.path != nullptr) | |||
| { | |||
| qWarning("CarlaEngineOsc::handleMsgRegister() - OSC backend already registered to %s", m_controlData.path); | |||
| qWarning("CarlaEngineOsc::handleMsgRegister() - OSC backend already registered to %s", fControlData.path); | |||
| return 1; | |||
| } | |||
| @@ -375,25 +375,23 @@ int CarlaEngineOsc::handleMsgRegister(const int argc, const lo_arg* const* const | |||
| host = lo_address_get_hostname(source); | |||
| port = lo_address_get_port(source); | |||
| m_controlData.source = lo_address_new_with_proto(LO_TCP, host, port); | |||
| fControlData.source = lo_address_new_with_proto(LO_TCP, host, port); | |||
| host = lo_url_get_hostname(url); | |||
| port = lo_url_get_port(url); | |||
| m_controlData.path = lo_url_get_path(url); | |||
| m_controlData.target = lo_address_new_with_proto(LO_TCP, host, port); | |||
| fControlData.path = lo_url_get_path(url); | |||
| fControlData.target = lo_address_new_with_proto(LO_TCP, host, port); | |||
| free((void*)host); | |||
| free((void*)port); | |||
| #if 0 | |||
| for (unsigned short i=0; i < engine->maxPluginNumber(); i++) | |||
| for (unsigned short i=0; i < kEngine->currentPluginCount(); i++) | |||
| { | |||
| CarlaPlugin* const plugin = engine->getPluginUnchecked(i); | |||
| CarlaPlugin* const plugin = kEngine->getPluginUnchecked(i); | |||
| if (plugin && plugin->enabled()) | |||
| plugin->registerToOscClient(); | |||
| } | |||
| #endif | |||
| return 0; | |||
| } | |||
| @@ -402,13 +400,13 @@ int CarlaEngineOsc::handleMsgUnregister() | |||
| { | |||
| qDebug("CarlaEngineOsc::handleMsgUnregister()"); | |||
| if (! m_controlData.path) | |||
| if (fControlData.path == nullptr) | |||
| { | |||
| qWarning("CarlaEngineOsc::handleMsgUnregister() - OSC backend is not registered yet"); | |||
| return 1; | |||
| } | |||
| m_controlData.free(); | |||
| fControlData.free(); | |||
| return 0; | |||
| } | |||
| #endif | |||
| @@ -37,18 +37,18 @@ class CarlaEngineJackAudioPort : public CarlaEngineAudioPort | |||
| public: | |||
| CarlaEngineJackAudioPort(const bool isInput, const ProcessMode processMode, jack_client_t* const client, jack_port_t* const port) | |||
| : CarlaEngineAudioPort(isInput, processMode), | |||
| m_client(client), | |||
| m_port(port) | |||
| kClient(client), | |||
| kPort(port) | |||
| { | |||
| 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); | |||
| CARLA_ASSERT(client != nullptr && port != nullptr); | |||
| } | |||
| else | |||
| { | |||
| CARLA_ASSERT(! (m_client || m_port)); | |||
| CARLA_ASSERT(client == nullptr && port == nullptr); | |||
| } | |||
| } | |||
| @@ -56,29 +56,29 @@ public: | |||
| { | |||
| qDebug("CarlaEngineJackAudioPort::~CarlaEngineJackAudioPort()"); | |||
| if (m_client && m_port) | |||
| jackbridge_port_unregister(m_client, m_port); | |||
| if (kClient != nullptr && kPort != nullptr) | |||
| jackbridge_port_unregister(kClient, kPort); | |||
| } | |||
| void initBuffer(CarlaEngine* const engine) | |||
| { | |||
| CARLA_ASSERT(engine); | |||
| CARLA_ASSERT(engine != nullptr); | |||
| if (! engine) | |||
| if (engine == nullptr) | |||
| { | |||
| fBuffer = nullptr; | |||
| return; | |||
| } | |||
| if (! m_port) | |||
| if (kPort == nullptr) | |||
| return CarlaEngineAudioPort::initBuffer(engine); | |||
| fBuffer = (float*)jackbridge_port_get_buffer(m_port, engine->getBufferSize()); | |||
| fBuffer = (float*)jackbridge_port_get_buffer(kPort, engine->getBufferSize()); | |||
| } | |||
| private: | |||
| jack_client_t* const m_client; | |||
| jack_port_t* const m_port; | |||
| jack_client_t* const kClient; | |||
| jack_port_t* const kPort; | |||
| CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineJackAudioPort) | |||
| }; | |||
| @@ -91,18 +91,19 @@ class CarlaEngineJackEventPort : public CarlaEngineEventPort | |||
| public: | |||
| 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) | |||
| kClient(client), | |||
| kPort(port), | |||
| fJackBuffer(nullptr) | |||
| { | |||
| 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); | |||
| CARLA_ASSERT(client != nullptr && port != nullptr); | |||
| } | |||
| else | |||
| { | |||
| CARLA_ASSERT(! (m_client || m_port)); | |||
| CARLA_ASSERT(client == nullptr && port == nullptr); | |||
| } | |||
| } | |||
| @@ -110,140 +111,141 @@ public: | |||
| { | |||
| qDebug("CarlaEngineJackEventPort::~CarlaEngineJackEventPort()"); | |||
| if (m_client && m_port) | |||
| jackbridge_port_unregister(m_client, m_port); | |||
| if (kClient != nullptr && kPort != nullptr) | |||
| jackbridge_port_unregister(kClient, kPort); | |||
| } | |||
| void initBuffer(CarlaEngine* const engine) | |||
| { | |||
| CARLA_ASSERT(engine); | |||
| CARLA_ASSERT(engine != nullptr); | |||
| if (! engine) | |||
| if (engine == nullptr) | |||
| { | |||
| fBuffer = nullptr; | |||
| fJackBuffer = nullptr; | |||
| return; | |||
| } | |||
| if (! m_port) | |||
| if (kPort == nullptr) | |||
| return CarlaEngineEventPort::initBuffer(engine); | |||
| fBuffer = jackbridge_port_get_buffer(m_port, engine->getBufferSize()); | |||
| fJackBuffer = jackbridge_port_get_buffer(kPort, engine->getBufferSize()); | |||
| if (! kIsInput) | |||
| jackbridge_midi_clear_buffer(fBuffer); | |||
| jackbridge_midi_clear_buffer(fJackBuffer); | |||
| } | |||
| uint32_t getEventCount() | |||
| { | |||
| if (! m_port) | |||
| if (kPort == nullptr) | |||
| return CarlaEngineEventPort::getEventCount(); | |||
| if (! kIsInput) | |||
| return 0; | |||
| CARLA_ASSERT(fBuffer); | |||
| CARLA_ASSERT(fJackBuffer != nullptr); | |||
| if (! fBuffer) | |||
| if (fJackBuffer != nullptr) | |||
| return 0; | |||
| return jackbridge_midi_get_event_count(fBuffer); | |||
| return jackbridge_midi_get_event_count(fJackBuffer); | |||
| } | |||
| const EngineEvent* getEvent(const uint32_t index) | |||
| { | |||
| if (! m_port) | |||
| if (kPort == nullptr) | |||
| return CarlaEngineEventPort::getEvent(index); | |||
| if (! kIsInput) | |||
| return nullptr; | |||
| CARLA_ASSERT(fBuffer); | |||
| CARLA_ASSERT(fJackBuffer != nullptr); | |||
| if (! fBuffer) | |||
| if (fJackBuffer != nullptr) | |||
| return nullptr; | |||
| jack_midi_event_t jackEvent; | |||
| if (jackbridge_midi_event_get(&jackEvent, fBuffer, index) != 0 || jackEvent.size > 3) | |||
| if (jackbridge_midi_event_get(&jackEvent, fJackBuffer, index) != 0 || jackEvent.size > 3) | |||
| return nullptr; | |||
| m_retEvent.clear(); | |||
| fRetEvent.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; | |||
| fRetEvent.time = jackEvent.time; | |||
| fRetEvent.channel = midiChannel; | |||
| if (MIDI_IS_STATUS_CONTROL_CHANGE(midiStatus)) | |||
| { | |||
| const uint8_t midiControl = jackEvent.buffer[1]; | |||
| m_retEvent.type = kEngineEventTypeControl; | |||
| fRetEvent.type = kEngineEventTypeControl; | |||
| if (MIDI_IS_CONTROL_BANK_SELECT(midiControl)) | |||
| { | |||
| const uint8_t midiBank = jackEvent.buffer[2]; | |||
| m_retEvent.ctrl.type = kEngineControlEventTypeMidiBank; | |||
| m_retEvent.ctrl.parameter = midiBank; | |||
| m_retEvent.ctrl.value = 0.0; | |||
| fRetEvent.ctrl.type = kEngineControlEventTypeMidiBank; | |||
| fRetEvent.ctrl.parameter = midiBank; | |||
| fRetEvent.ctrl.value = 0.0; | |||
| } | |||
| else if (midiControl == MIDI_CONTROL_ALL_SOUND_OFF) | |||
| { | |||
| m_retEvent.ctrl.type = kEngineControlEventTypeAllSoundOff; | |||
| m_retEvent.ctrl.parameter = 0; | |||
| m_retEvent.ctrl.value = 0.0; | |||
| fRetEvent.ctrl.type = kEngineControlEventTypeAllSoundOff; | |||
| fRetEvent.ctrl.parameter = 0; | |||
| fRetEvent.ctrl.value = 0.0; | |||
| } | |||
| else if (midiControl == MIDI_CONTROL_ALL_NOTES_OFF) | |||
| { | |||
| m_retEvent.ctrl.type = kEngineControlEventTypeAllNotesOff; | |||
| m_retEvent.ctrl.parameter = 0; | |||
| m_retEvent.ctrl.value = 0.0; | |||
| fRetEvent.ctrl.type = kEngineControlEventTypeAllNotesOff; | |||
| fRetEvent.ctrl.parameter = 0; | |||
| fRetEvent.ctrl.value = 0.0; | |||
| } | |||
| else | |||
| { | |||
| const uint8_t midiValue = jackEvent.buffer[2]; | |||
| m_retEvent.ctrl.type = kEngineControlEventTypeParameter; | |||
| m_retEvent.ctrl.parameter = midiControl; | |||
| m_retEvent.ctrl.value = double(midiValue)/127; | |||
| fRetEvent.ctrl.type = kEngineControlEventTypeParameter; | |||
| fRetEvent.ctrl.parameter = midiControl; | |||
| fRetEvent.ctrl.value = double(midiValue)/127; | |||
| } | |||
| } | |||
| else if (MIDI_IS_STATUS_PROGRAM_CHANGE(midiStatus)) | |||
| { | |||
| const uint8_t midiProgram = jackEvent.buffer[1]; | |||
| m_retEvent.type = kEngineEventTypeControl; | |||
| fRetEvent.type = kEngineEventTypeControl; | |||
| m_retEvent.ctrl.type = kEngineControlEventTypeMidiProgram; | |||
| m_retEvent.ctrl.parameter = midiProgram; | |||
| m_retEvent.ctrl.value = 0.0; | |||
| fRetEvent.ctrl.type = kEngineControlEventTypeMidiProgram; | |||
| fRetEvent.ctrl.parameter = midiProgram; | |||
| fRetEvent.ctrl.value = 0.0; | |||
| } | |||
| else | |||
| { | |||
| m_retEvent.type = kEngineEventTypeMidi; | |||
| fRetEvent.type = kEngineEventTypeMidi; | |||
| 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; | |||
| fRetEvent.midi.data[0] = midiStatus; | |||
| fRetEvent.midi.data[1] = jackEvent.buffer[1]; | |||
| fRetEvent.midi.data[2] = jackEvent.buffer[2]; | |||
| fRetEvent.midi.size = jackEvent.size; | |||
| } | |||
| return &m_retEvent; | |||
| return &fRetEvent; | |||
| } | |||
| void writeControlEvent(const uint32_t time, const uint8_t channel, const EngineControlEventType type, const uint16_t parameter, const double value) | |||
| { | |||
| if (! m_port) | |||
| if (kPort == nullptr) | |||
| return CarlaEngineEventPort::writeControlEvent(time, channel, type, parameter, value); | |||
| if (kIsInput) | |||
| return; | |||
| CARLA_ASSERT(fBuffer); | |||
| CARLA_ASSERT(fJackBuffer != nullptr); | |||
| CARLA_ASSERT(type != kEngineControlEventTypeNull); | |||
| CARLA_ASSERT(channel < MAX_MIDI_CHANNELS); | |||
| CARLA_ASSERT(value >= 0.0 && value <= 1.0); | |||
| if (! fBuffer) | |||
| if (fJackBuffer == nullptr) | |||
| return; | |||
| if (type == kEngineControlEventTypeNull) | |||
| return; | |||
| @@ -291,23 +293,23 @@ public: | |||
| } | |||
| if (size > 0) | |||
| jackbridge_midi_event_write(fBuffer, time, data, size); | |||
| 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) | |||
| { | |||
| if (! m_port) | |||
| if (kPort == nullptr) | |||
| return CarlaEngineEventPort::writeMidiEvent(time, channel, data, size); | |||
| if (kIsInput) | |||
| return; | |||
| CARLA_ASSERT(fBuffer); | |||
| CARLA_ASSERT(fJackBuffer != nullptr); | |||
| CARLA_ASSERT(channel < MAX_MIDI_CHANNELS); | |||
| CARLA_ASSERT(data); | |||
| CARLA_ASSERT(size > 0); | |||
| if (! fBuffer) | |||
| if (fJackBuffer == nullptr) | |||
| return; | |||
| if (channel >= MAX_MIDI_CHANNELS) | |||
| return; | |||
| @@ -319,16 +321,15 @@ public: | |||
| jdata[0] = data[0] + channel; | |||
| jackbridge_midi_event_write(fBuffer, time, jdata, size); | |||
| jackbridge_midi_event_write(fJackBuffer, time, jdata, size); | |||
| } | |||
| private: | |||
| void* fBuffer; | |||
| jack_client_t* const m_client; | |||
| jack_port_t* const m_port; | |||
| jack_client_t* const kClient; | |||
| jack_port_t* const kPort; | |||
| EngineEvent m_retEvent; | |||
| void* fJackBuffer; | |||
| EngineEvent fRetEvent; | |||
| CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineJackEventPort) | |||
| }; | |||
| @@ -341,15 +342,19 @@ class CarlaEngineJackClient : public CarlaEngineClient | |||
| public: | |||
| 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) | |||
| kClient(client), | |||
| kUseClient(processMode == PROCESS_MODE_SINGLE_CLIENT || processMode == PROCESS_MODE_MULTIPLE_CLIENTS) | |||
| { | |||
| qDebug("CarlaEngineJackClient::CarlaEngineJackClient(%s, %s, %p)", EngineType2Str(engineType), ProcessMode2Str(processMode), client); | |||
| if (m_usesClient) | |||
| CARLA_ASSERT(m_client); | |||
| if (kUseClient) | |||
| { | |||
| CARLA_ASSERT(kClient != nullptr); | |||
| } | |||
| else | |||
| CARLA_ASSERT(! m_client); | |||
| { | |||
| CARLA_ASSERT(kClient == nullptr); | |||
| } | |||
| } | |||
| ~CarlaEngineJackClient() | |||
| @@ -358,8 +363,8 @@ public: | |||
| if (kProcessMode == PROCESS_MODE_MULTIPLE_CLIENTS) | |||
| { | |||
| if (m_client) | |||
| jackbridge_client_close(m_client); | |||
| if (kClient) | |||
| jackbridge_client_close(kClient); | |||
| } | |||
| } | |||
| @@ -369,10 +374,10 @@ public: | |||
| if (kProcessMode == PROCESS_MODE_MULTIPLE_CLIENTS) | |||
| { | |||
| CARLA_ASSERT(m_client && ! isActive()); | |||
| CARLA_ASSERT(kClient && ! isActive()); | |||
| if (m_client && ! isActive()) | |||
| jackbridge_activate(m_client); | |||
| if (kClient && ! isActive()) | |||
| jackbridge_activate(kClient); | |||
| } | |||
| CarlaEngineClient::activate(); | |||
| @@ -384,10 +389,10 @@ public: | |||
| if (kProcessMode == PROCESS_MODE_MULTIPLE_CLIENTS) | |||
| { | |||
| CARLA_ASSERT(m_client && isActive()); | |||
| CARLA_ASSERT(kClient && isActive()); | |||
| if (m_client && isActive()) | |||
| jackbridge_deactivate(m_client); | |||
| if (kClient && isActive()) | |||
| jackbridge_deactivate(kClient); | |||
| } | |||
| CarlaEngineClient::deactivate(); | |||
| @@ -397,8 +402,8 @@ public: | |||
| { | |||
| qDebug("CarlaEngineClient::isOk()"); | |||
| if (m_usesClient) | |||
| return bool(m_client); | |||
| if (kUseClient) | |||
| return bool(kClient); | |||
| return CarlaEngineClient::isOk(); | |||
| } | |||
| @@ -407,8 +412,8 @@ public: | |||
| { | |||
| CarlaEngineClient::setLatency(samples); | |||
| if (m_usesClient) | |||
| jackbridge_recompute_total_latencies(m_client); | |||
| if (kUseClient) | |||
| jackbridge_recompute_total_latencies(kClient); | |||
| } | |||
| const CarlaEnginePort* addPort(const EnginePortType portType, const char* const name, const bool isInput) | |||
| @@ -418,17 +423,17 @@ public: | |||
| jack_port_t* port = nullptr; | |||
| // Create Jack port if needed | |||
| if (m_usesClient) | |||
| if (kUseClient) | |||
| { | |||
| switch (portType) | |||
| { | |||
| case kEnginePortTypeNull: | |||
| break; | |||
| case kEnginePortTypeAudio: | |||
| port = jackbridge_port_register(m_client, name, JACK_DEFAULT_AUDIO_TYPE, isInput ? JackPortIsInput : JackPortIsOutput, 0); | |||
| port = jackbridge_port_register(kClient, name, JACK_DEFAULT_AUDIO_TYPE, isInput ? JackPortIsInput : JackPortIsOutput, 0); | |||
| break; | |||
| case kEnginePortTypeEvent: | |||
| port = jackbridge_port_register(m_client, name, JACK_DEFAULT_MIDI_TYPE, isInput ? JackPortIsInput : JackPortIsOutput, 0); | |||
| port = jackbridge_port_register(kClient, name, JACK_DEFAULT_MIDI_TYPE, isInput ? JackPortIsInput : JackPortIsOutput, 0); | |||
| break; | |||
| } | |||
| } | |||
| @@ -439,9 +444,9 @@ public: | |||
| case kEnginePortTypeNull: | |||
| break; | |||
| case kEnginePortTypeAudio: | |||
| return new CarlaEngineJackAudioPort(isInput, kProcessMode, m_client, port); | |||
| return new CarlaEngineJackAudioPort(isInput, kProcessMode, kClient, port); | |||
| case kEnginePortTypeEvent: | |||
| return new CarlaEngineJackEventPort(isInput, kProcessMode, m_client, port); | |||
| return new CarlaEngineJackEventPort(isInput, kProcessMode, kClient, port); | |||
| } | |||
| qCritical("CarlaJackEngineClient::addPort(%s, \"%s\", %s) - invalid type", EnginePortType2Str(portType), name, bool2str(isInput)); | |||
| @@ -449,8 +454,8 @@ public: | |||
| } | |||
| private: | |||
| jack_client_t* const m_client; | |||
| const bool m_usesClient; | |||
| jack_client_t* const kClient; | |||
| const bool kUseClient; | |||
| CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineJackClient) | |||
| }; | |||
| @@ -462,30 +467,29 @@ class CarlaEngineJack : public CarlaEngine | |||
| { | |||
| public: | |||
| CarlaEngineJack() | |||
| : CarlaEngine() | |||
| #ifndef BUILD_BRIDGE | |||
| , fRackPorts{nullptr} | |||
| : CarlaEngine(), | |||
| #ifdef BUILD_BRIDGE | |||
| fHasQuit(false), | |||
| #else | |||
| fClient(nullptr), | |||
| fTransportState(JackTransportStopped), | |||
| fRackPorts{nullptr}, | |||
| #endif | |||
| fFreewheel(false) | |||
| { | |||
| qDebug("CarlaEngineJack::CarlaEngineJack()"); | |||
| m_client = nullptr; | |||
| m_state = JackTransportStopped; | |||
| m_freewheel = false; | |||
| memset(&m_pos, 0, sizeof(jack_position_t)); | |||
| #ifdef BUILD_BRIDGE | |||
| m_hasQuit = false; | |||
| fOptions.processMode = PROCESS_MODE_MULTIPLE_CLIENTS; | |||
| #endif | |||
| carla_zeroStruct<jack_position_t>(fTransportPos); | |||
| } | |||
| ~CarlaEngineJack() | |||
| { | |||
| qDebug("CarlaEngineJack::~CarlaEngineJack()"); | |||
| CARLA_ASSERT(! m_client); | |||
| CARLA_ASSERT(fClient == nullptr); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| @@ -518,37 +522,39 @@ public: | |||
| { | |||
| qDebug("CarlaEngineJack::init(\"%s\")", clientName); | |||
| m_state = JackTransportStopped; | |||
| m_freewheel = false; | |||
| fFreewheel = false; | |||
| fTransportState = JackTransportStopped; | |||
| carla_zeroStruct<jack_position_t>(fTransportPos); | |||
| #ifndef BUILD_BRIDGE | |||
| m_client = jackbridge_client_open(clientName, JackNullOption, nullptr); | |||
| fClient = jackbridge_client_open(clientName, JackNullOption, nullptr); | |||
| if (m_client) | |||
| if (fClient) | |||
| { | |||
| fBufferSize = jackbridge_get_buffer_size(m_client); | |||
| fSampleRate = jackbridge_get_sample_rate(m_client); | |||
| fBufferSize = jackbridge_get_buffer_size(fClient); | |||
| fSampleRate = jackbridge_get_sample_rate(fClient); | |||
| jackbridge_set_buffer_size_callback(m_client, carla_jack_bufsize_callback, this); | |||
| jackbridge_set_sample_rate_callback(m_client, carla_jack_srate_callback, this); | |||
| jackbridge_set_freewheel_callback(m_client, carla_jack_freewheel_callback, this); | |||
| jackbridge_set_process_callback(m_client, carla_jack_process_callback, this); | |||
| jackbridge_set_latency_callback(m_client, carla_jack_latency_callback, this); | |||
| jackbridge_on_shutdown(m_client, carla_jack_shutdown_callback, this); | |||
| jackbridge_set_buffer_size_callback(fClient, carla_jack_bufsize_callback, this); | |||
| jackbridge_set_sample_rate_callback(fClient, carla_jack_srate_callback, this); | |||
| jackbridge_set_freewheel_callback(fClient, carla_jack_freewheel_callback, this); | |||
| jackbridge_set_process_callback(fClient, carla_jack_process_callback, this); | |||
| jackbridge_set_latency_callback(fClient, carla_jack_latency_callback, this); | |||
| jackbridge_on_shutdown(fClient, carla_jack_shutdown_callback, this); | |||
| if (fOptions.processMode == PROCESS_MODE_CONTINUOUS_RACK) | |||
| { | |||
| fRackPorts[rackPortAudioIn1] = jackbridge_port_register(m_client, "audio-in1", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); | |||
| fRackPorts[rackPortAudioIn2] = jackbridge_port_register(m_client, "audio-in2", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); | |||
| fRackPorts[rackPortAudioOut1] = jackbridge_port_register(m_client, "audio-out1", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); | |||
| fRackPorts[rackPortAudioOut2] = jackbridge_port_register(m_client, "audio-out2", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); | |||
| fRackPorts[rackPortEventIn] = jackbridge_port_register(m_client, "events-in", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0); | |||
| fRackPorts[rackPortEventOut] = jackbridge_port_register(m_client, "events-out", JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0); | |||
| fRackPorts[rackPortAudioIn1] = jackbridge_port_register(fClient, "audio-in1", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); | |||
| fRackPorts[rackPortAudioIn2] = jackbridge_port_register(fClient, "audio-in2", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); | |||
| fRackPorts[rackPortAudioOut1] = jackbridge_port_register(fClient, "audio-out1", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); | |||
| fRackPorts[rackPortAudioOut2] = jackbridge_port_register(fClient, "audio-out2", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); | |||
| fRackPorts[rackPortEventIn] = jackbridge_port_register(fClient, "events-in", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0); | |||
| fRackPorts[rackPortEventOut] = jackbridge_port_register(fClient, "events-out", JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0); | |||
| } | |||
| if (jackbridge_activate(m_client) == 0) | |||
| if (jackbridge_activate(fClient) == 0) | |||
| { | |||
| const char* const clientName = jackbridge_get_client_name(m_client); | |||
| const char* const clientName = jackbridge_get_client_name(fClient); | |||
| CarlaEngine::init(clientName); | |||
| return true; | |||
| @@ -556,7 +562,7 @@ public: | |||
| else | |||
| { | |||
| setLastError("Failed to activate the JACK client"); | |||
| m_client = nullptr; | |||
| fClient = nullptr; | |||
| } | |||
| } | |||
| else | |||
| @@ -567,15 +573,15 @@ public: | |||
| // open temp client to get initial buffer-size and sample-rate values | |||
| if (fBufferSize == 0 || fSampleRate == 0.0) | |||
| { | |||
| m_client = jackbridge_client_open(clientName, JackNullOption, nullptr); | |||
| fClient = jackbridge_client_open(clientName, JackNullOption, nullptr); | |||
| if (m_client) | |||
| if (fClient) | |||
| { | |||
| fBufferSize = jackbridge_get_buffer_size(m_client); | |||
| fSampleRate = jackbridge_get_sample_rate(m_client); | |||
| fBufferSize = jackbridge_get_buffer_size(fClient); | |||
| fSampleRate = jackbridge_get_sample_rate(fClient); | |||
| jackbridge_client_close(m_client); | |||
| m_client = nullptr; | |||
| jackbridge_client_close(fClient); | |||
| fClient = nullptr; | |||
| } | |||
| } | |||
| @@ -590,25 +596,25 @@ public: | |||
| CarlaEngine::close(); | |||
| #ifdef BUILD_BRIDGE | |||
| m_client = nullptr; | |||
| m_hasQuit = true; | |||
| fClient = nullptr; | |||
| fHasQuit = true; | |||
| return true; | |||
| #else | |||
| if (jackbridge_deactivate(m_client) == 0) | |||
| if (jackbridge_deactivate(fClient) == 0) | |||
| { | |||
| if (fOptions.processMode == PROCESS_MODE_CONTINUOUS_RACK) | |||
| { | |||
| jackbridge_port_unregister(m_client, fRackPorts[rackPortAudioIn1]); | |||
| jackbridge_port_unregister(m_client, fRackPorts[rackPortAudioIn2]); | |||
| jackbridge_port_unregister(m_client, fRackPorts[rackPortAudioOut1]); | |||
| jackbridge_port_unregister(m_client, fRackPorts[rackPortAudioOut2]); | |||
| jackbridge_port_unregister(m_client, fRackPorts[rackPortEventIn]); | |||
| jackbridge_port_unregister(m_client, fRackPorts[rackPortEventOut]); | |||
| jackbridge_port_unregister(fClient, fRackPorts[rackPortAudioIn1]); | |||
| jackbridge_port_unregister(fClient, fRackPorts[rackPortAudioIn2]); | |||
| jackbridge_port_unregister(fClient, fRackPorts[rackPortAudioOut1]); | |||
| jackbridge_port_unregister(fClient, fRackPorts[rackPortAudioOut2]); | |||
| jackbridge_port_unregister(fClient, fRackPorts[rackPortEventIn]); | |||
| jackbridge_port_unregister(fClient, fRackPorts[rackPortEventOut]); | |||
| } | |||
| if (jackbridge_client_close(m_client) == 0) | |||
| if (jackbridge_client_close(fClient) == 0) | |||
| { | |||
| m_client = nullptr; | |||
| fClient = nullptr; | |||
| return true; | |||
| } | |||
| else | |||
| @@ -617,7 +623,7 @@ public: | |||
| else | |||
| setLastError("Failed to deactivate the JACK client"); | |||
| m_client = nullptr; | |||
| fClient = nullptr; | |||
| #endif | |||
| return false; | |||
| } | |||
| @@ -625,15 +631,15 @@ public: | |||
| bool isRunning() const | |||
| { | |||
| #ifdef BUILD_BRIDGE | |||
| return bool(m_client || ! m_hasQuit); | |||
| return (fClient != nullptr || ! m_hasQuit); | |||
| #else | |||
| return bool(m_client); | |||
| return (fClient != nullptr); | |||
| #endif | |||
| } | |||
| bool isOffline() const | |||
| { | |||
| return m_freewheel; | |||
| return fFreewheel; | |||
| } | |||
| EngineType type() const | |||
| @@ -646,7 +652,7 @@ public: | |||
| jack_client_t* client = nullptr; | |||
| #ifdef BUILD_BRIDGE | |||
| client = m_client = jackbridge_client_open(plugin->name(), JackNullOption, nullptr); | |||
| client = fClient = jackbridge_client_open(plugin->name(), JackNullOption, nullptr); | |||
| fBufferSize = jackbridge_get_buffer_size(client); | |||
| fSampleRate = jackbridge_get_sample_rate(client); | |||
| @@ -660,7 +666,7 @@ public: | |||
| #else | |||
| if (fOptions.processMode == PROCESS_MODE_SINGLE_CLIENT) | |||
| { | |||
| client = m_client; | |||
| client = fClient; | |||
| } | |||
| else if (fOptions.processMode == PROCESS_MODE_MULTIPLE_CLIENTS) | |||
| { | |||
| @@ -682,57 +688,66 @@ public: | |||
| protected: | |||
| void handleJackBufferSizeCallback(const uint32_t newBufferSize) | |||
| { | |||
| fBufferSize = newBufferSize; | |||
| if (fBufferSize != newBufferSize) | |||
| { | |||
| fBufferSize = newBufferSize; | |||
| bufferSizeChanged(newBufferSize); | |||
| bufferSizeChanged(newBufferSize); | |||
| } | |||
| } | |||
| void handleJackSampleRateCallback(const double newSampleRate) | |||
| { | |||
| fSampleRate = newSampleRate; | |||
| if (fSampleRate != newSampleRate) | |||
| { | |||
| fSampleRate = newSampleRate; | |||
| sampleRateChanged(newSampleRate); | |||
| } | |||
| } | |||
| void handleJackFreewheelCallback(const bool isFreewheel) | |||
| { | |||
| m_freewheel = isFreewheel; | |||
| fFreewheel = isFreewheel; | |||
| } | |||
| void handleJackProcessCallback(const uint32_t nframes) | |||
| { | |||
| #ifndef BUILD_BRIDGE | |||
| if (currentPluginCount() == 0) | |||
| if (fData->curPluginCount == 0) | |||
| return; | |||
| #endif | |||
| m_pos.unique_1 = m_pos.unique_2 + 1; // invalidate | |||
| m_state = jackbridge_transport_query(m_client, &m_pos); | |||
| fTransportPos.unique_1 = fTransportPos.unique_2 + 1; // invalidate | |||
| fTransportState = jackbridge_transport_query(fClient, &fTransportPos); | |||
| fTimeInfo.playing = (m_state != JackTransportStopped); | |||
| fTimeInfo.playing = (fTransportState == JackTransportRolling); | |||
| if (m_pos.unique_1 == m_pos.unique_2) | |||
| if (fTransportPos.unique_1 == fTransportPos.unique_2) | |||
| { | |||
| fTimeInfo.frame = m_pos.frame; | |||
| fTimeInfo.time = m_pos.usecs; | |||
| fTimeInfo.frame = fTransportPos.frame; | |||
| fTimeInfo.time = fTransportPos.usecs; | |||
| if (m_pos.valid & JackPositionBBT) | |||
| if (fTransportPos.valid & JackPositionBBT) | |||
| { | |||
| fTimeInfo.valid = EngineTimeInfo::ValidBBT; | |||
| fTimeInfo.bbt.bar = m_pos.bar; | |||
| fTimeInfo.bbt.beat = m_pos.beat; | |||
| fTimeInfo.bbt.tick = m_pos.tick; | |||
| fTimeInfo.bbt.barStartTick = m_pos.bar_start_tick; | |||
| fTimeInfo.bbt.beatsPerBar = m_pos.beats_per_bar; | |||
| fTimeInfo.bbt.beatType = m_pos.beat_type; | |||
| fTimeInfo.bbt.ticksPerBeat = m_pos.ticks_per_beat; | |||
| fTimeInfo.bbt.beatsPerMinute = m_pos.beats_per_minute; | |||
| fTimeInfo.valid = EngineTimeInfo::ValidBBT; | |||
| fTimeInfo.bbt.bar = fTransportPos.bar; | |||
| fTimeInfo.bbt.beat = fTransportPos.beat; | |||
| fTimeInfo.bbt.tick = fTransportPos.tick; | |||
| fTimeInfo.bbt.barStartTick = fTransportPos.bar_start_tick; | |||
| fTimeInfo.bbt.beatsPerBar = fTransportPos.beats_per_bar; | |||
| fTimeInfo.bbt.beatType = fTransportPos.beat_type; | |||
| fTimeInfo.bbt.ticksPerBeat = fTransportPos.ticks_per_beat; | |||
| fTimeInfo.bbt.beatsPerMinute = fTransportPos.beats_per_minute; | |||
| } | |||
| else | |||
| fTimeInfo.valid = 0; | |||
| fTimeInfo.valid = 0x0; | |||
| } | |||
| else | |||
| { | |||
| fTimeInfo.frame = 0; | |||
| fTimeInfo.valid = 0; | |||
| fTimeInfo.valid = 0x0; | |||
| } | |||
| #ifdef BUILD_BRIDGE | |||
| @@ -744,9 +759,9 @@ protected: | |||
| processPlugin(plugin, nframes); | |||
| } | |||
| #else | |||
| if (options.processMode == PROCESS_MODE_SINGLE_CLIENT) | |||
| if (fOptions.processMode == PROCESS_MODE_SINGLE_CLIENT) | |||
| { | |||
| for (unsigned short i=0, max=maxPluginNumber(); i < max; i++) | |||
| for (unsigned int i=0; i < fData->curPluginCount; i++) | |||
| { | |||
| CarlaPlugin* const plugin = getPluginUnchecked(i); | |||
| @@ -757,32 +772,29 @@ protected: | |||
| } | |||
| } | |||
| } | |||
| else if (options.processMode == PROCESS_MODE_CONTINUOUS_RACK) | |||
| else if (fOptions.processMode == PROCESS_MODE_CONTINUOUS_RACK) | |||
| { | |||
| // get buffers from jack | |||
| float* audioIn1 = (float*)jackbridge_port_get_buffer(m_rackPorts[rackPortAudioIn1], nframes); | |||
| float* audioIn2 = (float*)jackbridge_port_get_buffer(m_rackPorts[rackPortAudioIn2], nframes); | |||
| float* audioOut1 = (float*)jackbridge_port_get_buffer(m_rackPorts[rackPortAudioOut1], nframes); | |||
| float* audioOut2 = (float*)jackbridge_port_get_buffer(m_rackPorts[rackPortAudioOut2], nframes); | |||
| void* controlIn = jackbridge_port_get_buffer(m_rackPorts[rackPortControlIn], nframes); | |||
| void* controlOut = jackbridge_port_get_buffer(m_rackPorts[rackPortControlOut], nframes); | |||
| void* midiIn = jackbridge_port_get_buffer(m_rackPorts[rackPortMidiIn], nframes); | |||
| void* midiOut = jackbridge_port_get_buffer(m_rackPorts[rackPortMidiOut], nframes); | |||
| float* const audioIn1 = (float*)jackbridge_port_get_buffer(fRackPorts[rackPortAudioIn1], nframes); | |||
| float* const audioIn2 = (float*)jackbridge_port_get_buffer(fRackPorts[rackPortAudioIn2], nframes); | |||
| float* const audioOut1 = (float*)jackbridge_port_get_buffer(fRackPorts[rackPortAudioOut1], nframes); | |||
| float* const audioOut2 = (float*)jackbridge_port_get_buffer(fRackPorts[rackPortAudioOut2], nframes); | |||
| void* const eventIn = jackbridge_port_get_buffer(fRackPorts[rackPortEventIn], nframes); | |||
| void* const eventOut = jackbridge_port_get_buffer(fRackPorts[rackPortEventOut], nframes); | |||
| // assert buffers | |||
| CARLA_ASSERT(audioIn1); | |||
| CARLA_ASSERT(audioIn2); | |||
| CARLA_ASSERT(audioOut1); | |||
| CARLA_ASSERT(audioOut2); | |||
| CARLA_ASSERT(controlIn); | |||
| CARLA_ASSERT(controlOut); | |||
| CARLA_ASSERT(midiIn); | |||
| CARLA_ASSERT(midiOut); | |||
| CARLA_ASSERT(audioIn1 != nullptr); | |||
| CARLA_ASSERT(audioIn2 != nullptr); | |||
| CARLA_ASSERT(audioOut1 != nullptr); | |||
| CARLA_ASSERT(audioOut2 != nullptr); | |||
| CARLA_ASSERT(eventIn != nullptr); | |||
| CARLA_ASSERT(eventOut != nullptr); | |||
| // create audio buffers | |||
| float* inBuf[2] = { audioIn1, audioIn2 }; | |||
| float* outBuf[2] = { audioOut1, audioOut2 }; | |||
| #if 0 | |||
| // initialize control input | |||
| memset(rackControlEventsIn, 0, sizeof(CarlaEngineControlEvent)*MAX_CONTROL_EVENTS); | |||
| { | |||
| @@ -859,10 +871,12 @@ protected: | |||
| } | |||
| } | |||
| } | |||
| #endif | |||
| // process rack | |||
| processRack(inBuf, outBuf, nframes); | |||
| #if 0 | |||
| // output control | |||
| { | |||
| jackbridge_midi_clear_buffer(controlOut); | |||
| @@ -923,6 +937,7 @@ protected: | |||
| jackbridge_midi_event_write(midiOut, rackMidiEventsOut[i].time, rackMidiEventsOut[i].data, rackMidiEventsOut[i].size); | |||
| } | |||
| } | |||
| #endif | |||
| } | |||
| #endif | |||
| @@ -936,7 +951,7 @@ protected: | |||
| return; | |||
| #endif | |||
| for (unsigned short i=0, max=maxPluginNumber(); i < max; i++) | |||
| for (unsigned int i=0; i < fData->curPluginCount; i++) | |||
| { | |||
| CarlaPlugin* const plugin = getPluginUnchecked(i); | |||
| @@ -947,7 +962,7 @@ protected: | |||
| void handleJackShutdownCallback() | |||
| { | |||
| for (unsigned short i=0, max=maxPluginNumber(); i < max; i++) | |||
| for (unsigned int i=0; i < fData->curPluginCount; i++) | |||
| { | |||
| //CarlaPlugin* const plugin = getPluginUnchecked(i); | |||
| @@ -955,22 +970,21 @@ protected: | |||
| // plugin->x_client = nullptr; | |||
| } | |||
| m_client = nullptr; | |||
| fClient = nullptr; | |||
| callback(CALLBACK_QUIT, 0, 0, 0, 0.0f, nullptr); | |||
| } | |||
| // ------------------------------------- | |||
| private: | |||
| jack_client_t* m_client; | |||
| jack_transport_state_t m_state; | |||
| jack_position_t m_pos; | |||
| bool m_freewheel; | |||
| jack_client_t* fClient; | |||
| jack_position_t fTransportPos; | |||
| jack_transport_state_t fTransportState; | |||
| // ------------------------------------- | |||
| #ifdef BUILD_BRIDGE | |||
| bool m_hasQuit; | |||
| bool fHasQuit; | |||
| #else | |||
| enum RackPorts { | |||
| rackPortAudioIn1 = 0, | |||
| @@ -985,6 +999,8 @@ private: | |||
| jack_port_t* fRackPorts[rackPortCount]; | |||
| #endif | |||
| bool fFreewheel; | |||
| // ------------------------------------- | |||
| static void processPlugin(CarlaPlugin* const p, const uint32_t nframes) | |||
| @@ -1096,10 +1112,8 @@ private: | |||
| if (plugin && plugin->enabled()) | |||
| { | |||
| //plugin->engineProcessLock(); | |||
| plugin->initBuffers(); | |||
| processPlugin(plugin, nframes); | |||
| //plugin->engineProcessUnlock(); | |||
| } | |||
| return 0; | |||
| @@ -430,7 +430,7 @@ protected: | |||
| void d_activate() | |||
| { | |||
| #if 0 | |||
| for (unsigned short i=0, max=maxPluginNumber(); i < max; i++) | |||
| for (unsigned int i=0; i < fData->curPluginCount; i++) | |||
| { | |||
| CarlaPlugin* const plugin = getPluginUnchecked(i); | |||
| @@ -445,7 +445,7 @@ protected: | |||
| void d_deactivate() | |||
| { | |||
| #if 0 | |||
| for (unsigned short i=0, max=maxPluginNumber(); i < max; i++) | |||
| for (unsigned int i=0; i < fData->curPluginCount; i++) | |||
| { | |||
| CarlaPlugin* const plugin = getPluginUnchecked(i); | |||
| @@ -30,11 +30,11 @@ endif | |||
| OBJS = \ | |||
| carla_plugin.cpp.o \ | |||
| native.cpp.o | |||
| native.cpp.o \ | |||
| ladspa.cpp.o | |||
| # carla_plugin_thread.cpp.o \ | |||
| # carla_bridge.cpp.o \ | |||
| # ladspa.cpp.o \ | |||
| # dssi.cpp.o \ | |||
| # lv2.cpp.o \ | |||
| # vst.cpp.o \ | |||
| @@ -1231,7 +1231,7 @@ void CarlaPlugin::postRtEventsRun() | |||
| // Update OSC control client | |||
| if (fData->engine->isOscControlRegistered()) | |||
| { | |||
| fData->engine->osc_send_control_set_program(m_id, event->value1); | |||
| fData->engine->osc_send_control_set_program(fData->id, event->value1); | |||
| for (uint32_t j=0; j < fData->param.count; j++) | |||
| fData->engine->osc_send_control_set_default_value(fData->id, j, fData->param.ranges[j].def); | |||
| @@ -1253,7 +1253,7 @@ void CarlaPlugin::postRtEventsRun() | |||
| { | |||
| fData->engine->osc_send_control_set_midi_program(fData->id, event->value1); | |||
| for (uint32_t j=0; j < param.count; j++) | |||
| for (uint32_t j=0; j < fData->param.count; j++) | |||
| fData->engine->osc_send_control_set_default_value(fData->id, j, fData->param.ranges[j].def); | |||
| } | |||
| #endif | |||
| @@ -1668,11 +1668,13 @@ std::vector<const PluginDescriptor*> NativePlugin::pluginDescriptors; | |||
| // ----------------------------------------------------------------------- | |||
| #if 0 | |||
| CarlaPlugin* CarlaPlugin::newNative(const initializer& init) | |||
| CarlaPlugin* CarlaPlugin::newNative(const Initializer& init) | |||
| { | |||
| qDebug("CarlaPlugin::newNative(%p, \"%s\", \"%s\", \"%s\")", init.engine, init.filename, init.name, init.label); | |||
| return nullptr; | |||
| #if 0 | |||
| short id = init.engine->getNewPluginId(); | |||
| if (id < 0 || id > init.engine->maxPluginNumber()) | |||
| @@ -1704,8 +1706,8 @@ CarlaPlugin* CarlaPlugin::newNative(const initializer& init) | |||
| plugin->registerToOscClient(); | |||
| return plugin; | |||
| } | |||
| #endif | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| @@ -51,6 +51,7 @@ endif | |||
| LIBS = ../libcarla_engine.a | |||
| LIBS += ../libcarla_plugin.a | |||
| LIBS += ../libcarla_native.a | |||
| LIBS += ../../libs/rtmempool.a | |||
| OBJS = \ | |||
| carla_standalone.cpp.o | |||
| @@ -201,7 +201,8 @@ bool carla_engine_init(const char* driverName, const char* clientName) | |||
| } | |||
| #endif | |||
| standalone.engine->setCallback(standalone.callback, nullptr); | |||
| if (standalone.callback != nullptr) | |||
| standalone.engine->setCallback(standalone.callback, nullptr); | |||
| standalone.engine->setOption(CarlaBackend::OPTION_PROCESS_MODE, standalone.options.processMode, nullptr); | |||
| standalone.engine->setOption(CarlaBackend::OPTION_FORCE_STEREO, standalone.options.forceStereo, nullptr); | |||
| @@ -25,19 +25,19 @@ import sys | |||
| from codecs import open as codecopen | |||
| from copy import deepcopy | |||
| #from decimal import Decimal | |||
| from PyQt4.QtCore import pyqtSlot, qWarning, Qt, QSettings, QTimer, SIGNAL, SLOT | |||
| from PyQt4.QtCore import pyqtSlot, qWarning, Qt, QByteArray, QSettings, QTimer, SIGNAL, SLOT | |||
| #pyqtSlot, qFatal, | |||
| from PyQt4.QtGui import QDialog, QIcon, QMessageBox, QWidget | |||
| #from PyQt4.QtGui import QColor, QCursor, QFontMetrics, QFrame, QGraphicsScene, QInputDialog, QLinearGradient, QMenu, QPainter, QPainterPath, QVBoxLayout | |||
| from PyQt4.QtGui import QColor, QDialog, QIcon, QFontMetrics, QFrame, QMessageBox, QPainter, QPainterPath, QVBoxLayout, QWidget | |||
| #from PyQt4.QtGui import QCursor, QGraphicsScene, QInputDialog, QLinearGradient, QMenu, | |||
| #from PyQt4.QtXml import QDomDocument | |||
| # ------------------------------------------------------------------------------------------------------------ | |||
| # Imports (Custom) | |||
| import ui_carla_about | |||
| #import ui_carla_edit | |||
| import ui_carla_edit | |||
| import ui_carla_parameter | |||
| #import ui_carla_plugin | |||
| import ui_carla_plugin | |||
| # ------------------------------------------------------------------------------------------------------------ | |||
| # Try Import Signal | |||
| @@ -398,7 +398,7 @@ CarlaStateParameter = { | |||
| } | |||
| CarlaStateCustomData = { | |||
| 'type': None, #CUSTOM_DATA_INVALID, | |||
| 'type': "", | |||
| 'key': "", | |||
| 'value': "" | |||
| } | |||
| @@ -842,6 +842,10 @@ class PluginParameter(QWidget): | |||
| self.fMidiChannel = channel | |||
| self.ui.sb_channel.setValue(channel) | |||
| def setLabelWidth(self, width): | |||
| self.ui.label.setMinimumWidth(width) | |||
| self.ui.label.setMaximumWidth(width) | |||
| def tabIndex(self): | |||
| return self.fTabIndex | |||
| @@ -883,6 +887,598 @@ class PluginParameter(QWidget): | |||
| def _textCallBack(self): | |||
| return cString(Carla.host.get_parameter_text(self.fPluginId, self.fParameterId)) | |||
| # ------------------------------------------------------------------------------------------------------------ | |||
| # Plugin Editor (Built-in) | |||
| class PluginEdit(QDialog): | |||
| def __init__(self, parent, pluginId): | |||
| QDialog.__init__(self, Carla.gui) | |||
| self.ui = ui_carla_edit.Ui_PluginEdit() | |||
| self.ui.setupUi(self) | |||
| self.fGeometry = QByteArray() | |||
| self.fPluginId = pluginId | |||
| self.fPuginInfo = None | |||
| self.fRealParent = parent | |||
| self.fCurrentProgram = -1 | |||
| self.fCurrentMidiProgram = -1 | |||
| self.fCurrentStateFilename = None | |||
| self.fParameterCount = 0 | |||
| self.fParameterList = [] # (type, id, widget) | |||
| self.fParameterIdsToUpdate = [] # id | |||
| self.fTabIconOff = QIcon(":/bitmaps/led_off.png") | |||
| self.fTabIconOn = QIcon(":/bitmaps/led_yellow.png") | |||
| self.fTabIconCount = 0 | |||
| self.fTabIconTimers = [] | |||
| self.ui.keyboard.setMode(self.ui.keyboard.HORIZONTAL) | |||
| self.ui.keyboard.setOctaves(6) | |||
| self.ui.scrollArea.ensureVisible(self.ui.keyboard.width() * 1 / 5, 0) | |||
| self.ui.scrollArea.setVisible(False) | |||
| # TODO - not implemented yet | |||
| self.ui.b_reload_program.setEnabled(False) | |||
| self.ui.b_reload_midi_program.setEnabled(False) | |||
| # Not available for carla-control | |||
| if Carla.isControl: | |||
| self.ui.b_load_state.setEnabled(False) | |||
| self.ui.b_save_state.setEnabled(False) | |||
| else: | |||
| self.connect(self.ui.b_save_state, SIGNAL("clicked()"), SLOT("slot_saveState()")) | |||
| self.connect(self.ui.b_load_state, SIGNAL("clicked()"), SLOT("slot_loadState()")) | |||
| self.connect(self.ui.keyboard, SIGNAL("noteOn(int)"), SLOT("slot_noteOn(int)")) | |||
| self.connect(self.ui.keyboard, SIGNAL("noteOff(int)"), SLOT("slot_noteOff(int)")) | |||
| self.connect(self.ui.cb_programs, SIGNAL("currentIndexChanged(int)"), SLOT("slot_programIndexChanged(int)")) | |||
| self.connect(self.ui.cb_midi_programs, SIGNAL("currentIndexChanged(int)"), SLOT("slot_midiProgramIndexChanged(int)")) | |||
| self.connect(self, SIGNAL("finished(int)"), SLOT("slot_finished()")) | |||
| #self.reloadAll() | |||
| def reloadAll(self): | |||
| self.fPluginInfo = Carla.host.get_plugin_info(self.fPluginId) | |||
| self.fPluginInfo["binary"] = cString(self.fPluginInfo["binary"]) | |||
| self.fPluginInfo["name"] = cString(self.fPluginInfo["name"]) | |||
| self.fPluginInfo["label"] = cString(self.fPluginInfo["label"]) | |||
| self.fPluginInfo["maker"] = cString(self.fPluginInfo["maker"]) | |||
| self.fPluginInfo["copyright"] = cString(self.fPluginInfo["copyright"]) | |||
| self.reloadInfo() | |||
| self.reloadParameters() | |||
| self.reloadPrograms() | |||
| def reloadInfo(self): | |||
| pluginName = cString(Carla.host.get_real_plugin_name(self.fPluginId)) | |||
| pluginType = self.fPluginInfo['type'] | |||
| pluginHints = self.fPluginInfo['hints'] | |||
| # Automatically change to MidiProgram tab | |||
| if pluginType != PLUGIN_VST and not self.ui.le_name.text(): | |||
| self.ui.tab_programs.setCurrentIndex(1) | |||
| # Set Meta-Data | |||
| if pluginType == PLUGIN_INTERNAL: | |||
| self.ui.le_type.setText(self.tr("Internal")) | |||
| elif pluginType == PLUGIN_LADSPA: | |||
| self.ui.le_type.setText("LADSPA") | |||
| elif pluginType == PLUGIN_DSSI: | |||
| self.ui.le_type.setText("DSSI") | |||
| elif pluginType == PLUGIN_LV2: | |||
| self.ui.le_type.setText("LV2") | |||
| elif pluginType == PLUGIN_VST: | |||
| self.ui.le_type.setText("VST") | |||
| elif pluginType == PLUGIN_GIG: | |||
| self.ui.le_type.setText("GIG") | |||
| elif pluginType == PLUGIN_SF2: | |||
| self.ui.le_type.setText("SF2") | |||
| elif pluginType == PLUGIN_SFZ: | |||
| self.ui.le_type.setText("SFZ") | |||
| else: | |||
| self.ui.le_type.setText(self.tr("Unknown")) | |||
| self.ui.le_name.setText(pluginName) | |||
| self.ui.le_name.setToolTip(pluginName) | |||
| self.ui.le_label.setText(self.fPluginInfo['label']) | |||
| self.ui.le_label.setToolTip(self.fPluginInfo['label']) | |||
| self.ui.le_maker.setText(self.fPluginInfo['maker']) | |||
| self.ui.le_maker.setToolTip(self.fPluginInfo['maker']) | |||
| self.ui.le_copyright.setText(self.fPluginInfo['copyright']) | |||
| self.ui.le_copyright.setToolTip(self.fPluginInfo['copyright']) | |||
| self.ui.le_unique_id.setText(str(self.fPluginInfo['uniqueId'])) | |||
| self.ui.le_unique_id.setToolTip(str(self.fPluginInfo['uniqueId'])) | |||
| self.ui.label_plugin.setText("\n%s\n" % self.fPluginInfo['name']) | |||
| self.setWindowTitle(self.fPluginInfo['name']) | |||
| # Set Processing Data | |||
| audioCountInfo = Carla.host.get_audio_port_count_info(self.fPluginId) | |||
| midiCountInfo = Carla.host.get_midi_port_count_info(self.fPluginId) | |||
| paramCountInfo = Carla.host.get_parameter_count_info(self.fPluginId) | |||
| self.ui.le_ains.setText(str(audioCountInfo['ins'])) | |||
| self.ui.le_aouts.setText(str(audioCountInfo['outs'])) | |||
| self.ui.le_params.setText(str(paramCountInfo['ins'])) | |||
| self.ui.le_couts.setText(str(paramCountInfo['outs'])) | |||
| self.ui.le_is_synth.setText(self.tr("Yes") if (pluginHints & PLUGIN_IS_SYNTH) else self.tr("No")) | |||
| self.ui.le_has_gui.setText(self.tr("Yes") if (pluginHints & PLUGIN_HAS_GUI) else self.tr("No")) | |||
| # Show/hide keyboard | |||
| self.ui.scrollArea.setVisible((pluginHints & PLUGIN_IS_SYNTH) != 0 or (midiCountInfo['ins'] > 0 < midiCountInfo['outs'])) | |||
| # Force-Update parent for new hints (knobs) | |||
| if self.fRealParent: | |||
| self.fRealParent.recheckPluginHints(pluginHints) | |||
| def reloadParameters(self): | |||
| parameterCount = Carla.host.get_parameter_count(self.m_pluginId) | |||
| # Reset | |||
| self.fParameterCount = 0 | |||
| self.fParameterList = [] | |||
| self.fParameterIdsToUpdate = [] | |||
| self.fTabIconCount = 0 | |||
| self.fTabIconTimers = [] | |||
| # Remove all previous parameters | |||
| for i in range(self.ui.tabWidget.count()-1): | |||
| self.ui.tabWidget.widget(1).deleteLater() | |||
| self.ui.tabWidget.removeTab(1) | |||
| if parameterCount <= 0: | |||
| pass | |||
| elif parameterCount <= Carla.maxParameters: | |||
| paramInputListFull = [] | |||
| paramOutputListFull = [] | |||
| paramInputList = [] # ([params], width) | |||
| paramInputWidth = 0 | |||
| paramOutputList = [] # ([params], width) | |||
| paramOutputWidth = 0 | |||
| for i in range(parameterCount): | |||
| paramInfo = Carla.host.get_parameter_info(self.fPluginId, i) | |||
| paramData = Carla.host.get_parameter_data(self.fPluginId, i) | |||
| paramRanges = Carla.host.get_parameter_ranges(self.fPluginId, i) | |||
| if paramData['type'] not in (PARAMETER_INPUT, PARAMETER_OUTPUT): | |||
| continue | |||
| parameter = { | |||
| 'type': paramData['type'], | |||
| 'hints': paramData['hints'], | |||
| 'name': cString(paramInfo['name']), | |||
| 'unit': cString(paramInfo['unit']), | |||
| 'scalePoints': [], | |||
| 'index': paramData['index'], | |||
| 'default': paramRanges['def'], | |||
| 'minimum': paramRanges['min'], | |||
| 'maximum': paramRanges['max'], | |||
| 'step': paramRanges['step'], | |||
| 'stepSmall': paramRanges['stepSmall'], | |||
| 'stepLarge': paramRanges['stepLarge'], | |||
| 'midiCC': paramData['midiCC'], | |||
| 'midiChannel': paramData['midiChannel'], | |||
| 'current': Carla.host.get_current_parameter_value(self.fPluginId, i) | |||
| } | |||
| for j in range(paramInfo['scalePointCount']): | |||
| scalePointInfo = Carla.host.get_parameter_scalepoint_info(self.fPluginId, i, j) | |||
| parameter['scalepoints'].append( | |||
| { | |||
| 'value': scalePointInfo['value'], | |||
| 'label': cString(scalePointInfo['label']) | |||
| }) | |||
| paramInputList.append(parameter) | |||
| # ----------------------------------------------------------------- | |||
| # Get width values, in packs of 10 | |||
| if parameter['type'] == PARAMETER_INPUT: | |||
| paramInputWidthTMP = QFontMetrics(self.font()).width(parameter['name']) | |||
| if paramInputWidthTMP > paramInputWidth: | |||
| paramInputWidth = paramInputWidthTMP | |||
| if len(paramInputList) == 10: | |||
| paramInputListFull.append((paramInputList, paramInputWidth)) | |||
| paramInputList = [] | |||
| paramInputWidth = 0 | |||
| else: | |||
| paramOutputWidthTMP = QFontMetrics(self.font()).width(parameter['name']) | |||
| if paramOutputWidthTMP > paramOutputWidth: | |||
| paramOutputWidth = paramOutputWidthTMP | |||
| if len(paramOutputList) == 10: | |||
| paramOutputListFull.append((paramOutputList, paramOutputWidth)) | |||
| paramOutputList = [] | |||
| paramOutputWidth = 0 | |||
| # for i in range(parameterCount) | |||
| else: | |||
| # Final page width values | |||
| if 0 < len(paramInputList) < 10: | |||
| paramInputListFull.append((paramInputList, paramInputWidth)) | |||
| if 0 < len(paramOutputList) < 10: | |||
| paramOutputListFull.append((paramOutputList, paramOutputWidth)) | |||
| # ----------------------------------------------------------------- | |||
| # Create parameter widgets | |||
| self._createParameterWidgets(PARAMETER_INPUT, paramInputListFull, self.tr("Parameters")) | |||
| self._createParameterWidgets(PARAMETER_OUTPUT, paramOutputListFull, self.tr("Outputs")) | |||
| else: # > Carla.maxParameters | |||
| fakeName = self.tr("This plugin has too many parameters to display here!") | |||
| paramFakeListFull = [] | |||
| paramFakeList = [] | |||
| paramFakeWidth = QFontMetrics(self.font()).width(fakeName) | |||
| parameter = { | |||
| 'type': PARAMETER_UNKNOWN, | |||
| 'hints': 0, | |||
| 'name': fakeName, | |||
| 'unit': "", | |||
| 'scalepoints': [], | |||
| 'index': 0, | |||
| 'default': 0, | |||
| 'minimum': 0, | |||
| 'maximum': 0, | |||
| 'step': 0, | |||
| 'stepSmall': 0, | |||
| 'stepLarge': 0, | |||
| 'midiCC': -1, | |||
| 'midiChannel': 0, | |||
| 'current': 0.0 | |||
| } | |||
| paramFakeList.append(parameter) | |||
| paramFakeListFull.append((paramFakeList, paramFakeWidth)) | |||
| self.createParameterWidgets(PARAMETER_UNKNOWN, paramFakeListFull, self.tr("Information")) | |||
| def reloadPrograms(self): | |||
| # Programs | |||
| self.ui.cb_programs.blockSignals(True) | |||
| self.ui.cb_programs.clear() | |||
| programCount = Carla.host.get_program_count(self.fPluginId) | |||
| if programCount > 0: | |||
| self.ui.cb_programs.setEnabled(True) | |||
| for i in range(programCount): | |||
| pName = cString(Carla.host.get_program_name(self.fPluginId, i)) | |||
| self.ui.cb_programs.addItem(pName) | |||
| self.fCurrentProgram = Carla.host.get_current_program_index(self.fPluginId) | |||
| self.ui.cb_programs.setCurrentIndex(self.fCurrentProgram) | |||
| else: | |||
| self.fCurrentProgram = -1 | |||
| self.ui.cb_programs.setEnabled(False) | |||
| self.ui.cb_programs.blockSignals(False) | |||
| # MIDI Programs | |||
| self.ui.cb_midi_programs.blockSignals(True) | |||
| self.ui.cb_midi_programs.clear() | |||
| midiProgramCount = Carla.host.get_midi_program_count(self.fPluginId) | |||
| if midiProgramCount > 0: | |||
| self.ui.cb_midi_programs.setEnabled(True) | |||
| for i in range(midiProgramCount): | |||
| mpData = Carla.host.get_midi_program_data(self.fPluginId, i) | |||
| mpBank = int(mpData['bank']) | |||
| mpProg = int(mpData['program']) | |||
| mpLabel = cString(mpData['label']) | |||
| self.ui.cb_midi_programs.addItem("%03i:%03i - %s" % (mpBank, mpProg, mpLabel)) | |||
| self.fCurrentMidiProgram = Carla.host.get_current_midi_program_index(self.fPluginId) | |||
| self.ui.cb_midi_programs.setCurrentIndex(self.fCurrentMidiProgram) | |||
| else: | |||
| self.fCurrentMidiProgram = -1 | |||
| self.ui.cb_midi_programs.setEnabled(False) | |||
| self.ui.cb_midi_programs.blockSignals(False) | |||
| def setVisible(self, yesNo): | |||
| if yesNo: | |||
| if not self.fGeometry.isNull(): | |||
| self.restoreGeometry(self.fGeometry) | |||
| else: | |||
| self.fGeometry = self.saveGeometry() | |||
| QDialog.setVisible(self, yesNo) | |||
| @pyqtSlot(int, float) | |||
| def slot_parameterValueChanged(self, parameterId, value): | |||
| Carla.host.set_parameter_value(self.fPluginId, parameterId, value) | |||
| @pyqtSlot(int, int) | |||
| def slot_parameterMidiChannelChanged(self, parameterId, channel): | |||
| Carla.host.set_parameter_midi_channel(self.fPluginId, parameterId, channel-1) | |||
| @pyqtSlot(int, int) | |||
| def slot_parameterMidiCcChanged(self, parameterId, cc): | |||
| Carla.host.set_parameter_midi_cc(self.fPluginId, parameterId, cc) | |||
| @pyqtSlot(int) | |||
| def slot_programIndexChanged(self, index): | |||
| if self.fCurrentProgram != index: | |||
| self.fCurrentProgram = index | |||
| Carla.host.set_program(self.fPluginId, index) | |||
| @pyqtSlot(int) | |||
| def slot_midiProgramIndexChanged(self, index): | |||
| if self.fCurrentMidiProgram != index: | |||
| self.fCurrentMidiProgram = index | |||
| Carla.host.set_midi_program(self.fPluginId, index) | |||
| @pyqtSlot(int) | |||
| def slot_noteOn(self, note): | |||
| Carla.host.send_midi_note(self.fPluginId, 0, note, 100) | |||
| @pyqtSlot(int) | |||
| def slot_noteOff(self, note): | |||
| Carla.host.send_midi_note(self.fPluginId, 0, note, 0) | |||
| @pyqtSlot() | |||
| def slot_notesOn(self): | |||
| if self.fRealParent: | |||
| self.fRealParent.led_midi.setChecked(True) | |||
| @pyqtSlot() | |||
| def slot_notesOff(self): | |||
| if self.fRealParent: | |||
| self.fRealParent.led_midi.setChecked(False) | |||
| @pyqtSlot() | |||
| def slot_finished(self): | |||
| if self.fRealParent: | |||
| self.fRealParent.editClosed() | |||
| def _createParameterWidgets(self, paramType, paramListFull, tabPageName): | |||
| i = 1 | |||
| for paramList, width in paramListFull: | |||
| if len(paramList) == 0: | |||
| break | |||
| tabIndex = self.ui.tabWidget.count() | |||
| tabPageContainer = QWidget(self.ui.tabWidget) | |||
| tabPageLayout = QVBoxLayout(tabPageContainer) | |||
| tabPageContainer.setLayout(tabPageLayout) | |||
| for paramInfo in paramList: | |||
| paramWidget = PluginParameter(tabPageContainer, paramInfo, self.fPluginId, tabIndex) | |||
| paramWidget.setLabelWidth(width) | |||
| tabPageLayout.addWidget(paramWidget) | |||
| self.fParameterList.append((paramType, paramInfo['index'], paramWidget)) | |||
| if paramType == PARAMETER_INPUT: | |||
| self.connect(paramWidget, SIGNAL("valueChanged(int, double)"), SLOT("slot_parameterValueChanged(int, double)")) | |||
| self.connect(paramWidget, SIGNAL("midiChannelChanged(int, int)"), SLOT("slot_parameterMidiChannelChanged(int, int)")) | |||
| self.connect(paramWidget, SIGNAL("midiCcChanged(int, int)"), SLOT("slot_parameterMidiCcChanged(int, int)")) | |||
| tabPageLayout.addStretch() | |||
| self.ui.tabWidget.addTab(tabPageContainer, "%s (%i)" % (tabPageName, i)) | |||
| i += 1 | |||
| if paramType == PARAMETER_INPUT: | |||
| self.ui.tabWidget.setTabIcon(tabIndex, self.fTabIconOff) | |||
| self.fTabIconTimers.append(ICON_STATE_NULL) | |||
| def done(self, r): | |||
| QDialog.done(self, r) | |||
| self.close() | |||
| # ------------------------------------------------------------------------------------------------------------ | |||
| # Plugin Widget | |||
| class PluginWidget(QFrame): | |||
| def __init__(self, parent, pluginId): | |||
| QFrame.__init__(self, parent) | |||
| self.ui = ui_carla_plugin.Ui_PluginWidget() | |||
| self.ui.setupUi(self) | |||
| self.fPluginId = pluginId | |||
| #self.fPluginInfo = Carla.host.get_plugin_info(self.fPluginId) | |||
| #self.fPluginInfo["binary"] = cString(self.fPluginInfo["binary"]) | |||
| #self.fPluginInfo["name"] = cString(self.fPluginInfo["name"]) | |||
| #self.fPluginInfo["label"] = cString(self.fPluginInfo["label"]) | |||
| #self.fPluginInfo["maker"] = cString(self.fPluginInfo["maker"]) | |||
| #self.fPluginInfo["copyright"] = cString(self.fPluginInfo["copyright"]) | |||
| self.fParameterIconTimer = ICON_STATE_NULL | |||
| self.fLastGreenLedState = False | |||
| self.fLastBlueLedState = False | |||
| if Carla.processMode == PROCESS_MODE_CONTINUOUS_RACK: | |||
| self.fPeaksInputCount = 2 | |||
| self.fPeaksOutputCount = 2 | |||
| #self.ui.stackedWidget.setCurrentIndex(0) | |||
| else: | |||
| audioCountInfo = Carla.host.get_audio_port_count_info(self.fPluginId) | |||
| self.fPeaksInputCount = int(audioCountInfo['ins']) | |||
| self.fPeaksOutputCount = int(audioCountInfo['outs']) | |||
| if self.fPeaksInputCount > 2: | |||
| self.fPeaksInputCount = 2 | |||
| if self.fPeaksOutputCount > 2: | |||
| self.fPeaksOutputCount = 2 | |||
| #if audioCountInfo['total'] == 0: | |||
| #self.ui.stackedWidget.setCurrentIndex(1) | |||
| #else: | |||
| #self.ui.stackedWidget.setCurrentIndex(0) | |||
| # Background | |||
| self.fColorTop = QColor(60, 60, 60) | |||
| self.fColorBottom = QColor(47, 47, 47) | |||
| # Colorify | |||
| #if self.m_pluginInfo['category'] == PLUGIN_CATEGORY_SYNTH: | |||
| #self.setWidgetColor(PALETTE_COLOR_WHITE) | |||
| #elif self.m_pluginInfo['category'] == PLUGIN_CATEGORY_DELAY: | |||
| #self.setWidgetColor(PALETTE_COLOR_ORANGE) | |||
| #elif self.m_pluginInfo['category'] == PLUGIN_CATEGORY_EQ: | |||
| #self.setWidgetColor(PALETTE_COLOR_GREEN) | |||
| #elif self.m_pluginInfo['category'] == PLUGIN_CATEGORY_FILTER: | |||
| #self.setWidgetColor(PALETTE_COLOR_BLUE) | |||
| #elif self.m_pluginInfo['category'] == PLUGIN_CATEGORY_DYNAMICS: | |||
| #self.setWidgetColor(PALETTE_COLOR_PINK) | |||
| #elif self.m_pluginInfo['category'] == PLUGIN_CATEGORY_MODULATOR: | |||
| #self.setWidgetColor(PALETTE_COLOR_RED) | |||
| #elif self.m_pluginInfo['category'] == PLUGIN_CATEGORY_UTILITY: | |||
| #self.setWidgetColor(PALETTE_COLOR_YELLOW) | |||
| #elif self.m_pluginInfo['category'] == PLUGIN_CATEGORY_OTHER: | |||
| #self.setWidgetColor(PALETTE_COLOR_BROWN) | |||
| #else: | |||
| #self.setWidgetColor(PALETTE_COLOR_NONE) | |||
| self.ui.led_enable.setColor(self.ui.led_enable.BIG_RED) | |||
| self.ui.led_enable.setChecked(False) | |||
| self.ui.led_control.setColor(self.ui.led_control.YELLOW) | |||
| self.ui.led_control.setEnabled(False) | |||
| self.ui.led_midi.setColor(self.ui.led_midi.RED) | |||
| self.ui.led_midi.setEnabled(False) | |||
| self.ui.led_audio_in.setColor(self.ui.led_audio_in.GREEN) | |||
| self.ui.led_audio_in.setEnabled(False) | |||
| self.ui.led_audio_out.setColor(self.ui.led_audio_out.BLUE) | |||
| self.ui.led_audio_out.setEnabled(False) | |||
| self.ui.dial_drywet.setPixmap(3) | |||
| self.ui.dial_vol.setPixmap(3) | |||
| self.ui.dial_b_left.setPixmap(4) | |||
| self.ui.dial_b_right.setPixmap(4) | |||
| self.ui.dial_drywet.setCustomPaint(self.ui.dial_drywet.CUSTOM_PAINT_CARLA_WET) | |||
| self.ui.dial_vol.setCustomPaint(self.ui.dial_vol.CUSTOM_PAINT_CARLA_VOL) | |||
| self.ui.dial_b_left.setCustomPaint(self.ui.dial_b_left.CUSTOM_PAINT_CARLA_L) | |||
| self.ui.dial_b_right.setCustomPaint(self.ui.dial_b_right.CUSTOM_PAINT_CARLA_R) | |||
| self.ui.peak_in.setColor(self.ui.peak_in.GREEN) | |||
| self.ui.peak_in.setOrientation(self.ui.peak_in.HORIZONTAL) | |||
| self.ui.peak_out.setColor(self.ui.peak_in.BLUE) | |||
| self.ui.peak_out.setOrientation(self.ui.peak_out.HORIZONTAL) | |||
| self.ui.peak_in.setChannels(self.fPeaksInputCount) | |||
| self.ui.peak_out.setChannels(self.fPeaksOutputCount) | |||
| #self.ui.label_name.setText(self.fPluginInfo['name']) | |||
| self.ui.edit_dialog = PluginEdit(self, self.fPluginId) | |||
| self.ui.edit_dialog.hide() | |||
| #self.connect(self.ui.led_enable, SIGNAL("clicked(bool)"), SLOT("slot_setActive(bool)")) | |||
| #self.connect(self.ui.dial_drywet, SIGNAL("sliderMoved(int)"), SLOT("slot_setDryWet(int)")) | |||
| #self.connect(self.ui.dial_vol, SIGNAL("sliderMoved(int)"), SLOT("slot_setVolume(int)")) | |||
| #self.connect(self.ui.dial_b_left, SIGNAL("sliderMoved(int)"), SLOT("slot_setBalanceLeft(int)")) | |||
| #self.connect(self.ui.dial_b_right, SIGNAL("sliderMoved(int)"), SLOT("slot_setBalanceRight(int)")) | |||
| #self.connect(self.ui.b_gui, SIGNAL("clicked(bool)"), SLOT("slot_guiClicked(bool)")) | |||
| self.connect(self.ui.b_edit, SIGNAL("clicked(bool)"), SLOT("slot_editClicked(bool)")) | |||
| #self.connect(self.ui.b_remove, SIGNAL("clicked()"), SLOT("slot_removeClicked()")) | |||
| #self.connect(self.ui.dial_drywet, SIGNAL("customContextMenuRequested(QPoint)"), SLOT("slot_showCustomDialMenu()")) | |||
| #self.connect(self.ui.dial_vol, SIGNAL("customContextMenuRequested(QPoint)"), SLOT("slot_showCustomDialMenu()")) | |||
| #self.connect(self.ui.dial_b_left, SIGNAL("customContextMenuRequested(QPoint)"), SLOT("slot_showCustomDialMenu()")) | |||
| #self.connect(self.ui.dial_b_right, SIGNAL("customContextMenuRequested(QPoint)"), SLOT("slot_showCustomDialMenu()")) | |||
| # FIXME | |||
| self.ui.frame_controls.setVisible(False) | |||
| self.ui.pushButton.setVisible(False) | |||
| self.ui.pushButton_2.setVisible(False) | |||
| self.ui.pushButton_3.setVisible(False) | |||
| self.setMaximumHeight(30) | |||
| def editClosed(self): | |||
| self.ui.b_edit.setChecked(False) | |||
| def recheckPluginHints(self, hints): | |||
| self.fPluginInfo['hints'] = hints | |||
| self.ui.dial_drywet.setEnabled(hints & PLUGIN_CAN_DRYWET) | |||
| self.ui.dial_vol.setEnabled(hints & PLUGIN_CAN_VOLUME) | |||
| self.ui.dial_b_left.setEnabled(hints & PLUGIN_CAN_BALANCE) | |||
| self.ui.dial_b_right.setEnabled(hints & PLUGIN_CAN_BALANCE) | |||
| self.ui.b_gui.setEnabled(hints & PLUGIN_HAS_GUI) | |||
| def paintEvent(self, event): | |||
| painter = QPainter(self) | |||
| areaX = self.ui.area_right.x() | |||
| # background | |||
| #painter.setPen(self.m_colorTop) | |||
| #painter.setBrush(self.m_colorTop) | |||
| #painter.drawRect(0, 0, areaX+40, self.height()) | |||
| # bottom line | |||
| painter.setPen(self.fColorBottom) | |||
| painter.setBrush(self.fColorBottom) | |||
| painter.drawRect(0, self.height()-5, areaX, 5) | |||
| # top line | |||
| painter.drawLine(0, 0, areaX+40, 0) | |||
| # name -> leds arc | |||
| path = QPainterPath() | |||
| path.moveTo(areaX-80, self.height()) | |||
| path.cubicTo(areaX+40, self.height()-5, areaX-40, 30, areaX+20, 0) | |||
| path.lineTo(areaX+20, self.height()) | |||
| painter.drawPath(path) | |||
| # fill the rest | |||
| painter.drawRect(areaX+20, 0, self.width(), self.height()) | |||
| #painter.drawLine(0, 3, self.width(), 3) | |||
| #painter.drawLine(0, self.height() - 4, self.width(), self.height() - 4) | |||
| #painter.setPen(self.m_color2) | |||
| #painter.drawLine(0, 2, self.width(), 2) | |||
| #painter.drawLine(0, self.height() - 3, self.width(), self.height() - 3) | |||
| #painter.setPen(self.m_color3) | |||
| #painter.drawLine(0, 1, self.width(), 1) | |||
| #painter.drawLine(0, self.height() - 2, self.width(), self.height() - 2) | |||
| #painter.setPen(self.m_color4) | |||
| #painter.drawLine(0, 0, self.width(), 0) | |||
| #painter.drawLine(0, self.height() - 1, self.width(), self.height() - 1) | |||
| QFrame.paintEvent(self, event) | |||
| @pyqtSlot(bool) | |||
| def slot_editClicked(self, show): | |||
| self.ui.edit_dialog.setVisible(show) | |||
| # ------------------------------------------------------------------------------------------------------------ | |||
| # TESTING | |||
| @@ -912,6 +1508,10 @@ class PluginParameter(QWidget): | |||
| #app = QApplication(sys.argv) | |||
| #gui1 = CarlaAboutW(None) | |||
| #gui2 = PluginParameter(None, ptest, 0, 0) | |||
| #gui3 = PluginEdit(None, 0) | |||
| #gui4 = PluginWidget(None, 0) | |||
| #gui1.show() | |||
| #gui2.show() | |||
| #gui3.show() | |||
| #gui4.show() | |||
| #app.exec_() | |||
| @@ -633,6 +633,9 @@ private: | |||
| std::strcpy(buffer, strBuf); | |||
| // FIXME? | |||
| buffer[bufferLen-1] = '\0'; | |||
| firstInit = false; | |||
| } | |||
| } | |||
| @@ -651,7 +654,7 @@ private: | |||
| bufferLen = 0; | |||
| buffer = new char[1]; | |||
| buffer[0] = 0; | |||
| buffer[0] = '\0'; | |||
| firstInit = false; | |||
| } | |||