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,
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, parameterInfos)->getSerializedMessage(), sendIds);
116 if (m_networkServer && m_networkServer->hasActiveConnections())
118 DBG(juce::String(__FUNCTION__) <<
" sending to net: " <<
int(index) <<
" > " << currentValue);
119 auto sendIds = m_networkServer->getActiveConnectionIds();
120 sendIds.erase(std::remove(sendIds.begin(), sendIds.end(), userId), sendIds.end());
121 m_networkServer->enqueueMessage(std::make_unique<PluginParameterValueMessage>(index,
id, currentValue)->getSerializedMessage(), sendIds);
125 void setIOCount(std::uint16_t inputCount, std::uint16_t outputCount)
override
127 if (m_networkServer && m_networkServer->hasActiveConnections())
129 m_networkServer->enqueueMessage(std::make_unique<ReinitIOCountMessage>(inputCount, outputCount)->getSerializedMessage());
135 m_networkServer = networkServer;
139 void setChannelCount(std::uint16_t channelCount)
override { ignoreUnused(channelCount); };
142 std::shared_ptr<InterprocessConnectionServerImpl> m_networkServer;
148 juce::AudioProcessor()
150#ifdef RUN_MESSAGE_TESTS
161 m_processorChannels[i][j] = 0.0f;
165 m_inputDataAnalyzer = std::make_unique<ProcessorDataAnalyzer>();
166 m_inputDataAnalyzer->setUseProcessingTypes(
true,
false,
false);
167 m_outputDataAnalyzer = std::make_unique<ProcessorDataAnalyzer>();
168 m_outputDataAnalyzer->setUseProcessingTypes(
true,
false,
false);
170 m_deviceManager = std::make_unique<AudioDeviceManager>();
171 m_deviceManager->addAudioCallback(
this);
172 m_deviceManager->addChangeListener(
this);
177 triggerConfigurationUpdate(
false);
181 m_serviceTopologyManager = std::make_unique<JUCEAppBasics::ServiceTopologyManager>(
184 JUCEAppBasics::ServiceTopologyManager::getServiceDescription(),
185 JUCEAppBasics::ServiceTopologyManager::getServiceDescription(),
189 m_networkServer = std::make_shared<InterprocessConnectionServerImpl>();
191 m_networkServer->onConnectionCreated = [=](
int connectionId) {
195 connection->
onConnectionLost = [=](
int connectionId) { DBG(juce::String(__FUNCTION__) <<
" connection " << connectionId <<
" lost");
196 m_trafficTypesPerConnection.erase(connectionId);
198 connection->onConnectionMade = [=](
int connectionId ) { DBG(juce::String(__FUNCTION__) <<
" connection " << connectionId <<
" made");
199 m_trafficTypesPerConnection[connectionId].clear();
200 if (m_networkServer && m_networkServer->hasActiveConnection(connectionId))
202 auto paletteStyle = JUCEAppBasics::CustomLookAndFeel::PaletteStyle::PS_Dark;
203 if (getActiveEditor())
204 if (
auto claf =
dynamic_cast<JUCEAppBasics::CustomLookAndFeel*
>(&getActiveEditor()->getLookAndFeel()))
205 paletteStyle = claf->getPaletteStyle();
207 std::map<std::uint16_t, bool> inputMuteStates;
208 std::map<std::uint16_t, bool> outputMuteStates;
209 std::map<std::uint16_t, std::map<std::uint16_t, bool>> matrixCrosspointStates;
210 std::map<std::uint16_t, std::map<std::uint16_t, float>> matrixCrosspointValues;
212 const ScopedLock sl(m_audioDeviceIOCallbackLock);
213 inputMuteStates = m_inputMuteStates;
214 outputMuteStates = m_outputMuteStates;
215 matrixCrosspointStates = m_matrixCrosspointStates;
216 matrixCrosspointValues = m_matrixCrosspointValues;
219 auto sendIds = std::vector<int>{ connectionId };
221 success = success && m_networkServer->enqueueMessage(std::make_unique<AnalyzerParametersMessage>(
int(getSampleRate()), getBlockSize())->getSerializedMessage(), sendIds);
222 success = success && m_networkServer->enqueueMessage(std::make_unique<ReinitIOCountMessage>(m_inputChannelCount, m_outputChannelCount)->getSerializedMessage(), sendIds);
223 success = success && m_networkServer->enqueueMessage(std::make_unique<EnvironmentParametersMessage>(paletteStyle)->getSerializedMessage(), sendIds);
224 success = success && m_networkServer->enqueueMessage(std::make_unique<ControlParametersMessage>(inputMuteStates, outputMuteStates, matrixCrosspointStates, matrixCrosspointValues)->getSerializedMessage(), sendIds);
225 success = success && m_networkServer->enqueueMessage(std::make_unique<PluginParameterInfosMessage>(m_pluginInstance ? m_pluginInstance->getName().toStdString() :
"", m_pluginParameterInfos)->getSerializedMessage(), sendIds);
227 m_networkServer->cleanupDeadConnections();
230 connection->onMessageReceived = [=](
int connectionId,
const juce::MemoryBlock& message) {
233 knownMessage->setId(connectionId);
234 postMessage(knownMessage);
237 DBG(juce::String(__FUNCTION__) +
" ignoring unknown message");
241 m_networkCommanderWrapper = std::make_unique<MemaNetworkClientCommanderWrapper>();
242 m_networkCommanderWrapper->setNetworkConnection(m_networkServer);
248 m_timedConfigurationDumper = std::make_unique<juce::TimedCallback>([=]() {
251 auto config = JUCEAppBasics::AppConfigurationBase::getInstance();
252 if (config !=
nullptr)
253 config->triggerConfigurationDump(
false);
257 m_timedConfigurationDumper->startTimer(100);
262 m_timedConfigurationDumper->stopTimer();
265 auto config = JUCEAppBasics::AppConfigurationBase::getInstance();
266 if (config !=
nullptr)
267 config->triggerConfigurationDump(
false);
271 m_networkServer->stop();
273 m_deviceManager->removeAudioCallback(
this);
277 delete[] m_processorChannels[i];
278 delete[] m_processorChannels;
287 devConfElm->addChildElement(m_deviceManager->createStateXml().release());
288 stateXml->addChildElement(devConfElm.release());
293 if (m_pluginInstance)
295 plgConfElm->addChildElement(m_pluginInstance->getPluginDescription().createXml().release());
297 juce::MemoryBlock destData;
298 m_pluginInstance->getStateInformation(destData);
299 plgConfElm->addTextElement(juce::Base64::toBase64(destData.getData(), destData.getSize()));
306 plgParamElm->addTextElement(plgParam.toString());
307 plgConfElm->addChildElement(plgParamElm.release());
309 stateXml->addChildElement(plgConfElm.release());
311 std::map<std::uint16_t, bool> inputMuteStates;
312 std::map<std::uint16_t, bool> outputMuteStates;
313 std::map<std::uint16_t, std::map<std::uint16_t, bool>> matrixCrosspointStates;
314 std::map<std::uint16_t, std::map<std::uint16_t, float>> matrixCrosspointValues;
317 const ScopedLock sl(m_audioDeviceIOCallbackLock);
318 inputMuteStates = m_inputMuteStates;
319 outputMuteStates = m_outputMuteStates;
320 matrixCrosspointStates = m_matrixCrosspointStates;
321 matrixCrosspointValues = m_matrixCrosspointValues;
325 juce::StringArray imutestatestr;
326 for (
auto const& mutestate : inputMuteStates)
327 imutestatestr.add(juce::String(mutestate.first) +
"," + juce::String(mutestate.second ? 1 : 0));
328 inputMutesElm->addTextElement(imutestatestr.joinIntoString(
";"));
329 stateXml->addChildElement(inputMutesElm.release());
332 juce::StringArray omutestatestr;
333 for (
auto const& mutestate : outputMuteStates)
334 omutestatestr.add(juce::String(mutestate.first) +
"," + juce::String(mutestate.second ? 1 : 0));
335 outputMutesElm->addTextElement(omutestatestr.joinIntoString(
";"));
336 stateXml->addChildElement(outputMutesElm.release());
339 juce::StringArray cgainstatestr;
340 for (
auto const& insKV : matrixCrosspointStates)
341 for (
auto const& outsKV : insKV.second)
342 cgainstatestr.add(juce::String(insKV.first) +
"," + juce::String(outsKV.first) +
"," + juce::String(outsKV.second ? 1 : 0) +
"," + juce::String(matrixCrosspointValues[insKV.first][outsKV.first]));
343 crosspointGainsElm->addTextElement(cgainstatestr.joinIntoString(
";"));
344 stateXml->addChildElement(crosspointGainsElm.release());
357 juce::XmlElement* deviceSetupXml =
nullptr;
359 if (
nullptr != devConfElm)
360 deviceSetupXml = devConfElm->getChildByName(
"DEVICESETUP");
372 auto audioDeviceSetup = m_deviceManager->getAudioDeviceSetup();
374 if (result.isNotEmpty())
376 juce::AlertWindow::showMessageBoxAsync(juce::MessageBoxIconType::WarningIcon, juce::JUCEApplication::getInstance()->getApplicationName() +
" device init failed", result);
382 if (audioDeviceSetup.bufferSize < 512)
383 audioDeviceSetup.bufferSize = 512;
384 m_deviceManager->setAudioDeviceSetup(audioDeviceSetup,
true);
393 if (
nullptr != plgConfElm)
397 auto pluginDescriptionXml = plgConfElm->getChildByName(
"PLUGIN");
398 if (
nullptr != pluginDescriptionXml)
400 auto pluginDescription = juce::PluginDescription();
401 pluginDescription.loadFromXml(*pluginDescriptionXml);
403 if (m_pluginInstance)
405 juce::MemoryOutputStream destDataStream;
406 juce::Base64::convertFromBase64(destDataStream, pluginDescriptionXml->getAllSubText());
407 m_pluginInstance->setStateInformation(destDataStream.getData(),
int(destDataStream.getDataSize()));
413 if (
nullptr != plgParamElm)
416 auto paramString = plgParamElm->getAllSubText();
419 jassert(paramInfo.index == index);
423 iter->initializeFromString(paramString);
428 jassert(paramInfo.name == param->getName(100));
429 jassert(paramInfo.label == param->getLabel());
431 jassert(paramInfo.isAutomatable == param->isAutomatable());
432 jassert(paramInfo.category == param->getCategory());
433 if (
auto* rangedParam =
dynamic_cast<const juce::RangedAudioParameter*
>(param))
435 auto range = rangedParam->getNormalisableRange();
436 jassert(paramInfo.minValue == range.start);
437 jassert(paramInfo.maxValue == range.end);
438 jassert(paramInfo.stepSize == range.interval);
439 jassert(paramInfo.isDiscrete == range.interval > 0.0f);
443 param->setValue(paramInfo.currentValue);
449 std::map<std::uint16_t, bool> inputMuteStates;
450 std::map<std::uint16_t, bool> outputMuteStates;
451 std::map<std::uint16_t, std::map<std::uint16_t, bool>> matrixCrosspointStates;
452 std::map<std::uint16_t, std::map<std::uint16_t, float>> matrixCrosspointValues;
454 if (
nullptr != inputMutesElm)
456 juce::StringArray inMutestateStrList;
457 auto inputMutesElmTxt = inputMutesElm->getAllSubText();
458 inMutestateStrList.addTokens(inputMutesElmTxt,
";",
"");
459 jassert(inMutestateStrList.size() == m_inputChannelCount);
460 if (inMutestateStrList.size() != m_inputChannelCount)
463 DBG(juce::String(__FUNCTION__) +
" config data for input mutes is insane -> resetting to default.");
464 for (
auto in = std::uint16_t(1); in <= m_inputChannelCount; in++)
465 inputMuteStates[in] =
false;
470 for (
auto const& inMutestateStr : inMutestateStrList)
472 juce::StringArray inMutestateStrSplit;
473 inMutestateStrSplit.addTokens(inMutestateStr,
",",
"");
474 jassert(2 == inMutestateStrSplit.size());
475 if (2 == inMutestateStrSplit.size())
476 inputMuteStates[std::uint16_t(inMutestateStrSplit[0].getIntValue())] = (1 == std::uint16_t(inMutestateStrSplit[1].getIntValue()));
481 if (
nullptr != outputMutesElm)
483 juce::StringArray outMutestateStrList;
484 auto outputMutesElmTxt = outputMutesElm->getAllSubText();
485 outMutestateStrList.addTokens(outputMutesElmTxt,
";",
"");
486 jassert(outMutestateStrList.size() == m_outputChannelCount);
487 if (outMutestateStrList.size() != m_outputChannelCount)
490 DBG(juce::String(__FUNCTION__) +
" config data for output mutes is insane -> resetting to default.");
491 for (
auto out = std::uint16_t(1); out <= m_outputChannelCount; out++)
492 outputMuteStates[out] =
false;
497 for (
auto const& outMutestateStr : outMutestateStrList)
499 juce::StringArray outMutestateStrSplit;
500 outMutestateStrSplit.addTokens(outMutestateStr,
",",
"");
501 jassert(2 == outMutestateStrSplit.size());
502 if (2 == outMutestateStrSplit.size())
503 outputMuteStates[std::uint16_t(outMutestateStrSplit[0].getIntValue())] = (1 == std::uint16_t(outMutestateStrSplit[1].getIntValue()));
508 if (
nullptr != crosspointGainsElm)
510 juce::StringArray crossGainstateStrList;
511 auto crossGainsElmTxt = crosspointGainsElm->getAllSubText();
512 crossGainstateStrList.addTokens(crossGainsElmTxt,
";",
"");
513 jassert(crossGainstateStrList.size() == (m_inputChannelCount * m_outputChannelCount));
514 if (crossGainstateStrList.size() != (m_inputChannelCount * m_outputChannelCount))
517 DBG(juce::String(__FUNCTION__) +
" config data for crosspoints is insane -> resetting to default.");
518 for (
auto in = std::uint16_t(1); in <= m_inputChannelCount; in++)
520 for (
auto out = std::uint16_t(1); out <= m_outputChannelCount; out++)
529 matrixCrosspointStates[in][out] = state;
530 matrixCrosspointValues[in][out] = value;
537 for (
auto const& crossGainstateStr : crossGainstateStrList)
539 juce::StringArray crossGainstateStrSplit;
540 crossGainstateStrSplit.addTokens(crossGainstateStr,
",",
"");
541 jassert(4 == crossGainstateStrSplit.size());
542 if (4 == crossGainstateStrSplit.size())
544 matrixCrosspointStates[std::uint16_t(crossGainstateStrSplit[0].getIntValue())][std::uint16_t(crossGainstateStrSplit[1].getIntValue())] = 1 == std::uint16_t(crossGainstateStrSplit[2].getIntValue());
545 matrixCrosspointValues[std::uint16_t(crossGainstateStrSplit[0].getIntValue())][std::uint16_t(crossGainstateStrSplit[1].getIntValue())] = crossGainstateStrSplit[3].getFloatValue();
552 auto crosspointStateOutCount = size_t(0);
553 if (0 != matrixCrosspointStates.size())
555 crosspointStateOutCount = matrixCrosspointStates.begin()->second.size();
556 for (
auto const& cpStatKV : matrixCrosspointStates)
558 jassert(crosspointStateOutCount == cpStatKV.second.size());
565 auto crosspointValOutCount = size_t(0);
566 if (0 != matrixCrosspointValues.size())
568 crosspointValOutCount = matrixCrosspointValues.begin()->second.size();
569 for (
auto const& cpValKV : matrixCrosspointValues)
571 jassert(crosspointValOutCount == cpValKV.second.size());
579 const ScopedLock sl(m_audioDeviceIOCallbackLock);
580 m_inputMuteStates = inputMuteStates;
581 m_outputMuteStates = outputMuteStates;
582 m_matrixCrosspointStates = matrixCrosspointStates;
583 m_matrixCrosspointValues = matrixCrosspointValues;
591 auto paletteStyle = JUCEAppBasics::CustomLookAndFeel::PaletteStyle::PS_Dark;
592 if (getActiveEditor())
593 if (
auto claf =
dynamic_cast<JUCEAppBasics::CustomLookAndFeel*
>(&getActiveEditor()->getLookAndFeel()))
594 paletteStyle = claf->getPaletteStyle();
596 postMessage(std::make_unique<EnvironmentParametersMessage>(paletteStyle).release());
601 postMessage(std::make_unique<ReinitIOCountMessage>(m_inputChannelCount, m_outputChannelCount).release());
606 if (m_inputDataAnalyzer)
607 m_inputDataAnalyzer->addListener(listener);
612 if (m_inputDataAnalyzer)
613 m_inputDataAnalyzer->removeListener(listener);
618 if (m_outputDataAnalyzer)
619 m_outputDataAnalyzer->addListener(listener);
624 if (m_outputDataAnalyzer)
625 m_outputDataAnalyzer->removeListener(listener);
630 if (commander ==
nullptr)
633 if (std::find(m_inputCommanders.begin(), m_inputCommanders.end(), commander) == m_inputCommanders.end())
637 m_inputCommanders.push_back(commander);
644 if (
nullptr != commander)
646 const ScopedLock sl(m_audioDeviceIOCallbackLock);
647 for (
auto const& inputMuteStatesKV : m_inputMuteStates)
648 commander->
setInputMute(inputMuteStatesKV.first, inputMuteStatesKV.second);
654 if (commander ==
nullptr)
657 auto existingInputCommander = std::find(m_inputCommanders.begin(), m_inputCommanders.end(), commander);
658 if (existingInputCommander != m_inputCommanders.end())
659 m_inputCommanders.erase(existingInputCommander);
664 if (commander ==
nullptr)
667 if (std::find(m_outputCommanders.begin(), m_outputCommanders.end(), commander) == m_outputCommanders.end())
671 m_outputCommanders.push_back(commander);
678 if (
nullptr != commander)
680 const ScopedLock sl(m_audioDeviceIOCallbackLock);
681 for (
auto const& outputMuteStatesKV : m_outputMuteStates)
682 commander->
setOutputMute(outputMuteStatesKV.first, outputMuteStatesKV.second);
688 if (commander ==
nullptr)
691 auto existingOutputCommander = std::find(m_outputCommanders.begin(), m_outputCommanders.end(), commander);
692 if (existingOutputCommander != m_outputCommanders.end())
693 m_outputCommanders.erase(existingOutputCommander);
698 if (commander ==
nullptr)
701 if (std::find(m_crosspointCommanders.begin(), m_crosspointCommanders.end(), commander) == m_crosspointCommanders.end())
705 m_crosspointCommanders.push_back(commander);
713 if (
nullptr != commander)
715 auto matrixCrosspointStates = std::map<std::uint16_t, std::map<std::uint16_t, bool>>();
716 auto matrixCrosspointValues = std::map<std::uint16_t, std::map<std::uint16_t, float>>();
718 const ScopedLock sl(m_audioDeviceIOCallbackLock);
719 matrixCrosspointStates = m_matrixCrosspointStates;
720 matrixCrosspointValues = m_matrixCrosspointValues;
722 for (
auto const& matrixCrosspointStateKV : matrixCrosspointStates)
724 for (
auto const& matrixCrosspointStateNodeKV : matrixCrosspointStateKV.second)
726 auto& input = matrixCrosspointStateKV.first;
727 auto& output = matrixCrosspointStateNodeKV.first;
728 auto& enabled = matrixCrosspointStateNodeKV.second;
732 for (
auto const& matrixCrosspointValKV : matrixCrosspointValues)
734 for (
auto const& matrixCrosspointValNodeKV : matrixCrosspointValKV.second)
736 auto& input = matrixCrosspointValKV.first;
737 auto& output = matrixCrosspointValNodeKV.first;
738 auto& val = matrixCrosspointValNodeKV.second;
747 if (commander ==
nullptr)
750 auto existingCrosspointCommander = std::find(m_crosspointCommanders.begin(), m_crosspointCommanders.end(), commander);
751 if (existingCrosspointCommander != m_crosspointCommanders.end())
752 m_crosspointCommanders.erase(existingCrosspointCommander);
757 if (commander ==
nullptr)
760 if (std::find(m_pluginCommanders.begin(), m_pluginCommanders.end(), commander) == m_pluginCommanders.end())
764 m_pluginCommanders.push_back(commander);
771 if (
nullptr != commander)
781 if (commander ==
nullptr)
784 auto existingPluginCommander = std::find(m_pluginCommanders.begin(), m_pluginCommanders.end(), commander);
785 if (existingPluginCommander != m_pluginCommanders.end())
786 m_pluginCommanders.erase(existingPluginCommander);
791 for (
auto const& ic : m_inputCommanders)
793 ic->setChannelCount(m_inputChannelCount > 0 ? std::uint16_t(m_inputChannelCount) : 0);
796 for (
auto const& cc : m_crosspointCommanders)
798 cc->setIOCount(m_inputChannelCount > 0 ? std::uint16_t(m_inputChannelCount) : 0, m_outputChannelCount > 0 ? std::uint16_t(m_outputChannelCount) : 0);
801 for (
auto const& oc : m_outputCommanders)
803 oc->setChannelCount(m_outputChannelCount > 0 ? std::uint16_t(m_outputChannelCount) : 0);
806 for (
auto const& pc : m_pluginCommanders)
814 jassert(inputChannelNumber > 0);
815 const ScopedLock sl(m_audioDeviceIOCallbackLock);
816 return m_inputMuteStates[inputChannelNumber];
821 jassert(inputChannelNumber > 0);
823 for (
auto const& inputCommander : m_inputCommanders)
826 inputCommander->setInputMute(inputChannelNumber, muted, userId);
830 const ScopedLock sl(m_audioDeviceIOCallbackLock);
831 m_inputMuteStates[inputChannelNumber] = muted;
839 jassert(inputNumber > 0 && outputNumber > 0);
841 const ScopedLock sl(m_audioDeviceIOCallbackLock);
842 if (m_matrixCrosspointStates.count(inputNumber) != 0)
843 if (m_matrixCrosspointStates.at(inputNumber).count(outputNumber) != 0)
844 return m_matrixCrosspointStates.at(inputNumber).at(outputNumber);
852 jassert(inputNumber > 0 && outputNumber > 0);
854 for (
auto const& crosspointCommander : m_crosspointCommanders)
857 crosspointCommander->setCrosspointEnabledValue(inputNumber, outputNumber, enabled, userId);
861 const ScopedLock sl(m_audioDeviceIOCallbackLock);
864 jassert(0 != m_matrixCrosspointStates.count(inputNumber));
865 if (0 != m_matrixCrosspointStates.count(inputNumber))
867 jassert(0 != m_matrixCrosspointStates.at(inputNumber).count(outputNumber));
870 m_matrixCrosspointStates[inputNumber][outputNumber] = enabled;
878 jassert(inputNumber > 0 && outputNumber > 0);
880 const ScopedLock sl(m_audioDeviceIOCallbackLock);
881 if (m_matrixCrosspointValues.count(inputNumber) != 0)
882 if (m_matrixCrosspointValues.at(inputNumber).count(outputNumber) != 0)
883 return m_matrixCrosspointValues.at(inputNumber).at(outputNumber);
891 jassert(inputNumber > 0 && outputNumber > 0);
893 for (
auto const& crosspointCommander : m_crosspointCommanders)
896 crosspointCommander->setCrosspointFactorValue(inputNumber, outputNumber, factor, userId);
900 const ScopedLock sl(m_audioDeviceIOCallbackLock);
903 jassert(0 != m_matrixCrosspointValues.count(inputNumber));
904 if (0 != m_matrixCrosspointValues.count(inputNumber))
906 jassert(0 != m_matrixCrosspointValues.at(inputNumber).count(outputNumber));
909 m_matrixCrosspointValues[inputNumber][outputNumber] = factor;
917 jassert(outputChannelNumber > 0);
918 const ScopedLock sl(m_audioDeviceIOCallbackLock);
919 return m_outputMuteStates[outputChannelNumber];
924 jassert(outputChannelNumber > 0);
926 for (
auto const& outputCommander : m_outputCommanders)
929 outputCommander->setOutputMute(outputChannelNumber, muted, userId);
933 const ScopedLock sl(m_audioDeviceIOCallbackLock);
934 m_outputMuteStates[outputChannelNumber] = muted;
942 auto reinitRequired =
false;
943 if (m_inputChannelCount != inputChannelCount)
945 m_inputChannelCount = inputChannelCount;
946 reinitRequired =
true;
950 const ScopedLock sl(m_pluginProcessingLock);
951 if (m_pluginInstance)
952 m_pluginInstance->setPlayConfigDetails(m_inputChannelCount, m_inputChannelCount, getSampleRate(), getBlockSize());
955 if (m_outputChannelCount != outputChannelCount)
957 m_outputChannelCount = outputChannelCount;
958 reinitRequired =
true;
966 juce::AudioPluginFormatManager formatManager;
967 addDefaultFormatsToManager(formatManager);
968 auto registeredFormats = formatManager.getFormats();
970 auto success =
false;
971 juce::String errorMessage =
"Unsupported plug-in format.";
973 for (
auto const& format : registeredFormats)
975 if (format->getName() == pluginDescription.pluginFormatName)
981 const ScopedLock sl(m_pluginProcessingLock);
984 if (m_pluginInstance)
986 for (
auto const& param : m_pluginInstance->getParameters())
987 param->addListener(
this);
990 m_pluginParameterInfos.clear();
992 m_pluginInstance = format->createInstanceFromDescription(pluginDescription, getSampleRate(), getBlockSize(), errorMessage);
993 if (m_pluginInstance)
995 m_pluginInstance->setPlayConfigDetails(m_inputChannelCount, m_inputChannelCount, getSampleRate(), getBlockSize());
998 m_pluginParameterInfos.clear();
999 for (
auto const& param : m_pluginInstance->getParameters())
1001 postMessage(std::make_unique<PluginParameterInfosChangedMessage>().release());
1004 for (
auto const& param : m_pluginInstance->getParameters())
1005 param->addListener(
this);
1007 m_pluginInstance->prepareToPlay(getSampleRate(), getBlockSize());
1010 success = errorMessage.isEmpty();
1016 juce::AlertWindow::showMessageBoxAsync(juce::MessageBoxIconType::WarningIcon,
"Loading error",
"Loading of the selected plug-in " + pluginDescription.name +
" failed.\n" + errorMessage);
1020 triggerConfigurationUpdate(
false);
1027 if (m_pluginInstance)
1028 return m_pluginInstance->getPluginDescription();
1037 const ScopedLock sl(m_pluginProcessingLock);
1038 m_pluginEnabled = enabled;
1041 triggerConfigurationUpdate(
false);
1046 return m_pluginEnabled;
1053 const ScopedLock sl(m_pluginProcessingLock);
1054 m_pluginPost = post;
1057 triggerConfigurationUpdate(
false);
1062 return m_pluginPost;
1071 const ScopedLock sl(m_pluginProcessingLock);
1072 m_pluginInstance.reset();
1073 m_pluginParameterInfos.clear();
1084 if (m_pluginInstance)
1086 auto pluginEditorInstance = m_pluginInstance->createEditorIfNeeded();
1087 if (pluginEditorInstance && !m_pluginEditorWindow)
1089 m_pluginEditorWindow = std::make_unique<ResizeableWindowWithTitleBarAndCloseCallback>(juce::JUCEApplication::getInstance()->getApplicationName() +
" : " + m_pluginInstance->getName(),
true);
1090 m_pluginEditorWindow->setResizable(
false,
false);
1091 m_pluginEditorWindow->setContentOwned(pluginEditorInstance,
true);
1093 m_pluginEditorWindow->setVisible(
true);
1100 if (m_pluginInstance)
1101 std::unique_ptr<juce::AudioProcessorEditor>(m_pluginInstance->getActiveEditor()).reset();
1102 if (deleteEditorWindow)
1103 m_pluginEditorWindow.reset();
1108 return m_pluginParameterInfos;
1113 if (parameterIndex >= 0 && parameterIndex < m_pluginParameterInfos.size())
1115 m_pluginParameterInfos[parameterIndex].isRemoteControllable = remoteControllable;
1116 m_pluginParameterInfos[parameterIndex].type = type;
1117 m_pluginParameterInfos[parameterIndex].stepCount = steps;
1119 jassert(m_pluginInstance);
1120 if (m_pluginInstance)
1122 m_pluginParameterInfos[parameterIndex].stepNames.clear();
1123 auto param = m_pluginInstance->getParameters()[parameterIndex];
1124 if (param && steps > 1)
1126 auto stepSize = 1.0f / (steps - 1);
1127 for (
int i = 0; i < steps; i++)
1129 m_pluginParameterInfos[parameterIndex].stepNames.push_back(param->getText(i * stepSize, 100).toStdString());
1134 triggerConfigurationUpdate(
false);
1140 if (parameterIndex >= 0 && parameterIndex < m_pluginParameterInfos.size())
1141 return m_pluginParameterInfos[parameterIndex].isRemoteControllable;
1148 if (!m_pluginInstance)
1151 auto& parameters = m_pluginInstance->getParameters();
1152 auto idxInRange = parameterIndex >= 0 && parameterIndex < parameters.size();
1153 jassert(idxInRange);
1157 const ScopedLock sl(m_pluginProcessingLock);
1158 return parameters[parameterIndex]->getValue();
1163 if (!m_pluginInstance)
1166 auto& parameters = m_pluginInstance->getParameters();
1167 auto idxInRange = parameterIndex >= 0 && parameterIndex < parameters.size();
1168 jassert(idxInRange);
1172 for (
auto const& pluginCommander : m_pluginCommanders)
1175 pluginCommander->setPluginParameterValue(parameterIndex,
id, normalizedValue, userId);
1180 const ScopedLock sl(m_pluginProcessingLock);
1182 parameters[parameterIndex]->setValue(normalizedValue);
1185 if (parameterIndex < m_pluginParameterInfos.size())
1186 m_pluginParameterInfos[parameterIndex].currentValue = normalizedValue;
1194 const ScopedLock sl(m_pluginProcessingLock);
1196 if (!m_pluginInstance)
1199 auto& parameters = m_pluginInstance->getParameters();
1201 if (parameterIndex >= 0 && parameterIndex < parameters.size())
1202 return parameters[parameterIndex];
1209 if (m_deviceManager)
1210 return m_deviceManager.get();
1217 if (m_networkServer)
1218 return m_networkServer->getListHealth();
1225 if (m_serviceTopologyManager)
1226 return m_serviceTopologyManager->getDiscoveredServiceTopology();
1239 setRateAndBufferSizeDetails(sampleRate, maximumExpectedSamplesPerBlock);
1243 const ScopedLock sl(m_pluginProcessingLock);
1244 if (m_pluginInstance)
1245 m_pluginInstance->prepareToPlay(sampleRate, maximumExpectedSamplesPerBlock);
1248 if (m_inputDataAnalyzer)
1249 m_inputDataAnalyzer->initializeParameters(sampleRate, maximumExpectedSamplesPerBlock);
1250 if (m_outputDataAnalyzer)
1251 m_outputDataAnalyzer->initializeParameters(sampleRate, maximumExpectedSamplesPerBlock);
1253 postMessage(std::make_unique<AnalyzerParametersMessage>(
int(sampleRate), maximumExpectedSamplesPerBlock).release());
1260 const ScopedLock sl(m_pluginProcessingLock);
1261 if (m_pluginInstance)
1262 m_pluginInstance->releaseResources();
1265 if (m_inputDataAnalyzer)
1266 m_inputDataAnalyzer->clearParameters();
1267 if (m_outputDataAnalyzer)
1268 m_outputDataAnalyzer->clearParameters();
1273 ignoreUnused(midiMessages);
1278 auto reinitRequired =
false;
1283 if (m_inputChannelCount > m_inputMuteStates.size())
1284 reinitRequired =
true;
1286 for (std::uint16_t input = 1; input <= m_inputChannelCount; input++)
1288 if (m_inputMuteStates.count(input) != 0 && m_inputMuteStates.at(input))
1290 auto channelIdx = input - 1;
1291 buffer.clear(channelIdx, 0, buffer.getNumSamples());
1297 const ScopedLock sl(m_pluginProcessingLock);
1298 if (m_pluginInstance && m_pluginEnabled && !m_pluginPost)
1299 m_pluginInstance->processBlock(buffer, midiMessages);
1302 postMessage(std::make_unique<AudioInputBufferMessage>(buffer).release());
1305 juce::AudioBuffer<float> processedBuffer;
1306 processedBuffer.setSize(m_outputChannelCount, buffer.getNumSamples(),
false,
true,
true);
1307 for (std::uint16_t inputIdx = 0; inputIdx < m_inputChannelCount; inputIdx++)
1309 for (std::uint16_t outputIdx = 0; outputIdx < m_outputChannelCount; outputIdx++)
1311 if (0 != m_matrixCrosspointStates.count(inputIdx + 1) && 0 != m_matrixCrosspointValues.count(inputIdx + 1))
1313 if (0 != m_matrixCrosspointStates[inputIdx + 1].count(outputIdx + 1) && 0 != m_matrixCrosspointValues[inputIdx + 1].count(outputIdx + 1))
1315 auto& enabled = m_matrixCrosspointStates.at(inputIdx + 1).at(outputIdx + 1);
1316 auto& factor = m_matrixCrosspointValues.at(inputIdx + 1).at(outputIdx + 1);
1317 auto gain = !enabled ? 0.0f : factor;
1318 processedBuffer.addFrom(outputIdx, 0, buffer.getReadPointer(inputIdx), buffer.getNumSamples(), gain);
1323 buffer.makeCopyOf(processedBuffer,
true);
1325 if (m_outputChannelCount > m_outputMuteStates.size())
1326 reinitRequired =
true;
1330 const ScopedLock sl(m_pluginProcessingLock);
1331 if (m_pluginInstance && m_pluginEnabled && m_pluginPost)
1332 m_pluginInstance->processBlock(buffer, midiMessages);
1335 for (std::uint16_t output = 1; output <= m_outputChannelCount; output++)
1337 if (m_outputMuteStates.count(output) != 0 && m_outputMuteStates.at(output))
1339 auto channelIdx = output - 1;
1340 buffer.clear(channelIdx, 0, buffer.getNumSamples());
1344 postMessage(std::make_unique<AudioOutputBufferMessage>(buffer).release());
1347 postMessage(std::make_unique<ReinitIOCountMessage>(m_inputChannelCount, m_outputChannelCount).release());
1353 juce::MemoryBlock serializedMessageMemoryBlock;
1357 origId = sm->getId();
1361 serializedMessageMemoryBlock = epm->getSerializedMessage();
1362 tId = epm->getType();
1366 serializedMessageMemoryBlock = apm->getSerializedMessage();
1367 tId = apm->getType();
1371 auto inputCount = iom->getInputCount();
1372 jassert(inputCount > 0);
1373 auto outputCount = iom->getOutputCount();
1374 jassert(outputCount > 0);
1376 for (
auto const& inputCommander : m_inputCommanders)
1377 inputCommander->setChannelCount(inputCount);
1379 for (
auto const& outputCommander : m_outputCommanders)
1380 outputCommander->setChannelCount(outputCount);
1382 for (
auto const& crosspointCommander : m_crosspointCommanders)
1383 crosspointCommander->setIOCount(inputCount, outputCount);
1387 serializedMessageMemoryBlock = iom->getSerializedMessage();
1389 tId = iom->getType();
1395 m_inputDataAnalyzer->analyzeData(m->getAudioBuffer());
1399 m_outputDataAnalyzer->analyzeData(m->getAudioBuffer());
1402 serializedMessageMemoryBlock = m->getSerializedMessage();
1408 DBG(juce::String(__FUNCTION__) <<
" i:" << cpm->getInputMuteStates().size() <<
" o:" << cpm->getOutputMuteStates().size() <<
" c:" << cpm->getCrosspointStates().size());
1409 for (
auto const& inputMuteState : cpm->getInputMuteStates())
1411 for (
auto const& outputMuteState : cpm->getOutputMuteStates())
1413 for (
auto const& crosspointStateKV : cpm->getCrosspointStates())
1415 auto& inputNumber = crosspointStateKV.first;
1416 for (
auto const& crosspointOStateKV : crosspointStateKV.second)
1418 auto& outputNumber = crosspointOStateKV.first;
1422 for (
auto const& crosspointValueKV : cpm->getCrosspointValues())
1424 auto& inputNumber = crosspointValueKV.first;
1425 for (
auto const& crosspointOValueKV : crosspointValueKV.second)
1427 auto& outputNumber = crosspointOValueKV.first;
1432 tId = cpm->getType();
1436 if (!dtsm->hasUserId())
1437 DBG(
"Incoming DataTrafficTypeSelecitonMessage cannot be associated with a connection");
1441 tId = dtsm->getType();
1445 DBG(juce::String(__FUNCTION__) <<
" ppiCnt:" << ppim->getParameterInfos().size());
1449 serializedMessageMemoryBlock = ppim->getSerializedMessage();
1451 tId = ppim->getType();
1455 DBG(juce::String(__FUNCTION__) <<
" ppvIdx:" <<
int(ppvm->getParameterIndex()) <<
" > " << ppvm->getCurrentValue());
1459 serializedMessageMemoryBlock = ppvm->getSerializedMessage();
1461 tId = ppvm->getType();
1472 std::vector<int> sendIds;
1473 for (
auto const& cId : m_trafficTypesPerConnection)
1475 if (cId.first != origId)
1478 if (cId.second.empty())
1479 sendIds.push_back(cId.first);
1481 else if (cId.second.end() != std::find(cId.second.begin(), cId.second.end(), tId))
1482 sendIds.push_back(cId.first);
1485 if (!sendIds.empty())
1486 sendMessageToClients(serializedMessageMemoryBlock, sendIds);
1495 for (
auto const& pluginCommander : m_pluginCommanders)
1496 pluginCommander->setPluginParameterValue(
static_cast<std::uint16_t
>(parameterIndex), iter->id.toStdString(), newValue);
1499 if (parameterIndex < m_pluginParameterInfos.size())
1500 m_pluginParameterInfos[parameterIndex].currentValue = newValue;
1506 ignoreUnused(parameterIndex);
1507 ignoreUnused(gestureIsStarting);
1510void MemaProcessor::sendMessageToClients(
const MemoryBlock& messageMemoryBlock,
const std::vector<int>& sendIds)
1512 if (m_networkServer && m_networkServer->hasActiveConnections())
1514 if (!messageMemoryBlock.isEmpty() && !m_networkServer->enqueueMessage(messageMemoryBlock, sendIds))
1516 auto deadConnectionIds = m_networkServer->cleanupDeadConnections();
1517 if (!deadConnectionIds.empty())
1519 for (
auto const& dcId : deadConnectionIds)
1520 m_trafficTypesPerConnection.erase(dcId);
1543 if (!m_processorEditor)
1544 m_processorEditor = std::make_unique<MemaProcessorEditor>(
this);
1548 return m_processorEditor.get();
1553 return !!m_processorEditor;
1568 ignoreUnused(index);
1573 ignoreUnused(index);
1579 ignoreUnused(index);
1580 ignoreUnused(newName);
1585 ignoreUnused(destData);
1591 ignoreUnused(sizeInBytes);
1595 float*
const* outputChannelData,
int numOutputChannels,
int numSamples,
const AudioIODeviceCallbackContext& context)
1597 ignoreUnused(context);
1599 const juce::ScopedLock sl(m_audioDeviceIOCallbackLock);
1601 if (m_inputChannelCount != numInputChannels || m_outputChannelCount != numOutputChannels)
1603 m_inputChannelCount = numInputChannels;
1604 m_outputChannelCount = numOutputChannels;
1605 postMessage(std::make_unique<ReinitIOCountMessage>(m_inputChannelCount, m_outputChannelCount).release());
1608 auto maxActiveChannels = std::max(numInputChannels, numOutputChannels);
1617 for (
auto i = 0; i < numInputChannels && i < maxActiveChannels; i++)
1619 memcpy(m_processorChannels[i], inputChannelData[i], (
size_t)numSamples *
sizeof(
float));
1623 juce::AudioBuffer<float> audioBufferToProcess(m_processorChannels, maxActiveChannels, numSamples);
1624 juce::MidiBuffer midiBufferToProcess;
1625 processBlock(audioBufferToProcess, midiBufferToProcess);
1628 auto processedChannelCount = audioBufferToProcess.getNumChannels();
1629 auto processedSampleCount = audioBufferToProcess.getNumSamples();
1630 auto processedData = audioBufferToProcess.getArrayOfReadPointers();
1631 jassert(processedSampleCount == numSamples);
1632 for (
auto i = 0; i < numOutputChannels && i < processedChannelCount; i++)
1634 memcpy(outputChannelData[i], processedData[i], (
size_t)processedSampleCount *
sizeof(
float));
1643 auto activeInputs = device->getActiveInputChannels();
1644 auto inputChannelCnt = std::uint16_t(activeInputs.getHighestBit() + 1);
1645 auto activeOutputs = device->getActiveOutputChannels();
1646 auto outputChannelCnt = std::uint16_t(activeOutputs.getHighestBit() + 1);
1647 auto sampleRate = device->getCurrentSampleRate();
1648 auto bufferSize = device->getCurrentBufferSizeSamples();
1651 setPlayConfigDetails(inputChannelCnt, outputChannelCnt, sampleRate, bufferSize);
1664 if (source == m_deviceManager.get())
1670 std::map<std::uint16_t, bool> inputMuteStates;
1671 std::map<std::uint16_t, bool> outputMuteStates;
1672 std::map<std::uint16_t, std::map<std::uint16_t, bool>> matrixCrosspointStates;
1673 std::map<std::uint16_t, std::map<std::uint16_t, float>> matrixCrosspointValues;
1676 const ScopedLock sl(m_audioDeviceIOCallbackLock);
1677 inputMuteStates = m_inputMuteStates;
1678 outputMuteStates = m_outputMuteStates;
1679 matrixCrosspointValues = m_matrixCrosspointValues;
1680 matrixCrosspointStates = m_matrixCrosspointStates;
1684 for (std::uint16_t channel = 1; channel <= inputChannelCount; channel++)
1685 for (
auto& inputCommander : m_inputCommanders)
1686 inputCommander->setInputMute(channel, inputMuteStates[channel]);
1689 for (std::uint16_t channel = 1; channel <= outputChannelCount; channel++)
1690 for (
auto& outputCommander : m_outputCommanders)
1691 outputCommander->setOutputMute(channel, outputMuteStates[channel]);
1693 for (std::uint16_t in = 1; in <= inputChannelCount; in++)
1695 for (std::uint16_t out = 1; out <= outputChannelCount; out++)
1697 for (
auto& crosspointCommander : m_crosspointCommanders)
1699 crosspointCommander->setCrosspointEnabledValue(in, out, matrixCrosspointStates[in][out]);
1700 crosspointCommander->setCrosspointFactorValue(in, out, matrixCrosspointValues[in][out]);
1705 juce::Array<juce::AudioProcessorParameter*> pluginParameters;
1706 juce::String pluginName;
1707 if (m_pluginInstance)
1710 const ScopedLock sl(m_pluginProcessingLock);
1711 pluginName = m_pluginInstance->getName();
1712 pluginParameters = m_pluginInstance->getParameters();
1715 for (
auto& pluginCommander : m_pluginCommanders)
1716 pluginCommander->setPluginParameterInfos(pluginParameterInfos, pluginName.toStdString());
1722 const ScopedLock sl(m_audioDeviceIOCallbackLock);
1723 m_inputMuteStates.clear();
1724 m_outputMuteStates.clear();
1725 m_matrixCrosspointStates.clear();
1726 m_matrixCrosspointValues.clear();
1730 for (std::uint16_t channel = 1; channel <= inputChannelCount; channel++)
1734 for (std::uint16_t channel = 1; channel <= outputChannelCount; channel++)
1737 for (std::uint16_t in = 1; in <= inputChannelCount; in++)
1739 for (std::uint16_t out = 1; out <= outputChannelCount; out++)
1754 DBG(juce::String(__FUNCTION__) <<
" " << connectionId <<
" chose " << trafficTypes.size() <<
" types");
1755 for (
auto const& tt : trafficTypes)
1757 if (m_trafficTypesPerConnection[connectionId].end() == std::find(m_trafficTypesPerConnection[connectionId].begin(), m_trafficTypesPerConnection[connectionId].end(), tt))
1758 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.
@ 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 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 setIOCount(std::uint16_t inputCount, std::uint16_t outputCount) override
void setPluginParameterInfos(const std::vector< PluginParameterInfo > ¶meterInfos, const std::string &name, int userId=-1) 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 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.
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.
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.
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.