Core MIDI: Output to IAC is fine but virtual ports not

35 Views Asked by At

I can send MIDI note data to midi destination ports derived from MIDIGetDestination, but when I use MIDISourceCreateWithProtocol no note data seems to be sent, although I can select the virtual port in an external application:

let midiEndpointRef_bus1:   MIDIEndpointRef
let midiEndpointRef_bus2:   MIDIEndpointRef

var virtualEndpoint1:       MIDIEndpointRef
var virtualEndpoint2:       MIDIEndpointRef        

var midiClientRef1: MIDIClientRef = 0
MIDIClientCreate("client1" as CFString,nil,nil, &midiClientRef1)
    
var midiOutputPortRef: MIDIPortRef = 0
MIDIOutputPortCreate(midiClientRef1,"ouputPort" as CFString, &midiOutputPortRef)
    
let destinationNames = Self.midiDestinationNames()
guard
        let iac_bus1 = destinationNames.firstIndex(of: "IAC Driver Bus 1"),
        let iac_bus2 = destinationNames.firstIndex(of: "IAC Driver Bus 2")
    else {
        return nil
    }
    
midiEndpointRef_bus1 = MIDIGetDestination(iac_bus1)
midiEndpointRef_bus2 = MIDIGetDestination(iac_bus2)
    
    // Create virtual MIDI
virtualEndpoint1 = 0
virtualEndpoint2 = 0
if #available(macOS 11.0, *) {
        MIDISourceCreateWithProtocol(midiClientRef1, "Port A" as CFString, ._2_0, &virtualEndpoint1)
        MIDISourceCreateWithProtocol(midiClientRef1, "Port B" as CFString, ._2_0, &virtualEndpoint2)
    } else { print("ERROR: FAILED TO CREATE VIRTUAL MIDI SOURCE") }
    
//this works
// midiMessenger = MidiMessageSender(
// midiOutputPortRef: midiOutputPortRef,
// destinationEndpointRef_1: midiEndpointRef_bus1,
// destinationEndpointRef_2: midiEndpointRef_bus2
// )
    
    //this doesn't
midiMessenger = MidiMessageSender(
        midiOutputPortRef: midiOutputPortRef,
        destinationEndpointRef_1: virtualEndpoint1,
        destinationEndpointRef_2: virtualEndpoint2
    )

What am I missing?

[Edit: here is the MidiMessenger class]

public class MidiMessageSender: MidiDeviceService {
    var midiOutputPortRef: MIDIPortRef
    let destinationEndpointRef_1: MIDIEndpointRef
    let destinationEndpointRef_2: MIDIEndpointRef

    public init(
        midiOutputPortRef: MIDIPortRef,
        destinationEndpointRef_1: MIDIEndpointRef,
        destinationEndpointRef_2: MIDIEndpointRef
    ) {
        self.midiOutputPortRef           = midiOutputPortRef
        self.destinationEndpointRef_1   = destinationEndpointRef_1
        self.destinationEndpointRef_2   = destinationEndpointRef_2
    }

    public func sendNoteMidiMessage(
        channel: UInt8,
        noteNumber: UInt8,
        velocity: UInt8,
        timestamp: MIDITimeStamp
    ) {
        let endpoint = channel / 16
        let ch = channel % 16
        let selectedDestinationEndpointRef = endpoint == 0
            ? destinationEndpointRef_1
            : destinationEndpointRef_2
        
        let status = velocity == 0 ? .noteOff + ch : .noteOn + ch
        
        var midiPacket = MIDIPacket()
        var packetList = MIDIPacketList()
  
        midiPacket.length = 3
        midiPacket.timeStamp = timestamp
        midiPacket.data.0 = status
        midiPacket.data.1 = noteNumber
        midiPacket.data.2 = velocity
        packetList = MIDIPacketList(numPackets: 1, packet: midiPacket)
        MIDISend(midiOutputPortRef, selectedDestinationEndpointRef, &packetList)
    }

}
0

There are 0 best solutions below