Getting started with CoreMidi

January 12th, 2009 | Categories: Code | Tags: , , ,

So I finally started on Octopussy. I’ve always found CoreMidi and procedural APIs in general a bit puzzling so I thought I would start with the simplest of tasks to help me demystify it all. My goal was simply to send a MIDI note on message from the Mac to the blofeld.

After perusing MIDIService.h, I gathered that I had to ultimately use the MIDISend().

extern OSStatus MIDISend(
    MIDIPortRef port,
    MIDIEndpointRef dest,
    const MIDIPacketList *pktlist);

When it was time to create a MIDIEndpointRef, I was presented with numerous paths. My initial instinct was to traverse some hierachy to get to the Blofeld MIDI Out but it turns out that each MIDIEntity can be reference using a unique id. I was hoping that this info would be available in the Audio MIDI Setup utility but it turns out you can only get at it via code. So I created a foundation tool with the following code.

#import <Foundation/Foundation.h>

#import <CoreMIDI/CoreMIDI.h>

int main (int argc, const char * argv[]) {

    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

	MIDIDeviceRef midiDevice;

	int numOfDevices = MIDIGetNumberOfDevices();

	int numOfBlofeldEntities;

	for(int i=0; i< numOfDevices; i++ ){

		midiDevice = MIDIGetDevice(i);

		NSDictionary *midiDeviceProperties;

		MIDIObjectGetProperties(midiDevice, (CFPropertyListRef *)&midiDeviceProperties, YES);

		NSLog(@"midiDeviceProperties:%@", midiDeviceProperties);

	}

    [pool drain];

    return 0;

}

After running the tool, I get the ff output. I need to run this on multiple Macs to verify that the uniqueID is actually the same regardless of which machine I run it on.

2009-01-11 23:24:31.273 MidiProperties[4198:10b] midiDeviceProperties-5:{

    SerialNumber = "8290071532-023547011532";

    USBLocationID = -46923776;

    USBVendorProduct = 317063187;

    "apple.midi.audiomidisetup.widget.xPosition" = 385;

    "apple.midi.audiomidisetup.widget.yPosition" = 203;

    driver = "com.apple.AppleMIDIUSBDriver";

    entities =     (

                {

            destinations =             (

                                {

                    name = "Blofeld MIDI out";

                    uniqueID = -934632258;

                }

            );

            embedded = 0;

            maxSysExSpeed = 3125;

            name = "Waldorf Blofeld";

            sources =             (

                                {

                    name = "Blofeld MIDI in";

                    uniqueID = 1439776402;

                }

            );

            uniqueID = -1524681845;

        }

    );

    image = "/Library/Audio/MIDI Devices/Access Music/Images/Virus TI Snow.tiff";

    manufacturer = "Waldorf Music GmbH";

    model = "Waldorf Blofeld";

    name = Blofeld;

    offline = 0;

    "receives MTC" = 0;

    "receives clock" = 0;

    "supports General MIDI" = 0;

    "supports MMC" = 0;

    "transmits MTC" = 0;

    "transmits clock" = 0;

    uniqueID = 1111148707;

}

Finally armed with the blofeld’s MIDI Out uniqueID, the rest was cake. Here is the code I used to send the note on message.

#import <Foundation/Foundation.h>

#import <CoreMIDI/CoreMIDI.h>

MIDIEndpointRef getEndpointWithUniqueID(MIDIUniqueID id){

	MIDIObjectRef endPoint;

	MIDIObjectType foundObj;

	MIDIObjectFindByUniqueID(id, &endPoint, &foundObj);

	return (MIDIEndpointRef) endPoint;

}

MIDIClientRef getMidiClient(){

	MIDIClientRef midiClient;

	NSString *outPortName =@"blofeldOut";

	MIDIClientCreate((CFStringRef)outPortName, NULL, NULL, &midiClient);

	return midiClient;

}

MIDIPortRef getOutPutPort(){

	MIDIPortRef outPort;

	NSString *outPortName =@"blofeldOut";

	MIDIOutputPortCreate(getMidiClient(), (CFStringRef)outPortName, &outPort);

	return outPort;

}

MIDIPacketList getMidiPacketList(){

	MIDIPacketList packetList;

	packetList.numPackets = 1;

	MIDIPacket* firstPacket = &packetList.packet[0];

	firstPacket->timeStamp = 0;	// send immediately

	firstPacket->length = 3;

	firstPacket->data[0] = 0x90;

	firstPacket->data[1] = 60;

	firstPacket->data[2] = 64;

	// TODO: add end note sequence

	return packetList;

}

void play_note(void) {

	NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 

	MIDIPacketList packetList=getMidiPacketList();

	MIDIUniqueID blofeldEndpointID = -934632258;

	MIDIEndpointRef blofeldEndpoint = getEndpointWithUniqueID(blofeldEndpointID);

	MIDISend(getOutPutPort(), blofeldEndpoint, &packetList);

	MIDIEndpointDispose(blofeldEndpoint);

	[pool drain];

}

int main (int argc, const char * argv[]) {

    play_note();

    return 0;

}
  1. Melody Class
    January 1st, 2011 at 18:58
    Reply | Quote | #1

    nice

Powered by WP Hashcash