mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-09 23:34:20 +00:00
MIDI-CI: Simplify profile enablement API, and ensure that group/block member channels are always 0
This commit is contained in:
parent
fac6f4cb20
commit
1506bb3454
8 changed files with 103 additions and 55 deletions
|
|
@ -2,6 +2,26 @@
|
|||
|
||||
# develop
|
||||
|
||||
## Change
|
||||
|
||||
ProfileHost::enableProfile and ProfileHost::disableProfile have been combined
|
||||
into a single function, ProfileHost::setProfileEnablement.
|
||||
|
||||
**Possible Issues**
|
||||
|
||||
Code that calls this function will fail to compile until it is updated.
|
||||
|
||||
**Workaround**
|
||||
|
||||
To enable a profile, call setProfileEnablement with a positive number of
|
||||
channels. To disable a profile, call setProfileEnablement with zero channels.
|
||||
|
||||
**Rationale**
|
||||
|
||||
The new API is simpler, more compact, and more consistent, as it now mirrors
|
||||
the signature of Device::sendProfileEnablement.
|
||||
|
||||
|
||||
## Change
|
||||
|
||||
OpenGLContext::getRenderingScale() has been changed to include the effects of
|
||||
|
|
@ -98,12 +118,12 @@ and FormatOptions::getMaxDecimalPlaces() as necessary. To find whether the outpu
|
|||
should be multi-line, compare the result of FormatOptions::getSpacing() with
|
||||
JSON::Spacing::multiLine.
|
||||
|
||||
Callers of the function can construct the new argument type using the old
|
||||
Callers of the function can construct the new argument type using the old
|
||||
arguments accordingly
|
||||
|
||||
```
|
||||
JSON::FormatOptions{}.withIndentLevel (indentLevel)
|
||||
.withSpacing (allOnOneLine ? JSON::Spacing::singleLine
|
||||
.withSpacing (allOnOneLine ? JSON::Spacing::singleLine
|
||||
: JSON::Spacing::multiLine)
|
||||
.withMaxDecimalPlaces (maximumDecimalPlaces);
|
||||
```
|
||||
|
|
@ -119,7 +139,7 @@ FormatOptions type, which will not be a breaking change.
|
|||
|
||||
## Change
|
||||
|
||||
CachedValue::operator==() will now emit floating point comparison warnings if
|
||||
CachedValue::operator==() will now emit floating point comparison warnings if
|
||||
they are enabled for the project.
|
||||
|
||||
**Possible Issues**
|
||||
|
|
@ -135,7 +155,7 @@ CachedValue::get().
|
|||
|
||||
**Rationale**
|
||||
|
||||
The JUCE Framework now offers the free-standing exactlyEqual() and
|
||||
The JUCE Framework now offers the free-standing exactlyEqual() and
|
||||
approximatelyEqual() functions to clearly express the desired semantics when
|
||||
comparing floating point values. These functions are intended to eliminate
|
||||
the ambiguity in code-bases regarding these types. However, when such a value
|
||||
|
|
|
|||
|
|
@ -4088,10 +4088,7 @@ private:
|
|||
else
|
||||
h->addProfile (profileAtAddress, state.supported);
|
||||
|
||||
if (state.active == 0)
|
||||
h->disableProfile (profileAtAddress);
|
||||
else
|
||||
h->enableProfile (profileAtAddress, state.active);
|
||||
h->setProfileEnablement (profileAtAddress, state.active);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4589,12 +4586,9 @@ private:
|
|||
|
||||
if (auto* host = demo.getProfileHost())
|
||||
{
|
||||
if (enabled)
|
||||
host->enableProfile (profileAtAddress, numChannels);
|
||||
else
|
||||
host->disableProfile (profileAtAddress);
|
||||
|
||||
profiles.channels[profileAtAddress].active = (uint16_t) numChannels;
|
||||
const auto count = enabled ? jmax (1, numChannels) : 0;
|
||||
host->setProfileEnablement (profileAtAddress, count);
|
||||
profiles.channels[profileAtAddress].active = (uint16_t) count;
|
||||
|
||||
state = profiles;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -151,11 +151,15 @@ public:
|
|||
|
||||
if (numChannels > 0)
|
||||
{
|
||||
const auto channelsToSend = address == ChannelInGroup::wholeBlock || address == ChannelInGroup::wholeGroup
|
||||
? 0
|
||||
: numChannels;
|
||||
|
||||
detail::MessageTypeUtils::send (concreteBufferOutput,
|
||||
options.getFunctionBlock().firstGroup,
|
||||
m,
|
||||
address,
|
||||
Message::ProfileOn { profile, (uint16_t) numChannels });
|
||||
Message::ProfileOn { profile, (uint16_t) channelsToSend });
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1045,7 +1049,7 @@ private:
|
|||
return iter != device.discovered.end() ? jmin (defaultResult, (int) iter->second.discovery.maximumSysexSize) : defaultResult;
|
||||
}
|
||||
|
||||
public:
|
||||
private:
|
||||
Impl& device;
|
||||
};
|
||||
|
||||
|
|
@ -1062,13 +1066,10 @@ private:
|
|||
if (! device.profileHost.has_value())
|
||||
return;
|
||||
|
||||
if (enabled)
|
||||
device.profileHost->enableProfile (profileAtAddress, numChannels);
|
||||
else
|
||||
device.profileHost->disableProfile (profileAtAddress);
|
||||
device.profileHost->setProfileEnablement (profileAtAddress, enabled ? jmax (1, numChannels) : 0);
|
||||
}
|
||||
|
||||
public:
|
||||
private:
|
||||
Impl& device;
|
||||
};
|
||||
|
||||
|
|
@ -1127,7 +1128,7 @@ private:
|
|||
d->subscriptionWillEnd (m, subscription);
|
||||
}
|
||||
|
||||
public:
|
||||
private:
|
||||
Impl& device;
|
||||
};
|
||||
|
||||
|
|
@ -1755,8 +1756,7 @@ public:
|
|||
|
||||
beginTest ("If a device has previously acted as a responder to profile inquiry, then modifying profiles emits events");
|
||||
{
|
||||
const auto numChannels = 0;
|
||||
device.getProfileHost()->enableProfile ({ profile, ChannelAddress{}.withChannel (ChannelInGroup::wholeBlock) }, numChannels);
|
||||
device.getProfileHost()->setProfileEnablement ({ profile, ChannelAddress{}.withChannel (ChannelInGroup::wholeBlock) }, 1);
|
||||
|
||||
expect (output.messages.size() == 2);
|
||||
expect (output.messages.back().bytes == getMessageBytes ({ ChannelInGroup::wholeBlock,
|
||||
|
|
@ -1764,7 +1764,7 @@ public:
|
|||
detail::MessageMeta::implementationVersion,
|
||||
device.getMuid(),
|
||||
MUID::getBroadcast() },
|
||||
Message::ProfileEnabledReport { profile, numChannels }));
|
||||
Message::ProfileEnabledReport { profile, 0 }));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1834,7 +1834,7 @@ public:
|
|||
detail::MessageMeta::implementationVersion,
|
||||
inquiryMUID,
|
||||
device.getMuid() },
|
||||
Message::ProfileOn { profile, 1 }) });
|
||||
Message::ProfileOn { profile, 0 }) });
|
||||
|
||||
expect (output.messages.size() == 1);
|
||||
expect (output.messages.back().bytes == getMessageBytes ({ ChannelInGroup::wholeBlock,
|
||||
|
|
@ -1842,7 +1842,7 @@ public:
|
|||
detail::MessageMeta::implementationVersion,
|
||||
device.getMuid(),
|
||||
MUID::getBroadcast() },
|
||||
Message::ProfileEnabledReport { profile, 1 }));
|
||||
Message::ProfileEnabledReport { profile, 0 }));
|
||||
}
|
||||
|
||||
struct DoNothingProfileDelegate : public ProfileDelegate
|
||||
|
|
@ -1950,7 +1950,7 @@ public:
|
|||
std::byte { 0x05 } };
|
||||
|
||||
device.getProfileHost()->addProfile ({ profile, ChannelAddress{}.withChannel (ChannelInGroup::wholeBlock) });
|
||||
device.getProfileHost()->enableProfile ({ profile, ChannelAddress{}.withChannel (ChannelInGroup::wholeBlock) }, 0);
|
||||
device.getProfileHost()->setProfileEnablement ({ profile, ChannelAddress{}.withChannel (ChannelInGroup::wholeBlock) }, 0);
|
||||
|
||||
const auto inquiryMUID = MUID::makeRandom (random);
|
||||
|
||||
|
|
@ -1991,7 +1991,7 @@ public:
|
|||
std::byte { 0x05 } };
|
||||
|
||||
device.getProfileHost()->addProfile ({ profile, ChannelAddress{}.withChannel (ChannelInGroup::wholeBlock) });
|
||||
device.getProfileHost()->enableProfile ({ profile, ChannelAddress{}.withChannel (ChannelInGroup::wholeBlock) }, 1);
|
||||
device.getProfileHost()->setProfileEnablement ({ profile, ChannelAddress{}.withChannel (ChannelInGroup::wholeBlock) }, 1);
|
||||
|
||||
const auto inquiryMUID = MUID::makeRandom (random);
|
||||
|
||||
|
|
@ -2008,7 +2008,7 @@ public:
|
|||
detail::MessageMeta::implementationVersion,
|
||||
device.getMuid(),
|
||||
MUID::getBroadcast() },
|
||||
Message::ProfileEnabledReport { profile, 1 }));
|
||||
Message::ProfileEnabledReport { profile, 0 }));
|
||||
}
|
||||
|
||||
beginTest ("If a device receives a set profile off for an unsupported profile, NAK is emitted");
|
||||
|
|
|
|||
|
|
@ -127,6 +127,12 @@ public:
|
|||
void sendProfileSpecificData (MUID muid, ChannelInGroup address, Profile profile, Span<const std::byte>);
|
||||
|
||||
/** Sets a profile on or off. Pass 0 or less to disable the profile, or a positive number to enable it.
|
||||
|
||||
This also goes for group/block profiles. If the request is addressed to a group/block, then
|
||||
a positive number will cause a "profile on" message to be sent, and a non-positive number
|
||||
will cause a "profile off" message to be sent. The channel count of the sent message will
|
||||
always be zero for messages addressed to groups/blocks.regardless of the value of the
|
||||
numChannels argument.
|
||||
*/
|
||||
void sendProfileEnablement (MUID muid, ChannelInGroup address, Profile profile, int numChannels);
|
||||
|
||||
|
|
|
|||
|
|
@ -47,6 +47,10 @@ struct ProfileDelegate
|
|||
is enabled with zero channels active - in this situation, it is
|
||||
recommended that you use ProfileHost::enableProfile to enable the
|
||||
default number of channels for that profile.
|
||||
|
||||
Additionally, profiles for entire groups or function blocks may be enabled with zero
|
||||
active channels. In this case, the profile should be enabled on the entire group or
|
||||
function block.
|
||||
*/
|
||||
virtual void profileEnablementRequested ([[maybe_unused]] MUID x,
|
||||
[[maybe_unused]] ProfileAtAddress profileAtAddress,
|
||||
|
|
|
|||
|
|
@ -136,11 +136,11 @@ private:
|
|||
.withChannel (output->getIncomingHeader().deviceID);
|
||||
if (auto* state = host->states.getStateForDestination (destination))
|
||||
{
|
||||
if (state->get (request.profile).isSupported())
|
||||
const auto previousState = state->get (request.profile);
|
||||
|
||||
if (previousState.isSupported())
|
||||
{
|
||||
const auto address = ChannelAddress{}.withGroup (output->getIncomingGroup())
|
||||
.withChannel (output->getIncomingHeader().deviceID);
|
||||
const ProfileAtAddress profileAtAddress { request.profile, address };
|
||||
const ProfileAtAddress profileAtAddress { request.profile, destination };
|
||||
|
||||
{
|
||||
const ScopedValueSetter scope { host->currentEnablementMessage,
|
||||
|
|
@ -167,10 +167,16 @@ private:
|
|||
detail::MessageTypeUtils::send (*output, profileAtAddress.address.getGroup(), header, response);
|
||||
};
|
||||
|
||||
const auto numIndividualChannels = (std::is_same_v<Message::ProfileOn, Body> ? currentState : previousState).active;
|
||||
|
||||
const auto numChannelsToSend = destination.isSingleChannel()
|
||||
? numIndividualChannels
|
||||
: uint16_t{};
|
||||
|
||||
if (currentState.isActive())
|
||||
sendResponse (Message::ProfileEnabledReport { profileAtAddress.profile, currentState.active });
|
||||
sendResponse (Message::ProfileEnabledReport { profileAtAddress.profile, numChannelsToSend });
|
||||
else
|
||||
sendResponse (Message::ProfileDisabledReport { profileAtAddress.profile, 0 });
|
||||
sendResponse (Message::ProfileDisabledReport { profileAtAddress.profile, numChannelsToSend });
|
||||
|
||||
host->isResponder = true;
|
||||
return true;
|
||||
|
|
@ -196,6 +202,14 @@ private:
|
|||
bool* handled = nullptr;
|
||||
};
|
||||
|
||||
void ProfileHost::setProfileEnablement (ProfileAtAddress profileAtAddress, int numChannels)
|
||||
{
|
||||
if (numChannels > 0)
|
||||
enableProfileImpl (profileAtAddress, numChannels);
|
||||
else
|
||||
disableProfileImpl (profileAtAddress);
|
||||
}
|
||||
|
||||
void ProfileHost::addProfile (ProfileAtAddress profileAtAddress, int maxNumChannels)
|
||||
{
|
||||
auto* state = states.getStateForDestination (profileAtAddress.address);
|
||||
|
|
@ -206,7 +220,7 @@ void ProfileHost::addProfile (ProfileAtAddress profileAtAddress, int maxNumChann
|
|||
// There are only 256 channels on a UMP endpoint, so requesting more probably doesn't make sense!
|
||||
jassert (maxNumChannels <= 256);
|
||||
|
||||
state->set (profileAtAddress.profile, { (uint16_t) maxNumChannels, 0 });
|
||||
state->set (profileAtAddress.profile, { (uint16_t) jmax (1, maxNumChannels), 0 });
|
||||
|
||||
if (! isResponder || profileAtAddress == currentEnablementMessage)
|
||||
return;
|
||||
|
|
@ -233,7 +247,7 @@ void ProfileHost::removeProfile (ProfileAtAddress profileAtAddress)
|
|||
if (state == nullptr)
|
||||
return;
|
||||
|
||||
disableProfile (profileAtAddress);
|
||||
setProfileEnablement (profileAtAddress, 0);
|
||||
|
||||
if (! state->get (profileAtAddress.profile).isSupported())
|
||||
return;
|
||||
|
|
@ -258,7 +272,7 @@ void ProfileHost::removeProfile (ProfileAtAddress profileAtAddress)
|
|||
Message::ProfileRemoved { profileAtAddress.profile });
|
||||
}
|
||||
|
||||
void ProfileHost::enableProfile (ProfileAtAddress profileAtAddress, int numChannels)
|
||||
void ProfileHost::enableProfileImpl (ProfileAtAddress profileAtAddress, int numChannels)
|
||||
{
|
||||
auto* state = states.getStateForDestination (profileAtAddress.address);
|
||||
|
||||
|
|
@ -273,7 +287,7 @@ void ProfileHost::enableProfile (ProfileAtAddress profileAtAddress, int numChann
|
|||
// There are only 256 channels on a UMP endpoint, so requesting more probably doesn't make sense!
|
||||
jassert (numChannels <= 256);
|
||||
|
||||
const auto enabledChannels = jmin (old.supported, (uint16_t) numChannels);
|
||||
const auto enabledChannels = jmax ((uint16_t) 1, jmin (old.supported, (uint16_t) numChannels));
|
||||
state->set (profileAtAddress.profile, { old.supported, enabledChannels });
|
||||
|
||||
if (! isResponder || profileAtAddress == currentEnablementMessage)
|
||||
|
|
@ -288,13 +302,15 @@ void ProfileHost::enableProfile (ProfileAtAddress profileAtAddress, int numChann
|
|||
MUID::getBroadcast(),
|
||||
};
|
||||
|
||||
const auto numChannelsToSend = profileAtAddress.address.isSingleChannel() ? enabledChannels : uint16_t{};
|
||||
|
||||
detail::MessageTypeUtils::send (output,
|
||||
profileAtAddress.address.getGroup(),
|
||||
header,
|
||||
Message::ProfileEnabledReport { profileAtAddress.profile, enabledChannels });
|
||||
Message::ProfileEnabledReport { profileAtAddress.profile, numChannelsToSend });
|
||||
}
|
||||
|
||||
void ProfileHost::disableProfile (ProfileAtAddress profileAtAddress)
|
||||
void ProfileHost::disableProfileImpl (ProfileAtAddress profileAtAddress)
|
||||
{
|
||||
auto* state = states.getStateForDestination (profileAtAddress.address);
|
||||
|
||||
|
|
@ -320,10 +336,12 @@ void ProfileHost::disableProfile (ProfileAtAddress profileAtAddress)
|
|||
MUID::getBroadcast(),
|
||||
};
|
||||
|
||||
const auto numChannelsToSend = profileAtAddress.address.isSingleChannel() ? old.active : uint16_t{};
|
||||
|
||||
detail::MessageTypeUtils::send (output,
|
||||
profileAtAddress.address.getGroup(),
|
||||
header,
|
||||
Message::ProfileDisabledReport { profileAtAddress.profile, old.active });
|
||||
Message::ProfileDisabledReport { profileAtAddress.profile, numChannelsToSend });
|
||||
}
|
||||
|
||||
bool ProfileHost::tryRespond (ResponderOutput& responderOutput, const Message::Parsed& message)
|
||||
|
|
|
|||
|
|
@ -58,18 +58,14 @@ public:
|
|||
*/
|
||||
void removeProfile (ProfileAtAddress);
|
||||
|
||||
/** Activates a profile on the specified group/channel with the provided
|
||||
number of channels.
|
||||
/** Activates or deactivates a profile on the specified group/channel.
|
||||
|
||||
The profile should previously have been added with addProfile(), and
|
||||
numChannels should be in the closed range between 1 and the maximum
|
||||
number of channels allowed for that profile.
|
||||
The profile should previously have been added with addProfile().
|
||||
A positive value of numChannels will enable the profile, and a non-positive value
|
||||
will disable it. This includes group and function-block profiles; passing any positive
|
||||
value will enable the profile on the entire group or block.
|
||||
*/
|
||||
void enableProfile (ProfileAtAddress, int numChannels);
|
||||
|
||||
/** Deactivates a profile on the specified group/channel.
|
||||
*/
|
||||
void disableProfile (ProfileAtAddress);
|
||||
void setProfileEnablement (ProfileAtAddress, int numChannels);
|
||||
|
||||
/** Returns the profile states (supported/active) for all groups and channels.
|
||||
*/
|
||||
|
|
@ -98,6 +94,9 @@ public:
|
|||
private:
|
||||
class Visitor;
|
||||
|
||||
void enableProfileImpl (ProfileAtAddress, int);
|
||||
void disableProfileImpl (ProfileAtAddress);
|
||||
|
||||
template <typename Body>
|
||||
bool profileEnablementReceived (ResponderOutput&, const Body&);
|
||||
|
||||
|
|
|
|||
|
|
@ -34,8 +34,15 @@ namespace juce::midi_ci
|
|||
*/
|
||||
struct SupportedAndActive
|
||||
{
|
||||
uint16_t supported{}; ///< The maximum number of member channels for a profile. 0 indicates that the profile is unsupported.
|
||||
uint16_t active{}; ///< The number of member channels currently active for a profile. 0 indicates that the profile is inactive.
|
||||
uint16_t supported{}; ///< The maximum number of member channels for a profile.
|
||||
///< 0 indicates that the profile is unsupported.
|
||||
///< For group/block profiles, 1/0 indicates that the
|
||||
///< profile is supported/unsupported respectively.
|
||||
|
||||
uint16_t active{}; ///< The number of member channels currently active for a profile.
|
||||
///< 0 indicates that the profile is inactive.
|
||||
///< For group/block profiles, 1/0 indicates that the
|
||||
///< profile is supported/unsupported respectively.
|
||||
|
||||
/** Returns true if supported is non-zero. */
|
||||
bool isSupported() const { return supported != 0; }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue