Mema
Memory Matrix — multi-channel audio matrix monitor and router
Loading...
Searching...
No Matches
MemaMessages.h
Go to the documentation of this file.
1/* Copyright (c) 2024-2025, Christian Ahrens
2 *
3 * This file is part of Mema <https://github.com/ChristianAhrens/Mema>
4 *
5 * This tool is free software; you can redistribute it and/or modify it under
6 * the terms of the GNU Lesser General Public License version 3.0 as published
7 * by the Free Software Foundation.
8 *
9 * This tool is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12 * details.
13 *
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this tool; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18
19#pragma once
20
21#include <JuceHeader.h>
22
23#include <CustomLookAndFeel.h>
24
26
27namespace Mema
28{
29
30
31//==============================================================================
32/*
33 * Forward declarations of SerializableMessage-derived specializations
34 */
35class EnvironmentParametersMessage;
36class AnalyzerParametersMessage;
37class ReinitIOCountMessage;
38class AudioInputBufferMessage;
39class AudioOutputBufferMessage;
40class DataTrafficTypeSelectionMessage;
41class ControlParametersMessage;
42class PluginParameterInfosMessage;
43class PluginParameterValueMessage;
44class PluginProcessingStateMessage;
45
76class SerializableMessage : public juce::Message
77{
78public:
93
94public:
96 virtual ~SerializableMessage() = default;
97
99 void setId(int id) { m_userId = id; };
101 int getId() const { return m_userId; };
103 bool hasUserId() const { return -1 != m_userId; };
104
106 const SerializableMessageType getType() const { return m_type; };
107
114 juce::MemoryBlock getSerializedMessage() const
115 {
116 size_t contentSize = 0;
117 juce::MemoryBlock blob;
118 blob.append(&m_type, sizeof(SerializableMessageType));
119 auto sc = createSerializedContent(contentSize);
120 blob.append(sc.getData(), contentSize);
121 return blob;
122 };
131 static SerializableMessage* initFromMemoryBlock(const juce::MemoryBlock& blob)
132 {
133 auto minSize = sizeof(SerializableMessageType);
134 jassert(blob.getSize() >= minSize);
135 if (blob.getSize() < minSize)
136 return nullptr;
137
138 auto type = static_cast<SerializableMessageType>(blob[0]);
139 switch (type)
140 {
142 return reinterpret_cast<SerializableMessage*>(std::make_unique<EnvironmentParametersMessage>(blob).release());
144 return reinterpret_cast<SerializableMessage*>(std::make_unique<AnalyzerParametersMessage>(blob).release());
145 case ReinitIOCount:
146 return reinterpret_cast<SerializableMessage*>(std::make_unique<ReinitIOCountMessage>(blob).release());
147 case AudioInputBuffer:
148 return reinterpret_cast<SerializableMessage*>(std::make_unique<AudioInputBufferMessage>(blob).release());
150 return reinterpret_cast<SerializableMessage*>(std::make_unique<AudioOutputBufferMessage>(blob).release());
152 return reinterpret_cast<SerializableMessage*>(std::make_unique<DataTrafficTypeSelectionMessage>(blob).release());
154 return reinterpret_cast<SerializableMessage*>(std::make_unique<ControlParametersMessage>(blob).release());
156 return reinterpret_cast<SerializableMessage*>(std::make_unique<PluginParameterInfosMessage>(blob).release());
158 return reinterpret_cast<SerializableMessage*>(std::make_unique<PluginParameterValueMessage>(blob).release());
160 return reinterpret_cast<SerializableMessage*>(std::make_unique<PluginProcessingStateMessage>(blob).release());
161 case None:
162 default:
163 return nullptr;
164 }
165 };
173 {
174 if (nullptr != message)
175 {
176 switch (message->getType())
177 {
179 {
180 auto apm = std::unique_ptr<AnalyzerParametersMessage>(reinterpret_cast<AnalyzerParametersMessage*>(message));
181 }
182 break;
183 case ReinitIOCount:
184 {
185 auto riocm = std::unique_ptr<ReinitIOCountMessage>(reinterpret_cast<ReinitIOCountMessage*>(message));
186 }
187 break;
188 case AudioInputBuffer:
189 {
190 auto aibm = std::unique_ptr<AudioInputBufferMessage>(reinterpret_cast<AudioInputBufferMessage*>(message));
191 }
192 break;
194 {
195 auto aobm = std::unique_ptr<AudioOutputBufferMessage>(reinterpret_cast<AudioOutputBufferMessage*>(message));
196 }
197 break;
199 {
200 auto dtsm = std::unique_ptr<DataTrafficTypeSelectionMessage>(reinterpret_cast<DataTrafficTypeSelectionMessage*>(message));
201 }
202 break;
204 {
205 auto cpm = std::unique_ptr<ControlParametersMessage>(reinterpret_cast<ControlParametersMessage*>(message));
206 }
207 break;
209 {
210 auto ppim = std::unique_ptr<PluginParameterInfosMessage>(reinterpret_cast<PluginParameterInfosMessage*>(message));
211 }
212 break;
214 {
215 auto ppvm = std::unique_ptr<PluginParameterValueMessage>(reinterpret_cast<PluginParameterValueMessage*>(message));
216 }
217 break;
219 {
220 auto pesm = std::unique_ptr<PluginProcessingStateMessage>(reinterpret_cast<PluginProcessingStateMessage*>(message));
221 }
222 break;
223 case None:
224 default:
225 break;
226 }
227 }
228 };
229
230protected:
231 //==============================================================================
237 virtual juce::MemoryBlock createSerializedContent(size_t& contentSize) const = 0;
238
239 //==============================================================================
241 std::uint32_t ReadUint32(const char* buffer)
242 {
243 return (((static_cast<std::uint8_t>(buffer[0]) << 24) & 0xff000000) +
244 ((static_cast<std::uint8_t>(buffer[1]) << 16) & 0x00ff0000) +
245 ((static_cast<std::uint8_t>(buffer[2]) << 8) & 0x0000ff00) +
246 static_cast<std::uint8_t>(buffer[3]));
247 };
249 std::uint16_t ReadUint16(const char* buffer)
250 {
251 return (((static_cast<std::uint8_t>(buffer[0]) << 8) & 0xff00) +
252 static_cast<std::uint8_t>(buffer[1]));
253 };
254
255 //==============================================================================
257 int m_userId = -1;
258};
259
260//==============================================================================
273{
274public:
276 EnvironmentParametersMessage(JUCEAppBasics::CustomLookAndFeel::PaletteStyle paletteStyle) { m_type = SerializableMessageType::EnvironmentParameters; m_paletteStyle = paletteStyle; };
277 EnvironmentParametersMessage(const juce::MemoryBlock& blob)
278 {
280
282 blob.copyTo(&m_paletteStyle, sizeof(SerializableMessageType), sizeof(JUCEAppBasics::CustomLookAndFeel::PaletteStyle));
283
284 };
286
288 JUCEAppBasics::CustomLookAndFeel::PaletteStyle getPaletteStyle() const { return m_paletteStyle; };
289
290protected:
291 juce::MemoryBlock createSerializedContent(size_t& contentSize) const override
292 {
293 juce::MemoryBlock blob;
294 blob.append(&m_paletteStyle, sizeof(JUCEAppBasics::CustomLookAndFeel::PaletteStyle));
295 contentSize = blob.getSize();
296 return blob;
297 };
298
299private:
300 JUCEAppBasics::CustomLookAndFeel::PaletteStyle m_paletteStyle = JUCEAppBasics::CustomLookAndFeel::PS_Dark;
301};
302
303//==============================================================================
316{
317public:
319 AnalyzerParametersMessage(int sampleRate, int maximumExpectedSamplesPerBlock) { m_type = SerializableMessageType::AnalyzerParameters; m_sampleRate = std::uint16_t(sampleRate); m_maximumExpectedSamplesPerBlock = std::uint16_t(maximumExpectedSamplesPerBlock); };
320 AnalyzerParametersMessage(const juce::MemoryBlock& blob)
321 {
323
325 blob.copyTo(&m_sampleRate, sizeof(SerializableMessageType), sizeof(std::uint16_t));
326 blob.copyTo(&m_maximumExpectedSamplesPerBlock, sizeof(SerializableMessageType) + sizeof(std::uint16_t), sizeof(std::uint16_t));
327
328 };
330
332 int getSampleRate() const { return m_sampleRate; };
334 int getMaximumExpectedSamplesPerBlock() const { return m_maximumExpectedSamplesPerBlock; };
335
336protected:
337 juce::MemoryBlock createSerializedContent(size_t& contentSize) const override
338 {
339 juce::MemoryBlock blob;
340 blob.append(&m_sampleRate, sizeof(std::uint16_t));
341 blob.append(&m_maximumExpectedSamplesPerBlock, sizeof(std::uint16_t));
342 contentSize = blob.getSize();
343 return blob;
344 };
345
346private:
347 std::uint16_t m_sampleRate = 0;
348 std::uint16_t m_maximumExpectedSamplesPerBlock = 0;
349};
350
351//==============================================================================
364{
365public:
367 ReinitIOCountMessage(int inputs, int outputs) { m_type = SerializableMessageType::ReinitIOCount; m_inputCount = std::uint16_t(inputs); m_outputCount = std::uint16_t(outputs); };
368 ReinitIOCountMessage(const juce::MemoryBlock& blob)
369 {
370 jassert(SerializableMessageType::ReinitIOCount == static_cast<SerializableMessageType>(blob[0]));
371
373 blob.copyTo(&m_inputCount, sizeof(SerializableMessageType), sizeof(std::uint16_t));
374 blob.copyTo(&m_outputCount, sizeof(SerializableMessageType) + sizeof(std::uint16_t), sizeof(std::uint16_t));
375
376 };
378
380 std::uint16_t getInputCount() const { return m_inputCount; };
382 std::uint16_t getOutputCount() const { return m_outputCount; };
383
384protected:
385 juce::MemoryBlock createSerializedContent(size_t& contentSize) const override
386 {
387 juce::MemoryBlock blob;
388 blob.append(&m_inputCount, sizeof(std::uint16_t));
389 blob.append(&m_outputCount, sizeof(std::uint16_t));
390 contentSize = blob.getSize();
391 return blob;
392 };
393
394private:
395 std::uint16_t m_inputCount = 0;
396 std::uint16_t m_outputCount = 0;
397};
398
399//==============================================================================
417{
418public:
426
427public:
429 AudioBufferMessage(juce::AudioBuffer<float>& buffer) { m_buffer = buffer; };
431
433 const juce::AudioBuffer<float>& getAudioBuffer() const { return m_buffer; };
435 const FlowDirection getFlowDirection() const { return m_direction; };
436
437protected:
438 juce::MemoryBlock createSerializedContent(size_t& contentSize) const {
439 auto numChannels = std::uint16_t(m_buffer.getNumChannels());
440 auto numSamples = std::uint16_t(m_buffer.getNumSamples());
441 juce::MemoryBlock blob;
442 blob.append(&m_direction, sizeof(FlowDirection));
443 blob.append(&numChannels, sizeof(std::uint16_t));
444 blob.append(&numSamples, sizeof(std::uint16_t));
445 for (int channelNumber = 0; channelNumber < numChannels; channelNumber++)
446 blob.append(m_buffer.getReadPointer(channelNumber), sizeof(float) * numSamples);
447 contentSize = blob.getSize();
448
449 return blob;
450 };
451
453 juce::AudioBuffer<float> m_buffer;
454
455};
456
467{
468public:
471 AudioInputBufferMessage(const juce::MemoryBlock& blob)
472 {
474
476
477 auto readPos = int(sizeof(SerializableMessageType));
478
479 blob.copyTo(&m_direction, readPos, sizeof(FlowDirection));
481
482 readPos += sizeof(FlowDirection);
483 auto numChannels = std::uint16_t(0);
484 blob.copyTo(&numChannels, readPos, sizeof(std::uint16_t));
485 readPos += sizeof(std::uint16_t);
486 auto numSamples = std::uint16_t(0);
487 blob.copyTo(&numSamples, readPos, sizeof(std::uint16_t));
488 readPos += sizeof(std::uint16_t);
489 auto data = reinterpret_cast<const float*>(blob.begin() + readPos);
490
491 m_buffer = juce::AudioBuffer<float>(numChannels, numSamples);
492 auto samplePos = 0;
493 for (int i = 0; i < numChannels; i++)
494 {
495 m_buffer.copyFrom(i, 0, data + samplePos, numSamples);
496 samplePos += numSamples;
497 }
498 };
500};
501
512{
513public:
516 AudioOutputBufferMessage(const juce::MemoryBlock& blob)
517 {
519
520 auto readPos = int(sizeof(SerializableMessageType));
521
522 blob.copyTo(&m_direction, readPos, sizeof(FlowDirection));
524
525 readPos += sizeof(FlowDirection);
526 auto numChannels = std::uint16_t(0);
527 blob.copyTo(&numChannels, readPos, sizeof(std::uint16_t));
528 readPos += sizeof(std::uint16_t);
529 auto numSamples = std::uint16_t(0);
530 blob.copyTo(&numSamples, readPos, sizeof(std::uint16_t));
531 readPos += sizeof(std::uint16_t);
532 auto data = reinterpret_cast<const float*>(blob.begin() + readPos);
533
534 m_buffer = juce::AudioBuffer<float>(numChannels, numSamples);
535 auto samplePos = 0;
536 for (int i = 0; i < numChannels; i++)
537 {
538 m_buffer.copyFrom(i, 0, data + samplePos, numSamples);
539 samplePos += numSamples;
540 }
541 };
543};
544
545//==============================================================================
562{
563public:
565 DataTrafficTypeSelectionMessage(const std::vector<SerializableMessageType>& trafficTypes) { m_type = SerializableMessageType::DataTrafficTypeSelection; m_trafficTypes = trafficTypes; };
566 DataTrafficTypeSelectionMessage(const juce::MemoryBlock& blob)
567 {
569
571
572 auto readPos = int(sizeof(SerializableMessageType));
573
574 std::uint16_t typesCount;
575 blob.copyTo(&typesCount, readPos, sizeof(std::uint16_t));
576 readPos += sizeof(std::uint16_t);
577 m_trafficTypes.resize(typesCount);
578 for (int i = 0; i < typesCount; i++)
579 {
580 blob.copyTo(&m_trafficTypes[i], readPos, sizeof(SerializableMessageType));
581 readPos += sizeof(SerializableMessageType);
582 }
583
584 };
586
588 const std::vector<SerializableMessageType>& getTrafficTypes() const { return m_trafficTypes; };
589
590protected:
591 juce::MemoryBlock createSerializedContent(size_t& contentSize) const override
592 {
593 juce::MemoryBlock blob;
594 auto typesCount = std::uint16_t(m_trafficTypes.size());
595 blob.append(&typesCount, sizeof(std::uint16_t));
596 for (auto& trafficType : m_trafficTypes)
597 blob.append(&trafficType, sizeof(SerializableMessageType));
598 contentSize = blob.getSize();
599 return blob;
600 };
601
602private:
603 std::vector<SerializableMessageType> m_trafficTypes;
604};
605
636{
637public:
639 ControlParametersMessage(const std::map<std::uint16_t, bool>& inputMuteStates, const std::map<std::uint16_t, bool>& outputMuteStates,
640 const std::map<std::uint16_t, std::map<std::uint16_t, bool>>& crosspointStates, const std::map<std::uint16_t, std::map<std::uint16_t, float>>& crosspointValues)
641 {
642#ifdef DEBUG
643 // sanity check symmetry of crosspoint states
644 auto crosspointStateOutCount = size_t(0);
645 if (0 != crosspointStates.size())
646 {
647 crosspointStateOutCount = crosspointStates.begin()->second.size();
648 for (auto const& cpStatKV : crosspointStates)
649 {
650 jassert(crosspointStateOutCount == cpStatKV.second.size());
651 }
652 }
653
654 // sanity check symmetry of crosspoint values
655 auto crosspointValOutCount = size_t(0);
656 if (0 != crosspointValues.size())
657 {
658 crosspointValOutCount = crosspointValues.begin()->second.size();
659 for (auto const& cpValKV : crosspointValues)
660 {
661 jassert(crosspointValOutCount == cpValKV.second.size());
662 }
663 }
664#endif
665
667 m_inputMuteStates = inputMuteStates;
668 m_outputMuteStates = outputMuteStates;
669 m_crosspointStates = crosspointStates;
670 m_crosspointValues = crosspointValues;
671 };
672 ControlParametersMessage(const juce::MemoryBlock& blob)
673 {
675
677
678 auto readPos = int(sizeof(SerializableMessageType));
679
680 std::uint16_t inputMuteStatesCount;
681 blob.copyTo(&inputMuteStatesCount, readPos, sizeof(std::uint16_t));
682 readPos += sizeof(inputMuteStatesCount);
683 for (int i = 0; i < inputMuteStatesCount; i++)
684 {
685 std::pair<std::uint16_t, bool> inputMuteState;
686 blob.copyTo(&inputMuteState.first, readPos, sizeof(inputMuteState.first));
687 readPos += sizeof(inputMuteState.first);
688 blob.copyTo(&inputMuteState.second, readPos, sizeof(inputMuteState.second));
689 readPos += sizeof(inputMuteState.second);
690
691 m_inputMuteStates[inputMuteState.first] = inputMuteState.second;
692 }
693
694 std::uint16_t outputMuteStatesCount;
695 blob.copyTo(&outputMuteStatesCount, readPos, sizeof(std::uint16_t));
696 readPos += sizeof(outputMuteStatesCount);
697 for (int i = 0; i < outputMuteStatesCount; i++)
698 {
699 std::pair<std::uint16_t, bool> outputMuteState;
700 blob.copyTo(&outputMuteState.first, readPos, sizeof(outputMuteState.first));
701 readPos += sizeof(outputMuteState.first);
702 blob.copyTo(&outputMuteState.second, readPos, sizeof(outputMuteState.second));
703 readPos += sizeof(outputMuteState.second);
704
705 m_outputMuteStates[outputMuteState.first] = outputMuteState.second;
706 }
707
708 std::uint16_t crosspointStatesCount;
709 blob.copyTo(&crosspointStatesCount, readPos, sizeof(std::uint16_t));
710 readPos += sizeof(crosspointStatesCount);
711 for (int i = 0; i < crosspointStatesCount; i++)
712 {
713 std::uint16_t in, out;
714 bool state;
715 blob.copyTo(&in, readPos, sizeof(in));
716 readPos += sizeof(in);
717 blob.copyTo(&out, readPos, sizeof(out));
718 readPos += sizeof(out);
719 blob.copyTo(&state, readPos, sizeof(state));
720 readPos += sizeof(state);
721
722 m_crosspointStates[in][out] = state;
723 }
724
725 std::uint16_t crosspointValuesCount;
726 blob.copyTo(&crosspointValuesCount, readPos, sizeof(std::uint16_t));
727 readPos += sizeof(crosspointValuesCount);
728 for (int i = 0; i < crosspointValuesCount; i++)
729 {
730 std::uint16_t in, out;
731 float value;
732 blob.copyTo(&in, readPos, sizeof(in));
733 readPos += sizeof(in);
734 blob.copyTo(&out, readPos, sizeof(out));
735 readPos += sizeof(out);
736 blob.copyTo(&value, readPos, sizeof(value));
737 readPos += sizeof(value);
738
739 m_crosspointValues[in][out] = value;
740 }
741 };
743
745 const std::map<std::uint16_t, bool>& getInputMuteStates() const { return m_inputMuteStates; };
747 const std::map<std::uint16_t, bool>& getOutputMuteStates() const { return m_outputMuteStates; };
749 const std::map<std::uint16_t, std::map<std::uint16_t, bool>>& getCrosspointStates() const { return m_crosspointStates; };
751 const std::map<std::uint16_t, std::map<std::uint16_t, float>>& getCrosspointValues() const { return m_crosspointValues; };
752
753protected:
754 juce::MemoryBlock createSerializedContent(size_t& contentSize) const override
755 {
756 juce::MemoryBlock blob;
757
758 auto inputMuteStatesCount = std::uint16_t(m_inputMuteStates.size());
759 blob.append(&inputMuteStatesCount, sizeof(inputMuteStatesCount));
760 for (auto& inputMuteStateKV : m_inputMuteStates)
761 {
762 blob.append(&inputMuteStateKV.first, sizeof(inputMuteStateKV.first));
763 blob.append(&inputMuteStateKV.second, sizeof(inputMuteStateKV.second));
764 }
765
766 auto outputMuteStatesCount = std::uint16_t(m_outputMuteStates.size());
767 blob.append(&outputMuteStatesCount, sizeof(outputMuteStatesCount));
768 for (auto& outputMuteStateKV : m_outputMuteStates)
769 {
770 blob.append(&outputMuteStateKV.first, sizeof(outputMuteStateKV.first));
771 blob.append(&outputMuteStateKV.second, sizeof(outputMuteStateKV.second));
772 }
773
774 auto crosspointStatesCount = std::uint16_t(0);
775 if (0 < m_crosspointStates.size())
776 crosspointStatesCount = std::uint16_t(m_crosspointStates.size() * m_crosspointStates.begin()->second.size());
777 blob.append(&crosspointStatesCount, sizeof(crosspointStatesCount));
778 auto crosspointStatesCountRef = std::uint16_t(0);
779 for (auto& crosspointStatesFirstDKV : m_crosspointStates)
780 {
781 for (auto& crosspointStatesSecDKV : crosspointStatesFirstDKV.second)
782 {
783 auto& in = crosspointStatesFirstDKV.first;
784 blob.append(&in, sizeof(in));
785 auto& out = crosspointStatesSecDKV.first;
786 blob.append(&out, sizeof(out));
787 auto& state = crosspointStatesSecDKV.second;
788 blob.append(&state, sizeof(state));
789 crosspointStatesCountRef++;
790 }
791 }
792 jassert(crosspointStatesCount == crosspointStatesCountRef);
793
794 auto crosspointValuesCount = std::uint16_t(0);
795 if (0 < m_crosspointValues.size())
796 crosspointValuesCount = std::uint16_t(m_crosspointValues.size() * m_crosspointValues.begin()->second.size());
797 blob.append(&crosspointValuesCount, sizeof(crosspointValuesCount));
798 auto crosspointValuesCountRef = std::uint16_t(0);
799 for (auto& crosspointValuesFirstDKV : m_crosspointValues)
800 {
801 for (auto& crosspointValuesSecDKV : crosspointValuesFirstDKV.second)
802 {
803 auto& in = crosspointValuesFirstDKV.first;
804 blob.append(&in, sizeof(in));
805 auto& out = crosspointValuesSecDKV.first;
806 blob.append(&out, sizeof(out));
807 auto& value = crosspointValuesSecDKV.second;
808 blob.append(&value, sizeof(value));
809 crosspointValuesCountRef++;
810 }
811 }
812 jassert(crosspointValuesCount == crosspointValuesCountRef);
813
814 contentSize = blob.getSize();
815 return blob;
816 };
817
818private:
819 std::map<std::uint16_t, bool> m_inputMuteStates;
820 std::map<std::uint16_t, bool> m_outputMuteStates;
821 std::map<std::uint16_t, std::map<std::uint16_t, bool>> m_crosspointStates;
822 std::map<std::uint16_t, std::map<std::uint16_t, float>> m_crosspointValues;
823};
824
845{
846public:
848 PluginParameterInfosMessage(const std::string& pluginName, bool pluginEnabled, bool pluginPost, const std::vector<PluginParameterInfo>& parameterInfos)
849 {
851 m_parameterInfos = parameterInfos;
852 m_pluginName = pluginName;
853 m_pluginEnabled = pluginEnabled;
854 m_pluginPost = pluginPost;
855 }
856
857 PluginParameterInfosMessage(const juce::MemoryBlock& blob)
858 {
860
862
863 auto readPos = int(sizeof(SerializableMessageType));
864
865 // Read plugin string length and string
866 std::uint16_t pluginNameLength;
867 blob.copyTo(&pluginNameLength, readPos, sizeof(std::uint16_t));
868 readPos += sizeof(std::uint16_t);
869 m_pluginName = juce::String(juce::CharPointer_UTF8(static_cast<const char*>(blob.begin()) + readPos), pluginNameLength);
870 readPos += pluginNameLength;
871
872 // Read enabled and post state
873 blob.copyTo(&m_pluginEnabled, readPos, sizeof(bool));
874 readPos += sizeof(bool);
875 blob.copyTo(&m_pluginPost, readPos, sizeof(bool));
876 readPos += sizeof(bool);
877
878 std::uint16_t paramCount;
879 blob.copyTo(&paramCount, readPos, sizeof(std::uint16_t));
880 readPos += sizeof(std::uint16_t);
881
882 m_parameterInfos.reserve(paramCount);
883
884 for (int i = 0; i < paramCount; i++)
885 {
887
888 // Read index
889 std::int32_t index;
890 blob.copyTo(&index, readPos, sizeof(std::int32_t));
891 info.index = index;
892 readPos += sizeof(std::int32_t);
893
894 // Read id string length and string
895 std::uint16_t idLength;
896 blob.copyTo(&idLength, readPos, sizeof(std::uint16_t));
897 readPos += sizeof(std::uint16_t);
898 info.id = juce::String(juce::CharPointer_UTF8(static_cast<const char*>(blob.begin()) + readPos), idLength);
899 readPos += idLength;
900
901 // Read name string length and string
902 std::uint16_t nameLength;
903 blob.copyTo(&nameLength, readPos, sizeof(std::uint16_t));
904 readPos += sizeof(std::uint16_t);
905 info.name = juce::String(juce::CharPointer_UTF8(static_cast<const char*>(blob.begin()) + readPos), nameLength);
906 readPos += nameLength;
907
908 // Read float values
909 blob.copyTo(&info.defaultValue, readPos, sizeof(float));
910 readPos += sizeof(float);
911 blob.copyTo(&info.currentValue, readPos, sizeof(float));
912 readPos += sizeof(float);
913
914 // Read label string length and string
915 std::uint16_t labelLength;
916 blob.copyTo(&labelLength, readPos, sizeof(std::uint16_t));
917 readPos += sizeof(std::uint16_t);
918 info.label = juce::String(juce::CharPointer_UTF8(static_cast<const char*>(blob.begin()) + readPos), labelLength);
919 readPos += labelLength;
920
921 // Read bool values
922 blob.copyTo(&info.isAutomatable, readPos, sizeof(bool));
923 readPos += sizeof(bool);
924 blob.copyTo(&info.isRemoteControllable, readPos, sizeof(bool));
925 readPos += sizeof(bool);
926
927 // Read category as int
928 std::int32_t categoryInt;
929 blob.copyTo(&categoryInt, readPos, sizeof(std::int32_t));
930 info.category = static_cast<juce::AudioProcessorParameter::Category>(categoryInt);
931 readPos += sizeof(std::int32_t);
932
933 // Read range values
934 blob.copyTo(&info.minValue, readPos, sizeof(float));
935 readPos += sizeof(float);
936 blob.copyTo(&info.maxValue, readPos, sizeof(float));
937 readPos += sizeof(float);
938 blob.copyTo(&info.stepSize, readPos, sizeof(float));
939 readPos += sizeof(float);
940 blob.copyTo(&info.isDiscrete, readPos, sizeof(bool));
941 readPos += sizeof(bool);
942
943 // Read type
944 blob.copyTo(&info.type, readPos, sizeof(ParameterControlType));
945 readPos += sizeof(ParameterControlType);
946
947 // Read stepCount
948 std::int32_t stepCount;
949 blob.copyTo(&stepCount, readPos, sizeof(std::int32_t));
950 info.stepCount = stepCount;
951 readPos += sizeof(std::int32_t);
952
953 // Read stepNames (count already known from stepCount)
954 for (int s = 0; s < stepCount; s++)
955 {
956 std::uint16_t stepNameLength;
957 blob.copyTo(&stepNameLength, readPos, sizeof(std::uint16_t));
958 readPos += sizeof(std::uint16_t);
959 auto stepName = juce::String(juce::CharPointer_UTF8(
960 static_cast<const char*>(blob.begin()) + readPos), stepNameLength);
961 readPos += stepNameLength;
962 info.stepNames.push_back(stepName.toStdString());
963 }
964
965 m_parameterInfos.push_back(info);
966 }
967 }
968
970
972 const juce::String& getPluginName() const { return m_pluginName; }
974 const std::vector<PluginParameterInfo>& getParameterInfos() const { return m_parameterInfos; }
976 bool isPluginEnabled() const { return m_pluginEnabled; }
978 bool isPluginPost() const { return m_pluginPost; }
979
980protected:
981 juce::MemoryBlock createSerializedContent(size_t& contentSize) const override
982 {
983 juce::MemoryBlock blob;
984
985 // Write name string (length + UTF8 bytes)
986 auto pluginNameUtf8 = m_pluginName.toUTF8();
987 std::uint16_t pluginNameLength = std::uint16_t(strlen(pluginNameUtf8));
988 blob.append(&pluginNameLength, sizeof(std::uint16_t));
989 blob.append(pluginNameUtf8, pluginNameLength);
990
991 // Write enabled and post state
992 blob.append(&m_pluginEnabled, sizeof(bool));
993 blob.append(&m_pluginPost, sizeof(bool));
994
995 auto paramCount = std::uint16_t(m_parameterInfos.size());
996 blob.append(&paramCount, sizeof(std::uint16_t));
997
998 for (const auto& info : m_parameterInfos)
999 {
1000 // Write index
1001 std::int32_t index = info.index;
1002 blob.append(&index, sizeof(std::int32_t));
1003
1004 // Write id string (length + UTF8 bytes)
1005 auto idUtf8 = info.id.toUTF8();
1006 std::uint16_t idLength = std::uint16_t(strlen(idUtf8));
1007 blob.append(&idLength, sizeof(std::uint16_t));
1008 blob.append(idUtf8, idLength);
1009
1010 // Write name string (length + UTF8 bytes)
1011 auto nameUtf8 = info.name.toUTF8();
1012 std::uint16_t nameLength = std::uint16_t(strlen(nameUtf8));
1013 blob.append(&nameLength, sizeof(std::uint16_t));
1014 blob.append(nameUtf8, nameLength);
1015
1016 // Write float values
1017 blob.append(&info.defaultValue, sizeof(float));
1018 blob.append(&info.currentValue, sizeof(float));
1019
1020 // Write label string (length + UTF8 bytes)
1021 auto labelUtf8 = info.label.toUTF8();
1022 std::uint16_t labelLength = std::uint16_t(strlen(labelUtf8));
1023 blob.append(&labelLength, sizeof(std::uint16_t));
1024 blob.append(labelUtf8, labelLength);
1025
1026 // Write bool values
1027 blob.append(&info.isAutomatable, sizeof(bool));
1028 blob.append(&info.isRemoteControllable, sizeof(bool));
1029
1030 // Write category as int
1031 std::int32_t categoryInt = static_cast<std::int32_t>(info.category);
1032 blob.append(&categoryInt, sizeof(std::int32_t));
1033
1034 // Write range values
1035 blob.append(&info.minValue, sizeof(float));
1036 blob.append(&info.maxValue, sizeof(float));
1037 blob.append(&info.stepSize, sizeof(float));
1038 blob.append(&info.isDiscrete, sizeof(bool));
1039
1040 // Write type
1041 blob.append(&info.type, sizeof(ParameterControlType));
1042
1043 // Write stepCount
1044 std::int32_t stepCount = info.stepCount;
1045 blob.append(&stepCount, sizeof(std::int32_t));
1046
1047 // Write stepNames
1048 for (const auto& stepName : info.stepNames)
1049 {
1050 juce::String juceStepName(stepName);
1051 auto stepNameUtf8 = juceStepName.toUTF8();
1052 std::uint16_t stepNameLength = std::uint16_t(strlen(stepNameUtf8));
1053 blob.append(&stepNameLength, sizeof(std::uint16_t));
1054 blob.append(stepNameUtf8, stepNameLength);
1055 }
1056 }
1057
1058 contentSize = blob.getSize();
1059 return blob;
1060 }
1061
1062private:
1063 std::vector<PluginParameterInfo> m_parameterInfos;
1064 juce::String m_pluginName;
1065 bool m_pluginEnabled = false;
1066 bool m_pluginPost = false;
1067};
1068
1085{
1086public:
1088 PluginParameterValueMessage(std::uint16_t parameterIndex, const juce::String& parameterId, float value)
1089 {
1091 m_parameterIndex = parameterIndex;
1092 m_parameterId = parameterId;
1093 m_currentValue = value;
1094 }
1095
1096 PluginParameterValueMessage(const juce::MemoryBlock& blob)
1097 {
1099
1101
1102 auto readPos = int(sizeof(SerializableMessageType));
1103
1104 // Read index
1105 blob.copyTo(&m_parameterIndex, readPos, sizeof(std::uint16_t));
1106 readPos += sizeof(std::uint16_t);
1107
1108 // Read id string length and string
1109 std::uint16_t idLength;
1110 blob.copyTo(&idLength, readPos, sizeof(std::uint16_t));
1111 readPos += sizeof(std::uint16_t);
1112 m_parameterId = juce::String(juce::CharPointer_UTF8(static_cast<const char*>(blob.begin()) + readPos), idLength);
1113 readPos += idLength;
1114
1115 // Read current value
1116 blob.copyTo(&m_currentValue, readPos, sizeof(float));
1117 readPos += sizeof(float);
1118 }
1119
1121
1123 std::uint16_t getParameterIndex() const { return m_parameterIndex; }
1125 const juce::String& getParameterId() const { return m_parameterId; }
1127 float getCurrentValue() const { return m_currentValue; }
1128
1129protected:
1130 juce::MemoryBlock createSerializedContent(size_t& contentSize) const override
1131 {
1132 juce::MemoryBlock blob;
1133
1134 // Write index
1135 blob.append(&m_parameterIndex, sizeof(std::uint16_t));
1136
1137 // Write id string (length + UTF8 bytes)
1138 auto idUtf8 = m_parameterId.toUTF8();
1139 std::uint16_t idLength = std::uint16_t(strlen(idUtf8));
1140 blob.append(&idLength, sizeof(std::uint16_t));
1141 blob.append(idUtf8, idLength);
1142
1143 // Write current value
1144 blob.append(&m_currentValue, sizeof(float));
1145
1146 contentSize = blob.getSize();
1147 return blob;
1148 }
1149
1150private:
1151 std::uint16_t m_parameterIndex = 0;
1152 juce::String m_parameterId;
1153 float m_currentValue = 0.0f;
1154};
1155
1156
1168{
1169public:
1171 PluginProcessingStateMessage(bool enabled, bool post)
1172 {
1174 m_enabled = enabled;
1175 m_post = post;
1176 }
1177
1178 PluginProcessingStateMessage(const juce::MemoryBlock& blob)
1179 {
1181
1183
1184 auto readPos = int(sizeof(SerializableMessageType));
1185
1186 blob.copyTo(&m_enabled, readPos, sizeof(bool));
1187 readPos += sizeof(bool);
1188 blob.copyTo(&m_post, readPos, sizeof(bool));
1189 readPos += sizeof(bool);
1190 }
1191
1193
1195 bool isEnabled() const { return m_enabled; }
1197 bool isPost() const { return m_post; }
1198
1199protected:
1200 juce::MemoryBlock createSerializedContent(size_t& contentSize) const override
1201 {
1202 juce::MemoryBlock blob;
1203 blob.append(&m_enabled, sizeof(bool));
1204 blob.append(&m_post, sizeof(bool));
1205 contentSize = blob.getSize();
1206 return blob;
1207 }
1208
1209private:
1210 bool m_enabled = false;
1211 bool m_post = false;
1212};
1213
1214
1215#ifdef NIX // DEBUG
1216#define RUN_MESSAGE_TESTS
1217#endif
1218#ifdef RUN_MESSAGE_TESTS
1219static void runTests()
1220{
1221 auto inputs = 11;
1222 auto outputs = 12;
1223 auto buffer = juce::AudioBuffer<float>();
1224 auto refSample = 11.11f;
1225 auto sr = 48000;
1226 auto mespb = 256;
1227
1228 // test AnalyzerParametersMessage
1229 auto apm = std::make_unique<AnalyzerParametersMessage>(sr, mespb);
1230 auto apmb = apm->getSerializedMessage();
1231 auto apmcpy = AnalyzerParametersMessage(apmb);
1232 auto test5 = apmcpy.getSampleRate();
1233 auto test6 = apmcpy.getMaximumExpectedSamplesPerBlock();
1234 jassert(test5 == sr);
1235 jassert(test6 == mespb);
1236
1237 // test ReinitIOCountMessage
1238 auto rcm = std::make_unique<ReinitIOCountMessage>(inputs, outputs);
1239 auto rcmb = rcm->getSerializedMessage();
1240 auto rcmcpy = ReinitIOCountMessage(rcmb);
1241 auto test7 = rcmcpy.getInputCount();
1242 auto test8 = rcmcpy.getOutputCount();
1243 jassert(test7 == inputs);
1244 jassert(test8 == outputs);
1245
1246 // test AudioInputBufferMessage
1247 auto channelCount = 2;
1248 auto sampleCount = 6;
1249 buffer.setSize(channelCount, sampleCount, false, true, false);
1250 for (int i = 0; i < channelCount; i++)
1251 {
1252 for (int j = 0; j < sampleCount; j++)
1253 {
1254 buffer.setSample(i, j, ++refSample);
1255 }
1256 }
1257 auto rrefSample1 = refSample;
1258 auto aibm1 = std::make_unique<AudioInputBufferMessage>(buffer);
1259 for (int i = channelCount - 1; i >= 0; i--)
1260 {
1261 for (int j = sampleCount - 1; j >= 0; j--)
1262 {
1263 auto test1 = aibm1->getAudioBuffer().getSample(i, j);
1264 jassert(int(test1) == int(refSample));
1265 refSample--;
1266 }
1267 }
1268 auto aibmb1 = aibm1->getSerializedMessage();
1269 auto aibmcpy1 = AudioInputBufferMessage(aibmb1);
1270 for (int i = channelCount - 1; i >= 0; i--)
1271 {
1272 for (int j = sampleCount - 1; j >= 0; j--)
1273 {
1274 auto test1 = aibmcpy1.getAudioBuffer().getSample(i, j);
1275 jassert(int(test1) == int(rrefSample1));
1276 rrefSample1--;
1277 }
1278 }
1279
1280 // test AudioOutputBufferMessage
1281 buffer.setSize(channelCount, sampleCount, false, true, false);
1282 for (int i = 0; i < channelCount; i++)
1283 {
1284 for (int j = 0; j < sampleCount; j++)
1285 {
1286 buffer.setSample(i, j, ++refSample);
1287 }
1288 }
1289 auto rrefSample2 = refSample;
1290 auto aibm2 = std::make_unique<AudioOutputBufferMessage>(buffer);
1291 for (int i = channelCount - 1; i >= 0; i--)
1292 {
1293 for (int j = sampleCount - 1; j >= 0; j--)
1294 {
1295 auto test2 = aibm2->getAudioBuffer().getSample(i, j);
1296 jassert(int(test2) == int(rrefSample2));
1297 rrefSample2--;
1298 }
1299 }
1300 auto aibmb2 = aibm2->getSerializedMessage();
1301 auto aibmcpy2 = AudioOutputBufferMessage(aibmb2);
1302 for (int i = channelCount - 1; i >= 0; i--)
1303 {
1304 for (int j = sampleCount - 1; j >= 0; j--)
1305 {
1306 auto test2 = aibmcpy2.getAudioBuffer().getSample(i, j);
1307 jassert(int(test2) == int(refSample));
1308 refSample--;
1309 }
1310 }
1311
1312 // test EnvironmentParametersMessage
1313 auto paletteStyle = JUCEAppBasics::CustomLookAndFeel::PaletteStyle::PS_Light;
1314 auto epm = std::make_unique<EnvironmentParametersMessage>(paletteStyle);
1315 auto epmb = epm->getSerializedMessage();
1316 auto epmcpy = EnvironmentParametersMessage(epmb);
1317 auto test9 = epmcpy.getPaletteStyle();
1318 jassert(test9 == paletteStyle);
1319
1320 // test DataTrafficTypeSelectionMessage
1321 auto trafficTypes = std::vector<SerializableMessage::SerializableMessageType>({ SerializableMessage::ControlParameters, SerializableMessage::AnalyzerParameters });
1322 auto dttm = std::make_unique<DataTrafficTypeSelectionMessage>(trafficTypes);
1323 auto dttmb = dttm->getSerializedMessage();
1324 auto dttmcpy = DataTrafficTypeSelectionMessage(dttmb);
1325 auto test10 = dttmcpy.getTrafficTypes();
1326 jassert(test10 == trafficTypes);
1327
1328 // test ControlParametersMessage
1329 auto inputMuteStates = std::map<std::uint16_t, bool>{ { std::uint16_t(1), true}, { std::uint16_t(2), false}, { std::uint16_t(3), true} };
1330 auto outputMuteStates = std::map<std::uint16_t, bool>{ { std::uint16_t(4), false}, { std::uint16_t(5), true}, { std::uint16_t(6), false} };
1331 auto crosspointStates = std::map<std::uint16_t, std::map<std::uint16_t, bool>>();
1332 auto crosspointValues = std::map<std::uint16_t, std::map<std::uint16_t, float>>();
1333 crosspointStates[1][1] = false;
1334 crosspointStates[1][2] = true;
1335 crosspointStates[2][1] = true;
1336 crosspointStates[2][2] = true;
1337 crosspointValues[1][1] = 0.0f;
1338 crosspointValues[1][2] = 1.0f;
1339 crosspointValues[2][1] = 0.5f;
1340 crosspointValues[2][2] = 0.7f;
1341 auto cpm = std::make_unique<ControlParametersMessage>(inputMuteStates, outputMuteStates, crosspointStates, crosspointValues);
1342 auto cpmb = cpm->getSerializedMessage();
1343 auto cpmcpy = ControlParametersMessage(cpmb);
1344 auto test11 = cpmcpy.getInputMuteStates();
1345 auto test12 = cpmcpy.getOutputMuteStates();
1346 auto test13 = cpmcpy.getCrosspointStates();
1347 auto test14 = cpmcpy.getCrosspointValues();
1348 jassert(test11 == inputMuteStates);
1349 jassert(test12 == outputMuteStates);
1350 jassert(test13 == crosspointStates);
1351 jassert(test14 == crosspointValues);
1352}
1353#endif
1354
1355
1356};
Carries audio-device parameters (sample rate, block size) from Mema to clients.
int getSampleRate() const
Returns the audio device sample rate in Hz.
int getMaximumExpectedSamplesPerBlock() const
Returns the maximum number of samples per processing block.
AnalyzerParametersMessage(int sampleRate, int maximumExpectedSamplesPerBlock)
juce::MemoryBlock createSerializedContent(size_t &contentSize) const override
Subclass hook — produces the type-specific payload bytes (everything after the type discriminator).
AnalyzerParametersMessage(const juce::MemoryBlock &blob)
Base message carrying a serialised audio buffer and its flow-direction metadata.
juce::MemoryBlock createSerializedContent(size_t &contentSize) const
Subclass hook — produces the type-specific payload bytes (everything after the type discriminator).
FlowDirection
Identifies whether the buffer contains pre-matrix input or post-matrix output samples.
@ Invalid
Uninitialised direction.
@ Input
Pre-matrix input samples (as seen by the input analyzers).
@ Output
Post-matrix output samples (as seen by the output analyzers).
FlowDirection m_direction
Input or output flow direction.
const juce::AudioBuffer< float > & getAudioBuffer() const
Returns a const reference to the decoded audio buffer.
const FlowDirection getFlowDirection() const
Returns the flow direction encoded in the message.
juce::AudioBuffer< float > m_buffer
Decoded float audio buffer.
AudioBufferMessage(juce::AudioBuffer< float > &buffer)
Carries a pre-matrix input audio buffer streamed continuously from Mema to subscribed clients.
AudioInputBufferMessage(const juce::MemoryBlock &blob)
AudioInputBufferMessage(juce::AudioBuffer< float > &buffer)
Carries a post-matrix output audio buffer streamed continuously from Mema to subscribed clients.
AudioOutputBufferMessage(const juce::MemoryBlock &blob)
AudioOutputBufferMessage(juce::AudioBuffer< float > &buffer)
Full routing-matrix state snapshot exchanged bidirectionally between Mema and Mema....
const std::map< std::uint16_t, std::map< std::uint16_t, bool > > & getCrosspointStates() const
Returns the crosspoint enable matrix (input index → output index → enabled).
const std::map< std::uint16_t, bool > & getOutputMuteStates() const
Returns the per-output mute states (channel index → muted).
ControlParametersMessage(const juce::MemoryBlock &blob)
const std::map< std::uint16_t, std::map< std::uint16_t, float > > & getCrosspointValues() const
Returns the crosspoint gain matrix (input index → output index → linear gain [0, 1]).
ControlParametersMessage(const std::map< std::uint16_t, bool > &inputMuteStates, const std::map< std::uint16_t, bool > &outputMuteStates, const std::map< std::uint16_t, std::map< std::uint16_t, bool > > &crosspointStates, const std::map< std::uint16_t, std::map< std::uint16_t, float > > &crosspointValues)
const std::map< std::uint16_t, bool > & getInputMuteStates() const
Returns the per-input mute states (channel index → muted).
juce::MemoryBlock createSerializedContent(size_t &contentSize) const override
Subclass hook — produces the type-specific payload bytes (everything after the type discriminator).
Sent by a client to opt in to receiving specific message types from Mema.
DataTrafficTypeSelectionMessage(const juce::MemoryBlock &blob)
juce::MemoryBlock createSerializedContent(size_t &contentSize) const override
Subclass hook — produces the type-specific payload bytes (everything after the type discriminator).
DataTrafficTypeSelectionMessage(const std::vector< SerializableMessageType > &trafficTypes)
const std::vector< SerializableMessageType > & getTrafficTypes() const
Returns the list of message types this client wants to receive.
Carries the active look-and-feel palette style from Mema to connected clients.
EnvironmentParametersMessage(JUCEAppBasics::CustomLookAndFeel::PaletteStyle paletteStyle)
juce::MemoryBlock createSerializedContent(size_t &contentSize) const override
Subclass hook — produces the type-specific payload bytes (everything after the type discriminator).
EnvironmentParametersMessage(const juce::MemoryBlock &blob)
JUCEAppBasics::CustomLookAndFeel::PaletteStyle getPaletteStyle() const
Returns the palette style carried by this message.
Carries the plugin name and complete parameter descriptor list from Mema to Mema.Re clients.
const std::vector< PluginParameterInfo > & getParameterInfos() const
Returns the ordered list of parameter descriptors for the loaded plugin.
PluginParameterInfosMessage(const juce::MemoryBlock &blob)
bool isPluginEnabled() const
Returns whether plugin processing is currently enabled.
PluginParameterInfosMessage(const std::string &pluginName, bool pluginEnabled, bool pluginPost, const std::vector< PluginParameterInfo > &parameterInfos)
const juce::String & getPluginName() const
Returns the display name of the currently loaded plugin.
bool isPluginPost() const
Returns whether the plugin is inserted post-matrix (true) or pre-matrix (false).
juce::MemoryBlock createSerializedContent(size_t &contentSize) const override
Subclass hook — produces the type-specific payload bytes (everything after the type discriminator).
Carries a single normalised plugin parameter value from Mema.Re to Mema.
float getCurrentValue() const
Returns the normalised parameter value in [0, 1].
juce::MemoryBlock createSerializedContent(size_t &contentSize) const override
Subclass hook — produces the type-specific payload bytes (everything after the type discriminator).
const juce::String & getParameterId() const
Returns the stable string identifier of the parameter (used for cross-session safety).
PluginParameterValueMessage(std::uint16_t parameterIndex, const juce::String &parameterId, float value)
std::uint16_t getParameterIndex() const
Returns the zero-based parameter index within the plugin's parameter list.
PluginParameterValueMessage(const juce::MemoryBlock &blob)
Carries the plugin enabled and pre/post insertion state between Mema and Mema.Re.
PluginProcessingStateMessage(const juce::MemoryBlock &blob)
bool isEnabled() const
Returns whether plugin processing is enabled.
PluginProcessingStateMessage(bool enabled, bool post)
bool isPost() const
Returns whether the plugin is inserted post-matrix (true) or pre-matrix (false).
juce::MemoryBlock createSerializedContent(size_t &contentSize) const override
Subclass hook — produces the type-specific payload bytes (everything after the type discriminator).
Instructs clients to tear down and rebuild their UI for a new channel count.
ReinitIOCountMessage(const juce::MemoryBlock &blob)
ReinitIOCountMessage(int inputs, int outputs)
std::uint16_t getInputCount() const
Returns the new number of active input channels.
std::uint16_t getOutputCount() const
Returns the new number of active output channels.
juce::MemoryBlock createSerializedContent(size_t &contentSize) const override
Subclass hook — produces the type-specific payload bytes (everything after the type discriminator).
Base class for all messages exchanged between Mema, Mema.Mo, and Mema.Re over TCP.
juce::MemoryBlock getSerializedMessage() const
Serialises the message to a MemoryBlock ready to send over the socket.
virtual juce::MemoryBlock createSerializedContent(size_t &contentSize) const =0
Subclass hook — produces the type-specific payload bytes (everything after the type discriminator).
const SerializableMessageType getType() const
Returns the concrete message type discriminator.
std::uint32_t ReadUint32(const char *buffer)
Reads a big-endian uint32 from buffer.
static void freeMessageData(SerializableMessage *message)
Type-correctly destroys a SerializableMessage* returned by initFromMemoryBlock().
void setId(int id)
Tags the message with a connection-id used for echo-suppression on the server.
int m_userId
Optional connection-id tag for echo-suppression (-1 = not set).
int getId() const
Returns the connection-id tag, or -1 if not set.
bool hasUserId() const
Returns true when a non-default connection-id has been assigned.
static SerializableMessage * initFromMemoryBlock(const juce::MemoryBlock &blob)
Deserialises a raw TCP frame into the correct concrete SerializableMessage subclass.
std::uint16_t ReadUint16(const char *buffer)
Reads a big-endian uint16 from buffer.
@ None
Sentinel / uninitialised type.
@ PluginParameterValue
Single parameter value update sent from Mema.Re to Mema.
@ DataTrafficTypeSelection
Sent by a client to opt in/out of specific message types (bandwidth control).
@ AnalyzerParameters
Audio device sample rate and block size; lets clients initialise their local ProcessorDataAnalyzer.
@ ReinitIOCount
New input/output channel count; clients must rebuild their UI accordingly.
@ PluginProcessingState
Plugin enabled and pre/post processing state; sent bidirectionally between Mema and Mema....
@ ControlParameters
Full routing-matrix state snapshot; sent by Mema on connect and echoed by Mema.Re on change.
@ AudioInputBuffer
Raw PCM input buffer streamed from Mema to subscribed clients.
@ AudioOutputBuffer
Raw PCM output buffer streamed from Mema to subscribed clients.
@ EnvironmentParameters
Look-and-feel palette sent by Mema to clients on connect.
@ PluginParameterInfos
Plugin name and full parameter descriptor list; sent by Mema when a plugin is loaded or changed.
virtual ~SerializableMessage()=default
SerializableMessageType m_type
Type discriminator stored in the first 4 bytes of every serialised frame.
Metadata describing a single plugin parameter exposed for remote control.
std::vector< std::string > stepNames
Display names for each discrete step.
juce::String name
Human-readable parameter name.
bool isRemoteControllable
Whether this parameter is exposed for remote control.
int stepCount
Number of discrete steps (0 if continuous).
bool isAutomatable
Whether the host can automate this parameter.
int index
Zero-based parameter index within the plugin.
ParameterControlType type
Control widget type (slider, combo, toggle).
float defaultValue
Factory default value (normalised 0..1).
juce::String id
Unique string identifier of the parameter.
float stepSize
Step interval for discrete parameters (0 = continuous).
float minValue
Minimum value in the parameter's native range.
float currentValue
Current parameter value (normalised 0..1).
float maxValue
Maximum value in the parameter's native range.
bool isDiscrete
True if the parameter has a finite set of steps.
juce::AudioProcessorParameter::Category category
JUCE parameter category.
juce::String label
Unit label (e.g. "dB", "Hz").