| @@ -314,8 +314,7 @@ void CarlaEngine::removeAllPlugins() | |||||
| { | { | ||||
| qDebug("CarlaEngine::removeAllPlugins()"); | qDebug("CarlaEngine::removeAllPlugins()"); | ||||
| if (m_checkThread.isRunning()) | |||||
| m_checkThread.stopNow(); | |||||
| const CarlaCheckThread::ScopedLocker m(&m_checkThread); | |||||
| for (unsigned short i=0; i < MAX_PLUGINS; i++) | for (unsigned short i=0; i < MAX_PLUGINS; i++) | ||||
| { | { | ||||
| @@ -333,9 +332,6 @@ void CarlaEngine::removeAllPlugins() | |||||
| m_uniqueNames[i] = nullptr; | m_uniqueNames[i] = nullptr; | ||||
| } | } | ||||
| } | } | ||||
| if (isRunning()) | |||||
| m_checkThread.start(QThread::HighPriority); | |||||
| } | } | ||||
| void CarlaEngine::idlePluginGuis() | void CarlaEngine::idlePluginGuis() | ||||
| @@ -391,6 +391,42 @@ public: | |||||
| // ------------------------------------- | // ------------------------------------- | ||||
| /*! | |||||
| * \class CarlaEngineScopedLocker | |||||
| * | |||||
| * \brief Carla engine scoped locker | |||||
| * | |||||
| * This is a handy class that temporarily locks an engine during a function scope. | |||||
| */ | |||||
| class ScopedLocker | |||||
| { | |||||
| public: | |||||
| /*! | |||||
| * Lock the engine \a engine if \a lock is true. | |||||
| * The engine is unlocked in the deconstructor of this class if \a lock is true. | |||||
| * | |||||
| * \param engine The engine to lock | |||||
| * \param lock Wherever to lock the engine or not, true by default | |||||
| */ | |||||
| ScopedLocker(CarlaEngine* const engine, bool lock = true) : | |||||
| m_engine(engine), | |||||
| m_lock(lock) | |||||
| { | |||||
| if (m_lock) | |||||
| m_engine->processLock(); | |||||
| } | |||||
| ~ScopedLocker() | |||||
| { | |||||
| if (m_lock) | |||||
| m_engine->processUnlock(); | |||||
| } | |||||
| private: | |||||
| CarlaEngine* const m_engine; | |||||
| const bool m_lock; | |||||
| }; | |||||
| protected: | protected: | ||||
| CarlaEngineType type; | CarlaEngineType type; | ||||
| const char* name; | const char* name; | ||||
| @@ -420,42 +456,6 @@ private: | |||||
| double m_outsPeak[MAX_PLUGINS * MAX_PEAKS]; | double m_outsPeak[MAX_PLUGINS * MAX_PEAKS]; | ||||
| }; | }; | ||||
| /*! | |||||
| * \class CarlaEngineScopedLocker | |||||
| * | |||||
| * \brief Carla engine scoped locker | |||||
| * | |||||
| * This is a handy class that temporarily locks an engine during a function scope. | |||||
| */ | |||||
| class CarlaEngineScopedLocker | |||||
| { | |||||
| public: | |||||
| /*! | |||||
| * Lock the engine \a engine if \a lock is true. | |||||
| * The engine is unlocked in the deconstructor of this class if \a lock is true. | |||||
| * | |||||
| * \param engine The engine to lock | |||||
| * \param lock Wherever to lock the engine or not, true by default | |||||
| */ | |||||
| CarlaEngineScopedLocker(CarlaEngine* const engine, bool lock = true) : | |||||
| m_engine(engine), | |||||
| m_lock(lock) | |||||
| { | |||||
| if (m_lock) | |||||
| m_engine->processLock(); | |||||
| } | |||||
| ~CarlaEngineScopedLocker() | |||||
| { | |||||
| if (m_lock) | |||||
| m_engine->processUnlock(); | |||||
| } | |||||
| private: | |||||
| CarlaEngine* const m_engine; | |||||
| const bool m_lock; | |||||
| }; | |||||
| // ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
| class CarlaEngineClient | class CarlaEngineClient | ||||
| @@ -2033,6 +2033,57 @@ public: | |||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| /*! | |||||
| * \class CarlaPluginScopedDisabler | |||||
| * | |||||
| * \brief Carla plugin scoped disabler | |||||
| * | |||||
| * This is a handy class that temporarily disables a plugin during a function scope.\n | |||||
| * It should be used when the plugin needs reload or state change, something like this: | |||||
| * \code | |||||
| * { | |||||
| * const CarlaPluginScopedDisabler m(plugin); | |||||
| * plugin->setChunkData(data); | |||||
| * } | |||||
| * \endcode | |||||
| */ | |||||
| class ScopedDisabler | |||||
| { | |||||
| public: | |||||
| /*! | |||||
| * Disable plugin \a plugin if \a disable is true. | |||||
| * The plugin is re-enabled in the deconstructor of this class if \a disable is true. | |||||
| * | |||||
| * \param plugin The plugin to disable | |||||
| * \param disable Wherever to disable the plugin or not, true by default | |||||
| */ | |||||
| ScopedDisabler(CarlaPlugin* const plugin, bool disable = true) : | |||||
| m_plugin(plugin), | |||||
| m_disable(disable) | |||||
| { | |||||
| if (m_disable) | |||||
| { | |||||
| m_plugin->engineProcessLock(); | |||||
| m_plugin->setEnabled(false); | |||||
| m_plugin->engineProcessUnlock(); | |||||
| } | |||||
| } | |||||
| ~ScopedDisabler() | |||||
| { | |||||
| if (m_disable) | |||||
| { | |||||
| m_plugin->engineProcessLock(); | |||||
| m_plugin->setEnabled(true); | |||||
| m_plugin->engineProcessUnlock(); | |||||
| } | |||||
| } | |||||
| private: | |||||
| CarlaPlugin* const m_plugin; | |||||
| const bool m_disable; | |||||
| }; | |||||
| protected: | protected: | ||||
| unsigned short m_id; | unsigned short m_id; | ||||
| CarlaEngine* const x_engine; | CarlaEngine* const x_engine; | ||||
| @@ -2108,57 +2159,6 @@ protected: | |||||
| } | } | ||||
| }; | }; | ||||
| /*! | |||||
| * \class CarlaPluginScopedDisabler | |||||
| * | |||||
| * \brief Carla plugin scoped disabler | |||||
| * | |||||
| * This is a handy class that temporarily disables a plugin during a function scope.\n | |||||
| * It should be used when the plugin needs reload or state change, something like this: | |||||
| * \code | |||||
| * { | |||||
| * const CarlaPluginScopedDisabler m(plugin); | |||||
| * plugin->setChunkData(data); | |||||
| * } | |||||
| * \endcode | |||||
| */ | |||||
| class CarlaPluginScopedDisabler | |||||
| { | |||||
| public: | |||||
| /*! | |||||
| * Disable plugin \a plugin if \a disable is true. | |||||
| * The plugin is re-enabled in the deconstructor of this class if \a disable is true. | |||||
| * | |||||
| * \param plugin The plugin to disable | |||||
| * \param disable Wherever to disable the plugin or not, true by default | |||||
| */ | |||||
| CarlaPluginScopedDisabler(CarlaPlugin* const plugin, bool disable = true) : | |||||
| m_plugin(plugin), | |||||
| m_disable(disable) | |||||
| { | |||||
| if (m_disable) | |||||
| { | |||||
| m_plugin->engineProcessLock(); | |||||
| m_plugin->setEnabled(false); | |||||
| m_plugin->engineProcessUnlock(); | |||||
| } | |||||
| } | |||||
| ~CarlaPluginScopedDisabler() | |||||
| { | |||||
| if (m_disable) | |||||
| { | |||||
| m_plugin->engineProcessLock(); | |||||
| m_plugin->setEnabled(true); | |||||
| m_plugin->engineProcessUnlock(); | |||||
| } | |||||
| } | |||||
| private: | |||||
| CarlaPlugin* const m_plugin; | |||||
| const bool m_disable; | |||||
| }; | |||||
| /**@}*/ | /**@}*/ | ||||
| CARLA_BACKEND_END_NAMESPACE | CARLA_BACKEND_END_NAMESPACE | ||||
| @@ -64,7 +64,7 @@ void CarlaCheckThread::run() | |||||
| while (engine->isRunning() && ! m_stopNow) | while (engine->isRunning() && ! m_stopNow) | ||||
| { | { | ||||
| QMutexLocker(&this->mutex); // FIXME | |||||
| const ScopedLocker m(this); | |||||
| oscControllerRegisted = engine->isOscControllerRegisted(); | oscControllerRegisted = engine->isOscControllerRegisted(); | ||||
| for (unsigned short i=0; i < CarlaBackend::MAX_PLUGINS; i++) | for (unsigned short i=0; i < CarlaBackend::MAX_PLUGINS; i++) | ||||
| @@ -23,8 +23,6 @@ | |||||
| #include <QtCore/QMutex> | #include <QtCore/QMutex> | ||||
| #include <QtCore/QThread> | #include <QtCore/QThread> | ||||
| class QProcess; | |||||
| // -------------------------------------------------------------------------------------------------------- | // -------------------------------------------------------------------------------------------------------- | ||||
| // CarlaCheckThread | // CarlaCheckThread | ||||
| @@ -36,15 +34,23 @@ public: | |||||
| void stopNow(); | void stopNow(); | ||||
| void lock() | |||||
| { | |||||
| mutex.lock(); | |||||
| } | |||||
| void unlock() | |||||
| class ScopedLocker | |||||
| { | { | ||||
| mutex.unlock(); | |||||
| } | |||||
| public: | |||||
| ScopedLocker(CarlaCheckThread* const thread) | |||||
| : m_thread(thread) | |||||
| { | |||||
| m_thread->mutex.lock(); | |||||
| } | |||||
| ~ScopedLocker() | |||||
| { | |||||
| m_thread->mutex.unlock(); | |||||
| } | |||||
| private: | |||||
| CarlaCheckThread* const m_thread; | |||||
| }; | |||||
| protected: | protected: | ||||
| void run(); | void run(); | ||||
| @@ -58,6 +64,8 @@ private: | |||||
| // -------------------------------------------------------------------------------------------------------- | // -------------------------------------------------------------------------------------------------------- | ||||
| // CarlaPluginThread | // CarlaPluginThread | ||||
| class QProcess; | |||||
| class CarlaPluginThread : public QThread | class CarlaPluginThread : public QThread | ||||
| { | { | ||||
| public: | public: | ||||
| @@ -226,7 +226,7 @@ public: | |||||
| if (strcmp(key, "reloadprograms") == 0 || strcmp(key, "load") == 0 || strncmp(key, "patches", 7) == 0) | if (strcmp(key, "reloadprograms") == 0 || strcmp(key, "load") == 0 || strncmp(key, "patches", 7) == 0) | ||||
| { | { | ||||
| const CarlaPluginScopedDisabler m(this); | |||||
| const ScopedDisabler m(this); | |||||
| reloadPrograms(false); | reloadPrograms(false); | ||||
| } | } | ||||
| @@ -242,13 +242,12 @@ public: | |||||
| if (x_engine->isOffline()) | if (x_engine->isOffline()) | ||||
| { | { | ||||
| engineProcessLock(); | |||||
| const CarlaEngine::ScopedLocker m(x_engine); | |||||
| descriptor->set_custom_data(handle, chunk.data(), chunk.size()); | descriptor->set_custom_data(handle, chunk.data(), chunk.size()); | ||||
| engineProcessUnlock(); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| const CarlaPluginScopedDisabler m(this); | |||||
| const ScopedDisabler m(this); | |||||
| descriptor->set_custom_data(handle, chunk.data(), chunk.size()); | descriptor->set_custom_data(handle, chunk.data(), chunk.size()); | ||||
| } | } | ||||
| } | } | ||||
| @@ -261,13 +260,12 @@ public: | |||||
| { | { | ||||
| if (x_engine->isOffline()) | if (x_engine->isOffline()) | ||||
| { | { | ||||
| if (block) engineProcessLock(); | |||||
| const CarlaEngine::ScopedLocker m(x_engine, block); | |||||
| descriptor->select_program(handle, midiprog.data[index].bank, midiprog.data[index].program); | descriptor->select_program(handle, midiprog.data[index].bank, midiprog.data[index].program); | ||||
| if (block) engineProcessUnlock(); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| const CarlaPluginScopedDisabler m(this, block); | |||||
| const ScopedDisabler m(this, block); | |||||
| descriptor->select_program(handle, midiprog.data[index].bank, midiprog.data[index].program); | descriptor->select_program(handle, midiprog.data[index].bank, midiprog.data[index].program); | ||||
| } | } | ||||
| @@ -316,7 +314,7 @@ public: | |||||
| qDebug("DssiPlugin::reload() - start"); | qDebug("DssiPlugin::reload() - start"); | ||||
| // Safely disable plugin for reload | // Safely disable plugin for reload | ||||
| const CarlaPluginScopedDisabler m(this); | |||||
| const ScopedDisabler m(this); | |||||
| if (x_client->isActive()) | if (x_client->isActive()) | ||||
| x_client->deactivate(); | x_client->deactivate(); | ||||
| @@ -316,7 +316,7 @@ public: | |||||
| case FluidSynthChorusOnOff: | case FluidSynthChorusOnOff: | ||||
| { | { | ||||
| const CarlaPluginScopedDisabler m(this, ! x_engine->isOffline()); | |||||
| const ScopedDisabler m(this, ! x_engine->isOffline()); | |||||
| value = value > 0.5 ? 1 : 0; | value = value > 0.5 ? 1 : 0; | ||||
| fluid_synth_set_chorus_on(f_synth, value); | fluid_synth_set_chorus_on(f_synth, value); | ||||
| break; | break; | ||||
| @@ -328,21 +328,21 @@ public: | |||||
| case FluidSynthChorusDepthMs: | case FluidSynthChorusDepthMs: | ||||
| case FluidSynthChorusType: | case FluidSynthChorusType: | ||||
| { | { | ||||
| const CarlaPluginScopedDisabler m(this, ! x_engine->isOffline()); | |||||
| const ScopedDisabler m(this, ! x_engine->isOffline()); | |||||
| fluid_synth_set_chorus(f_synth, rint(param_buffers[FluidSynthChorusNr]), param_buffers[FluidSynthChorusLevel], param_buffers[FluidSynthChorusSpeedHz], param_buffers[FluidSynthChorusDepthMs], rint(param_buffers[FluidSynthChorusType])); | fluid_synth_set_chorus(f_synth, rint(param_buffers[FluidSynthChorusNr]), param_buffers[FluidSynthChorusLevel], param_buffers[FluidSynthChorusSpeedHz], param_buffers[FluidSynthChorusDepthMs], rint(param_buffers[FluidSynthChorusType])); | ||||
| break; | break; | ||||
| } | } | ||||
| case FluidSynthPolyphony: | case FluidSynthPolyphony: | ||||
| { | { | ||||
| const CarlaPluginScopedDisabler m(this, ! x_engine->isOffline()); | |||||
| const ScopedDisabler m(this, ! x_engine->isOffline()); | |||||
| fluid_synth_set_polyphony(f_synth, rint(value)); | fluid_synth_set_polyphony(f_synth, rint(value)); | ||||
| break; | break; | ||||
| } | } | ||||
| case FluidSynthInterpolation: | case FluidSynthInterpolation: | ||||
| { | { | ||||
| const CarlaPluginScopedDisabler m(this, ! x_engine->isOffline()); | |||||
| const ScopedDisabler m(this, ! x_engine->isOffline()); | |||||
| for (int i=0; i < 16; i++) | for (int i=0; i < 16; i++) | ||||
| fluid_synth_set_interp_method(f_synth, i, rint(value)); | fluid_synth_set_interp_method(f_synth, i, rint(value)); | ||||
| break; | break; | ||||
| @@ -366,13 +366,12 @@ public: | |||||
| { | { | ||||
| if (x_engine->isOffline()) | if (x_engine->isOffline()) | ||||
| { | { | ||||
| if (block) engineProcessLock(); | |||||
| const CarlaEngine::ScopedLocker m(x_engine, block); | |||||
| fluid_synth_program_select(f_synth, cin_channel, f_id, midiprog.data[index].bank, midiprog.data[index].program); | fluid_synth_program_select(f_synth, cin_channel, f_id, midiprog.data[index].bank, midiprog.data[index].program); | ||||
| if (block) engineProcessUnlock(); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| const CarlaPluginScopedDisabler m(this, block); | |||||
| const ScopedDisabler m(this, block); | |||||
| fluid_synth_program_select(f_synth, cin_channel, f_id, midiprog.data[index].bank, midiprog.data[index].program); | fluid_synth_program_select(f_synth, cin_channel, f_id, midiprog.data[index].bank, midiprog.data[index].program); | ||||
| } | } | ||||
| } | } | ||||
| @@ -388,7 +387,7 @@ public: | |||||
| qDebug("FluidSynthPlugin::reload() - start"); | qDebug("FluidSynthPlugin::reload() - start"); | ||||
| // Safely disable plugin for reload | // Safely disable plugin for reload | ||||
| const CarlaPluginScopedDisabler m(this); | |||||
| const ScopedDisabler m(this); | |||||
| if (x_client->isActive()) | if (x_client->isActive()) | ||||
| x_client->deactivate(); | x_client->deactivate(); | ||||
| @@ -300,7 +300,7 @@ public: | |||||
| qDebug("LadspaPlugin::reload() - start"); | qDebug("LadspaPlugin::reload() - start"); | ||||
| // Safely disable plugin for reload | // Safely disable plugin for reload | ||||
| const CarlaPluginScopedDisabler m(this); | |||||
| const ScopedDisabler m(this); | |||||
| if (x_client->isActive()) | if (x_client->isActive()) | ||||
| x_client->deactivate(); | x_client->deactivate(); | ||||
| @@ -136,7 +136,7 @@ public: | |||||
| qDebug("LinuxSamplerPlugin::reload() - start"); | qDebug("LinuxSamplerPlugin::reload() - start"); | ||||
| // Safely disable plugin for reload | // Safely disable plugin for reload | ||||
| const CarlaPluginScopedDisabler m(this); | |||||
| const ScopedDisabler m(this); | |||||
| if (x_client->isActive()) | if (x_client->isActive()) | ||||
| x_client->deactivate(); | x_client->deactivate(); | ||||
| @@ -714,13 +714,12 @@ public: | |||||
| if (x_engine->isOffline()) | if (x_engine->isOffline()) | ||||
| { | { | ||||
| engineProcessLock(); | |||||
| const CarlaEngine::ScopedLocker m(x_engine); | |||||
| status = ext.state->restore(handle, carla_lv2_state_retrieve, this, 0, features); | status = ext.state->restore(handle, carla_lv2_state_retrieve, this, 0, features); | ||||
| engineProcessUnlock(); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| const CarlaPluginScopedDisabler m(this); | |||||
| const ScopedDisabler m(this); | |||||
| status = ext.state->restore(handle, carla_lv2_state_retrieve, this, 0, features); | status = ext.state->restore(handle, carla_lv2_state_retrieve, this, 0, features); | ||||
| } | } | ||||
| @@ -756,13 +755,12 @@ public: | |||||
| { | { | ||||
| if (x_engine->isOffline()) | if (x_engine->isOffline()) | ||||
| { | { | ||||
| if (block) engineProcessLock(); | |||||
| const CarlaEngine::ScopedLocker m(x_engine, block); | |||||
| ext.programs->select_program(handle, midiprog.data[index].bank, midiprog.data[index].program); | ext.programs->select_program(handle, midiprog.data[index].bank, midiprog.data[index].program); | ||||
| if (block) engineProcessUnlock(); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| const CarlaPluginScopedDisabler m(this, block); | |||||
| const ScopedDisabler m(this, block); | |||||
| ext.programs->select_program(handle, midiprog.data[index].bank, midiprog.data[index].program); | ext.programs->select_program(handle, midiprog.data[index].bank, midiprog.data[index].program); | ||||
| } | } | ||||
| @@ -922,7 +920,7 @@ public: | |||||
| qDebug("Lv2Plugin::reload() - start"); | qDebug("Lv2Plugin::reload() - start"); | ||||
| // Safely disable plugin for reload | // Safely disable plugin for reload | ||||
| const CarlaPluginScopedDisabler m(this); | |||||
| const ScopedDisabler m(this); | |||||
| if (x_client->isActive()) | if (x_client->isActive()) | ||||
| x_client->deactivate(); | x_client->deactivate(); | ||||
| @@ -2539,7 +2537,7 @@ public: | |||||
| { | { | ||||
| if (index == -1) | if (index == -1) | ||||
| { | { | ||||
| const CarlaPluginScopedDisabler m(this); | |||||
| const ScopedDisabler m(this); | |||||
| reloadPrograms(false); | reloadPrograms(false); | ||||
| } | } | ||||
| else | else | ||||
| @@ -223,13 +223,12 @@ public: | |||||
| if (x_engine->isOffline()) | if (x_engine->isOffline()) | ||||
| { | { | ||||
| engineProcessLock(); | |||||
| const CarlaEngine::ScopedLocker m(x_engine); | |||||
| effect->dispatcher(effect, effSetChunk, 0 /* bank */, chunk.size(), chunk.data(), 0.0f); | effect->dispatcher(effect, effSetChunk, 0 /* bank */, chunk.size(), chunk.data(), 0.0f); | ||||
| engineProcessUnlock(); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| const CarlaPluginScopedDisabler m(this); | |||||
| const ScopedDisabler m(this); | |||||
| effect->dispatcher(effect, effSetChunk, 0 /* bank */, chunk.size(), chunk.data(), 0.0f); | effect->dispatcher(effect, effSetChunk, 0 /* bank */, chunk.size(), chunk.data(), 0.0f); | ||||
| } | } | ||||
| } | } | ||||
| @@ -242,13 +241,12 @@ public: | |||||
| { | { | ||||
| if (x_engine->isOffline()) | if (x_engine->isOffline()) | ||||
| { | { | ||||
| if (block) engineProcessLock(); | |||||
| const CarlaEngine::ScopedLocker m(x_engine, block); | |||||
| effect->dispatcher(effect, effSetProgram, 0, index, nullptr, 0.0f); | effect->dispatcher(effect, effSetProgram, 0, index, nullptr, 0.0f); | ||||
| if (block) engineProcessUnlock(); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| const CarlaPluginScopedDisabler m(this, block); | |||||
| const ScopedDisabler m(this, block); | |||||
| effect->dispatcher(effect, effSetProgram, 0, index, nullptr, 0.0f); | effect->dispatcher(effect, effSetProgram, 0, index, nullptr, 0.0f); | ||||
| } | } | ||||
| } | } | ||||
| @@ -324,7 +322,7 @@ public: | |||||
| qDebug("VstPlugin::reload() - start"); | qDebug("VstPlugin::reload() - start"); | ||||
| // Safely disable plugin for reload | // Safely disable plugin for reload | ||||
| const CarlaPluginScopedDisabler m(this); | |||||
| const ScopedDisabler m(this); | |||||
| if (x_client->isActive()) | if (x_client->isActive()) | ||||
| x_client->deactivate(); | x_client->deactivate(); | ||||