listen for midi binding control range.
This commit is contained in:
+20
-12
@@ -294,12 +294,14 @@ class SystemMidiBinding
|
||||
private:
|
||||
MidiBinding currentBinding;
|
||||
bool controlState = false;
|
||||
uint8_t lastControlValue = 0;
|
||||
|
||||
public:
|
||||
void SetBinding(const MidiBinding &binding)
|
||||
{
|
||||
currentBinding = binding;
|
||||
controlState = false;
|
||||
lastControlValue = 0;
|
||||
}
|
||||
|
||||
bool IsMatch(const MidiEvent &event);
|
||||
@@ -335,13 +337,18 @@ bool SystemMidiBinding::IsTriggered(const MidiEvent &event)
|
||||
return false;
|
||||
if (event.buffer[1] != currentBinding.control())
|
||||
return false;
|
||||
bool state = event.buffer[2] >= 0x64;
|
||||
if (state != this->controlState)
|
||||
|
||||
uint8_t value = event.buffer[2];
|
||||
bool result = false;
|
||||
if (currentBinding.switchControlType() == SwitchControlTypeT::TRIGGER_ON_RISING_EDGE)
|
||||
{
|
||||
this->controlState = state;
|
||||
return state;
|
||||
result = value >= 0x64 && lastControlValue < 0x64;
|
||||
} else if (currentBinding.switchControlType() == SwitchControlTypeT::TRIGGER_ON_ANY)
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
return false;
|
||||
lastControlValue = value;
|
||||
return result;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -918,11 +925,12 @@ private:
|
||||
if (event.size >= 3)
|
||||
{
|
||||
uint8_t cmd = (uint8_t)(event.buffer[0] & 0xF0);
|
||||
bool isNote = cmd == 0x90;
|
||||
bool isNote = cmd == 0x90 && event.buffer[2] != 0; // note on with velocity > 0.
|
||||
bool isControl = cmd == 0xB0;
|
||||
if (isNote || isControl)
|
||||
{
|
||||
realtimeWriter.OnMidiListen(isNote, event.buffer[1]);
|
||||
MidiNotifyBody notifyBody (event.buffer[0],event.buffer[1], event.buffer[2]);
|
||||
realtimeWriter.OnMidiListen(notifyBody);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1333,11 +1341,11 @@ public:
|
||||
{
|
||||
if (command == RingBufferCommand::OnMidiListen)
|
||||
{
|
||||
uint16_t msg;
|
||||
hostReader.read(&msg);
|
||||
MidiNotifyBody body;
|
||||
hostReader.read(&body);
|
||||
if (this->pNotifyCallbacks)
|
||||
{
|
||||
pNotifyCallbacks->OnNotifyMidiListen((msg & 0xFF00) != 0, (uint8_t)msg);
|
||||
pNotifyCallbacks->OnNotifyMidiListen(body.cc0_, body.cc1_, body.cc2_);
|
||||
}
|
||||
}
|
||||
else if (command == RingBufferCommand::MidiValueChanged)
|
||||
@@ -2080,8 +2088,8 @@ public:
|
||||
|
||||
return result;
|
||||
}
|
||||
volatile bool listenForMidiEvent = false;
|
||||
volatile bool listenForAtomOutput = false;
|
||||
std::atomic<bool> listenForMidiEvent = false;
|
||||
std::atomic<bool> listenForAtomOutput = false;
|
||||
|
||||
virtual void SetListenForMidiEvent(bool listen)
|
||||
{
|
||||
|
||||
+1
-1
@@ -158,7 +158,7 @@ namespace pipedal
|
||||
virtual void OnNotifyVusSubscription(const std::vector<VuUpdate> &updates) = 0;
|
||||
virtual void OnNotifyMonitorPort(const MonitorPortUpdate &update) = 0;
|
||||
virtual void OnNotifyMidiValueChanged(int64_t instanceId, int portIndex, float value) = 0;
|
||||
virtual void OnNotifyMidiListen(bool isNote, uint8_t noteOrControl) = 0;
|
||||
virtual void OnNotifyMidiListen(uint8_t cc0, uint8_t cc1, uint8_t cc2) = 0;
|
||||
|
||||
virtual void OnNotifyPathPatchPropertyReceived(
|
||||
int64_t instanceId,
|
||||
|
||||
@@ -824,7 +824,7 @@ void Lv2Pedalboard::OnMidiMessage(size_t size, uint8_t *message,
|
||||
case MidiControlType::Dial:
|
||||
{
|
||||
IEffect *pEffect = this->realtimeEffects[mapping.effectIndex];
|
||||
range = mapping.midiBinding.adjustRange(range);
|
||||
float range = mapping.midiBinding.calculateRange(value);
|
||||
float currentValue = mapping.pPortInfo->rangeToValue(range);
|
||||
if (pEffect->GetControlValue(mapping.controlIndex) != currentValue)
|
||||
{
|
||||
|
||||
@@ -58,6 +58,8 @@ JSON_MAP_BEGIN(MidiBinding)
|
||||
JSON_MAP_REFERENCE(MidiBinding,bindingType)
|
||||
JSON_MAP_REFERENCE(MidiBinding,note)
|
||||
JSON_MAP_REFERENCE(MidiBinding,control)
|
||||
JSON_MAP_REFERENCE(MidiBinding,minControlValue)
|
||||
JSON_MAP_REFERENCE(MidiBinding,maxControlValue)
|
||||
JSON_MAP_REFERENCE(MidiBinding,minValue)
|
||||
JSON_MAP_REFERENCE(MidiBinding,maxValue)
|
||||
JSON_MAP_REFERENCE(MidiBinding,rotaryScale)
|
||||
|
||||
+19
-2
@@ -80,6 +80,8 @@ private:
|
||||
int bindingType_ = BINDING_TYPE_NONE;
|
||||
int note_ = 12*4+24;
|
||||
int control_ = 1;
|
||||
int minControlValue_ = 0;
|
||||
int maxControlValue_ = 127;
|
||||
float minValue_ = 0;
|
||||
float maxValue_ = 1;
|
||||
float rotaryScale_ = 1;
|
||||
@@ -99,6 +101,8 @@ public:
|
||||
&& this->bindingType_ == other.bindingType_
|
||||
&& this->note_ == other.note_
|
||||
&& this->control_ == other.control_
|
||||
&& this->minControlValue_ == other.minControlValue_
|
||||
&& this->maxControlValue_ == other.maxControlValue_
|
||||
&& this->minValue_ == other.minValue_
|
||||
&& this->maxValue_ == other.maxValue_
|
||||
&& this->rotaryScale_ == other.rotaryScale_
|
||||
@@ -111,6 +115,8 @@ public:
|
||||
GETTER_SETTER(bindingType);
|
||||
GETTER_SETTER(note);
|
||||
GETTER_SETTER(control);
|
||||
GETTER_SETTER(minControlValue);
|
||||
GETTER_SETTER(maxControlValue);
|
||||
GETTER_SETTER(minValue);
|
||||
GETTER_SETTER(maxValue);
|
||||
GETTER_SETTER(rotaryScale);
|
||||
@@ -120,9 +126,20 @@ public:
|
||||
void switchControlType(SwitchControlTypeT value) { switchControlType_ = (int)value; }
|
||||
|
||||
|
||||
float adjustRange(float range)
|
||||
float calculateRange(uint8_t value)
|
||||
{
|
||||
return maxValue_*range+minValue_*(1.0f-range);
|
||||
float controlRange;
|
||||
if (maxControlValue_ == minControlValue_)
|
||||
{
|
||||
controlRange = minControlValue_;
|
||||
} else {
|
||||
controlRange =
|
||||
(float)((int8_t)value - (int8_t)minControlValue_) /
|
||||
(float)((int8_t)maxControlValue_ - (int8_t)minControlValue_);
|
||||
}
|
||||
if (controlRange < 0) controlRange = 0;
|
||||
else if (controlRange > 1) controlRange = 1;
|
||||
return maxValue_*controlRange+minValue_*(1.0f-controlRange);
|
||||
}
|
||||
DECLARE_JSON_MAP(MidiBinding);
|
||||
|
||||
|
||||
@@ -136,6 +136,15 @@ bool Pedalboard::SetControlValue(int64_t pedalItemId, const std::string &symbol,
|
||||
return item->SetControlValue(symbol,value);
|
||||
}
|
||||
|
||||
bool Pedalboard::SetItemTitle(int64_t pedalItemId, const std::string &title)
|
||||
{
|
||||
PedalboardItem*item = GetItem(pedalItemId);
|
||||
if (!item) return false;
|
||||
if (item->title() == title) return false; // no change.
|
||||
item->title(title);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
PedalboardItem Pedalboard::MakeEmptyItem()
|
||||
{
|
||||
@@ -503,6 +512,7 @@ JSON_MAP_BEGIN(PedalboardItem)
|
||||
JSON_MAP_REFERENCE(PedalboardItem,lv2State)
|
||||
JSON_MAP_REFERENCE(PedalboardItem,lilvPresetUri)
|
||||
JSON_MAP_REFERENCE(PedalboardItem,pathProperties)
|
||||
JSON_MAP_REFERENCE(PedalboardItem,title)
|
||||
JSON_MAP_END()
|
||||
|
||||
|
||||
|
||||
@@ -98,6 +98,7 @@ public:
|
||||
Lv2PluginState lv2State_;
|
||||
std::string lilvPresetUri_;
|
||||
std::map<std::string,std::string> pathProperties_;
|
||||
std::string title_;
|
||||
|
||||
// non persistent state.
|
||||
PropertyMap patchProperties;
|
||||
@@ -126,6 +127,8 @@ public:
|
||||
GETTER_SETTER_REF(midiChannelBinding)
|
||||
GETTER_SETTER(stateUpdateCount)
|
||||
GETTER_SETTER_REF(lv2State)
|
||||
GETTER_SETTER_REF(title)
|
||||
|
||||
Lv2PluginState&lv2State() { return lv2State_; } // non-const version.
|
||||
GETTER_SETTER_REF(lilvPresetUri)
|
||||
|
||||
@@ -198,6 +201,7 @@ public:
|
||||
static constexpr int64_t INPUT_VOLUME_ID = -2; // synthetic PedalboardItem for input volume.
|
||||
static constexpr int64_t OUTPUT_VOLUME_ID = -3; // synthetic PedalboardItem for output volume.
|
||||
bool SetControlValue(int64_t pedalItemId, const std::string &symbol, float value);
|
||||
bool SetItemTitle(int64_t pedalItemId, const std::string &title);
|
||||
bool SetItemEnabled(int64_t pedalItemId, bool enabled);
|
||||
void SetCurrentSnapshotModified(bool modified);
|
||||
|
||||
|
||||
+34
-15
@@ -2192,34 +2192,40 @@ void PiPedalModel::OnNotifyPathPatchPropertyReceived(
|
||||
}
|
||||
}
|
||||
|
||||
void PiPedalModel::OnNotifyMidiListen(bool isNote, uint8_t noteOrControl)
|
||||
void PiPedalModel::OnNotifyMidiListen(uint8_t cc0, uint8_t cc1, uint8_t cc2)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(mutex);
|
||||
bool isNote = (cc0 & 0xF0) == 0x90; // Note On
|
||||
if (isNote && cc2 == 0) {
|
||||
return; // Note off. Oopsie.
|
||||
}
|
||||
bool isControl = (cc0 & 0xF0) == 0xB0; // Control Change
|
||||
if (!isNote && !isControl) {
|
||||
return; // Not a note on or control change.
|
||||
}
|
||||
|
||||
|
||||
for (int i = 0; i < midiEventListeners.size(); ++i)
|
||||
{
|
||||
auto &listener = midiEventListeners[i];
|
||||
if ((!isNote) == (listener.listenForControls))
|
||||
auto subscriber = this->GetNotificationSubscriber(listener.clientId);
|
||||
if (subscriber)
|
||||
{
|
||||
auto subscriber = this->GetNotificationSubscriber(listener.clientId);
|
||||
if (subscriber)
|
||||
{
|
||||
subscriber->OnNotifyMidiListener(listener.clientHandle, isNote, noteOrControl);
|
||||
}
|
||||
else
|
||||
{
|
||||
midiEventListeners.erase(midiEventListeners.begin() + i);
|
||||
--i;
|
||||
}
|
||||
subscriber->OnNotifyMidiListener(listener.clientHandle, cc0,cc1,cc2);
|
||||
}
|
||||
else
|
||||
{
|
||||
midiEventListeners.erase(midiEventListeners.begin() + i);
|
||||
--i;
|
||||
}
|
||||
}
|
||||
audioHost->SetListenForMidiEvent(midiEventListeners.size() != 0);
|
||||
}
|
||||
|
||||
void PiPedalModel::ListenForMidiEvent(int64_t clientId, int64_t clientHandle, bool listenForControls)
|
||||
void PiPedalModel::ListenForMidiEvent(int64_t clientId, int64_t clientHandle)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(mutex);
|
||||
MidiListener listener{clientId, clientHandle, listenForControls};
|
||||
MidiListener listener{clientId, clientHandle};
|
||||
midiEventListeners.push_back(listener);
|
||||
audioHost->SetListenForMidiEvent(true);
|
||||
}
|
||||
@@ -2946,4 +2952,17 @@ void PiPedalModel::MoveAudioFile(
|
||||
}
|
||||
AudioDirectoryInfo::Ptr dir = AudioDirectoryInfo::Create(directory);
|
||||
dir->MoveAudioFile(directory, fromPosition, toPosition);
|
||||
}
|
||||
}
|
||||
void PiPedalModel::SetPedalboardItemTitle(int64_t instanceId, const std::string &title)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(mutex);
|
||||
if (!this->pedalboard.SetItemTitle(instanceId,title))
|
||||
{
|
||||
return;
|
||||
}
|
||||
// no need to reload the pedalboard, but we do need to notify subscribers.
|
||||
this->SetPresetChanged(-1, true);
|
||||
this->FirePedalboardChanged(-1,false);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ namespace pipedal
|
||||
virtual void OnJackConfigurationChanged(const JackConfiguration &jackServerConfiguration) = 0;
|
||||
virtual void OnLoadPluginPreset(int64_t instanceId, const std::vector<ControlValue> &controlValues) = 0;
|
||||
virtual void OnMidiValueChanged(int64_t instanceId, const std::string &symbol, float value) = 0;
|
||||
virtual void OnNotifyMidiListener(int64_t clientHandle, bool isNote, uint8_t noteOrControl) = 0;
|
||||
virtual void OnNotifyMidiListener(int64_t clientHandle, uint8_t cc0, uint8_t cc1, uint8_t cc2) = 0;
|
||||
virtual void OnNotifyPatchProperty(int64_t clientModel, uint64_t instanceId, const std::string &propertyUri, const std::string &atomJson) = 0;
|
||||
virtual void OnWifiConfigSettingsChanged(const WifiConfigSettings &wifiConfigSettings) = 0;
|
||||
virtual void OnWifiDirectConfigSettingsChanged(const WifiDirectConfigSettings &wifiDirectConfigSettings) = 0;
|
||||
@@ -146,7 +146,6 @@ namespace pipedal
|
||||
public:
|
||||
int64_t clientId;
|
||||
int64_t clientHandle;
|
||||
bool listenForControls;
|
||||
};
|
||||
class AtomOutputListener
|
||||
{
|
||||
@@ -234,7 +233,7 @@ namespace pipedal
|
||||
virtual void OnNotifyVusSubscription(const std::vector<VuUpdate> &updates) override;
|
||||
virtual void OnNotifyMonitorPort(const MonitorPortUpdate &update) override;
|
||||
virtual void OnNotifyMidiValueChanged(int64_t instanceId, int portIndex, float value) override;
|
||||
virtual void OnNotifyMidiListen(bool isNote, uint8_t noteOrControl) override;
|
||||
virtual void OnNotifyMidiListen(uint8_t cc0, uint8_t cc1, uint8_t cc2) override;
|
||||
virtual void OnPatchSetReply(uint64_t instanceId, LV2_URID patchSetProperty, const LV2_Atom *atomValue) override;
|
||||
virtual void OnNotifyMidiRealtimeEvent(RealtimeMidiEventType eventType) override;
|
||||
virtual void OnNotifyMidiRealtimeSnapshotRequest(int32_t snapshotIndex,int64_t snapshotRequestId) override;
|
||||
@@ -437,7 +436,7 @@ namespace pipedal
|
||||
JackServerSettings GetJackServerSettings();
|
||||
void SetJackServerSettings(const JackServerSettings &jackServerSettings);
|
||||
|
||||
void ListenForMidiEvent(int64_t clientId, int64_t clientHandle, bool listenForControls);
|
||||
void ListenForMidiEvent(int64_t clientId, int64_t clientHandle);
|
||||
void CancelListenForMidiEvent(int64_t clientId, int64_t clientHandle);
|
||||
|
||||
void MonitorPatchProperty(int64_t clientId, int64_t clientHandle, uint64_t instanceId, const std::string &propertyUri);
|
||||
@@ -469,6 +468,8 @@ namespace pipedal
|
||||
const std::string & path,
|
||||
int32_t from,
|
||||
int32_t to);
|
||||
|
||||
void SetPedalboardItemTitle(int64_t instanceId, const std::string &title);
|
||||
};
|
||||
|
||||
} // namespace pipedal.
|
||||
+33
-11
@@ -174,18 +174,36 @@ JSON_MAP_REFERENCE(SetPatchPropertyBody, propertyUri)
|
||||
JSON_MAP_REFERENCE(SetPatchPropertyBody, value)
|
||||
JSON_MAP_END()
|
||||
|
||||
class SetPedalboardItemTitleBody
|
||||
{
|
||||
public:
|
||||
uint64_t instanceId_;
|
||||
std::string title_;
|
||||
DECLARE_JSON_MAP(SetPedalboardItemTitleBody);
|
||||
};
|
||||
|
||||
JSON_MAP_BEGIN(SetPedalboardItemTitleBody)
|
||||
JSON_MAP_REFERENCE(SetPedalboardItemTitleBody, instanceId)
|
||||
JSON_MAP_REFERENCE(SetPedalboardItemTitleBody, title)
|
||||
JSON_MAP_END()
|
||||
|
||||
|
||||
|
||||
|
||||
class NotifyMidiListenerBody
|
||||
{
|
||||
public:
|
||||
int64_t clientHandle_;
|
||||
bool isNote_;
|
||||
int32_t noteOrControl_;
|
||||
uint16_t cc0_;
|
||||
uint16_t cc1_;
|
||||
uint16_t cc2_;
|
||||
DECLARE_JSON_MAP(NotifyMidiListenerBody);
|
||||
};
|
||||
JSON_MAP_BEGIN(NotifyMidiListenerBody)
|
||||
JSON_MAP_REFERENCE(NotifyMidiListenerBody, clientHandle)
|
||||
JSON_MAP_REFERENCE(NotifyMidiListenerBody, isNote)
|
||||
JSON_MAP_REFERENCE(NotifyMidiListenerBody, noteOrControl)
|
||||
JSON_MAP_REFERENCE(NotifyMidiListenerBody, cc0)
|
||||
JSON_MAP_REFERENCE(NotifyMidiListenerBody, cc1)
|
||||
JSON_MAP_REFERENCE(NotifyMidiListenerBody, cc2)
|
||||
JSON_MAP_END()
|
||||
|
||||
class NotifyAtomOutputBody
|
||||
@@ -208,13 +226,11 @@ JSON_MAP_END()
|
||||
class ListenForMidiEventBody
|
||||
{
|
||||
public:
|
||||
bool listenForControls_;
|
||||
int64_t handle_;
|
||||
DECLARE_JSON_MAP(ListenForMidiEventBody);
|
||||
};
|
||||
|
||||
JSON_MAP_BEGIN(ListenForMidiEventBody)
|
||||
JSON_MAP_REFERENCE(ListenForMidiEventBody, listenForControls)
|
||||
JSON_MAP_REFERENCE(ListenForMidiEventBody, handle)
|
||||
JSON_MAP_END()
|
||||
|
||||
@@ -1099,7 +1115,7 @@ public:
|
||||
{
|
||||
ListenForMidiEventBody body;
|
||||
pReader->read(&body);
|
||||
this->model.ListenForMidiEvent(this->clientId, body.handle_, body.listenForControls_);
|
||||
this->model.ListenForMidiEvent(this->clientId, body.handle_);
|
||||
}
|
||||
else if (message == "cancelListenForMidiEvent")
|
||||
{
|
||||
@@ -1503,7 +1519,12 @@ public:
|
||||
{ this->JsonReply(replyTo, "setPatchProperty", "true"); }, [this, replyTo](const std::string &error)
|
||||
{ this->SendError(replyTo, error.c_str()); });
|
||||
}
|
||||
|
||||
else if (message == "setPedalboardItemTitle")
|
||||
{
|
||||
SetPedalboardItemTitleBody body;
|
||||
pReader->read(&body);
|
||||
model.SetPedalboardItemTitle(body.instanceId_, body.title_);
|
||||
}
|
||||
else if (message == "getPatchProperty")
|
||||
{
|
||||
GetPatchPropertyBody body;
|
||||
@@ -2121,12 +2142,13 @@ private:
|
||||
Send("onNotifyPathPatchPropertyChanged", body);
|
||||
}
|
||||
|
||||
virtual void OnNotifyMidiListener(int64_t clientHandle, bool isNote, uint8_t noteOrControl)
|
||||
virtual void OnNotifyMidiListener(int64_t clientHandle, uint8_t cc0, uint8_t cc1, uint8_t cc2) override
|
||||
{
|
||||
NotifyMidiListenerBody body;
|
||||
body.clientHandle_ = clientHandle;
|
||||
body.isNote_ = isNote;
|
||||
body.noteOrControl_ = noteOrControl;
|
||||
body.cc0_ = cc0;
|
||||
body.cc1_ = cc1;
|
||||
body.cc2_ = cc2;
|
||||
|
||||
Send("onNotifyMidiListener", body);
|
||||
}
|
||||
|
||||
@@ -31,6 +31,20 @@ namespace pipedal
|
||||
{
|
||||
class IndexedSnapshot;
|
||||
|
||||
class MidiNotifyBody
|
||||
{
|
||||
public:
|
||||
MidiNotifyBody() = default;
|
||||
MidiNotifyBody(uint8_t cc0, uint8_t cc1, uint8_t cc2)
|
||||
: cc0_(cc0), cc1_(cc1), cc2_(cc2)
|
||||
{
|
||||
}
|
||||
|
||||
uint8_t cc0_;
|
||||
uint8_t cc1_;
|
||||
uint8_t cc2_;
|
||||
};
|
||||
|
||||
enum class RingBufferCommand : int64_t
|
||||
{
|
||||
Invalid = 0,
|
||||
@@ -38,7 +52,7 @@ namespace pipedal
|
||||
EffectReplaced,
|
||||
SetValue,
|
||||
SetBypass,
|
||||
//AudioStopped,
|
||||
// AudioStopped,
|
||||
AudioTerminatedAbnormally, // specifically for an ALSA loss of connection.
|
||||
SetVuSubscriptions,
|
||||
FreeVuSubscriptions,
|
||||
@@ -327,7 +341,7 @@ namespace pipedal
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void write(RingBufferCommand command, const T &value, size_t dataLength, uint8_t *variableData)
|
||||
{
|
||||
@@ -374,12 +388,9 @@ namespace pipedal
|
||||
write(RingBufferCommand::MidiValueChanged, body);
|
||||
}
|
||||
|
||||
void OnMidiListen(bool isNote, uint8_t noteOrControl)
|
||||
void OnMidiListen(const MidiNotifyBody &body)
|
||||
{
|
||||
uint16_t msg = noteOrControl;
|
||||
if (isNote)
|
||||
msg |= 0x100;
|
||||
write(RingBufferCommand::OnMidiListen, msg);
|
||||
write(RingBufferCommand::OnMidiListen, body);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -485,7 +496,8 @@ namespace pipedal
|
||||
{
|
||||
write(RingBufferCommand::AckMidiProgramChange, requestId);
|
||||
}
|
||||
void AckMidiSnapshotRequest(uint64_t snapshotRequestId) {
|
||||
void AckMidiSnapshotRequest(uint64_t snapshotRequestId)
|
||||
{
|
||||
write(RingBufferCommand::AckMidiSnapshotRequest, snapshotRequestId);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user