From 8e6f506803de9ba2cccfc4500764ddf9c1df95d0 Mon Sep 17 00:00:00 2001 From: jules Date: Wed, 27 May 2015 10:00:50 +0100 Subject: [PATCH] Fixed an issue with CFString releasing in OSX midi when devices fail to open. --- .../native/juce_mac_CoreMidi.cpp | 70 ++++++++++--------- 1 file changed, 37 insertions(+), 33 deletions(-) diff --git a/modules/juce_audio_devices/native/juce_mac_CoreMidi.cpp b/modules/juce_audio_devices/native/juce_mac_CoreMidi.cpp index 5f8b3d5a67..dee763316c 100644 --- a/modules/juce_audio_devices/native/juce_mac_CoreMidi.cpp +++ b/modules/juce_audio_devices/native/juce_mac_CoreMidi.cpp @@ -45,6 +45,14 @@ namespace CoreMidiHelpers #define CHECK_ERROR(a) CoreMidiHelpers::checkError (a, __LINE__) //============================================================================== + struct ScopedCFString + { + ScopedCFString() noexcept : cfString (nullptr) {} + ~ScopedCFString() noexcept { if (cfString != nullptr) CFRelease (cfString); } + + CFStringRef cfString; + }; + static String getMidiObjectName (MIDIObjectRef entity) { String result; @@ -116,7 +124,7 @@ namespace CoreMidiHelpers if (numConnections > 0) { - const SInt32* pid = reinterpret_cast (CFDataGetBytePtr (connections)); + const SInt32* pid = reinterpret_cast (CFDataGetBytePtr (connections)); for (int i = 0; i < numConnections; ++i, ++pid) { @@ -133,7 +141,7 @@ namespace CoreMidiHelpers || connObjectType == kMIDIObjectType_ExternalDestination) { // Connected to an external device's endpoint (10.3 and later). - s = getEndpointName (static_cast (connObject), true); + s = getEndpointName (static_cast (connObject), true); } else { @@ -208,9 +216,9 @@ namespace CoreMidiHelpers // correctly when called from the message thread! jassert (MessageManager::getInstance()->isThisTheMessageThread()); - CFStringRef name = getGlobalMidiClientName().toCFString(); - CHECK_ERROR (MIDIClientCreate (name, &globalSystemChangeCallback, nullptr, &globalMidiClient)); - CFRelease (name); + CoreMidiHelpers::ScopedCFString name; + name.cfString = getGlobalMidiClientName().toCFString(); + CHECK_ERROR (MIDIClientCreate (name.cfString, &globalSystemChangeCallback, nullptr, &globalMidiClient)); } return globalMidiClient; @@ -220,12 +228,12 @@ namespace CoreMidiHelpers class MidiPortAndEndpoint { public: - MidiPortAndEndpoint (MIDIPortRef p, MIDIEndpointRef ep) + MidiPortAndEndpoint (MIDIPortRef p, MIDIEndpointRef ep) noexcept : port (p), endPoint (ep) { } - ~MidiPortAndEndpoint() + ~MidiPortAndEndpoint() noexcept { if (port != 0) MIDIPortDispose (port); @@ -234,7 +242,7 @@ namespace CoreMidiHelpers MIDIEndpointDispose (endPoint); } - void send (const MIDIPacketList* const packets) + void send (const MIDIPacketList* const packets) noexcept { if (port != 0) MIDISend (port, endPoint, packets); @@ -302,7 +310,7 @@ namespace CoreMidiHelpers static void midiInputProc (const MIDIPacketList* pktlist, void* readProcRefCon, void* /*srcConnRefCon*/) { - static_cast (readProcRefCon)->handlePackets (pktlist); + static_cast (readProcRefCon)->handlePackets (pktlist); } } @@ -318,19 +326,18 @@ MidiOutput* MidiOutput::openDevice (int index) { MIDIEndpointRef endPoint = MIDIGetDestination ((ItemCount) index); - CFStringRef pname; - if (CHECK_ERROR (MIDIObjectGetStringProperty (endPoint, kMIDIPropertyName, &pname))) + CoreMidiHelpers::ScopedCFString pname; + + if (CHECK_ERROR (MIDIObjectGetStringProperty (endPoint, kMIDIPropertyName, &pname.cfString))) { MIDIClientRef client = CoreMidiHelpers::getGlobalMidiClient(); MIDIPortRef port; - if (client != 0 && CHECK_ERROR (MIDIOutputPortCreate (client, pname, &port))) + if (client != 0 && CHECK_ERROR (MIDIOutputPortCreate (client, pname.cfString, &port))) { mo = new MidiOutput(); mo->internal = new CoreMidiHelpers::MidiPortAndEndpoint (port, endPoint); } - - CFRelease (pname); } } @@ -339,20 +346,20 @@ MidiOutput* MidiOutput::openDevice (int index) MidiOutput* MidiOutput::createNewDevice (const String& deviceName) { - MidiOutput* mo = nullptr; MIDIClientRef client = CoreMidiHelpers::getGlobalMidiClient(); - MIDIEndpointRef endPoint; - CFStringRef name = deviceName.toCFString(); - if (client != 0 && CHECK_ERROR (MIDISourceCreate (client, name, &endPoint))) + CoreMidiHelpers::ScopedCFString name; + name.cfString = deviceName.toCFString(); + + if (client != 0 && CHECK_ERROR (MIDISourceCreate (client, name.cfString, &endPoint))) { - mo = new MidiOutput(); + MidiOutput* mo = new MidiOutput(); mo->internal = new CoreMidiHelpers::MidiPortAndEndpoint (0, endPoint); + return mo; } - CFRelease (name); - return mo; + return nullptr; } MidiOutput::~MidiOutput() @@ -370,7 +377,7 @@ void MidiOutput::sendMessageNow (const MidiMessage& message) const MIDITimeStamp timeStamp = AudioGetCurrentHostTime(); #endif - HeapBlock allocatedPackets; + HeapBlock allocatedPackets; MIDIPacketList stackPacket; MIDIPacketList* packetToSend = &stackPacket; const size_t dataSize = (size_t) message.getRawDataSize(); @@ -436,16 +443,16 @@ MidiInput* MidiInput::openDevice (int index, MidiInputCallback* callback) { if (MIDIEndpointRef endPoint = MIDIGetSource ((ItemCount) index)) { - CFStringRef name; + ScopedCFString name; - if (CHECK_ERROR (MIDIObjectGetStringProperty (endPoint, kMIDIPropertyName, &name))) + if (CHECK_ERROR (MIDIObjectGetStringProperty (endPoint, kMIDIPropertyName, &name.cfString))) { if (MIDIClientRef client = getGlobalMidiClient()) { MIDIPortRef port; - ScopedPointer mpc (new MidiPortAndCallback (*callback)); + ScopedPointer mpc (new MidiPortAndCallback (*callback)); - if (CHECK_ERROR (MIDIInputPortCreate (client, name, midiInputProc, mpc, &port))) + if (CHECK_ERROR (MIDIInputPortCreate (client, name.cfString, midiInputProc, mpc, &port))) { if (CHECK_ERROR (MIDIPortConnectSource (port, endPoint, nullptr))) { @@ -465,8 +472,6 @@ MidiInput* MidiInput::openDevice (int index, MidiInputCallback* callback) } } } - - CFRelease (name); } } @@ -482,13 +487,14 @@ MidiInput* MidiInput::createNewDevice (const String& deviceName, MidiInputCallba if (MIDIClientRef client = getGlobalMidiClient()) { - ScopedPointer mpc (new MidiPortAndCallback (*callback)); + ScopedPointer mpc (new MidiPortAndCallback (*callback)); mpc->active = false; MIDIEndpointRef endPoint; - CFStringRef name = deviceName.toCFString(); + ScopedCFString name; + name.cfString = deviceName.toCFString(); - if (CHECK_ERROR (MIDIDestinationCreate (client, name, midiInputProc, mpc, &endPoint))) + if (CHECK_ERROR (MIDIDestinationCreate (client, name.cfString, midiInputProc, mpc, &endPoint))) { mpc->portAndEndpoint = new MidiPortAndEndpoint (0, endPoint); @@ -499,8 +505,6 @@ MidiInput* MidiInput::createNewDevice (const String& deviceName, MidiInputCallba const ScopedLock sl (callbackLock); activeCallbacks.add (mpc.release()); } - - CFRelease (name); } return mi;