Re: CoreMIDI via Java and MIDISport -- funny you should ask
Re: CoreMIDI via Java and MIDISport -- funny you should ask
- Subject: Re: CoreMIDI via Java and MIDISport -- funny you should ask
- From: Kenneth Welch <email@hidden>
- Date: Sun, 26 May 2002 14:56:43 -0400
Has anyone been able to get CoreMIDI via Java to work with a MIDISport
USB interface? As soon as I try to log in (calling
MIDISetup.RestartMIDISystem or new MIDIClient) the application hangs.
I just subscribed to this list a couple days ago, intending to ask about
the same problem. But I was able to get it working on my own. I have a
Quicksilver G4 running 10.1.4, with a USB MIDISport 2x2 I bought a
couple months ago attached. I've noticed two separate things -- the app
hangs as soon as you first make a RestartMIDISystem call or a call that
has to fetch a device/entity/destination/endpoint, and secondly, that
under certain circumstances MIDI Monitor will detect outgoing packets
even when they don't seem to do anything on any synth hardware attached
to the MIDISport. These appear to be separate issues, so I will tell you
what I know about them separately.
As for the application hang: when the app is run from inside
ProjectBuilder, you can kickstart it by clicking on the app's menubar,
after which it works normally. If you don't do the kickstarting within
about 5 seconds, a runtime exception will get thrown out of nowhere,
something to do with a Buckyball Timer object, which is something I had
never heard of before, though I assume it's related to Apple's
Carbon-API-related naming cuteness (buckyballs being very large hollow
molecules made out of carbon).
Alternatively, if you run your app by launching it from the Finder or
the Dock (having Bulit it first in ProjectBuilder), simply moving the
mouse after it hangs is sufficient to kickstart it (at least on my
system).
In order to only have the hang issue occur once per use, I made all of
the MIDI objects my app uses be static fields in my MIDI-related class,
and the app's main constructor that runs on launch calls a static
initialization method that assigns them all at the beginning. My app
itself never needs to change the MIDI objects -- all it ever does is
send packets from the client object to the various destination objects
and that doesn't cause hangs -- so I guess I sort've lucked out there.
I am able run MIDIMonitor (from snoize) and am able to write a Carbon
test application to work, but I can't get the MIDISport to work when
called from my Java code.
This is the second problem I was having. I couldn't get mine to work
either. MIDI Monitor, in spy mode, was detecting the packets my app was
sending to the MIDISport -- but the packets weren't actually doing
anything w.r.t. activating the activity LEDs or affecting the attached
synth hardware in any way.
I was able to get it working, so let me show you what I found worked and
didn't work; maybe it'll be relevant to your code.
First, the static method MIDIData.newMIDINoteMessage() does not work. I
could not get MIDI Monitor to detect any NoteOn/Off outgoing packets
when I had my app trying to create them with this call. Use
newMIDIRawData() instead.
Second, if you try to put more than one event/message into a MIDIData
structure before adding it to your MIDIPacketList, none of the packets
you send will work on the MIDISport, even though MIDI Monitor detects
and parses them correctly in spy mode. I suspect this is because you
supply a timestamp when adding a MIDIData object to your MIDIPacketList,
and having one timestamp for more than one event is probably what's
tripping it up.
Here's some code that works for me:
private static MIDIClient client;
private static MIDIOutputPort output;
private static MIDIDevice sport;
private static MIDIEntity ports;
private static MIDIEndpoint synth;
public static void initMIDI() { // I call this on app launch so the
hang thing only happens once
try {
client = new MIDIClient(new CAFString("App"), null);
output = client.outputPortCreate(new CAFString("App
Output"));
sport = MIDIDevice.getDevice(0);
ports = sport.getEntity(0);
synth = ports.getDestination(0); // an endpoint for the
MIDISport 2x2's Port A output
}
catch (Exception egg) {
System.exit(1);
}
}
public static void playNote() {
try {
MIDIData event;
MIDIPacketList list = new MIDIPacketList();
event = MIDIData.newMIDIRawData(3); // three being the
number of bytes the event will hold
event.addRawData(144, 60, 127); // NoteOn message for
channel 0, middle C, max volume
list.add(0, event); // zero is the timestamp, meaning
"immediately"
event = MIDIData.newMIDIRawData(3);
event.addRawData(128, 60, 0); // NoteOff message for channel
0, middle C
list.add(33000000, event); // I think this timestamp
translates into about 0.9 seconds; I could be wrong
output.send(synth, list);
}
catch (Exception egg) {
System.exit(2);
}
}
Is it time to get a different MIDI Interface? Since it only seems to
have problems when accessed via Java, I am assuming it is a problem on
Apple's end, but I'm not convinced, since I believe others have said
that all this works with the Roland USB interface.
Hope that helps. I haven't tried it on anything other than
ProjectBuilder in "pure java" mode, so if other approaches don't have
the hang issue then I'd certainly like to see it fixed in java. Oh, and
here's the full runtime exception it throws when you just let it sit
there hanging for about 5 seconds from within ProjectBuilder (LlamaWare
is my app's name):
A Buckyball Timer threw an exception:
java.lang.IllegalMonitorStateException: current thread not owner
at com.apple.mrj.macos.carbon.CarbonLock.release0(Native Method)
at com.apple.mrj.macos.carbon.CarbonLock.release(CarbonLock.java:43)
at com.apple.buckyball.app.Timer.EventLoopTimer(Timer.java:213)
at com.apple.audio.midi.MIDIClient.MIDIClientCreate(Native Method)
at com.apple.audio.midi.MIDIClient.alloc(MIDIClient.java:59)
at com.apple.audio.midi.MIDIClient.<init>(MIDIClient.java:43)
at MyMIDI.initMIDI(MyMIDI.java:22)
at LlamaWare.<init>(LlamaWare.java:271)
at LlamaWare.main(LlamaWare.java:253)
at java.lang.reflect.Method.invoke(Native Method)
at com.apple.buckyball.app.LaunchRunner.run(LaunchRunner.java:82)
at com.apple.buckyball.app.LaunchRunner.callMain(LaunchRunner.java:44)
at com.apple.buckyball.app.CarbonLibApp.launch(CarbonLibApp.java:67)
~ Kenny
_______________________________________________
coreaudio-api mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/coreaudio-api
Do not post admin requests to the list. They will be ignored.