| @@ -308,6 +308,14 @@ struct EngineTimeInfo { | |||||
| frame(0), | frame(0), | ||||
| time(0), | time(0), | ||||
| valid(0x0) {} | valid(0x0) {} | ||||
| void clear() | |||||
| { | |||||
| playing = false; | |||||
| frame = 0; | |||||
| time = 0; | |||||
| valid = 0x0; | |||||
| } | |||||
| }; | }; | ||||
| // ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
| @@ -539,9 +547,9 @@ private: | |||||
| /*! | /*! | ||||
| * Private data used in CarlaEngine. | * 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. | * Carla Engine. | ||||
| @@ -857,6 +865,25 @@ protected: | |||||
| EngineOptions fOptions; | EngineOptions fOptions; | ||||
| EngineTimeInfo fTimeInfo; | 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 | #ifndef BUILD_BRIDGE | ||||
| // Rack mode data | // Rack mode data | ||||
| EngineEvent* getRackEventBuffer(const bool isInput); | 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); | void processPatchbay(float** inBuf, float** outBuf, const uint32_t bufCount[2], const uint32_t frames); | ||||
| #endif | #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: | private: | ||||
| ScopedPointer<CarlaEnginePrivateData> const fData; | |||||
| #ifdef WANT_JACK | #ifdef WANT_JACK | ||||
| static CarlaEngine* newJack(); | static CarlaEngine* newJack(); | ||||
| #endif | #endif | ||||
| @@ -182,6 +182,7 @@ void CarlaEngineEventPort::writeControlEvent(const uint32_t time, const uint8_t | |||||
| CARLA_ASSERT(fBuffer != nullptr); | CARLA_ASSERT(fBuffer != nullptr); | ||||
| CARLA_ASSERT(type != kEngineControlEventTypeNull); | CARLA_ASSERT(type != kEngineControlEventTypeNull); | ||||
| CARLA_ASSERT(channel < MAX_MIDI_CHANNELS); | CARLA_ASSERT(channel < MAX_MIDI_CHANNELS); | ||||
| CARLA_ASSERT(value >= 0.0 && value <= 1.0); | |||||
| if (fBuffer == nullptr) | if (fBuffer == nullptr) | ||||
| return; | return; | ||||
| @@ -340,7 +341,7 @@ void CarlaEngineClient::setLatency(const uint32_t samples) | |||||
| CarlaEngine::CarlaEngine() | CarlaEngine::CarlaEngine() | ||||
| : fBufferSize(0), | : fBufferSize(0), | ||||
| fSampleRate(0.0), | fSampleRate(0.0), | ||||
| fData(new CarlaEnginePrivateData(this)) | |||||
| fData(new CarlaEngineProtectedData(this)) | |||||
| { | { | ||||
| qDebug("CarlaEngine::CarlaEngine()"); | qDebug("CarlaEngine::CarlaEngine()"); | ||||
| } | } | ||||
| @@ -355,7 +356,7 @@ CarlaEngine::~CarlaEngine() | |||||
| // ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
| // Helpers | // Helpers | ||||
| void doPluginRemove(CarlaEnginePrivateData* const fData, const bool unlock) | |||||
| void doPluginRemove(CarlaEngineProtectedData* const fData, const bool unlock) | |||||
| { | { | ||||
| CARLA_ASSERT(fData->curPluginCount > 0); | CARLA_ASSERT(fData->curPluginCount > 0); | ||||
| fData->curPluginCount--; | fData->curPluginCount--; | ||||
| @@ -511,6 +512,8 @@ bool CarlaEngine::init(const char* const clientName) | |||||
| fName = clientName; | fName = clientName; | ||||
| fName.toBasic(); | fName.toBasic(); | ||||
| fTimeInfo.clear(); | |||||
| fData->aboutToClose = false; | fData->aboutToClose = false; | ||||
| fData->curPluginCount = 0; | fData->curPluginCount = 0; | ||||
| @@ -1198,6 +1201,40 @@ void CarlaEngine::setOscBridgeData(const CarlaOscData* const oscData) | |||||
| // ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
| // protected calls | // 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 | #ifndef BUILD_BRIDGE | ||||
| EngineEvent* CarlaEngine::getRackEventBuffer(const bool isInput) | 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) | // initialize outputs (zero) | ||||
| carla_zeroFloat(outBuf[0], frames); | carla_zeroFloat(outBuf[0], frames); | ||||
| carla_zeroFloat(outBuf[1], 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 | // 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); | CarlaPlugin* const plugin = getPluginUnchecked(i); | ||||
| if (! (plugin && plugin->enabled())) | |||||
| if (plugin == nullptr || ! plugin->enabled()) | |||||
| continue; | continue; | ||||
| #if 0 | |||||
| if (processed) | if (processed) | ||||
| { | { | ||||
| // initialize inputs (from previous outputs) | // 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 + 0] = outPeak1; | ||||
| data->outsPeak[i*MAX_PEAKS + 1] = outPeak2; | data->outsPeak[i*MAX_PEAKS + 1] = outPeak2; | ||||
| } | } | ||||
| #endif | |||||
| processed = true; | 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[0], inBuf[0], sizeof(float)*frames); | ||||
| std::memcpy(outBuf[1], inBuf[1], 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) | 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 | #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 | // Carla Engine OSC stuff | ||||
| @@ -1,10 +1,9 @@ | |||||
| # QtCreator project file | # QtCreator project file | ||||
| # QT = core | |||||
| QT = core | |||||
| CONFIG = debug | CONFIG = debug | ||||
| CONFIG += link_pkgconfig shared warn_on | |||||
| # qt | |||||
| CONFIG += link_pkgconfig qt shared warn_on | |||||
| DEFINES = DEBUG | DEFINES = DEBUG | ||||
| DEFINES += QTCREATOR_TEST | DEFINES += QTCREATOR_TEST | ||||
| @@ -30,7 +29,7 @@ DEFINES += WANT_JACK WANT_RTAUDIO | |||||
| PKGCONFIG = liblo jack alsa libpulse-simple | PKGCONFIG = liblo jack alsa libpulse-simple | ||||
| TARGET = carla_engine | TARGET = carla_engine | ||||
| TEMPLATE = app | |||||
| TEMPLATE = lib | |||||
| VERSION = 0.5.0 | VERSION = 0.5.0 | ||||
| SOURCES = \ | SOURCES = \ | ||||
| @@ -92,4 +91,5 @@ WARN_FLAGS = \ | |||||
| -fipa-pure-const -Wsuggest-attribute=const #pure,const,noreturn | -fipa-pure-const -Wsuggest-attribute=const #pure,const,noreturn | ||||
| QMAKE_CFLAGS *= $${WARN_FLAGS} -std=c99 -Wc++-compat -Wunsuffixed-float-constants -Wwrite-strings | 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; | CarlaEngineOsc osc; | ||||
| CarlaEngineThread thread; | CarlaEngineThread thread; | ||||
| @@ -172,7 +172,7 @@ struct CarlaEnginePrivateData { | |||||
| EnginePluginData* plugins; | EnginePluginData* plugins; | ||||
| CarlaEnginePrivateData(CarlaEngine* const engine) | |||||
| CarlaEngineProtectedData(CarlaEngine* const engine) | |||||
| : osc(engine), | : osc(engine), | ||||
| thread(engine), | thread(engine), | ||||
| oscData(nullptr), | oscData(nullptr), | ||||
| @@ -183,9 +183,9 @@ struct CarlaEnginePrivateData { | |||||
| maxPluginNumber(0), | maxPluginNumber(0), | ||||
| plugins(nullptr) {} | plugins(nullptr) {} | ||||
| CarlaEnginePrivateData() = delete; | |||||
| CarlaEngineProtectedData() = delete; | |||||
| CARLA_LEAK_DETECTOR(CarlaEnginePrivateData) | |||||
| CARLA_LEAK_DETECTOR(CarlaEngineProtectedData) | |||||
| }; | }; | ||||
| CARLA_BACKEND_END_NAMESPACE | CARLA_BACKEND_END_NAMESPACE | ||||
| @@ -361,9 +361,9 @@ int CarlaEngineOsc::handleMsgRegister(const int argc, const lo_arg* const* const | |||||
| qDebug("CarlaEngineOsc::handleMsgRegister()"); | qDebug("CarlaEngineOsc::handleMsgRegister()"); | ||||
| CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "s"); | 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; | return 1; | ||||
| } | } | ||||
| @@ -375,25 +375,23 @@ int CarlaEngineOsc::handleMsgRegister(const int argc, const lo_arg* const* const | |||||
| host = lo_address_get_hostname(source); | host = lo_address_get_hostname(source); | ||||
| port = lo_address_get_port(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); | host = lo_url_get_hostname(url); | ||||
| port = lo_url_get_port(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*)host); | ||||
| free((void*)port); | 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()) | if (plugin && plugin->enabled()) | ||||
| plugin->registerToOscClient(); | plugin->registerToOscClient(); | ||||
| } | } | ||||
| #endif | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| @@ -402,13 +400,13 @@ int CarlaEngineOsc::handleMsgUnregister() | |||||
| { | { | ||||
| qDebug("CarlaEngineOsc::handleMsgUnregister()"); | qDebug("CarlaEngineOsc::handleMsgUnregister()"); | ||||
| if (! m_controlData.path) | |||||
| if (fControlData.path == nullptr) | |||||
| { | { | ||||
| qWarning("CarlaEngineOsc::handleMsgUnregister() - OSC backend is not registered yet"); | qWarning("CarlaEngineOsc::handleMsgUnregister() - OSC backend is not registered yet"); | ||||
| return 1; | return 1; | ||||
| } | } | ||||
| m_controlData.free(); | |||||
| fControlData.free(); | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| #endif | #endif | ||||
| @@ -37,18 +37,18 @@ class CarlaEngineJackAudioPort : public CarlaEngineAudioPort | |||||
| public: | public: | ||||
| CarlaEngineJackAudioPort(const bool isInput, const ProcessMode processMode, jack_client_t* const client, jack_port_t* const port) | CarlaEngineJackAudioPort(const bool isInput, const ProcessMode processMode, jack_client_t* const client, jack_port_t* const port) | ||||
| : CarlaEngineAudioPort(isInput, processMode), | : 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); | qDebug("CarlaEngineJackAudioPort::CarlaEngineJackAudioPort(%s, %s, %p, %p)", bool2str(isInput), ProcessMode2Str(processMode), client, port); | ||||
| if (processMode == PROCESS_MODE_SINGLE_CLIENT || processMode == PROCESS_MODE_MULTIPLE_CLIENTS) | if (processMode == PROCESS_MODE_SINGLE_CLIENT || processMode == PROCESS_MODE_MULTIPLE_CLIENTS) | ||||
| { | { | ||||
| CARLA_ASSERT(m_client && m_port); | |||||
| CARLA_ASSERT(client != nullptr && port != nullptr); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| CARLA_ASSERT(! (m_client || m_port)); | |||||
| CARLA_ASSERT(client == nullptr && port == nullptr); | |||||
| } | } | ||||
| } | } | ||||
| @@ -56,29 +56,29 @@ public: | |||||
| { | { | ||||
| qDebug("CarlaEngineJackAudioPort::~CarlaEngineJackAudioPort()"); | 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) | void initBuffer(CarlaEngine* const engine) | ||||
| { | { | ||||
| CARLA_ASSERT(engine); | |||||
| CARLA_ASSERT(engine != nullptr); | |||||
| if (! engine) | |||||
| if (engine == nullptr) | |||||
| { | { | ||||
| fBuffer = nullptr; | fBuffer = nullptr; | ||||
| return; | return; | ||||
| } | } | ||||
| if (! m_port) | |||||
| if (kPort == nullptr) | |||||
| return CarlaEngineAudioPort::initBuffer(engine); | return CarlaEngineAudioPort::initBuffer(engine); | ||||
| fBuffer = (float*)jackbridge_port_get_buffer(m_port, engine->getBufferSize()); | |||||
| fBuffer = (float*)jackbridge_port_get_buffer(kPort, engine->getBufferSize()); | |||||
| } | } | ||||
| private: | 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) | CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineJackAudioPort) | ||||
| }; | }; | ||||
| @@ -91,18 +91,19 @@ class CarlaEngineJackEventPort : public CarlaEngineEventPort | |||||
| public: | public: | ||||
| CarlaEngineJackEventPort(const bool isInput, const ProcessMode processMode, jack_client_t* const client, jack_port_t* const port) | CarlaEngineJackEventPort(const bool isInput, const ProcessMode processMode, jack_client_t* const client, jack_port_t* const port) | ||||
| : CarlaEngineEventPort(isInput, processMode), | : 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); | qDebug("CarlaEngineJackEventPort::CarlaEngineJackEventPort(%s, %s, %p, %p)", bool2str(isInput), ProcessMode2Str(processMode), client, port); | ||||
| if (processMode == PROCESS_MODE_SINGLE_CLIENT || processMode == PROCESS_MODE_MULTIPLE_CLIENTS) | if (processMode == PROCESS_MODE_SINGLE_CLIENT || processMode == PROCESS_MODE_MULTIPLE_CLIENTS) | ||||
| { | { | ||||
| CARLA_ASSERT(m_client && m_port); | |||||
| CARLA_ASSERT(client != nullptr && port != nullptr); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| CARLA_ASSERT(! (m_client || m_port)); | |||||
| CARLA_ASSERT(client == nullptr && port == nullptr); | |||||
| } | } | ||||
| } | } | ||||
| @@ -110,140 +111,141 @@ public: | |||||
| { | { | ||||
| qDebug("CarlaEngineJackEventPort::~CarlaEngineJackEventPort()"); | 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) | void initBuffer(CarlaEngine* const engine) | ||||
| { | { | ||||
| CARLA_ASSERT(engine); | |||||
| CARLA_ASSERT(engine != nullptr); | |||||
| if (! engine) | |||||
| if (engine == nullptr) | |||||
| { | { | ||||
| fBuffer = nullptr; | |||||
| fJackBuffer = nullptr; | |||||
| return; | return; | ||||
| } | } | ||||
| if (! m_port) | |||||
| if (kPort == nullptr) | |||||
| return CarlaEngineEventPort::initBuffer(engine); | return CarlaEngineEventPort::initBuffer(engine); | ||||
| fBuffer = jackbridge_port_get_buffer(m_port, engine->getBufferSize()); | |||||
| fJackBuffer = jackbridge_port_get_buffer(kPort, engine->getBufferSize()); | |||||
| if (! kIsInput) | if (! kIsInput) | ||||
| jackbridge_midi_clear_buffer(fBuffer); | |||||
| jackbridge_midi_clear_buffer(fJackBuffer); | |||||
| } | } | ||||
| uint32_t getEventCount() | uint32_t getEventCount() | ||||
| { | { | ||||
| if (! m_port) | |||||
| if (kPort == nullptr) | |||||
| return CarlaEngineEventPort::getEventCount(); | return CarlaEngineEventPort::getEventCount(); | ||||
| if (! kIsInput) | if (! kIsInput) | ||||
| return 0; | return 0; | ||||
| CARLA_ASSERT(fBuffer); | |||||
| CARLA_ASSERT(fJackBuffer != nullptr); | |||||
| if (! fBuffer) | |||||
| if (fJackBuffer != nullptr) | |||||
| return 0; | return 0; | ||||
| return jackbridge_midi_get_event_count(fBuffer); | |||||
| return jackbridge_midi_get_event_count(fJackBuffer); | |||||
| } | } | ||||
| const EngineEvent* getEvent(const uint32_t index) | const EngineEvent* getEvent(const uint32_t index) | ||||
| { | { | ||||
| if (! m_port) | |||||
| if (kPort == nullptr) | |||||
| return CarlaEngineEventPort::getEvent(index); | return CarlaEngineEventPort::getEvent(index); | ||||
| if (! kIsInput) | if (! kIsInput) | ||||
| return nullptr; | return nullptr; | ||||
| CARLA_ASSERT(fBuffer); | |||||
| CARLA_ASSERT(fJackBuffer != nullptr); | |||||
| if (! fBuffer) | |||||
| if (fJackBuffer != nullptr) | |||||
| return nullptr; | return nullptr; | ||||
| jack_midi_event_t jackEvent; | 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; | return nullptr; | ||||
| m_retEvent.clear(); | |||||
| fRetEvent.clear(); | |||||
| const uint8_t midiStatus = MIDI_GET_STATUS_FROM_DATA(jackEvent.buffer); | const uint8_t midiStatus = MIDI_GET_STATUS_FROM_DATA(jackEvent.buffer); | ||||
| const uint8_t midiChannel = MIDI_GET_CHANNEL_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)) | if (MIDI_IS_STATUS_CONTROL_CHANGE(midiStatus)) | ||||
| { | { | ||||
| const uint8_t midiControl = jackEvent.buffer[1]; | const uint8_t midiControl = jackEvent.buffer[1]; | ||||
| m_retEvent.type = kEngineEventTypeControl; | |||||
| fRetEvent.type = kEngineEventTypeControl; | |||||
| if (MIDI_IS_CONTROL_BANK_SELECT(midiControl)) | if (MIDI_IS_CONTROL_BANK_SELECT(midiControl)) | ||||
| { | { | ||||
| const uint8_t midiBank = jackEvent.buffer[2]; | 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) | 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) | 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 | else | ||||
| { | { | ||||
| const uint8_t midiValue = jackEvent.buffer[2]; | 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)) | else if (MIDI_IS_STATUS_PROGRAM_CHANGE(midiStatus)) | ||||
| { | { | ||||
| const uint8_t midiProgram = jackEvent.buffer[1]; | 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 | 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) | 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); | return CarlaEngineEventPort::writeControlEvent(time, channel, type, parameter, value); | ||||
| if (kIsInput) | if (kIsInput) | ||||
| return; | return; | ||||
| CARLA_ASSERT(fBuffer); | |||||
| CARLA_ASSERT(fJackBuffer != nullptr); | |||||
| CARLA_ASSERT(type != kEngineControlEventTypeNull); | CARLA_ASSERT(type != kEngineControlEventTypeNull); | ||||
| CARLA_ASSERT(channel < MAX_MIDI_CHANNELS); | CARLA_ASSERT(channel < MAX_MIDI_CHANNELS); | ||||
| CARLA_ASSERT(value >= 0.0 && value <= 1.0); | |||||
| if (! fBuffer) | |||||
| if (fJackBuffer == nullptr) | |||||
| return; | return; | ||||
| if (type == kEngineControlEventTypeNull) | if (type == kEngineControlEventTypeNull) | ||||
| return; | return; | ||||
| @@ -291,23 +293,23 @@ public: | |||||
| } | } | ||||
| if (size > 0) | 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) | 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); | return CarlaEngineEventPort::writeMidiEvent(time, channel, data, size); | ||||
| if (kIsInput) | if (kIsInput) | ||||
| return; | return; | ||||
| CARLA_ASSERT(fBuffer); | |||||
| CARLA_ASSERT(fJackBuffer != nullptr); | |||||
| CARLA_ASSERT(channel < MAX_MIDI_CHANNELS); | CARLA_ASSERT(channel < MAX_MIDI_CHANNELS); | ||||
| CARLA_ASSERT(data); | CARLA_ASSERT(data); | ||||
| CARLA_ASSERT(size > 0); | CARLA_ASSERT(size > 0); | ||||
| if (! fBuffer) | |||||
| if (fJackBuffer == nullptr) | |||||
| return; | return; | ||||
| if (channel >= MAX_MIDI_CHANNELS) | if (channel >= MAX_MIDI_CHANNELS) | ||||
| return; | return; | ||||
| @@ -319,16 +321,15 @@ public: | |||||
| jdata[0] = data[0] + channel; | jdata[0] = data[0] + channel; | ||||
| jackbridge_midi_event_write(fBuffer, time, jdata, size); | |||||
| jackbridge_midi_event_write(fJackBuffer, time, jdata, size); | |||||
| } | } | ||||
| private: | 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) | CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineJackEventPort) | ||||
| }; | }; | ||||
| @@ -341,15 +342,19 @@ class CarlaEngineJackClient : public CarlaEngineClient | |||||
| public: | public: | ||||
| CarlaEngineJackClient(const EngineType engineType, const ProcessMode processMode, jack_client_t* const client) | CarlaEngineJackClient(const EngineType engineType, const ProcessMode processMode, jack_client_t* const client) | ||||
| : CarlaEngineClient(engineType, processMode), | : 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); | 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 | else | ||||
| CARLA_ASSERT(! m_client); | |||||
| { | |||||
| CARLA_ASSERT(kClient == nullptr); | |||||
| } | |||||
| } | } | ||||
| ~CarlaEngineJackClient() | ~CarlaEngineJackClient() | ||||
| @@ -358,8 +363,8 @@ public: | |||||
| if (kProcessMode == PROCESS_MODE_MULTIPLE_CLIENTS) | 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) | 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(); | CarlaEngineClient::activate(); | ||||
| @@ -384,10 +389,10 @@ public: | |||||
| if (kProcessMode == PROCESS_MODE_MULTIPLE_CLIENTS) | 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(); | CarlaEngineClient::deactivate(); | ||||
| @@ -397,8 +402,8 @@ public: | |||||
| { | { | ||||
| qDebug("CarlaEngineClient::isOk()"); | qDebug("CarlaEngineClient::isOk()"); | ||||
| if (m_usesClient) | |||||
| return bool(m_client); | |||||
| if (kUseClient) | |||||
| return bool(kClient); | |||||
| return CarlaEngineClient::isOk(); | return CarlaEngineClient::isOk(); | ||||
| } | } | ||||
| @@ -407,8 +412,8 @@ public: | |||||
| { | { | ||||
| CarlaEngineClient::setLatency(samples); | 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) | const CarlaEnginePort* addPort(const EnginePortType portType, const char* const name, const bool isInput) | ||||
| @@ -418,17 +423,17 @@ public: | |||||
| jack_port_t* port = nullptr; | jack_port_t* port = nullptr; | ||||
| // Create Jack port if needed | // Create Jack port if needed | ||||
| if (m_usesClient) | |||||
| if (kUseClient) | |||||
| { | { | ||||
| switch (portType) | switch (portType) | ||||
| { | { | ||||
| case kEnginePortTypeNull: | case kEnginePortTypeNull: | ||||
| break; | break; | ||||
| case kEnginePortTypeAudio: | 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; | break; | ||||
| case kEnginePortTypeEvent: | 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; | break; | ||||
| } | } | ||||
| } | } | ||||
| @@ -439,9 +444,9 @@ public: | |||||
| case kEnginePortTypeNull: | case kEnginePortTypeNull: | ||||
| break; | break; | ||||
| case kEnginePortTypeAudio: | case kEnginePortTypeAudio: | ||||
| return new CarlaEngineJackAudioPort(isInput, kProcessMode, m_client, port); | |||||
| return new CarlaEngineJackAudioPort(isInput, kProcessMode, kClient, port); | |||||
| case kEnginePortTypeEvent: | 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)); | qCritical("CarlaJackEngineClient::addPort(%s, \"%s\", %s) - invalid type", EnginePortType2Str(portType), name, bool2str(isInput)); | ||||
| @@ -449,8 +454,8 @@ public: | |||||
| } | } | ||||
| private: | 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) | CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineJackClient) | ||||
| }; | }; | ||||
| @@ -462,30 +467,29 @@ class CarlaEngineJack : public CarlaEngine | |||||
| { | { | ||||
| public: | public: | ||||
| CarlaEngineJack() | CarlaEngineJack() | ||||
| : CarlaEngine() | |||||
| #ifndef BUILD_BRIDGE | |||||
| , fRackPorts{nullptr} | |||||
| : CarlaEngine(), | |||||
| #ifdef BUILD_BRIDGE | |||||
| fHasQuit(false), | |||||
| #else | |||||
| fClient(nullptr), | |||||
| fTransportState(JackTransportStopped), | |||||
| fRackPorts{nullptr}, | |||||
| #endif | #endif | ||||
| fFreewheel(false) | |||||
| { | { | ||||
| qDebug("CarlaEngineJack::CarlaEngineJack()"); | qDebug("CarlaEngineJack::CarlaEngineJack()"); | ||||
| m_client = nullptr; | |||||
| m_state = JackTransportStopped; | |||||
| m_freewheel = false; | |||||
| memset(&m_pos, 0, sizeof(jack_position_t)); | |||||
| #ifdef BUILD_BRIDGE | #ifdef BUILD_BRIDGE | ||||
| m_hasQuit = false; | |||||
| fOptions.processMode = PROCESS_MODE_MULTIPLE_CLIENTS; | fOptions.processMode = PROCESS_MODE_MULTIPLE_CLIENTS; | ||||
| #endif | #endif | ||||
| carla_zeroStruct<jack_position_t>(fTransportPos); | |||||
| } | } | ||||
| ~CarlaEngineJack() | ~CarlaEngineJack() | ||||
| { | { | ||||
| qDebug("CarlaEngineJack::~CarlaEngineJack()"); | qDebug("CarlaEngineJack::~CarlaEngineJack()"); | ||||
| CARLA_ASSERT(! m_client); | |||||
| CARLA_ASSERT(fClient == nullptr); | |||||
| } | } | ||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| @@ -518,37 +522,39 @@ public: | |||||
| { | { | ||||
| qDebug("CarlaEngineJack::init(\"%s\")", clientName); | qDebug("CarlaEngineJack::init(\"%s\")", clientName); | ||||
| m_state = JackTransportStopped; | |||||
| m_freewheel = false; | |||||
| fFreewheel = false; | |||||
| fTransportState = JackTransportStopped; | |||||
| carla_zeroStruct<jack_position_t>(fTransportPos); | |||||
| #ifndef BUILD_BRIDGE | #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) | 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); | CarlaEngine::init(clientName); | ||||
| return true; | return true; | ||||
| @@ -556,7 +562,7 @@ public: | |||||
| else | else | ||||
| { | { | ||||
| setLastError("Failed to activate the JACK client"); | setLastError("Failed to activate the JACK client"); | ||||
| m_client = nullptr; | |||||
| fClient = nullptr; | |||||
| } | } | ||||
| } | } | ||||
| else | else | ||||
| @@ -567,15 +573,15 @@ public: | |||||
| // open temp client to get initial buffer-size and sample-rate values | // open temp client to get initial buffer-size and sample-rate values | ||||
| if (fBufferSize == 0 || fSampleRate == 0.0) | 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(); | CarlaEngine::close(); | ||||
| #ifdef BUILD_BRIDGE | #ifdef BUILD_BRIDGE | ||||
| m_client = nullptr; | |||||
| m_hasQuit = true; | |||||
| fClient = nullptr; | |||||
| fHasQuit = true; | |||||
| return true; | return true; | ||||
| #else | #else | ||||
| if (jackbridge_deactivate(m_client) == 0) | |||||
| if (jackbridge_deactivate(fClient) == 0) | |||||
| { | { | ||||
| if (fOptions.processMode == PROCESS_MODE_CONTINUOUS_RACK) | 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; | return true; | ||||
| } | } | ||||
| else | else | ||||
| @@ -617,7 +623,7 @@ public: | |||||
| else | else | ||||
| setLastError("Failed to deactivate the JACK client"); | setLastError("Failed to deactivate the JACK client"); | ||||
| m_client = nullptr; | |||||
| fClient = nullptr; | |||||
| #endif | #endif | ||||
| return false; | return false; | ||||
| } | } | ||||
| @@ -625,15 +631,15 @@ public: | |||||
| bool isRunning() const | bool isRunning() const | ||||
| { | { | ||||
| #ifdef BUILD_BRIDGE | #ifdef BUILD_BRIDGE | ||||
| return bool(m_client || ! m_hasQuit); | |||||
| return (fClient != nullptr || ! m_hasQuit); | |||||
| #else | #else | ||||
| return bool(m_client); | |||||
| return (fClient != nullptr); | |||||
| #endif | #endif | ||||
| } | } | ||||
| bool isOffline() const | bool isOffline() const | ||||
| { | { | ||||
| return m_freewheel; | |||||
| return fFreewheel; | |||||
| } | } | ||||
| EngineType type() const | EngineType type() const | ||||
| @@ -646,7 +652,7 @@ public: | |||||
| jack_client_t* client = nullptr; | jack_client_t* client = nullptr; | ||||
| #ifdef BUILD_BRIDGE | #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); | fBufferSize = jackbridge_get_buffer_size(client); | ||||
| fSampleRate = jackbridge_get_sample_rate(client); | fSampleRate = jackbridge_get_sample_rate(client); | ||||
| @@ -660,7 +666,7 @@ public: | |||||
| #else | #else | ||||
| if (fOptions.processMode == PROCESS_MODE_SINGLE_CLIENT) | if (fOptions.processMode == PROCESS_MODE_SINGLE_CLIENT) | ||||
| { | { | ||||
| client = m_client; | |||||
| client = fClient; | |||||
| } | } | ||||
| else if (fOptions.processMode == PROCESS_MODE_MULTIPLE_CLIENTS) | else if (fOptions.processMode == PROCESS_MODE_MULTIPLE_CLIENTS) | ||||
| { | { | ||||
| @@ -682,57 +688,66 @@ public: | |||||
| protected: | protected: | ||||
| void handleJackBufferSizeCallback(const uint32_t newBufferSize) | void handleJackBufferSizeCallback(const uint32_t newBufferSize) | ||||
| { | { | ||||
| fBufferSize = newBufferSize; | |||||
| if (fBufferSize != newBufferSize) | |||||
| { | |||||
| fBufferSize = newBufferSize; | |||||
| bufferSizeChanged(newBufferSize); | |||||
| bufferSizeChanged(newBufferSize); | |||||
| } | |||||
| } | } | ||||
| void handleJackSampleRateCallback(const double newSampleRate) | void handleJackSampleRateCallback(const double newSampleRate) | ||||
| { | { | ||||
| fSampleRate = newSampleRate; | |||||
| if (fSampleRate != newSampleRate) | |||||
| { | |||||
| fSampleRate = newSampleRate; | |||||
| sampleRateChanged(newSampleRate); | |||||
| } | |||||
| } | } | ||||
| void handleJackFreewheelCallback(const bool isFreewheel) | void handleJackFreewheelCallback(const bool isFreewheel) | ||||
| { | { | ||||
| m_freewheel = isFreewheel; | |||||
| fFreewheel = isFreewheel; | |||||
| } | } | ||||
| void handleJackProcessCallback(const uint32_t nframes) | void handleJackProcessCallback(const uint32_t nframes) | ||||
| { | { | ||||
| #ifndef BUILD_BRIDGE | #ifndef BUILD_BRIDGE | ||||
| if (currentPluginCount() == 0) | |||||
| if (fData->curPluginCount == 0) | |||||
| return; | return; | ||||
| #endif | #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 | else | ||||
| fTimeInfo.valid = 0; | |||||
| fTimeInfo.valid = 0x0; | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| fTimeInfo.frame = 0; | fTimeInfo.frame = 0; | ||||
| fTimeInfo.valid = 0; | |||||
| fTimeInfo.valid = 0x0; | |||||
| } | } | ||||
| #ifdef BUILD_BRIDGE | #ifdef BUILD_BRIDGE | ||||
| @@ -744,9 +759,9 @@ protected: | |||||
| processPlugin(plugin, nframes); | processPlugin(plugin, nframes); | ||||
| } | } | ||||
| #else | #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); | 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 | // 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 | // 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 | // create audio buffers | ||||
| float* inBuf[2] = { audioIn1, audioIn2 }; | float* inBuf[2] = { audioIn1, audioIn2 }; | ||||
| float* outBuf[2] = { audioOut1, audioOut2 }; | float* outBuf[2] = { audioOut1, audioOut2 }; | ||||
| #if 0 | |||||
| // initialize control input | // initialize control input | ||||
| memset(rackControlEventsIn, 0, sizeof(CarlaEngineControlEvent)*MAX_CONTROL_EVENTS); | memset(rackControlEventsIn, 0, sizeof(CarlaEngineControlEvent)*MAX_CONTROL_EVENTS); | ||||
| { | { | ||||
| @@ -859,10 +871,12 @@ protected: | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| #endif | |||||
| // process rack | // process rack | ||||
| processRack(inBuf, outBuf, nframes); | processRack(inBuf, outBuf, nframes); | ||||
| #if 0 | |||||
| // output control | // output control | ||||
| { | { | ||||
| jackbridge_midi_clear_buffer(controlOut); | jackbridge_midi_clear_buffer(controlOut); | ||||
| @@ -923,6 +937,7 @@ protected: | |||||
| jackbridge_midi_event_write(midiOut, rackMidiEventsOut[i].time, rackMidiEventsOut[i].data, rackMidiEventsOut[i].size); | jackbridge_midi_event_write(midiOut, rackMidiEventsOut[i].time, rackMidiEventsOut[i].data, rackMidiEventsOut[i].size); | ||||
| } | } | ||||
| } | } | ||||
| #endif | |||||
| } | } | ||||
| #endif | #endif | ||||
| @@ -936,7 +951,7 @@ protected: | |||||
| return; | return; | ||||
| #endif | #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); | CarlaPlugin* const plugin = getPluginUnchecked(i); | ||||
| @@ -947,7 +962,7 @@ protected: | |||||
| void handleJackShutdownCallback() | 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); | //CarlaPlugin* const plugin = getPluginUnchecked(i); | ||||
| @@ -955,22 +970,21 @@ protected: | |||||
| // plugin->x_client = nullptr; | // plugin->x_client = nullptr; | ||||
| } | } | ||||
| m_client = nullptr; | |||||
| fClient = nullptr; | |||||
| callback(CALLBACK_QUIT, 0, 0, 0, 0.0f, nullptr); | callback(CALLBACK_QUIT, 0, 0, 0, 0.0f, nullptr); | ||||
| } | } | ||||
| // ------------------------------------- | // ------------------------------------- | ||||
| private: | 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 | #ifdef BUILD_BRIDGE | ||||
| bool m_hasQuit; | |||||
| bool fHasQuit; | |||||
| #else | #else | ||||
| enum RackPorts { | enum RackPorts { | ||||
| rackPortAudioIn1 = 0, | rackPortAudioIn1 = 0, | ||||
| @@ -985,6 +999,8 @@ private: | |||||
| jack_port_t* fRackPorts[rackPortCount]; | jack_port_t* fRackPorts[rackPortCount]; | ||||
| #endif | #endif | ||||
| bool fFreewheel; | |||||
| // ------------------------------------- | // ------------------------------------- | ||||
| static void processPlugin(CarlaPlugin* const p, const uint32_t nframes) | static void processPlugin(CarlaPlugin* const p, const uint32_t nframes) | ||||
| @@ -1096,10 +1112,8 @@ private: | |||||
| if (plugin && plugin->enabled()) | if (plugin && plugin->enabled()) | ||||
| { | { | ||||
| //plugin->engineProcessLock(); | |||||
| plugin->initBuffers(); | plugin->initBuffers(); | ||||
| processPlugin(plugin, nframes); | processPlugin(plugin, nframes); | ||||
| //plugin->engineProcessUnlock(); | |||||
| } | } | ||||
| return 0; | return 0; | ||||
| @@ -430,7 +430,7 @@ protected: | |||||
| void d_activate() | void d_activate() | ||||
| { | { | ||||
| #if 0 | #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); | CarlaPlugin* const plugin = getPluginUnchecked(i); | ||||
| @@ -445,7 +445,7 @@ protected: | |||||
| void d_deactivate() | void d_deactivate() | ||||
| { | { | ||||
| #if 0 | #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); | CarlaPlugin* const plugin = getPluginUnchecked(i); | ||||
| @@ -30,11 +30,11 @@ endif | |||||
| OBJS = \ | OBJS = \ | ||||
| carla_plugin.cpp.o \ | carla_plugin.cpp.o \ | ||||
| native.cpp.o | |||||
| native.cpp.o \ | |||||
| ladspa.cpp.o | |||||
| # carla_plugin_thread.cpp.o \ | # carla_plugin_thread.cpp.o \ | ||||
| # carla_bridge.cpp.o \ | # carla_bridge.cpp.o \ | ||||
| # ladspa.cpp.o \ | |||||
| # dssi.cpp.o \ | # dssi.cpp.o \ | ||||
| # lv2.cpp.o \ | # lv2.cpp.o \ | ||||
| # vst.cpp.o \ | # vst.cpp.o \ | ||||
| @@ -1231,7 +1231,7 @@ void CarlaPlugin::postRtEventsRun() | |||||
| // Update OSC control client | // Update OSC control client | ||||
| if (fData->engine->isOscControlRegistered()) | 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++) | 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); | 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); | 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); | fData->engine->osc_send_control_set_default_value(fData->id, j, fData->param.ranges[j].def); | ||||
| } | } | ||||
| #endif | #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); | qDebug("CarlaPlugin::newNative(%p, \"%s\", \"%s\", \"%s\")", init.engine, init.filename, init.name, init.label); | ||||
| return nullptr; | |||||
| #if 0 | |||||
| short id = init.engine->getNewPluginId(); | short id = init.engine->getNewPluginId(); | ||||
| if (id < 0 || id > init.engine->maxPluginNumber()) | if (id < 0 || id > init.engine->maxPluginNumber()) | ||||
| @@ -1704,8 +1706,8 @@ CarlaPlugin* CarlaPlugin::newNative(const initializer& init) | |||||
| plugin->registerToOscClient(); | plugin->registerToOscClient(); | ||||
| return plugin; | return plugin; | ||||
| } | |||||
| #endif | #endif | ||||
| } | |||||
| // ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
| @@ -51,6 +51,7 @@ endif | |||||
| LIBS = ../libcarla_engine.a | LIBS = ../libcarla_engine.a | ||||
| LIBS += ../libcarla_plugin.a | LIBS += ../libcarla_plugin.a | ||||
| LIBS += ../libcarla_native.a | LIBS += ../libcarla_native.a | ||||
| LIBS += ../../libs/rtmempool.a | |||||
| OBJS = \ | OBJS = \ | ||||
| carla_standalone.cpp.o | carla_standalone.cpp.o | ||||
| @@ -201,7 +201,8 @@ bool carla_engine_init(const char* driverName, const char* clientName) | |||||
| } | } | ||||
| #endif | #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_PROCESS_MODE, standalone.options.processMode, nullptr); | ||||
| standalone.engine->setOption(CarlaBackend::OPTION_FORCE_STEREO, standalone.options.forceStereo, 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 codecs import open as codecopen | ||||
| from copy import deepcopy | from copy import deepcopy | ||||
| #from decimal import Decimal | #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, | #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 | #from PyQt4.QtXml import QDomDocument | ||||
| # ------------------------------------------------------------------------------------------------------------ | # ------------------------------------------------------------------------------------------------------------ | ||||
| # Imports (Custom) | # Imports (Custom) | ||||
| import ui_carla_about | import ui_carla_about | ||||
| #import ui_carla_edit | |||||
| import ui_carla_edit | |||||
| import ui_carla_parameter | import ui_carla_parameter | ||||
| #import ui_carla_plugin | |||||
| import ui_carla_plugin | |||||
| # ------------------------------------------------------------------------------------------------------------ | # ------------------------------------------------------------------------------------------------------------ | ||||
| # Try Import Signal | # Try Import Signal | ||||
| @@ -398,7 +398,7 @@ CarlaStateParameter = { | |||||
| } | } | ||||
| CarlaStateCustomData = { | CarlaStateCustomData = { | ||||
| 'type': None, #CUSTOM_DATA_INVALID, | |||||
| 'type': "", | |||||
| 'key': "", | 'key': "", | ||||
| 'value': "" | 'value': "" | ||||
| } | } | ||||
| @@ -842,6 +842,10 @@ class PluginParameter(QWidget): | |||||
| self.fMidiChannel = channel | self.fMidiChannel = channel | ||||
| self.ui.sb_channel.setValue(channel) | self.ui.sb_channel.setValue(channel) | ||||
| def setLabelWidth(self, width): | |||||
| self.ui.label.setMinimumWidth(width) | |||||
| self.ui.label.setMaximumWidth(width) | |||||
| def tabIndex(self): | def tabIndex(self): | ||||
| return self.fTabIndex | return self.fTabIndex | ||||
| @@ -883,6 +887,598 @@ class PluginParameter(QWidget): | |||||
| def _textCallBack(self): | def _textCallBack(self): | ||||
| return cString(Carla.host.get_parameter_text(self.fPluginId, self.fParameterId)) | 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 | # TESTING | ||||
| @@ -912,6 +1508,10 @@ class PluginParameter(QWidget): | |||||
| #app = QApplication(sys.argv) | #app = QApplication(sys.argv) | ||||
| #gui1 = CarlaAboutW(None) | #gui1 = CarlaAboutW(None) | ||||
| #gui2 = PluginParameter(None, ptest, 0, 0) | #gui2 = PluginParameter(None, ptest, 0, 0) | ||||
| #gui3 = PluginEdit(None, 0) | |||||
| #gui4 = PluginWidget(None, 0) | |||||
| #gui1.show() | #gui1.show() | ||||
| #gui2.show() | #gui2.show() | ||||
| #gui3.show() | |||||
| #gui4.show() | |||||
| #app.exec_() | #app.exec_() | ||||
| @@ -633,6 +633,9 @@ private: | |||||
| std::strcpy(buffer, strBuf); | std::strcpy(buffer, strBuf); | ||||
| // FIXME? | |||||
| buffer[bufferLen-1] = '\0'; | |||||
| firstInit = false; | firstInit = false; | ||||
| } | } | ||||
| } | } | ||||
| @@ -651,7 +654,7 @@ private: | |||||
| bufferLen = 0; | bufferLen = 0; | ||||
| buffer = new char[1]; | buffer = new char[1]; | ||||
| buffer[0] = 0; | |||||
| buffer[0] = '\0'; | |||||
| firstInit = false; | firstInit = false; | ||||
| } | } | ||||