hello again everyone!

so i have been trying to wrap my head around CoreMIDI and i think i got the 
basics down.

i’ve used francois ferland's casiousbmididriver for the basics.
(https://github.com/francoisferland/casiousbmididriver)

as it stands, i have an MPU401 sitting on a *PCI* device and i want to create 
an interface to talk to it.

i already know its address and, in fact, i write and read from it as-is but 
seek to leverage the hardware when it’s available.

the relevant code:

>     if (deviceRegisters->model.device_config & (MIDI_OUTPUT | MIDI_INPUT)) {
>         //pay some respect to francois ferland's casiousbmididriver
>         //(https://github.com/francoisferland/casiousbmididriver)
>         CFStringRef boxName = CFSTR("Oxygen MIDI Interface");
>         MIDIDeviceCreate(deviceRegisters->Self(), boxName, CFSTR("CMedia"), 
> boxName, &deviceRegisters->midi);
>         MIDIEntityRef ent;
>         CFStringRef str;
>         OSStatus err;
>         char portname[64];
> //        unsigned int info_flags =  MPU401_INFO_INTEGRATED | 
> MPU401_INFO_IRQ_HOOK;
>         sprintf(portname, "MPU401");
>         CFStringGetCString(boxName, portname, sizeof(portname), 
> kCFStringEncodingMacRoman);
>         str = CFStringCreateWithCString(NULL, portname, 0);
>         // make entity for each port, with 1 source, 1 destination
>         // (if they have them)
>         MIDIDeviceAddEntity(deviceRegisters->midi, str, true, (bool) 
> (deviceRegisters->model.device_config & MIDI_OUTPUT),
>                              (bool) (deviceRegisters->model.device_config & 
> MIDI_INPUT),
>                             &ent);
>         CFRelease(str);
>         __Require_noErr(err = MIDISetupAddDevice(deviceRegisters->midi), 
> Done);

if i am doing this correctly, this should create a single MIDI device with an 
input and/or output port, depending on the value of 
deviceRegisters->model.device_config

now, i don’t want to get ahead of myself because, as i’ve mentioned, i have the 
addresses where i want to read and write. so right now i am just creating an 
input and output port:
> 
> 
>          //lets get the source and destination endpoints and set them to the 
> same place
>          //boy i hope this is right.
>          //logic behind the call below:
>          // - we know the address is addr+OXYGEN_MPU401.
>          // - we just created the midi device and ent is the associated 
> entity for one input/output port
>          if(deviceRegisters->model.device_config & MIDI_OUTPUT) {
>              deviceRegisters->midiOut = 
> MIDIEntityGetDestination(MIDIDeviceGetEntity(deviceRegisters->midi,0), 0);
>              MIDIEndpointSetRefCons(deviceRegisters->midiOut, NULL, NULL);
>          }
>          if(deviceRegisters->model.device_config & MIDI_INPUT) {
>              deviceRegisters->midiIn = 
> MIDIEntityGetSource(MIDIDeviceGetEntity(deviceRegisters->midi,0), 0);
>              MIDIEndpointSetRefCons(deviceRegisters->midiIn, NULL, NULL);
>          }
>         
so by this point we should have a proper MIDIEndpointRef to both input and 
output. 
        -i know the NULL parameters must be filled in with the data i want to 
pass to MIDISend/MIDIReceived. i will worry about this when the time comes.

as of now, my main question is about generating interrupts in an 
IOWorkLoopContext.

is this as simple as calling 

> MIDIGetDriverIORunLoop


on the workloop? will this just magically find and generate the interrupt for 
the MIDIDevice? it seems too good to be true.

i am aware the documentation says i can call MIDIReceived or MIDISend from any 
context (including IOWorkLoop) however this isn’t ideal because i first want to 
check if anything needs to be done.

this is why the description of MIDIGetDriverIORunLoop is so tantalising: 

> Drivers typically need to receive asynchronous I/O completion callbacks on a 
> high-priority thread. So that the system can efficiently manage resources, 
> the MIDI server provides a thread which drivers may use. This is a 
> realtime-priority thread that drivers shouldn’t use for anything other than 
> I/O.


^ this is exactly what i want to do!!

next, i saw this nifty driver property

> kMIDIDriverPropertyUsesSerial


(https://developer.apple.com/documentation/coremidi/kmididriverpropertyusesserial?language=objc)

setting this property would be helpful given how i’m using the MPU401, but it’s 
not clear how such an attribute is set with an existing device.

i’ve googled each of these features and there is nothing (surprise!!).

anyways, i am hopeful a veteran could provide guidance on whether there is an 
easy way to generate an interrupt on a WorkLoop for a MIDI device, so that we 
EXCLUSIVELY deal with the “laundry list” of “things to do” in that context.
        -and, if we can set the device’s property to “using serial”, i think 
that would be cool and closer to what the linux API offers below for the MPU401:

> 
> //            err = snd_mpu401_uart_new(card, 0, MPU401_HW_CMIPCI,
> //                                      chipData->addr + OXYGEN_MPU401,
> //                                      info_flags, -1, &chip->midi);
>   //          if (err < 0)
>     //                goto err_card;
>     }
> 

knowing the destination and source addresses in memory (DMA) should make my 
goals way easier since i’m already reading/writing to this memory map.
        -i need CoreMIDI to take advantage of the MPU401’s hardware, in this 
case admitting interrupt handling.

any tips would be greatly appreciated!!

Thanks,
Gagan

 _______________________________________________
Do not post admin requests to the list. They will be ignored.
Coreaudio-api mailing list      ([email protected])
Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/coreaudio-api/archive%40mail-archive.com

This email sent to [email protected]

Reply via email to