Browse Source

macOS: Ensure that the global CoreMIDI client is initialised when calling MIDI I/O methods

tags/2021-05-28
ed 6 years ago
parent
commit
166e1d1185
1 changed files with 66 additions and 57 deletions
  1. +66
    -57
      modules/juce_audio_devices/native/juce_mac_CoreMidi.cpp

+ 66
- 57
modules/juce_audio_devices/native/juce_mac_CoreMidi.cpp View File

@@ -218,35 +218,6 @@ namespace CoreMidiHelpers
} }
} }
static StringArray findDevices (bool forInput)
{
// It seems that OSX can be a bit picky about the thread that's first used to
// search for devices. It's safest to use the message thread for calling this.
JUCE_ASSERT_MESSAGE_THREAD
StringArray s;
enableSimulatorMidiSession();
auto num = forInput ? MIDIGetNumberOfSources()
: MIDIGetNumberOfDestinations();
for (ItemCount i = 0; i < num; ++i)
{
String name;
if (auto dest = forInput ? MIDIGetSource (i)
: MIDIGetDestination (i))
name = getConnectedEndpointName (dest);
if (name.isEmpty())
name = "<error>";
s.add (name);
}
return s;
}
static void globalSystemChangeCallback (const MIDINotification*, void*) static void globalSystemChangeCallback (const MIDINotification*, void*)
{ {
// TODO.. Should pass-on this notification.. // TODO.. Should pass-on this notification..
@@ -280,6 +251,40 @@ namespace CoreMidiHelpers
return globalMidiClient; return globalMidiClient;
} }
static StringArray findDevices (bool forInput)
{
// It seems that OSX can be a bit picky about the thread that's first used to
// search for devices. It's safest to use the message thread for calling this.
JUCE_ASSERT_MESSAGE_THREAD
if (getGlobalMidiClient() == 0)
{
jassertfalse;
return {};
}
StringArray s;
enableSimulatorMidiSession();
auto num = forInput ? MIDIGetNumberOfSources()
: MIDIGetNumberOfDestinations();
for (ItemCount i = 0; i < num; ++i)
{
String name;
if (auto dest = forInput ? MIDIGetSource (i) : MIDIGetDestination (i))
name = getConnectedEndpointName (dest);
if (name.isEmpty())
name = "<error>";
s.add (name);
}
return s;
}
//============================================================================== //==============================================================================
class MidiPortAndEndpoint class MidiPortAndEndpoint
{ {
@@ -375,22 +380,24 @@ MidiOutput* MidiOutput::openDevice (int index)
{ {
MidiOutput* mo = nullptr; MidiOutput* mo = nullptr;
if (isPositiveAndBelow (index, MIDIGetNumberOfDestinations()))
if (auto client = CoreMidiHelpers::getGlobalMidiClient())
{ {
auto endPoint = MIDIGetDestination ((ItemCount) index);
CoreMidiHelpers::ScopedCFString pname;
if (CHECK_ERROR (MIDIObjectGetStringProperty (endPoint, kMIDIPropertyName, &pname.cfString)))
if (isPositiveAndBelow (index, MIDIGetNumberOfDestinations()))
{ {
auto client = CoreMidiHelpers::getGlobalMidiClient();
MIDIPortRef port;
auto deviceName = CoreMidiHelpers::getConnectedEndpointName (endPoint);
auto endPoint = MIDIGetDestination ((ItemCount) index);
if (client != 0 && CHECK_ERROR (MIDIOutputPortCreate (client, pname.cfString, &port)))
CoreMidiHelpers::ScopedCFString pname;
if (CHECK_ERROR (MIDIObjectGetStringProperty (endPoint, kMIDIPropertyName, &pname.cfString)))
{ {
mo = new MidiOutput (deviceName);
mo->internal = new CoreMidiHelpers::MidiPortAndEndpoint (port, endPoint);
MIDIPortRef port;
auto deviceName = CoreMidiHelpers::getConnectedEndpointName (endPoint);
if (CHECK_ERROR (MIDIOutputPortCreate (client, pname.cfString, &port)))
{
mo = new MidiOutput (deviceName);
mo->internal = new CoreMidiHelpers::MidiPortAndEndpoint (port, endPoint);
}
} }
} }
} }
@@ -400,19 +407,21 @@ MidiOutput* MidiOutput::openDevice (int index)
MidiOutput* MidiOutput::createNewDevice (const String& deviceName) MidiOutput* MidiOutput::createNewDevice (const String& deviceName)
{ {
MIDIClientRef client = CoreMidiHelpers::getGlobalMidiClient();
MIDIEndpointRef endPoint;
if (auto client = CoreMidiHelpers::getGlobalMidiClient())
{
MIDIEndpointRef endPoint;
CoreMidiHelpers::ScopedCFString name;
name.cfString = deviceName.toCFString();
CoreMidiHelpers::ScopedCFString name;
name.cfString = deviceName.toCFString();
if (client != 0 && CHECK_ERROR (MIDISourceCreate (client, name.cfString, &endPoint)))
{
CoreMidiHelpers::setUniqueIdForMidiPort (endPoint, deviceName, false);
if (CHECK_ERROR (MIDISourceCreate (client, name.cfString, &endPoint)))
{
CoreMidiHelpers::setUniqueIdForMidiPort (endPoint, deviceName, false);
auto mo = new MidiOutput (deviceName);
mo->internal = new CoreMidiHelpers::MidiPortAndEndpoint (0, endPoint);
return mo;
auto mo = new MidiOutput (deviceName);
mo->internal = new CoreMidiHelpers::MidiPortAndEndpoint (0, endPoint);
return mo;
}
} }
return nullptr; return nullptr;
@@ -495,15 +504,15 @@ MidiInput* MidiInput::openDevice (int index, MidiInputCallback* callback)
using namespace CoreMidiHelpers; using namespace CoreMidiHelpers;
MidiInput* newInput = nullptr; MidiInput* newInput = nullptr;
if (isPositiveAndBelow (index, MIDIGetNumberOfSources()))
if (auto client = getGlobalMidiClient())
{ {
if (auto endPoint = MIDIGetSource ((ItemCount) index))
if (isPositiveAndBelow (index, MIDIGetNumberOfSources()))
{ {
ScopedCFString name;
if (CHECK_ERROR (MIDIObjectGetStringProperty (endPoint, kMIDIPropertyName, &name.cfString)))
if (auto endPoint = MIDIGetSource ((ItemCount) index))
{ {
if (auto client = getGlobalMidiClient())
ScopedCFString name;
if (CHECK_ERROR (MIDIObjectGetStringProperty (endPoint, kMIDIPropertyName, &name.cfString)))
{ {
MIDIPortRef port; MIDIPortRef port;
std::unique_ptr<MidiPortAndCallback> mpc (new MidiPortAndCallback (*callback)); std::unique_ptr<MidiPortAndCallback> mpc (new MidiPortAndCallback (*callback));


Loading…
Cancel
Save