@@ -742,16 +742,6 @@ struct CustomData { | |||
: type(nullptr), | |||
key(nullptr), | |||
value(nullptr) {} | |||
~CustomData() | |||
{ | |||
if (type != nullptr) | |||
delete[] type; | |||
if (key != nullptr) | |||
delete[] key; | |||
if (value != nullptr) | |||
delete[] value; | |||
} | |||
}; | |||
/**@}*/ | |||
@@ -907,11 +907,6 @@ public: | |||
*/ | |||
void setAboutToClose(); | |||
/*! | |||
* Safely block-wait until a plugin proccessing callback ends. | |||
*/ | |||
void waitForProccessEnd(const unsigned int pluginId); | |||
#ifndef BUILD_BRIDGE | |||
// ------------------------------------------------------------------- | |||
// Options | |||
@@ -746,6 +746,7 @@ public: | |||
/*! | |||
* Post pone an event of type \a type.\n | |||
* The event will be processed later, but as soon as possible. | |||
* \note RT call | |||
*/ | |||
void postponeRtEvent(const PluginPostRtEventType type, const int32_t value1, const int32_t value2, const float value3); | |||
@@ -348,14 +348,6 @@ CarlaEngine::~CarlaEngine() | |||
// ----------------------------------------------------------------------- | |||
// Helpers | |||
void doIdle(CarlaEngineProtectedData* const kData, const bool unlock) | |||
{ | |||
kData->nextAction.opcode = EnginePostActionNull; | |||
if (unlock) | |||
kData->nextAction.mutex.unlock(); | |||
} | |||
void doPluginRemove(CarlaEngineProtectedData* const kData, const bool unlock) | |||
{ | |||
CARLA_ASSERT(kData->curPluginCount > 0); | |||
@@ -868,7 +860,7 @@ bool CarlaEngine::removePlugin(const unsigned int id) | |||
void CarlaEngine::removeAllPlugins() | |||
{ | |||
carla_debug("CarlaEngine::removeAllPlugins()"); | |||
carla_debug("CarlaEngine::removeAllPlugins() - START"); | |||
kData->thread.stopNow(); | |||
@@ -877,7 +869,6 @@ void CarlaEngine::removeAllPlugins() | |||
const unsigned int oldCount = kData->curPluginCount; | |||
kData->curPluginCount = 0; | |||
waitForProccessEnd(0); // FIXME - doesn't work for multi-client | |||
for (unsigned int i=0; i < oldCount; i++) | |||
{ | |||
@@ -885,20 +876,23 @@ void CarlaEngine::removeAllPlugins() | |||
CARLA_ASSERT(plugin != nullptr); | |||
kData->plugins[i].plugin = nullptr; | |||
if (plugin != nullptr) | |||
delete plugin; | |||
// clear this plugin | |||
kData->plugins[i].plugin = nullptr; | |||
kData->plugins[i].insPeak[0] = 0.0; | |||
kData->plugins[i].insPeak[1] = 0.0; | |||
kData->plugins[i].outsPeak[0] = 0.0; | |||
kData->plugins[i].outsPeak[1] = 0.0; | |||
kData->plugins[i].insPeak[0] = 0.0f; | |||
kData->plugins[i].insPeak[1] = 0.0f; | |||
kData->plugins[i].outsPeak[0] = 0.0f; | |||
kData->plugins[i].outsPeak[1] = 0.0f; | |||
} | |||
} | |||
if (isRunning() && ! kData->aboutToClose) | |||
kData->thread.startNow(); | |||
carla_debug("CarlaEngine::removeAllPlugins() - END"); | |||
} | |||
CarlaPlugin* CarlaEngine::getPlugin(const unsigned int id) const | |||
@@ -1154,14 +1148,14 @@ void CarlaEngine::setCallback(const CallbackFunc func, void* const ptr) | |||
// ----------------------------------------------------------------------- | |||
// Patchbay | |||
void CarlaEngine::patchbayConnect(int portA, int portB) | |||
void CarlaEngine::patchbayConnect(int, int) | |||
{ | |||
// TODO | |||
// nothing | |||
} | |||
void CarlaEngine::patchbayDisconnect(int connectionId) | |||
void CarlaEngine::patchbayDisconnect(int) | |||
{ | |||
// TODO | |||
// nothing | |||
} | |||
// ----------------------------------------------------------------------- | |||
@@ -1201,31 +1195,6 @@ void CarlaEngine::setAboutToClose() | |||
kData->aboutToClose = true; | |||
} | |||
// ----------------------------------------------------------------------- | |||
// Misc | |||
void CarlaEngine::waitForProccessEnd(const unsigned int pluginId) | |||
{ | |||
carla_debug("CarlaEngine::waitForProccessEnd()"); | |||
kData->nextAction.pluginId = pluginId; | |||
kData->nextAction.opcode = EnginePostActionIdle; | |||
kData->nextAction.mutex.lock(); | |||
if (isRunning()) | |||
{ | |||
// block wait for unlock on proccessing side | |||
kData->nextAction.mutex.lock(); | |||
} | |||
else | |||
{ | |||
doIdle(kData, false); | |||
} | |||
kData->nextAction.mutex.unlock(); | |||
} | |||
// ----------------------------------------------------------------------- | |||
// Global options | |||
@@ -1441,9 +1410,6 @@ void CarlaEngine::proccessPendingEvents() | |||
{ | |||
case EnginePostActionNull: | |||
break; | |||
case EnginePostActionIdle: | |||
doIdle(kData, true); | |||
break; | |||
case EnginePostActionRemovePlugin: | |||
doPluginRemove(kData, true); | |||
break; | |||
@@ -97,23 +97,8 @@ const uint32_t PATCHBAY_BUFFER_SIZE = 128; | |||
const unsigned short PATCHBAY_EVENT_COUNT = 512; | |||
const unsigned short RACK_EVENT_COUNT = 512; | |||
#if 0 | |||
struct EnginePostEvent { | |||
EnginePostEventType type; | |||
int32_t value1; | |||
void* valuePtr; | |||
EnginePostEvent() | |||
: type(EnginePostEventNull), | |||
value1(-1), | |||
valuePtr(nullptr) {} | |||
}; | |||
#endif | |||
enum EnginePostAction { | |||
EnginePostActionNull, | |||
EnginePostActionIdle, | |||
EnginePostActionInsertPlugin, | |||
EnginePostActionRemovePlugin | |||
}; | |||
@@ -1627,6 +1627,8 @@ private: | |||
engine->processPlugin(plugin, nframes); | |||
plugin->unlock(); | |||
} | |||
else | |||
carla_stdout("Plugin not enabled or locked"); | |||
return 0; | |||
} | |||
@@ -80,6 +80,9 @@ public: | |||
{ | |||
carla_debug("BridgePlugin::~BridgePlugin()"); | |||
kData->singleMutex.lock(); | |||
kData->masterMutex.lock(); | |||
if (osc.data.target) | |||
{ | |||
osc_send_hide(&osc.data); | |||
@@ -95,8 +95,6 @@ CarlaPlugin::~CarlaPlugin() | |||
{ | |||
carla_debug("CarlaPlugin::~CarlaPlugin()"); | |||
kData->mutex.lock(); | |||
// Remove client and ports | |||
if (kData->client != nullptr) | |||
{ | |||
@@ -120,7 +118,10 @@ CarlaPlugin::~CarlaPlugin() | |||
kData->prog.clear(); | |||
kData->midiprog.clear(); | |||
kData->custom.clear(); | |||
kData->mutex.unlock(); | |||
// MUST have been unlocked before | |||
kData->masterMutex.unlock(); | |||
kData->singleMutex.unlock(); | |||
libClose(); | |||
@@ -232,7 +233,7 @@ const CustomData& CarlaPlugin::customData(const size_t index) const | |||
{ | |||
CARLA_ASSERT(index < kData->custom.count()); | |||
return (index < kData->custom.count()) ? *kData->custom.getAt(index) : kCustomDataNull; | |||
return (index < kData->custom.count()) ? kData->custom.getAt(index) : kCustomDataNull; | |||
} | |||
int32_t CarlaPlugin::chunkData(void** const dataPtr) | |||
@@ -509,9 +510,9 @@ const SaveState& CarlaPlugin::getSaveState() | |||
// ---------------------------- | |||
// Custom Data | |||
for (uint32_t i=0, count=customDataCount(); i < count; i++) | |||
for (auto it = kData->custom.begin(); it.valid(); it.next()) | |||
{ | |||
const CustomData& cData = customData(i); | |||
const CustomData& cData(*it); | |||
if (cData.type == nullptr) | |||
continue; | |||
@@ -554,7 +555,7 @@ void CarlaPlugin::loadSaveState(const SaveState& saveState) | |||
for (auto it = saveState.customData.begin(); it != saveState.customData.end(); ++it) | |||
{ | |||
StateCustomData* stateCustomData = *it; | |||
const StateCustomData* const stateCustomData(*it); | |||
if (std::strcmp(stateCustomData->type, CUSTOM_DATA_CHUNK) != 0) | |||
setCustomData(stateCustomData->type, stateCustomData->key, stateCustomData->value, true); | |||
@@ -724,7 +725,7 @@ void CarlaPlugin::loadSaveState(const SaveState& saveState) | |||
for (auto it = saveState.customData.begin(); it != saveState.customData.end(); ++it) | |||
{ | |||
StateCustomData* stateCustomData = *it; | |||
const StateCustomData* const stateCustomData(*it); | |||
if (std::strcmp(stateCustomData->type, CUSTOM_DATA_CHUNK) == 0) | |||
setCustomData(stateCustomData->type, stateCustomData->key, stateCustomData->value, true); | |||
@@ -1147,27 +1148,29 @@ void CarlaPlugin::setCustomData(const char* const type, const char* const key, c | |||
if (saveData) | |||
{ | |||
// Check if we already have this key | |||
for (size_t i=0, count=kData->custom.count(); i < count; i++) | |||
for (auto it = kData->custom.begin(); it.valid(); it.next()) | |||
{ | |||
CustomData* const cData(kData->custom.getAt(i)); | |||
CustomData& cData(*it); | |||
assert(cData->type != nullptr); | |||
assert(cData->key != nullptr); | |||
assert(cData->value != nullptr); | |||
CARLA_ASSERT(cData.type != nullptr); | |||
CARLA_ASSERT(cData.key != nullptr); | |||
CARLA_ASSERT(cData.value != nullptr); | |||
if (std::strcmp(cData->key, key) == 0) | |||
if (std::strcmp(cData.key, key) == 0) | |||
{ | |||
delete[] cData->value; | |||
cData->value = carla_strdup(value); | |||
if (cData.value != nullptr) | |||
delete[] cData.value; | |||
cData.value = carla_strdup(value); | |||
return; | |||
} | |||
} | |||
// Otherwise store it | |||
CustomData* newData(new CustomData); | |||
newData->type = carla_strdup(type); | |||
newData->key = carla_strdup(key); | |||
newData->value = carla_strdup(value); | |||
CustomData newData; | |||
newData.type = carla_strdup(type); | |||
newData.key = carla_strdup(key); | |||
newData.value = carla_strdup(value); | |||
kData->custom.append(newData); | |||
} | |||
} | |||
@@ -1365,12 +1368,12 @@ void CarlaPlugin::recreateLatencyBuffers() | |||
bool CarlaPlugin::tryLock() | |||
{ | |||
return kData->mutex.tryLock(); | |||
return kData->masterMutex.tryLock(); | |||
} | |||
void CarlaPlugin::unlock() | |||
{ | |||
kData->mutex.unlock(); | |||
kData->masterMutex.unlock(); | |||
} | |||
// ------------------------------------------------------------------- | |||
@@ -1548,21 +1551,21 @@ void CarlaPlugin::updateOscData(const lo_address& source, const char* const url) | |||
osc_send_sample_rate(&kData->osc.data, kData->engine->getSampleRate()); | |||
for (size_t i=0, count=kData->custom.count(); i < count; i++) | |||
for (auto it = kData->custom.begin(); it.valid(); it.next()) | |||
{ | |||
CustomData* const cData(kData->custom.getAt(i)); | |||
const CustomData& cData(*it); | |||
assert(cData->type != nullptr); | |||
assert(cData->key != nullptr); | |||
assert(cData->value != nullptr); | |||
CARLA_ASSERT(cData.type != nullptr); | |||
CARLA_ASSERT(cData.key != nullptr); | |||
CARLA_ASSERT(cData.value != nullptr); | |||
#ifdef WANT_LV2 | |||
if (type() == PLUGIN_LV2) | |||
osc_send_lv2_transfer_event(&kData->osc.data, 0, cData->type, cData->value); | |||
osc_send_lv2_transfer_event(&kData->osc.data, 0, cData.type, cData.value); | |||
else | |||
#endif | |||
if (std::strcmp(cData->type, CUSTOM_DATA_STRING) == 0) | |||
osc_send_configure(&kData->osc.data, cData->key, cData->value); | |||
if (std::strcmp(cData.type, CUSTOM_DATA_STRING) == 0) | |||
osc_send_configure(&kData->osc.data, cData.key, cData.value); | |||
} | |||
if (kData->prog.current >= 0) | |||
@@ -1592,11 +1595,12 @@ void CarlaPlugin::freeOscData() | |||
bool CarlaPlugin::waitForOscGuiShow() | |||
{ | |||
carla_stdout("CarlaPlugin::waitForOscGuiShow()"); | |||
uint i=0, oscUiTimeout = kData->engine->getOptions().oscUiTimeout; | |||
// wait for UI 'update' call | |||
for (uint i=0, oscUiTimeout = kData->engine->getOptions().oscUiTimeout; i < oscUiTimeout; i++) | |||
for (; i < oscUiTimeout; i++) | |||
{ | |||
if (kData->osc.data.target) | |||
if (kData->osc.data.target != nullptr) | |||
{ | |||
carla_stdout("CarlaPlugin::waitForOscGuiShow() - got response, asking UI to show itself now"); | |||
osc_send_show(&kData->osc.data); | |||
@@ -1606,7 +1610,7 @@ bool CarlaPlugin::waitForOscGuiShow() | |||
carla_msleep(100); | |||
} | |||
carla_stdout("CarlaPlugin::waitForOscGuiShow() - Timeout while waiting for UI to respond (waited %u msecs)", kData->engine->getOptions().oscUiTimeout); | |||
carla_stdout("CarlaPlugin::waitForOscGuiShow() - Timeout while waiting for UI to respond (waited %u msecs)", oscUiTimeout); | |||
return false; | |||
} | |||
@@ -1651,26 +1655,25 @@ void CarlaPlugin::sendMidiSingleNote(const uint8_t channel, const uint8_t note, | |||
#endif | |||
if (sendCallback) | |||
kData->engine->callback(velo ? CALLBACK_NOTE_ON : CALLBACK_NOTE_OFF, fId, channel, note, velo, nullptr); | |||
kData->engine->callback((velo > 0) ? CALLBACK_NOTE_ON : CALLBACK_NOTE_OFF, fId, channel, note, velo, nullptr); | |||
} | |||
void CarlaPlugin::sendMidiAllNotesOff() | |||
{ | |||
kData->postRtEvents.mutex.lock(); | |||
if (kData->ctrlChannel < 0 || kData->ctrlChannel >= MAX_MIDI_CHANNELS) | |||
return; | |||
PluginPostRtEvent postEvent; | |||
postEvent.type = kPluginPostRtEventNoteOff; | |||
postEvent.value1 = kData->ctrlChannel; | |||
postEvent.value2 = 0; | |||
postEvent.value3 = 0.0; | |||
postEvent.value3 = 0.0f; | |||
for (unsigned short i=0; i < MAX_MIDI_NOTE; i++) | |||
{ | |||
postEvent.value2 = i; | |||
kData->postRtEvents.data.append(postEvent); | |||
kData->postRtEvents.appendRT(postEvent); | |||
} | |||
kData->postRtEvents.mutex.unlock(); | |||
} | |||
// ------------------------------------------------------------------- | |||
@@ -1902,7 +1905,7 @@ CarlaPlugin::ScopedDisabler::ScopedDisabler(CarlaPlugin* const plugin) | |||
carla_debug("CarlaPlugin::ScopedDisabler(%p)", plugin); | |||
CARLA_ASSERT(plugin != nullptr); | |||
plugin->kData->mutex.lock(); | |||
plugin->kData->masterMutex.lock(); | |||
if (plugin->fEnabled) | |||
plugin->fEnabled = false; | |||
@@ -1917,7 +1920,7 @@ CarlaPlugin::ScopedDisabler::~ScopedDisabler() | |||
kPlugin->fEnabled = true; | |||
kPlugin->kData->client->activate(); | |||
kPlugin->kData->mutex.unlock(); | |||
kPlugin->kData->masterMutex.unlock(); | |||
} | |||
// ------------------------------------------------------------------- | |||
@@ -1931,7 +1934,7 @@ CarlaPlugin::ScopedProcessLocker::ScopedProcessLocker(CarlaPlugin* const plugin, | |||
CARLA_ASSERT(plugin != nullptr); | |||
if (block) | |||
plugin->kData->mutex.lock(); | |||
plugin->kData->singleMutex.lock(); | |||
} | |||
CarlaPlugin::ScopedProcessLocker::~ScopedProcessLocker() | |||
@@ -1940,9 +1943,10 @@ CarlaPlugin::ScopedProcessLocker::~ScopedProcessLocker() | |||
if (kBlock) | |||
{ | |||
if (kPlugin->kData->mutex.wasTryLockCalled()) | |||
if (kPlugin->kData->singleMutex.wasTryLockCalled()) | |||
kPlugin->kData->needsReset = true; | |||
kPlugin->kData->mutex.unlock(); | |||
kPlugin->kData->singleMutex.unlock(); | |||
} | |||
} | |||
@@ -433,9 +433,10 @@ struct CarlaPluginProtectedData { | |||
PluginParameterData param; | |||
PluginProgramData prog; | |||
PluginMidiProgramData midiprog; | |||
NonRtList<CustomData*> custom; | |||
NonRtList<CustomData> custom; | |||
CarlaMutex mutex; | |||
CarlaMutex masterMutex; // global master lock | |||
CarlaMutex singleMutex; // small lock used only in processSingle() | |||
struct ExternalNotes { | |||
CarlaMutex mutex; | |||
@@ -52,6 +52,9 @@ public: | |||
{ | |||
carla_debug("DssiPlugin::~DssiPlugin()"); | |||
kData->singleMutex.lock(); | |||
kData->masterMutex.lock(); | |||
// close UI | |||
if (fHints & PLUGIN_HAS_GUI) | |||
{ | |||
@@ -269,8 +272,6 @@ public: | |||
if (fDssiDescriptor->configure != nullptr) | |||
{ | |||
const ScopedProcessLocker spl(this, true); | |||
fDssiDescriptor->configure(fHandle, key, value); | |||
if (fHandle2) | |||
@@ -1421,9 +1422,9 @@ public: | |||
if (kData->engine->isOffline()) | |||
{ | |||
kData->mutex.lock(); | |||
kData->singleMutex.lock(); | |||
} | |||
else if (! kData->mutex.tryLock()) | |||
else if (! kData->singleMutex.tryLock()) | |||
{ | |||
for (i=0; i < kData->audioOut.count; i++) | |||
{ | |||
@@ -1540,7 +1541,7 @@ public: | |||
// -------------------------------------------------------------------------------------------------------- | |||
kData->mutex.unlock(); | |||
kData->singleMutex.unlock(); | |||
return true; | |||
} | |||
@@ -71,6 +71,9 @@ public: | |||
{ | |||
carla_debug("FluidSynthPlugin::~FluidSynthPlugin()"); | |||
kData->singleMutex.lock(); | |||
kData->masterMutex.lock(); | |||
delete_fluid_synth(fSynth); | |||
delete_fluid_settings(fSettings); | |||
@@ -1226,9 +1229,9 @@ public: | |||
if (kData->engine->isOffline()) | |||
{ | |||
kData->mutex.lock(); | |||
kData->singleMutex.lock(); | |||
} | |||
else if (! kData->mutex.tryLock()) | |||
else if (! kData->singleMutex.tryLock()) | |||
{ | |||
for (i=0; i < kData->audioOut.count; i++) | |||
{ | |||
@@ -1307,7 +1310,7 @@ public: | |||
// -------------------------------------------------------------------------------------------------------- | |||
kData->mutex.unlock(); | |||
kData->singleMutex.unlock(); | |||
return true; | |||
} | |||
@@ -43,6 +43,9 @@ public: | |||
{ | |||
carla_debug("LadspaPlugin::~LadspaPlugin()"); | |||
kData->singleMutex.lock(); | |||
kData->masterMutex.lock(); | |||
if (fDescriptor != nullptr) | |||
{ | |||
if (fDescriptor->deactivate != nullptr && kData->activeBefore) | |||
@@ -1077,9 +1080,9 @@ public: | |||
if (kData->engine->isOffline()) | |||
{ | |||
kData->mutex.lock(); | |||
kData->singleMutex.lock(); | |||
} | |||
else if (! kData->mutex.tryLock()) | |||
else if (! kData->singleMutex.tryLock()) | |||
{ | |||
for (i=0; i < kData->audioOut.count; i++) | |||
{ | |||
@@ -1178,7 +1181,7 @@ public: | |||
// -------------------------------------------------------------------------------------------------------- | |||
kData->mutex.unlock(); | |||
kData->singleMutex.unlock(); | |||
return true; | |||
} | |||
@@ -188,6 +188,9 @@ public: | |||
{ | |||
carla_debug("LinuxSamplerPlugin::~LinuxSamplerPlugin()"); | |||
kData->singleMutex.lock(); | |||
kData->masterMutex.lock(); | |||
if (kData->activeBefore) | |||
fAudioOutputDevice->Stop(); | |||
@@ -801,7 +804,11 @@ public: | |||
// -------------------------------------------------------------------------------------------------------- | |||
// Try lock, silence otherwise | |||
if (! kData->mutex.tryLock()) | |||
if (kData->engine->isOffline()) | |||
{ | |||
kData->singleMutex.lock(); | |||
} | |||
else if (! kData->singleMutex.tryLock()) | |||
{ | |||
for (i=0; i < kData->audioOut.count; i++) | |||
{ | |||
@@ -869,7 +876,7 @@ public: | |||
// -------------------------------------------------------------------------------------------------------- | |||
kData->mutex.unlock(); | |||
kData->singleMutex.unlock(); | |||
return true; | |||
} | |||
@@ -329,6 +329,9 @@ public: | |||
#if 0 | |||
m_count -= 1; | |||
kData->singleMutex.lock(); | |||
kData->masterMutex.lock(); | |||
// close UI | |||
if (m_hints & PLUGIN_HAS_GUI) | |||
{ | |||
@@ -135,6 +135,9 @@ public: | |||
{ | |||
carla_debug("NativePlugin::~NativePlugin()"); | |||
kData->singleMutex.lock(); | |||
kData->masterMutex.lock(); | |||
if (fDescriptor != nullptr) | |||
{ | |||
if (fDescriptor->ui_show != nullptr && fIsUiVisible) | |||
@@ -1488,9 +1491,9 @@ public: | |||
if (kData->engine->isOffline()) | |||
{ | |||
kData->mutex.lock(); | |||
kData->singleMutex.lock(); | |||
} | |||
else if (! kData->mutex.tryLock()) | |||
else if (! kData->singleMutex.tryLock()) | |||
{ | |||
for (i=0; i < kData->audioOut.count; i++) | |||
{ | |||
@@ -1586,7 +1589,7 @@ public: | |||
// -------------------------------------------------------------------------------------------------------- | |||
kData->mutex.unlock(); | |||
kData->singleMutex.unlock(); | |||
return true; | |||
} | |||
@@ -81,6 +81,9 @@ public: | |||
// make plugin invalid | |||
unique2 += 1; | |||
kData->singleMutex.lock(); | |||
kData->masterMutex.lock(); | |||
if (effect) | |||
{ | |||
// close UI | |||
@@ -360,6 +360,9 @@ private: | |||
static void callback(void* ptr, CarlaBackend::CallbackType action, unsigned int pluginId, int value1, int value2, float value3, const char* valueStr) | |||
{ | |||
return ((CarlaPluginClient*)ptr)->handleCallback(action, value1, value2, value3, valueStr); | |||
// unused | |||
(void)pluginId; | |||
} | |||
}; | |||