24#include "../MemaAppConfiguration.h"
26#include <CustomLookAndFeel.h>
36 void setInputMute(std::uint16_t channel,
bool muteState,
int userId)
override
38 if (m_networkServer && m_networkServer->hasActiveConnections())
40 std::map<std::uint16_t, bool> inputMuteStates;
41 std::map<std::uint16_t, bool> outputMuteStates;
42 std::map<std::uint16_t, std::map<std::uint16_t, bool>> crosspointStates;
43 std::map<std::uint16_t, std::map<std::uint16_t, float>> crosspointValues;
45 inputMuteStates[channel] = muteState;
47 auto sendIds = m_networkServer->getActiveConnectionIds();
48 sendIds.erase(std::remove(sendIds.begin(), sendIds.end(), userId), sendIds.end());
49 m_networkServer->enqueueMessage(std::make_unique<ControlParametersMessage>(inputMuteStates, outputMuteStates, crosspointStates, crosspointValues)->getSerializedMessage(), sendIds);
53 void setOutputMute(std::uint16_t channel,
bool muteState,
int userId)
override
55 if (m_networkServer && m_networkServer->hasActiveConnections())
57 std::map<std::uint16_t, bool> inputMuteStates;
58 std::map<std::uint16_t, bool> outputMuteStates;
59 std::map<std::uint16_t, std::map<std::uint16_t, bool>> crosspointStates;
60 std::map<std::uint16_t, std::map<std::uint16_t, float>> crosspointValues;
62 outputMuteStates[channel] = muteState;
64 auto sendIds = m_networkServer->getActiveConnectionIds();
65 sendIds.erase(std::remove(sendIds.begin(), sendIds.end(), userId), sendIds.end());
66 m_networkServer->enqueueMessage(std::make_unique<ControlParametersMessage>(inputMuteStates, outputMuteStates, crosspointStates, crosspointValues)->getSerializedMessage(), sendIds);
72 if (m_networkServer && m_networkServer->hasActiveConnections())
74 std::map<std::uint16_t, bool> inputMuteStates;
75 std::map<std::uint16_t, bool> outputMuteStates;
76 std::map<std::uint16_t, std::map<std::uint16_t, bool>> crosspointStates;
77 std::map<std::uint16_t, std::map<std::uint16_t, float>> crosspointValues;
79 crosspointStates[input][output] = enabledState;
81 auto sendIds = m_networkServer->getActiveConnectionIds();
82 sendIds.erase(std::remove(sendIds.begin(), sendIds.end(), userId), sendIds.end());
83 m_networkServer->enqueueMessage(std::make_unique<ControlParametersMessage>(inputMuteStates, outputMuteStates, crosspointStates, crosspointValues)->getSerializedMessage(), sendIds);
89 if (m_networkServer && m_networkServer->hasActiveConnections())
91 std::map<std::uint16_t, bool> inputMuteStates;
92 std::map<std::uint16_t, bool> outputMuteStates;
93 std::map<std::uint16_t, std::map<std::uint16_t, bool>> crosspointStates;
94 std::map<std::uint16_t, std::map<std::uint16_t, float>> crosspointValues;
96 crosspointValues[input][output] = factor;
98 auto sendIds = m_networkServer->getActiveConnectionIds();
99 sendIds.erase(std::remove(sendIds.begin(), sendIds.end(), userId), sendIds.end());
100 m_networkServer->enqueueMessage(std::make_unique<ControlParametersMessage>(inputMuteStates, outputMuteStates, crosspointStates, crosspointValues)->getSerializedMessage(), sendIds);
104 void setPluginParameterInfos(
const std::vector<PluginParameterInfo>& parameterInfos,
const std::string& name,
bool enabled,
bool post,
int userId = -1)
override
106 if (m_networkServer && m_networkServer->hasActiveConnections())
108 auto sendIds = m_networkServer->getActiveConnectionIds();
109 sendIds.erase(std::remove(sendIds.begin(), sendIds.end(), userId), sendIds.end());
110 m_networkServer->enqueueMessage(std::make_unique<PluginParameterInfosMessage>(name, enabled, post, parameterInfos)->getSerializedMessage(), sendIds);
116 if (m_networkServer && m_networkServer->hasActiveConnections())
118 auto sendIds = m_networkServer->getActiveConnectionIds();
119 sendIds.erase(std::remove(sendIds.begin(), sendIds.end(), userId), sendIds.end());
120 m_networkServer->enqueueMessage(std::make_unique<PluginProcessingStateMessage>(enabled, post)->getSerializedMessage(), sendIds);
126 if (m_networkServer && m_networkServer->hasActiveConnections())
128 DBG(juce::String(__FUNCTION__) <<
" sending to net: " <<
int(index) <<
" > " << currentValue);
129 auto sendIds = m_networkServer->getActiveConnectionIds();
130 sendIds.erase(std::remove(sendIds.begin(), sendIds.end(), userId), sendIds.end());
131 m_networkServer->enqueueMessage(std::make_unique<PluginParameterValueMessage>(index,
id, currentValue)->getSerializedMessage(), sendIds);
135 void setIOCount(std::uint16_t inputCount, std::uint16_t outputCount)
override
137 if (m_networkServer && m_networkServer->hasActiveConnections())
139 m_networkServer->enqueueMessage(std::make_unique<ReinitIOCountMessage>(inputCount, outputCount)->getSerializedMessage());
145 m_networkServer = networkServer;
149 void setChannelCount(std::uint16_t channelCount)
override { ignoreUnused(channelCount); };
152 std::shared_ptr<InterprocessConnectionServerImpl> m_networkServer;
158 juce::AudioProcessor()
160#ifdef RUN_MESSAGE_TESTS
171 m_processorChannels[i][j] = 0.0f;
175 m_inputDataAnalyzer = std::make_unique<ProcessorDataAnalyzer>();
176 m_inputDataAnalyzer->setUseProcessingTypes(
true,
false,
false);
177 m_outputDataAnalyzer = std::make_unique<ProcessorDataAnalyzer>();
178 m_outputDataAnalyzer->setUseProcessingTypes(
true,
false,
false);
180 m_deviceManager = std::make_unique<AudioDeviceManager>();
181 m_deviceManager->addAudioCallback(
this);
182 m_deviceManager->addChangeListener(
this);
187 triggerConfigurationUpdate(
false);
191 m_serviceTopologyManager = std::make_unique<JUCEAppBasics::ServiceTopologyManager>(
194 JUCEAppBasics::ServiceTopologyManager::getServiceDescription(),
195 JUCEAppBasics::ServiceTopologyManager::getServiceDescription(),
199 m_networkServer = std::make_shared<InterprocessConnectionServerImpl>();
201 m_networkServer->onConnectionCreated = [=](
int connectionId) {
205 connection->
onConnectionLost = [=](
int connectionId) { DBG(juce::String(__FUNCTION__) <<
" connection " << connectionId <<
" lost");
206 m_trafficTypesPerConnection.erase(connectionId);
208 connection->onConnectionMade = [=](
int connectionId ) { DBG(juce::String(__FUNCTION__) <<
" connection " << connectionId <<
" made");
209 m_trafficTypesPerConnection[connectionId].clear();
210 if (m_networkServer && m_networkServer->hasActiveConnection(connectionId))
212 auto paletteStyle = JUCEAppBasics::CustomLookAndFeel::PaletteStyle::PS_Dark;
213 if (getActiveEditor())
214 if (
auto claf =
dynamic_cast<JUCEAppBasics::CustomLookAndFeel*
>(&getActiveEditor()->getLookAndFeel()))
215 paletteStyle = claf->getPaletteStyle();
217 std::map<std::uint16_t, bool> inputMuteStates;
218 std::map<std::uint16_t, bool> outputMuteStates;
219 std::map<std::uint16_t, std::map<std::uint16_t, bool>> matrixCrosspointStates;
220 std::map<std::uint16_t, std::map<std::uint16_t, float>> matrixCrosspointValues;
222 const ScopedLock sl(m_audioDeviceIOCallbackLock);
223 inputMuteStates = m_inputMuteStates;
224 outputMuteStates = m_outputMuteStates;
225 matrixCrosspointStates = m_matrixCrosspointStates;
226 matrixCrosspointValues = m_matrixCrosspointValues;
229 auto sendIds = std::vector<int>{ connectionId };
231 success = success && m_networkServer->enqueueMessage(std::make_unique<AnalyzerParametersMessage>(
int(getSampleRate()), getBlockSize())->getSerializedMessage(), sendIds);
232 success = success && m_networkServer->enqueueMessage(std::make_unique<ReinitIOCountMessage>(m_inputChannelCount, m_outputChannelCount)->getSerializedMessage(), sendIds);
233 success = success && m_networkServer->enqueueMessage(std::make_unique<EnvironmentParametersMessage>(paletteStyle)->getSerializedMessage(), sendIds);
234 success = success && m_networkServer->enqueueMessage(std::make_unique<ControlParametersMessage>(inputMuteStates, outputMuteStates, matrixCrosspointStates, matrixCrosspointValues)->getSerializedMessage(), sendIds);
236 auto orderedParams = m_pluginParameterInfos;
237 if (!m_pluginParameterDisplayOrder.empty() && m_pluginParameterDisplayOrder.size() == m_pluginParameterInfos.size())
239 orderedParams.clear();
240 for (
int idx : m_pluginParameterDisplayOrder)
241 if (idx >= 0 && idx <
static_cast<int>(m_pluginParameterInfos.size()))
242 orderedParams.push_back(m_pluginParameterInfos[idx]);
243 if (orderedParams.size() != m_pluginParameterInfos.size())
244 orderedParams = m_pluginParameterInfos;
246 success = success && m_networkServer->enqueueMessage(std::make_unique<PluginParameterInfosMessage>(m_pluginInstance ? m_pluginInstance->getName().toStdString() :
"", m_pluginEnabled, m_pluginPost, orderedParams)->getSerializedMessage(), sendIds);
249 m_networkServer->cleanupDeadConnections();
252 connection->onMessageReceived = [=](
int connectionId,
const juce::MemoryBlock& message) {
255 knownMessage->setId(connectionId);
256 postMessage(knownMessage);
259 DBG(juce::String(__FUNCTION__) +
" ignoring unknown message");
263 m_networkCommanderWrapper = std::make_unique<MemaNetworkClientCommanderWrapper>();
264 m_networkCommanderWrapper->setNetworkConnection(m_networkServer);
270 m_timedConfigurationDumper = std::make_unique<juce::TimedCallback>([=]() {
273 auto config = JUCEAppBasics::AppConfigurationBase::getInstance();
274 if (config !=
nullptr)
275 config->triggerConfigurationDump(
false);
279 m_timedConfigurationDumper->startTimer(100);
284 m_timedConfigurationDumper->stopTimer();
287 auto config = JUCEAppBasics::AppConfigurationBase::getInstance();
288 if (config !=
nullptr)
289 config->triggerConfigurationDump(
false);
293 m_networkServer->stop();
295 m_deviceManager->removeAudioCallback(
this);
299 delete[] m_processorChannels[i];
300 delete[] m_processorChannels;
309 devConfElm->addChildElement(m_deviceManager->createStateXml().release());
310 stateXml->addChildElement(devConfElm.release());
315 if (m_pluginInstance)
317 plgConfElm->addChildElement(m_pluginInstance->getPluginDescription().createXml().release());
319 juce::MemoryBlock destData;
320 m_pluginInstance->getStateInformation(destData);
321 plgConfElm->addTextElement(juce::Base64::toBase64(destData.getData(), destData.getSize()));
328 plgParamElm->addTextElement(plgParam.toString());
329 plgConfElm->addChildElement(plgParamElm.release());
331 if (!m_pluginParameterDisplayOrder.empty())
333 juce::StringArray orderStrs;
334 for (
int idx : m_pluginParameterDisplayOrder)
335 orderStrs.add(juce::String(idx));
338 stateXml->addChildElement(plgConfElm.release());
340 std::map<std::uint16_t, bool> inputMuteStates;
341 std::map<std::uint16_t, bool> outputMuteStates;
342 std::map<std::uint16_t, std::map<std::uint16_t, bool>> matrixCrosspointStates;
343 std::map<std::uint16_t, std::map<std::uint16_t, float>> matrixCrosspointValues;
346 const ScopedLock sl(m_audioDeviceIOCallbackLock);
347 inputMuteStates = m_inputMuteStates;
348 outputMuteStates = m_outputMuteStates;
349 matrixCrosspointStates = m_matrixCrosspointStates;
350 matrixCrosspointValues = m_matrixCrosspointValues;
354 juce::StringArray imutestatestr;
355 for (
auto const& mutestate : inputMuteStates)
356 imutestatestr.add(juce::String(mutestate.first) +
"," + juce::String(mutestate.second ? 1 : 0));
357 inputMutesElm->addTextElement(imutestatestr.joinIntoString(
";"));
358 stateXml->addChildElement(inputMutesElm.release());
361 juce::StringArray omutestatestr;
362 for (
auto const& mutestate : outputMuteStates)
363 omutestatestr.add(juce::String(mutestate.first) +
"," + juce::String(mutestate.second ? 1 : 0));
364 outputMutesElm->addTextElement(omutestatestr.joinIntoString(
";"));
365 stateXml->addChildElement(outputMutesElm.release());
368 juce::StringArray cgainstatestr;
369 for (
auto const& insKV : matrixCrosspointStates)
370 for (
auto const& outsKV : insKV.second)
371 cgainstatestr.add(juce::String(insKV.first) +
"," + juce::String(outsKV.first) +
"," + juce::String(outsKV.second ? 1 : 0) +
"," + juce::String(matrixCrosspointValues[insKV.first][outsKV.first]));
372 crosspointGainsElm->addTextElement(cgainstatestr.joinIntoString(
";"));
373 stateXml->addChildElement(crosspointGainsElm.release());
386 juce::XmlElement* deviceSetupXml =
nullptr;
388 if (
nullptr != devConfElm)
389 deviceSetupXml = devConfElm->getChildByName(
"DEVICESETUP");
397 bool deviceConfigChanged =
true;
398 if (m_lastAppliedDeviceConfigXml && devConfElm)
399 deviceConfigChanged = !devConfElm->isEquivalentTo(m_lastAppliedDeviceConfigXml.get(),
true);
400 else if (!m_lastAppliedDeviceConfigXml && !devConfElm)
401 deviceConfigChanged =
false;
403 if (deviceConfigChanged)
413 auto audioDeviceSetup = m_deviceManager->getAudioDeviceSetup();
415 if (result.isNotEmpty())
422 juce::AlertWindow::showMessageBoxAsync(juce::MessageBoxIconType::WarningIcon, juce::JUCEApplication::getInstance()->getApplicationName() +
" device init failed", result);
425 if (audioDeviceSetup.bufferSize < 512)
426 audioDeviceSetup.bufferSize = 512;
427 m_deviceManager->setAudioDeviceSetup(audioDeviceSetup,
true);
429 m_lastAppliedDeviceConfigXml = devConfElm ? std::make_unique<juce::XmlElement>(*devConfElm) :
nullptr;
437 if (
nullptr != plgConfElm)
441 auto pluginDescriptionXml = plgConfElm->getChildByName(
"PLUGIN");
442 if (
nullptr != pluginDescriptionXml)
444 auto pluginDescription = juce::PluginDescription();
445 pluginDescription.loadFromXml(*pluginDescriptionXml);
447 if (m_pluginInstance)
449 juce::MemoryOutputStream destDataStream;
450 juce::Base64::convertFromBase64(destDataStream, pluginDescriptionXml->getAllSubText());
451 m_pluginInstance->setStateInformation(destDataStream.getData(),
int(destDataStream.getDataSize()));
456 if (orderAttr.isNotEmpty())
458 m_pluginParameterDisplayOrder.clear();
459 juce::StringArray orderStrs;
460 orderStrs.addTokens(orderAttr,
",",
"");
461 for (
auto const& s : orderStrs)
462 m_pluginParameterDisplayOrder.push_back(s.getIntValue());
467 if (
nullptr != plgParamElm)
470 auto paramString = plgParamElm->getAllSubText();
473 jassert(paramInfo.index == index);
477 iter->initializeFromString(paramString);
482 jassert(paramInfo.name == param->getName(100));
483 jassert(paramInfo.label == param->getLabel());
485 jassert(paramInfo.isAutomatable == param->isAutomatable());
486 jassert(paramInfo.category == param->getCategory());
487 if (
auto* rangedParam =
dynamic_cast<const juce::RangedAudioParameter*
>(param))
489 auto range = rangedParam->getNormalisableRange();
490 jassert(paramInfo.minValue == range.start);
491 jassert(paramInfo.maxValue == range.end);
492 jassert(paramInfo.stepSize == range.interval);
493 jassert(paramInfo.isDiscrete == range.interval > 0.0f);
497 param->setValue(paramInfo.currentValue);
503 std::map<std::uint16_t, bool> inputMuteStates;
504 std::map<std::uint16_t, bool> outputMuteStates;
505 std::map<std::uint16_t, std::map<std::uint16_t, bool>> matrixCrosspointStates;
506 std::map<std::uint16_t, std::map<std::uint16_t, float>> matrixCrosspointValues;
508 if (
nullptr != inputMutesElm)
510 juce::StringArray inMutestateStrList;
511 auto inputMutesElmTxt = inputMutesElm->getAllSubText();
512 inMutestateStrList.addTokens(inputMutesElmTxt,
";",
"");
513 jassert(inMutestateStrList.size() == m_inputChannelCount);
514 if (inMutestateStrList.size() != m_inputChannelCount)
517 DBG(juce::String(__FUNCTION__) +
" config data for input mutes is insane -> resetting to default.");
518 for (
auto in = std::uint16_t(1); in <= m_inputChannelCount; in++)
519 inputMuteStates[in] =
false;
524 for (
auto const& inMutestateStr : inMutestateStrList)
526 juce::StringArray inMutestateStrSplit;
527 inMutestateStrSplit.addTokens(inMutestateStr,
",",
"");
528 jassert(2 == inMutestateStrSplit.size());
529 if (2 == inMutestateStrSplit.size())
530 inputMuteStates[std::uint16_t(inMutestateStrSplit[0].getIntValue())] = (1 == std::uint16_t(inMutestateStrSplit[1].getIntValue()));
535 if (
nullptr != outputMutesElm)
537 juce::StringArray outMutestateStrList;
538 auto outputMutesElmTxt = outputMutesElm->getAllSubText();
539 outMutestateStrList.addTokens(outputMutesElmTxt,
";",
"");
540 jassert(outMutestateStrList.size() == m_outputChannelCount);
541 if (outMutestateStrList.size() != m_outputChannelCount)
544 DBG(juce::String(__FUNCTION__) +
" config data for output mutes is insane -> resetting to default.");
545 for (
auto out = std::uint16_t(1); out <= m_outputChannelCount; out++)
546 outputMuteStates[out] =
false;
551 for (
auto const& outMutestateStr : outMutestateStrList)
553 juce::StringArray outMutestateStrSplit;
554 outMutestateStrSplit.addTokens(outMutestateStr,
",",
"");
555 jassert(2 == outMutestateStrSplit.size());
556 if (2 == outMutestateStrSplit.size())
557 outputMuteStates[std::uint16_t(outMutestateStrSplit[0].getIntValue())] = (1 == std::uint16_t(outMutestateStrSplit[1].getIntValue()));
562 if (
nullptr != crosspointGainsElm)
564 juce::StringArray crossGainstateStrList;
565 auto crossGainsElmTxt = crosspointGainsElm->getAllSubText();
566 crossGainstateStrList.addTokens(crossGainsElmTxt,
";",
"");
567 jassert(crossGainstateStrList.size() == (m_inputChannelCount * m_outputChannelCount));
568 if (crossGainstateStrList.size() != (m_inputChannelCount * m_outputChannelCount))
571 DBG(juce::String(__FUNCTION__) +
" config data for crosspoints is insane -> resetting to default.");
572 for (
auto in = std::uint16_t(1); in <= m_inputChannelCount; in++)
574 for (
auto out = std::uint16_t(1); out <= m_outputChannelCount; out++)
583 matrixCrosspointStates[in][out] = state;
584 matrixCrosspointValues[in][out] = value;
591 for (
auto const& crossGainstateStr : crossGainstateStrList)
593 juce::StringArray crossGainstateStrSplit;
594 crossGainstateStrSplit.addTokens(crossGainstateStr,
",",
"");
595 jassert(4 == crossGainstateStrSplit.size());
596 if (4 == crossGainstateStrSplit.size())
598 matrixCrosspointStates[std::uint16_t(crossGainstateStrSplit[0].getIntValue())][std::uint16_t(crossGainstateStrSplit[1].getIntValue())] = 1 == std::uint16_t(crossGainstateStrSplit[2].getIntValue());
599 matrixCrosspointValues[std::uint16_t(crossGainstateStrSplit[0].getIntValue())][std::uint16_t(crossGainstateStrSplit[1].getIntValue())] = crossGainstateStrSplit[3].getFloatValue();
606 auto crosspointStateOutCount = size_t(0);
607 if (0 != matrixCrosspointStates.size())
609 crosspointStateOutCount = matrixCrosspointStates.begin()->second.size();
610 for (
auto const& cpStatKV : matrixCrosspointStates)
612 jassert(crosspointStateOutCount == cpStatKV.second.size());
619 auto crosspointValOutCount = size_t(0);
620 if (0 != matrixCrosspointValues.size())
622 crosspointValOutCount = matrixCrosspointValues.begin()->second.size();
623 for (
auto const& cpValKV : matrixCrosspointValues)
625 jassert(crosspointValOutCount == cpValKV.second.size());
633 const ScopedLock sl(m_audioDeviceIOCallbackLock);
634 m_inputMuteStates = inputMuteStates;
635 m_outputMuteStates = outputMuteStates;
636 m_matrixCrosspointStates = matrixCrosspointStates;
637 m_matrixCrosspointValues = matrixCrosspointValues;
645 auto paletteStyle = JUCEAppBasics::CustomLookAndFeel::PaletteStyle::PS_Dark;
646 if (getActiveEditor())
647 if (
auto claf =
dynamic_cast<JUCEAppBasics::CustomLookAndFeel*
>(&getActiveEditor()->getLookAndFeel()))
648 paletteStyle = claf->getPaletteStyle();
650 postMessage(std::make_unique<EnvironmentParametersMessage>(paletteStyle).release());
655 postMessage(std::make_unique<ReinitIOCountMessage>(m_inputChannelCount, m_outputChannelCount).release());
660 if (m_inputDataAnalyzer)
661 m_inputDataAnalyzer->addListener(listener);
666 if (m_inputDataAnalyzer)
667 m_inputDataAnalyzer->removeListener(listener);
672 if (m_outputDataAnalyzer)
673 m_outputDataAnalyzer->addListener(listener);
678 if (m_outputDataAnalyzer)
679 m_outputDataAnalyzer->removeListener(listener);
684 if (commander ==
nullptr)
687 if (std::find(m_inputCommanders.begin(), m_inputCommanders.end(), commander) == m_inputCommanders.end())
691 m_inputCommanders.push_back(commander);
698 if (
nullptr != commander)
700 const ScopedLock sl(m_audioDeviceIOCallbackLock);
701 for (
auto const& inputMuteStatesKV : m_inputMuteStates)
702 commander->
setInputMute(inputMuteStatesKV.first, inputMuteStatesKV.second);
708 if (commander ==
nullptr)
711 auto existingInputCommander = std::find(m_inputCommanders.begin(), m_inputCommanders.end(), commander);
712 if (existingInputCommander != m_inputCommanders.end())
713 m_inputCommanders.erase(existingInputCommander);
718 if (commander ==
nullptr)
721 if (std::find(m_outputCommanders.begin(), m_outputCommanders.end(), commander) == m_outputCommanders.end())
725 m_outputCommanders.push_back(commander);
732 if (
nullptr != commander)
734 const ScopedLock sl(m_audioDeviceIOCallbackLock);
735 for (
auto const& outputMuteStatesKV : m_outputMuteStates)
736 commander->
setOutputMute(outputMuteStatesKV.first, outputMuteStatesKV.second);
742 if (commander ==
nullptr)
745 auto existingOutputCommander = std::find(m_outputCommanders.begin(), m_outputCommanders.end(), commander);
746 if (existingOutputCommander != m_outputCommanders.end())
747 m_outputCommanders.erase(existingOutputCommander);
752 if (commander ==
nullptr)
755 if (std::find(m_crosspointCommanders.begin(), m_crosspointCommanders.end(), commander) == m_crosspointCommanders.end())
759 m_crosspointCommanders.push_back(commander);
767 if (
nullptr != commander)
769 auto matrixCrosspointStates = std::map<std::uint16_t, std::map<std::uint16_t, bool>>();
770 auto matrixCrosspointValues = std::map<std::uint16_t, std::map<std::uint16_t, float>>();
772 const ScopedLock sl(m_audioDeviceIOCallbackLock);
773 matrixCrosspointStates = m_matrixCrosspointStates;
774 matrixCrosspointValues = m_matrixCrosspointValues;
776 for (
auto const& matrixCrosspointStateKV : matrixCrosspointStates)
778 for (
auto const& matrixCrosspointStateNodeKV : matrixCrosspointStateKV.second)
780 auto& input = matrixCrosspointStateKV.first;
781 auto& output = matrixCrosspointStateNodeKV.first;
782 auto& enabled = matrixCrosspointStateNodeKV.second;
786 for (
auto const& matrixCrosspointValKV : matrixCrosspointValues)
788 for (
auto const& matrixCrosspointValNodeKV : matrixCrosspointValKV.second)
790 auto& input = matrixCrosspointValKV.first;
791 auto& output = matrixCrosspointValNodeKV.first;
792 auto& val = matrixCrosspointValNodeKV.second;
801 if (commander ==
nullptr)
804 auto existingCrosspointCommander = std::find(m_crosspointCommanders.begin(), m_crosspointCommanders.end(), commander);
805 if (existingCrosspointCommander != m_crosspointCommanders.end())
806 m_crosspointCommanders.erase(existingCrosspointCommander);
811 if (commander ==
nullptr)
814 if (std::find(m_pluginCommanders.begin(), m_pluginCommanders.end(), commander) == m_pluginCommanders.end())
818 m_pluginCommanders.push_back(commander);
825 if (
nullptr != commander)
835 if (commander ==
nullptr)
838 auto existingPluginCommander = std::find(m_pluginCommanders.begin(), m_pluginCommanders.end(), commander);
839 if (existingPluginCommander != m_pluginCommanders.end())
840 m_pluginCommanders.erase(existingPluginCommander);
845 for (
auto const& ic : m_inputCommanders)
847 ic->setChannelCount(m_inputChannelCount > 0 ? std::uint16_t(m_inputChannelCount) : 0);
850 for (
auto const& cc : m_crosspointCommanders)
852 cc->setIOCount(m_inputChannelCount > 0 ? std::uint16_t(m_inputChannelCount) : 0, m_outputChannelCount > 0 ? std::uint16_t(m_outputChannelCount) : 0);
855 for (
auto const& oc : m_outputCommanders)
857 oc->setChannelCount(m_outputChannelCount > 0 ? std::uint16_t(m_outputChannelCount) : 0);
860 for (
auto const& pc : m_pluginCommanders)
868 jassert(inputChannelNumber > 0);
869 const ScopedLock sl(m_audioDeviceIOCallbackLock);
870 return m_inputMuteStates[inputChannelNumber];
875 jassert(inputChannelNumber > 0);
877 for (
auto const& inputCommander : m_inputCommanders)
880 inputCommander->setInputMute(inputChannelNumber, muted, userId);
884 const ScopedLock sl(m_audioDeviceIOCallbackLock);
885 m_inputMuteStates[inputChannelNumber] = muted;
893 jassert(inputNumber > 0 && outputNumber > 0);
895 const ScopedLock sl(m_audioDeviceIOCallbackLock);
896 if (m_matrixCrosspointStates.count(inputNumber) != 0)
897 if (m_matrixCrosspointStates.at(inputNumber).count(outputNumber) != 0)
898 return m_matrixCrosspointStates.at(inputNumber).at(outputNumber);
906 jassert(inputNumber > 0 && outputNumber > 0);
908 for (
auto const& crosspointCommander : m_crosspointCommanders)
911 crosspointCommander->setCrosspointEnabledValue(inputNumber, outputNumber, enabled, userId);
915 const ScopedLock sl(m_audioDeviceIOCallbackLock);
918 jassert(0 != m_matrixCrosspointStates.count(inputNumber));
919 if (0 != m_matrixCrosspointStates.count(inputNumber))
921 jassert(0 != m_matrixCrosspointStates.at(inputNumber).count(outputNumber));
924 m_matrixCrosspointStates[inputNumber][outputNumber] = enabled;
932 jassert(inputNumber > 0 && outputNumber > 0);
934 const ScopedLock sl(m_audioDeviceIOCallbackLock);
935 if (m_matrixCrosspointValues.count(inputNumber) != 0)
936 if (m_matrixCrosspointValues.at(inputNumber).count(outputNumber) != 0)
937 return m_matrixCrosspointValues.at(inputNumber).at(outputNumber);
945 jassert(inputNumber > 0 && outputNumber > 0);
947 for (
auto const& crosspointCommander : m_crosspointCommanders)
950 crosspointCommander->setCrosspointFactorValue(inputNumber, outputNumber, factor, userId);
954 const ScopedLock sl(m_audioDeviceIOCallbackLock);
957 jassert(0 != m_matrixCrosspointValues.count(inputNumber));
958 if (0 != m_matrixCrosspointValues.count(inputNumber))
960 jassert(0 != m_matrixCrosspointValues.at(inputNumber).count(outputNumber));
963 m_matrixCrosspointValues[inputNumber][outputNumber] = factor;
971 jassert(outputChannelNumber > 0);
972 const ScopedLock sl(m_audioDeviceIOCallbackLock);
973 return m_outputMuteStates[outputChannelNumber];
978 jassert(outputChannelNumber > 0);
980 for (
auto const& outputCommander : m_outputCommanders)
983 outputCommander->setOutputMute(outputChannelNumber, muted, userId);
987 const ScopedLock sl(m_audioDeviceIOCallbackLock);
988 m_outputMuteStates[outputChannelNumber] = muted;
996 auto reinitRequired =
false;
997 if (m_inputChannelCount != inputChannelCount)
999 m_inputChannelCount = inputChannelCount;
1000 reinitRequired =
true;
1002 if (m_outputChannelCount != outputChannelCount)
1004 m_outputChannelCount = outputChannelCount;
1005 reinitRequired =
true;
1012 const ScopedLock sl(m_pluginProcessingLock);
1013 configurePluginForCurrentPosition();
1019void MemaProcessor::configurePluginForCurrentPosition()
1022 if (!m_pluginInstance)
1028 m_pluginInstance->releaseResources();
1032 auto channelLimit = m_pluginPost ? m_outputChannelCount : m_inputChannelCount;
1041 auto tryLayout = [&](
const juce::AudioChannelSet& candidate) ->
bool
1043 juce::AudioProcessor::BusesLayout layout;
1044 layout.inputBuses.add(candidate);
1045 layout.outputBuses.add(candidate);
1047 if (m_pluginInstance->setBusesLayout(layout))
1049 m_pluginConfiguredChannelCount = candidate.size();
1050 m_pluginInstance->prepareToPlay(getSampleRate(), getBlockSize());
1056 for (
int count = channelLimit; count >= 1; --count)
1058 for (
auto const& named : juce::AudioChannelSet::channelSetsWithNumberOfChannels(count))
1059 if (tryLayout(named))
1062 if (tryLayout(juce::AudioChannelSet::discreteChannels(count)))
1067 m_pluginInstance->setPlayConfigDetails(channelLimit, channelLimit, getSampleRate(), getBlockSize());
1068 m_pluginConfiguredChannelCount = channelLimit;
1069 m_pluginInstance->prepareToPlay(getSampleRate(), getBlockSize());
1074 juce::AudioPluginFormatManager formatManager;
1075 addDefaultFormatsToManager(formatManager);
1076 auto registeredFormats = formatManager.getFormats();
1078 auto success =
false;
1079 juce::String errorMessage =
"Unsupported plug-in format.";
1081 for (
auto const& format : registeredFormats)
1083 if (format->getName() == pluginDescription.pluginFormatName)
1089 const ScopedLock sl(m_pluginProcessingLock);
1092 if (m_pluginInstance)
1094 for (
auto const& param : m_pluginInstance->getParameters())
1095 param->removeListener(
this);
1098 m_pluginParameterInfos.clear();
1099 m_pluginParameterDisplayOrder.clear();
1101 m_pluginInstance = format->createInstanceFromDescription(pluginDescription, getSampleRate(), getBlockSize(), errorMessage);
1102 if (m_pluginInstance)
1107 configurePluginForCurrentPosition();
1110 m_pluginParameterInfos.clear();
1111 for (
auto const& param : m_pluginInstance->getParameters())
1113 postMessage(std::make_unique<PluginParameterInfosChangedMessage>().release());
1116 for (
auto const& param : m_pluginInstance->getParameters())
1117 param->addListener(
this);
1120 success = errorMessage.isEmpty();
1126 juce::AlertWindow::showMessageBoxAsync(juce::MessageBoxIconType::WarningIcon,
"Loading error",
"Loading of the selected plug-in " + pluginDescription.name +
" failed.\n" + errorMessage);
1130 triggerConfigurationUpdate(
false);
1137 if (m_pluginInstance)
1138 return m_pluginInstance->getPluginDescription();
1147 const ScopedLock sl(m_pluginProcessingLock);
1148 m_pluginEnabled = enabled;
1151 for (
auto& pluginCommander : m_pluginCommanders)
1152 pluginCommander->setPluginProcessingState(m_pluginEnabled, m_pluginPost);
1154 triggerConfigurationUpdate(
false);
1159 return m_pluginEnabled;
1166 const ScopedLock sl(m_pluginProcessingLock);
1167 if (m_pluginPost != post)
1169 m_pluginPost = post;
1174 configurePluginForCurrentPosition();
1178 for (
auto& pluginCommander : m_pluginCommanders)
1179 pluginCommander->setPluginProcessingState(m_pluginEnabled, m_pluginPost);
1181 triggerConfigurationUpdate(
false);
1186 return m_pluginPost;
1195 const ScopedLock sl(m_pluginProcessingLock);
1196 m_pluginInstance.reset();
1197 m_pluginParameterInfos.clear();
1198 m_pluginParameterDisplayOrder.clear();
1201 postMessage(std::make_unique<PluginParameterInfosChangedMessage>().release());
1211 if (m_pluginInstance)
1213 auto pluginEditorInstance = m_pluginInstance->createEditorIfNeeded();
1214 if (pluginEditorInstance && !m_pluginEditorWindow)
1216 m_pluginEditorWindow = std::make_unique<ResizeableWindowWithTitleBarAndCloseCallback>(juce::JUCEApplication::getInstance()->getApplicationName() +
" : " + m_pluginInstance->getName(),
true);
1217 m_pluginEditorWindow->setResizable(
false,
false);
1218 m_pluginEditorWindow->setContentOwned(pluginEditorInstance,
true);
1220 m_pluginEditorWindow->setVisible(
true);
1227 if (m_pluginInstance)
1228 std::unique_ptr<juce::AudioProcessorEditor>(m_pluginInstance->getActiveEditor()).reset();
1229 if (deleteEditorWindow)
1230 m_pluginEditorWindow.reset();
1235 return m_pluginParameterInfos;
1240 if (parameterIndex >= 0 && parameterIndex < m_pluginParameterInfos.size())
1242 m_pluginParameterInfos[parameterIndex].isRemoteControllable = remoteControllable;
1243 m_pluginParameterInfos[parameterIndex].type = type;
1244 m_pluginParameterInfos[parameterIndex].stepCount = steps;
1246 jassert(m_pluginInstance);
1247 if (m_pluginInstance)
1249 m_pluginParameterInfos[parameterIndex].stepNames.clear();
1250 auto param = m_pluginInstance->getParameters()[parameterIndex];
1251 if (param && steps > 1)
1253 auto stepSize = 1.0f / (steps - 1);
1254 for (
int i = 0; i < steps; i++)
1256 m_pluginParameterInfos[parameterIndex].stepNames.push_back(param->getText(i * stepSize, 100).toStdString());
1261 triggerConfigurationUpdate(
false);
1262 postMessage(std::make_unique<PluginParameterInfosChangedMessage>().release());
1268 m_pluginParameterDisplayOrder = order;
1269 triggerConfigurationUpdate(
false);
1270 postMessage(std::make_unique<PluginParameterInfosChangedMessage>().release());
1275 return m_pluginParameterDisplayOrder;
1280 if (parameterIndex >= 0 && parameterIndex < m_pluginParameterInfos.size())
1281 return m_pluginParameterInfos[parameterIndex].isRemoteControllable;
1288 if (!m_pluginInstance)
1291 auto& parameters = m_pluginInstance->getParameters();
1292 auto idxInRange = parameterIndex >= 0 && parameterIndex < parameters.size();
1293 jassert(idxInRange);
1297 const ScopedLock sl(m_pluginProcessingLock);
1298 return parameters[parameterIndex]->getValue();
1303 if (!m_pluginInstance)
1306 auto& parameters = m_pluginInstance->getParameters();
1307 auto idxInRange = parameterIndex >= 0 && parameterIndex < parameters.size();
1308 jassert(idxInRange);
1312 for (
auto const& pluginCommander : m_pluginCommanders)
1315 pluginCommander->setPluginParameterValue(parameterIndex,
id, normalizedValue, userId);
1320 const ScopedLock sl(m_pluginProcessingLock);
1322 parameters[parameterIndex]->setValue(normalizedValue);
1325 if (parameterIndex < m_pluginParameterInfos.size())
1326 m_pluginParameterInfos[parameterIndex].currentValue = normalizedValue;
1334 const ScopedLock sl(m_pluginProcessingLock);
1336 if (!m_pluginInstance)
1339 auto& parameters = m_pluginInstance->getParameters();
1341 if (parameterIndex >= 0 && parameterIndex < parameters.size())
1342 return parameters[parameterIndex];
1349 if (m_deviceManager)
1350 return m_deviceManager.get();
1357 if (m_networkServer)
1358 return m_networkServer->getListHealth();
1365 if (m_serviceTopologyManager)
1366 return m_serviceTopologyManager->getDiscoveredServiceTopology();
1379 setRateAndBufferSizeDetails(sampleRate, maximumExpectedSamplesPerBlock);
1383 const ScopedLock sl(m_pluginProcessingLock);
1388 configurePluginForCurrentPosition();
1391 if (m_inputDataAnalyzer)
1392 m_inputDataAnalyzer->initializeParameters(sampleRate, maximumExpectedSamplesPerBlock);
1393 if (m_outputDataAnalyzer)
1394 m_outputDataAnalyzer->initializeParameters(sampleRate, maximumExpectedSamplesPerBlock);
1396 postMessage(std::make_unique<AnalyzerParametersMessage>(
int(sampleRate), maximumExpectedSamplesPerBlock).release());
1403 const ScopedLock sl(m_pluginProcessingLock);
1404 if (m_pluginInstance)
1405 m_pluginInstance->releaseResources();
1408 if (m_inputDataAnalyzer)
1409 m_inputDataAnalyzer->clearParameters();
1410 if (m_outputDataAnalyzer)
1411 m_outputDataAnalyzer->clearParameters();
1416 ignoreUnused(midiMessages);
1421 auto reinitRequired =
false;
1426 if (m_inputChannelCount > m_inputMuteStates.size())
1427 reinitRequired =
true;
1429 for (std::uint16_t input = 1; input <= m_inputChannelCount; input++)
1431 if (m_inputMuteStates.count(input) != 0 && m_inputMuteStates.at(input))
1433 auto channelIdx = input - 1;
1434 buffer.clear(channelIdx, 0, buffer.getNumSamples());
1438 postMessage(std::make_unique<AudioInputBufferMessage>(buffer).release());
1442 const ScopedLock sl(m_pluginProcessingLock);
1443 if (m_pluginInstance && m_pluginEnabled && !m_pluginPost)
1448 juce::AudioBuffer<float> pluginBuffer(buffer.getArrayOfWritePointers(), m_pluginConfiguredChannelCount, buffer.getNumSamples());
1449 m_pluginInstance->processBlock(pluginBuffer, midiMessages);
1454 juce::AudioBuffer<float> processedBuffer;
1455 processedBuffer.setSize(m_outputChannelCount, buffer.getNumSamples(),
false,
true,
true);
1456 for (std::uint16_t inputIdx = 0; inputIdx < m_inputChannelCount; inputIdx++)
1458 for (std::uint16_t outputIdx = 0; outputIdx < m_outputChannelCount; outputIdx++)
1460 if (0 != m_matrixCrosspointStates.count(inputIdx + 1) && 0 != m_matrixCrosspointValues.count(inputIdx + 1))
1462 if (0 != m_matrixCrosspointStates[inputIdx + 1].count(outputIdx + 1) && 0 != m_matrixCrosspointValues[inputIdx + 1].count(outputIdx + 1))
1464 auto& enabled = m_matrixCrosspointStates.at(inputIdx + 1).at(outputIdx + 1);
1465 auto& factor = m_matrixCrosspointValues.at(inputIdx + 1).at(outputIdx + 1);
1466 auto gain = !enabled ? 0.0f : factor;
1467 processedBuffer.addFrom(outputIdx, 0, buffer.getReadPointer(inputIdx), buffer.getNumSamples(), gain);
1472 buffer.makeCopyOf(processedBuffer,
true);
1474 if (m_outputChannelCount > m_outputMuteStates.size())
1475 reinitRequired =
true;
1479 const ScopedLock sl(m_pluginProcessingLock);
1480 if (m_pluginInstance && m_pluginEnabled && m_pluginPost)
1485 juce::AudioBuffer<float> pluginBuffer(buffer.getArrayOfWritePointers(), m_pluginConfiguredChannelCount, buffer.getNumSamples());
1486 m_pluginInstance->processBlock(pluginBuffer, midiMessages);
1490 for (std::uint16_t output = 1; output <= m_outputChannelCount; output++)
1492 if (m_outputMuteStates.count(output) != 0 && m_outputMuteStates.at(output))
1494 auto channelIdx = output - 1;
1495 buffer.clear(channelIdx, 0, buffer.getNumSamples());
1499 postMessage(std::make_unique<AudioOutputBufferMessage>(buffer).release());
1502 postMessage(std::make_unique<ReinitIOCountMessage>(m_inputChannelCount, m_outputChannelCount).release());
1508 juce::MemoryBlock serializedMessageMemoryBlock;
1512 origId = sm->getId();
1516 serializedMessageMemoryBlock = epm->getSerializedMessage();
1517 tId = epm->getType();
1521 serializedMessageMemoryBlock = apm->getSerializedMessage();
1522 tId = apm->getType();
1526 auto inputCount = iom->getInputCount();
1527 jassert(inputCount > 0);
1528 auto outputCount = iom->getOutputCount();
1529 jassert(outputCount > 0);
1531 for (
auto const& inputCommander : m_inputCommanders)
1532 inputCommander->setChannelCount(inputCount);
1534 for (
auto const& outputCommander : m_outputCommanders)
1535 outputCommander->setChannelCount(outputCount);
1537 for (
auto const& crosspointCommander : m_crosspointCommanders)
1538 crosspointCommander->setIOCount(inputCount, outputCount);
1542 serializedMessageMemoryBlock = iom->getSerializedMessage();
1544 tId = iom->getType();
1550 m_inputDataAnalyzer->analyzeData(m->getAudioBuffer());
1554 m_outputDataAnalyzer->analyzeData(m->getAudioBuffer());
1557 serializedMessageMemoryBlock = m->getSerializedMessage();
1563 DBG(juce::String(__FUNCTION__) <<
" i:" << cpm->getInputMuteStates().size() <<
" o:" << cpm->getOutputMuteStates().size() <<
" c:" << cpm->getCrosspointStates().size());
1564 for (
auto const& inputMuteState : cpm->getInputMuteStates())
1566 for (
auto const& outputMuteState : cpm->getOutputMuteStates())
1568 for (
auto const& crosspointStateKV : cpm->getCrosspointStates())
1570 auto& inputNumber = crosspointStateKV.first;
1571 for (
auto const& crosspointOStateKV : crosspointStateKV.second)
1573 auto& outputNumber = crosspointOStateKV.first;
1577 for (
auto const& crosspointValueKV : cpm->getCrosspointValues())
1579 auto& inputNumber = crosspointValueKV.first;
1580 for (
auto const& crosspointOValueKV : crosspointValueKV.second)
1582 auto& outputNumber = crosspointOValueKV.first;
1587 tId = cpm->getType();
1591 if (!dtsm->hasUserId())
1592 DBG(
"Incoming DataTrafficTypeSelecitonMessage cannot be associated with a connection");
1596 tId = dtsm->getType();
1600 DBG(juce::String(__FUNCTION__) <<
" ppiCnt:" << ppim->getParameterInfos().size());
1604 serializedMessageMemoryBlock = ppim->getSerializedMessage();
1606 tId = ppim->getType();
1610 DBG(juce::String(__FUNCTION__) <<
" ppvIdx:" <<
int(ppvm->getParameterIndex()) <<
" > " << ppvm->getCurrentValue());
1614 serializedMessageMemoryBlock = ppvm->getSerializedMessage();
1616 tId = ppvm->getType();
1620 DBG(juce::String(__FUNCTION__) <<
" pluginEnabled:" <<
int(pesm->isEnabled()) <<
" pluginPost:" <<
int(pesm->isPost()));
1625 const ScopedLock sl(m_pluginProcessingLock);
1626 m_pluginEnabled = pesm->isEnabled();
1627 if (m_pluginPost != pesm->isPost())
1629 m_pluginPost = pesm->isPost();
1630 configurePluginForCurrentPosition();
1633 triggerConfigurationUpdate(
false);
1638 serializedMessageMemoryBlock = pesm->getSerializedMessage();
1640 tId = pesm->getType();
1646 auto orderedParams = m_pluginParameterInfos;
1647 if (!m_pluginParameterDisplayOrder.empty() && m_pluginParameterDisplayOrder.size() == m_pluginParameterInfos.size())
1649 orderedParams.clear();
1650 for (
int idx : m_pluginParameterDisplayOrder)
1651 if (idx >= 0 && idx <
static_cast<int>(m_pluginParameterInfos.size()))
1652 orderedParams.push_back(m_pluginParameterInfos[idx]);
1653 if (orderedParams.size() != m_pluginParameterInfos.size())
1654 orderedParams = m_pluginParameterInfos;
1658 for (
auto& pluginCommander : m_pluginCommanders)
1659 pluginCommander->setPluginParameterInfos(orderedParams,
1660 m_pluginInstance ? m_pluginInstance->getName().toStdString() :
"",
1661 m_pluginEnabled, m_pluginPost);
1669 std::vector<int> sendIds;
1670 for (
auto const& cId : m_trafficTypesPerConnection)
1672 if (cId.first != origId)
1675 if (cId.second.empty())
1676 sendIds.push_back(cId.first);
1678 else if (cId.second.end() != std::find(cId.second.begin(), cId.second.end(), tId))
1679 sendIds.push_back(cId.first);
1682 if (!sendIds.empty())
1683 sendMessageToClients(serializedMessageMemoryBlock, sendIds);
1692 for (
auto const& pluginCommander : m_pluginCommanders)
1693 pluginCommander->setPluginParameterValue(
static_cast<std::uint16_t
>(parameterIndex), iter->id.toStdString(), newValue);
1696 if (parameterIndex < m_pluginParameterInfos.size())
1697 m_pluginParameterInfos[parameterIndex].currentValue = newValue;
1703 ignoreUnused(parameterIndex);
1704 ignoreUnused(gestureIsStarting);
1707void MemaProcessor::sendMessageToClients(
const MemoryBlock& messageMemoryBlock,
const std::vector<int>& sendIds)
1709 if (m_networkServer && m_networkServer->hasActiveConnections())
1711 if (!messageMemoryBlock.isEmpty() && !m_networkServer->enqueueMessage(messageMemoryBlock, sendIds))
1713 auto deadConnectionIds = m_networkServer->cleanupDeadConnections();
1714 if (!deadConnectionIds.empty())
1716 for (
auto const& dcId : deadConnectionIds)
1717 m_trafficTypesPerConnection.erase(dcId);
1740 if (!m_processorEditor)
1741 m_processorEditor = std::make_unique<MemaProcessorEditor>(
this);
1745 return m_processorEditor.get();
1750 return !!m_processorEditor;
1765 ignoreUnused(index);
1770 ignoreUnused(index);
1776 ignoreUnused(index);
1777 ignoreUnused(newName);
1782 ignoreUnused(destData);
1788 ignoreUnused(sizeInBytes);
1792 float*
const* outputChannelData,
int numOutputChannels,
int numSamples,
const AudioIODeviceCallbackContext& context)
1794 ignoreUnused(context);
1796 const juce::ScopedLock sl(m_audioDeviceIOCallbackLock);
1798 if (m_inputChannelCount != numInputChannels || m_outputChannelCount != numOutputChannels)
1800 m_inputChannelCount = numInputChannels;
1801 m_outputChannelCount = numOutputChannels;
1802 postMessage(std::make_unique<ReinitIOCountMessage>(m_inputChannelCount, m_outputChannelCount).release());
1805 auto maxActiveChannels = std::max(numInputChannels, numOutputChannels);
1814 for (
auto i = 0; i < numInputChannels && i < maxActiveChannels; i++)
1816 memcpy(m_processorChannels[i], inputChannelData[i], (
size_t)numSamples *
sizeof(
float));
1820 juce::AudioBuffer<float> audioBufferToProcess(m_processorChannels, maxActiveChannels, numSamples);
1821 juce::MidiBuffer midiBufferToProcess;
1822 processBlock(audioBufferToProcess, midiBufferToProcess);
1825 auto processedChannelCount = audioBufferToProcess.getNumChannels();
1826 auto processedSampleCount = audioBufferToProcess.getNumSamples();
1827 auto processedData = audioBufferToProcess.getArrayOfReadPointers();
1828 jassert(processedSampleCount == numSamples);
1829 for (
auto i = 0; i < numOutputChannels && i < processedChannelCount; i++)
1831 memcpy(outputChannelData[i], processedData[i], (
size_t)processedSampleCount *
sizeof(
float));
1840 auto activeInputs = device->getActiveInputChannels();
1841 auto inputChannelCnt = std::uint16_t(activeInputs.getHighestBit() + 1);
1842 auto activeOutputs = device->getActiveOutputChannels();
1843 auto outputChannelCnt = std::uint16_t(activeOutputs.getHighestBit() + 1);
1844 auto sampleRate = device->getCurrentSampleRate();
1845 auto bufferSize = device->getCurrentBufferSizeSamples();
1848 setPlayConfigDetails(inputChannelCnt, outputChannelCnt, sampleRate, bufferSize);
1861 if (source == m_deviceManager.get())
1867 std::map<std::uint16_t, bool> inputMuteStates;
1868 std::map<std::uint16_t, bool> outputMuteStates;
1869 std::map<std::uint16_t, std::map<std::uint16_t, bool>> matrixCrosspointStates;
1870 std::map<std::uint16_t, std::map<std::uint16_t, float>> matrixCrosspointValues;
1873 const ScopedLock sl(m_audioDeviceIOCallbackLock);
1874 inputMuteStates = m_inputMuteStates;
1875 outputMuteStates = m_outputMuteStates;
1876 matrixCrosspointValues = m_matrixCrosspointValues;
1877 matrixCrosspointStates = m_matrixCrosspointStates;
1881 for (std::uint16_t channel = 1; channel <= inputChannelCount; channel++)
1882 for (
auto& inputCommander : m_inputCommanders)
1883 inputCommander->setInputMute(channel, inputMuteStates[channel]);
1886 for (std::uint16_t channel = 1; channel <= outputChannelCount; channel++)
1887 for (
auto& outputCommander : m_outputCommanders)
1888 outputCommander->setOutputMute(channel, outputMuteStates[channel]);
1890 for (std::uint16_t in = 1; in <= inputChannelCount; in++)
1892 for (std::uint16_t out = 1; out <= outputChannelCount; out++)
1894 for (
auto& crosspointCommander : m_crosspointCommanders)
1896 crosspointCommander->setCrosspointEnabledValue(in, out, matrixCrosspointStates[in][out]);
1897 crosspointCommander->setCrosspointFactorValue(in, out, matrixCrosspointValues[in][out]);
1902 juce::Array<juce::AudioProcessorParameter*> pluginParameters;
1903 juce::String pluginName;
1904 if (m_pluginInstance)
1907 const ScopedLock sl(m_pluginProcessingLock);
1908 pluginName = m_pluginInstance->getName();
1909 pluginParameters = m_pluginInstance->getParameters();
1912 for (
auto& pluginCommander : m_pluginCommanders)
1913 pluginCommander->setPluginParameterInfos(pluginParameterInfos, pluginName.toStdString(), m_pluginEnabled, m_pluginPost);
1919 const ScopedLock sl(m_audioDeviceIOCallbackLock);
1920 m_inputMuteStates.clear();
1921 m_outputMuteStates.clear();
1922 m_matrixCrosspointStates.clear();
1923 m_matrixCrosspointValues.clear();
1927 for (std::uint16_t channel = 1; channel <= inputChannelCount; channel++)
1931 for (std::uint16_t channel = 1; channel <= outputChannelCount; channel++)
1934 for (std::uint16_t in = 1; in <= inputChannelCount; in++)
1936 for (std::uint16_t out = 1; out <= outputChannelCount; out++)
1951 DBG(juce::String(__FUNCTION__) <<
" " << connectionId <<
" chose " << trafficTypes.size() <<
" types");
1952 for (
auto const& tt : trafficTypes)
1954 if (m_trafficTypesPerConnection[connectionId].end() == std::find(m_trafficTypesPerConnection[connectionId].begin(), m_trafficTypesPerConnection[connectionId].end(), tt))
1955 m_trafficTypesPerConnection[connectionId].push_back(tt);
Carries audio-device parameters (sample rate, block size) from Mema to clients.
Base message carrying a serialised audio buffer and its flow-direction metadata.
@ Input
Pre-matrix input samples (as seen by the input analyzers).
@ Output
Post-matrix output samples (as seen by the output analyzers).
Full routing-matrix state snapshot exchanged bidirectionally between Mema and Mema....
Sent by a client to opt in to receiving specific message types from Mema.
Carries the active look-and-feel palette style from Mema to connected clients.
Client-side TCP connection wrapper that forwards JUCE IPC events to std::function callbacks.
std::function< void(int)> onConnectionLost
static juce::String getTagName(TagID ID)
@ PLUGINCONFIG
Plugin host settings.
@ PROCESSORCONFIG
Audio processor settings.
@ CROSSPOINTGAINS
Crosspoint matrix gain values.
@ DEVCONFIG
Audio device configuration.
@ OUTPUTMUTES
Per-channel output mute states.
@ PLUGINPARAM
Individual plugin parameter entry.
@ INPUTMUTES
Per-channel input mute states.
static juce::String getAttributeName(AttributeID ID)
@ ENABLED
Boolean enabled flag.
@ POST
Post-matrix plugin insertion flag.
@ PARAMORDER
Comma-separated list of parameter indices defining the display order.
@ CONTROLLABLE
Whether a plugin parameter is remotely controllable.
@ IDX
Channel or parameter index.
virtual void setCrosspointFactorValue(std::uint16_t input, std::uint16_t output, float factor, int userId=-1)=0
void setCrosspointEnabledChangeCallback(const std::function< void(MemaCrosspointCommander *sender, std::uint16_t, std::uint16_t, bool)> &callback)
virtual void setCrosspointEnabledValue(std::uint16_t input, std::uint16_t output, bool enabledState, int userId=-1)=0
void setCrosspointFactorChangeCallback(const std::function< void(MemaCrosspointCommander *sender, std::uint16_t, std::uint16_t, float)> &callback)
void setInputMuteChangeCallback(const std::function< void(MemaInputCommander *sender, std::uint16_t, bool)> &callback)
virtual void setInputMute(std::uint16_t channel, bool muteState, int userId=-1)=0
void setPluginParameterValue(std::uint16_t index, std::string id, float currentValue, int userId=-1) override
void setPluginProcessingState(bool enabled, bool post, int userId=-1) override
void setCrosspointFactorValue(std::uint16_t input, std::uint16_t output, float factor, int userId) override
void setCrosspointEnabledValue(std::uint16_t input, std::uint16_t output, bool enabledState, int userId) override
void setInputMute(std::uint16_t channel, bool muteState, int userId) override
void setNetworkConnection(const std::shared_ptr< InterprocessConnectionServerImpl > &networkServer)
void setOutputMute(std::uint16_t channel, bool muteState, int userId) override
void setPluginParameterInfos(const std::vector< PluginParameterInfo > ¶meterInfos, const std::string &name, bool enabled, bool post, int userId=-1) override
void setIOCount(std::uint16_t inputCount, std::uint16_t outputCount) override
void setOutputMuteChangeCallback(const std::function< void(MemaOutputCommander *sender, std::uint16_t, bool)> &callback)
virtual void setOutputMute(std::uint16_t channel, bool muteState, int userId=-1)=0
void setPluginParameterValueChangeCallback(const std::function< void(MemaPluginCommander *sender, std::uint16_t, std::string, float)> &callback)
bool getOutputMuteState(std::uint16_t channelNumber)
Returns the mute state of a specific output channel.
bool acceptsMidi() const override
void openPluginEditor()
Opens (or raises) the plugin's editor UI in a floating ResizeableWindowWithTitleBarAndCloseCallback w...
std::function< void(const juce::PluginDescription &)> onPluginSet
Invoked on the message thread after a new plugin has been successfully loaded.
void setPluginParameterDisplayOrder(const std::vector< int > &order)
Sets the display order in which plugin parameters are presented to Mema.Re clients.
void addOutputCommander(MemaOutputCommander *commander)
Adds an output commander and immediately pushes the current mute states to it.
static constexpr int s_maxChannelCount
Maximum number of input or output channels supported by the routing matrix.
void changeListenerCallback(ChangeBroadcaster *source) override
Receives notifications from the AudioDeviceManager when the device configuration changes.
bool isTimedConfigurationDumpPending()
Returns true when a deferred XML configuration dump has been scheduled.
void initializePluginCommander(MemaPluginCommander *commander)
Pushes the current plugin parameter descriptors and values to an already-registered commander.
void setTrafficTypesForConnectionId(const std::vector< SerializableMessage::SerializableMessageType > &trafficTypes, int connectionId)
Updates the set of message types a specific TCP client has subscribed to receive.
void audioDeviceIOCallbackWithContext(const float *const *inputChannelData, int numInputChannels, float *const *outputChannelData, int numOutputChannels, int numSamples, const AudioIODeviceCallbackContext &context) override
Hot audio callback — implements the complete Mema signal chain.
void clearPlugin()
Unloads the hosted plugin, closes its editor window, and resets all plugin commander state.
double getTailLengthSeconds() const override
juce::PluginDescription getPluginDescription()
Returns the JUCE description of the currently loaded plugin.
bool getMatrixCrosspointEnabledValue(std::uint16_t inputNumber, std::uint16_t outputNumber)
Returns whether a specific crosspoint node is enabled (routing active).
void setMatrixCrosspointFactorValue(std::uint16_t inputNumber, std::uint16_t outputNumber, float factor, MemaChannelCommander *sender=nullptr, int userId=-1)
Sets the linear gain factor of a crosspoint node.
void initializeCtrlValuesToUnity()
Resets all crosspoint gains to 1.0 (unity) and enables all crosspoints. Used when creating a default ...
bool hasEditor() const override
void setCurrentProgram(int index) override
static constexpr int s_maxNumSamples
Maximum audio block size in samples.
void setInputMuteState(std::uint16_t channelNumber, bool muted, MemaChannelCommander *sender=nullptr, int userId=-1)
Sets the mute state of an input channel and notifies all commanders except the sender.
AudioDeviceManager * getDeviceManager()
Returns a raw pointer to the JUCE AudioDeviceManager. Used by the audio-setup UI component.
int getNumPrograms() override
bool producesMidi() const override
void setOutputMuteState(std::uint16_t channelNumber, bool muted, MemaChannelCommander *sender=nullptr, int userId=-1)
Sets the mute state of an output channel and notifies all commanders except the sender.
void addOutputListener(ProcessorDataAnalyzer::Listener *listener)
Registers a listener to receive output-channel level/spectrum data from the output analyzer.
void parameterValueChanged(int parameterIndex, float newValue) override
Called by the hosted plugin when a parameter value changes.
void removeInputCommander(MemaInputCommander *commander)
Removes a previously registered input commander.
bool setStateXml(XmlElement *stateXml) override
Restores the processor state from a previously serialised <PROCESSORCONFIG> XmlElement.
juce::AudioProcessorParameter * getPluginParameter(int parameterIndex) const
Returns a pointer to the underlying JUCE AudioProcessorParameter at the given index.
bool isPluginPost()
Returns true when the plugin is inserted post-matrix.
void setPluginEnabledState(bool enabled)
Enables or disables plugin processing without unloading the plugin instance.
void updateCommanders()
Forces all registered commanders to re-synchronise with the current processor state.
void addInputCommander(MemaInputCommander *commander)
Adds an input commander and immediately pushes the current mute states to it.
bool getInputMuteState(std::uint16_t channelNumber)
Returns the mute state of a specific input channel.
std::map< int, std::pair< double, bool > > getNetworkHealth()
Returns per-client network health metrics.
std::function< void(bool enabled, bool post)> onPluginProcessingStateChanged
Fired when the plugin enabled or pre/post state changes externally (e.g. from a Mema....
void setStateInformation(const void *data, int sizeInBytes) override
int getCurrentProgram() override
void handleMessage(const Message &message) override
Dispatches JUCE messages posted to the message thread.
const std::vector< int > & getPluginParameterDisplayOrder() const
Returns the current display order vector, or an empty vector if none has been set.
void setTimedConfigurationDumpPending()
Schedules a deferred XML configuration dump (called on state change to avoid excessive disk I/O).
JUCEAppBasics::SessionServiceTopology getDiscoveredServicesTopology()
Returns the most recent multicast service topology snapshot from ServiceTopologyManager.
void changeProgramName(int index, const String &newName) override
void resetTimedConfigurationDumpPending()
Clears the deferred dump flag after the dump has been performed.
void setPluginParameterValue(std::uint16_t pluginParameterIndex, std::string id, float normalizedValue, MemaPluginCommander *sender=nullptr, int userId=-1)
Sets a hosted plugin parameter to a normalised value.
void addInputListener(ProcessorDataAnalyzer::Listener *listener)
Registers a listener to receive input-channel level/spectrum data from the input analyzer.
void audioDeviceAboutToStart(AudioIODevice *device) override
Called when the audio device is about to start streaming.
void setChannelCounts(std::uint16_t inputChannelCount, std::uint16_t outputChannelCount)
Resizes all internal routing structures for a new input/output channel count.
void initializeCrosspointCommander(MemaCrosspointCommander *commander)
Pushes the current crosspoint enable/gain matrix to an already-registered commander.
float getMatrixCrosspointFactorValue(std::uint16_t inputNumber, std::uint16_t outputNumber)
Returns the linear gain factor of a crosspoint node.
void closePluginEditor(bool deleteEditorWindow=true)
Closes the plugin editor window.
void initializeCtrlValues(int inputCount, int outputCount)
MemaProcessor(XmlElement *stateXml)
Constructs the processor, optionally restoring state from XML.
void removePluginCommander(MemaPluginCommander *commander)
Removes a previously registered plugin commander.
float getPluginParameterValue(std::uint16_t pluginParameterIndex) const
Returns the current normalised value of a hosted plugin parameter.
void addPluginCommander(MemaPluginCommander *commander)
Adds a plugin commander and immediately pushes the current parameter infos and values.
void environmentChanged()
Called when the OS look-and-feel or palette changes; broadcasts EnvironmentParametersMessage to all c...
bool setPlugin(const juce::PluginDescription &pluginDescription)
Loads and instantiates a plugin from the given description.
void addCrosspointCommander(MemaCrosspointCommander *commander)
Adds a crosspoint commander and immediately pushes the full crosspoint state to it.
std::unique_ptr< XmlElement > createStateXml() override
Serialises the current processor state (mutes, crosspoints, plugin settings) to XML.
void getStateInformation(juce::MemoryBlock &destData) override
void initializeOutputCommander(MemaOutputCommander *commander)
Pushes the current output mute states to an already-registered commander.
static constexpr int s_minOutputsCount
Minimum number of output channels (always at least 1).
void parameterGestureChanged(int parameterIndex, bool gestureIsStarting) override
Called by the hosted plugin when a gesture (e.g. mouse drag) starts or ends.
bool isPluginParameterRemoteControllable(int parameterIndex)
Returns true if the given parameter is flagged as remotely controllable.
std::vector< PluginParameterInfo > & getPluginParameterInfos()
Returns a mutable reference to the loaded plugin's parameter descriptor list.
void triggerIOUpdate()
Forces a full re-broadcast of device parameters and routing state to all connected clients.
void prepareToPlay(double sampleRate, int maximumExpectedSamplesPerBlock) override
Called by the JUCE audio engine before playback starts.
const String getProgramName(int index) override
const String getName() const override
Returns the processor name ("Mema").
void releaseResources() override
Called when playback stops; releases audio processing resources.
void audioDeviceStopped() override
Called when the audio device stops; notifies analyzers to clear their state.
void setPluginParameterRemoteControlInfos(int pluginParameterIndex, bool remoteControllable, ParameterControlType type, int steps)
Marks a plugin parameter as remotely controllable (or not) and sets its control widget type.
void removeOutputCommander(MemaOutputCommander *comander)
Removes a previously registered output commander.
void processBlock(AudioBuffer< float > &buffer, MidiBuffer &midiMessages) override
Standard JUCE AudioProcessor entry point — not used for live audio.
void removeOutputListener(ProcessorDataAnalyzer::Listener *listener)
Unregisters a previously added output analyzer listener.
static constexpr int s_minInputsCount
Minimum number of input channels (always at least 1).
void setMatrixCrosspointEnabledValue(std::uint16_t inputNumber, std::uint16_t outputNumber, bool enabled, MemaChannelCommander *sender=nullptr, int userId=-1)
Enables or disables a crosspoint routing node.
AudioProcessorEditor * createEditor() override
std::function< void()> onPluginParameterInfosChanged
Fired when the set of exposed plugin parameters changes (plugin load/unload or controllability settin...
bool isPluginEnabled()
Returns true when a plugin is loaded and its processing is enabled.
void removeInputListener(ProcessorDataAnalyzer::Listener *listener)
Unregisters a previously added input analyzer listener.
void setPluginPrePostState(bool post)
Selects whether the plugin processes audio before or after the crosspoint matrix.
void initializeInputCommander(MemaInputCommander *commander)
Pushes the current input mute states to a commander that was already registered.
void removeCrosspointCommander(MemaCrosspointCommander *comander)
Removes a previously registered crosspoint commander.
Internal JUCE message posted to the message thread when plugin parameter descriptors change.
Carries the plugin name and complete parameter descriptor list from Mema to Mema.Re clients.
Carries a single normalised plugin parameter value from Mema.Re to Mema.
Carries the plugin enabled and pre/post insertion state between Mema and Mema.Re.
Instructs clients to tear down and rebuild their UI for a new channel count.
Base class for all messages exchanged between Mema, Mema.Mo, and Mema.Re over TCP.
static SerializableMessage * initFromMemoryBlock(const juce::MemoryBlock &blob)
Deserialises a raw TCP frame into the correct concrete SerializableMessage subclass.
@ None
Sentinel / uninitialised type.
static PluginParameterInfo fromString(const juce::String ¶meterString)
static PluginParameterInfo fromAudioProcessorParameter(juce::AudioProcessorParameter &processorParameter)
static std::vector< PluginParameterInfo > parametersToInfos(juce::Array< juce::AudioProcessorParameter * > processorParameters)
static juce::String getMasterServiceTypeUID()
Returns the UID for the Mema master (server) service.
static int getConnectionPort()
Returns the TCP port used for client connections (55668).
static juce::String getServiceTypeUIDBase()
Returns the base string for building service type UIDs.
static int getBroadcastPort()
Returns the UDP port used for multicast service announcements.