I second what Jeremy said. A nice Midi wrapper would be great. Jeremy, regarding your MusicPlayer lib, the other option is to port it to FFI and therefore making it JRuby and MacRuby compatible.
- Matt On Thu, May 28, 2009 at 10:32 AM, Jeremy Voorhis <jvoor...@gmail.com> wrote: > Mike, > > Is your code available anywhere, e.g. on github? I haven't looked at > the PyObjC code myself, but I'd be interested in having really decent > CoreMIDI support available in MacRuby. > > Btw, when C extensions are supported, simple apps will be able to use > my MusicPlayer lib at > http://github.com/jvoorhis/music_player/tree/master, which wraps much > of the MusicPlayer/MusicSequence api in AudioToolbox.framework. It's > short on documentation, but it's easy to get up and running on MRI > 1.8.x or 1.9.1. > > Best, > > Jeremy > > On Wed, May 27, 2009 at 11:25 PM, Mike Laurence <mklaure...@gmail.com> > wrote: > > Hmmm... I'm doing several things different, perhaps one or more of > > them are impossible :-) > > > > Basically, I'm trying to get MIDI support into Ruby via the PYMIDI > > obj-c library, which is really just a wrapper around CoreMIDI. One way > > I had thought of: create an additional obj-c class (MidiReceiver) > > which processes incoming packets for a given MIDI source and then call > > methods such as "note", "controlChange", "clockTick", etc. This > > MidiReceiver class can then be overridden by a custom ruby class that > > contains those same methods. > > > > Here is a quick version of the MidiReceiver class (with only the > > clockTick method for simplicity): > > > > ------------- MidiReceiver -------------- > > > > #import <MacRuby/MacRuby.h> > > #include <CoreMIDI/CoreMIDI.h> > > > > @interface MidiReceiver : NSObject > > > > - (void) processMIDIPacket: (MIDIPacket*) packet; > > - (void) clockTick; > > > > @end > > > > @implementation MidiReceiver > > > > - (void) processMIDIPacket: (MIDIPacket*) packet { > > if (packet->length > 0) { > > > > int statusByte = packet->data[0]; > > int status = statusByte >= 0xf0 ? statusByte : statusByte >> 4 << > 4; > > > > switch (status) { > > case 0x90: // Note on, etc... > > case 0xf8: // Clock tick > > [self performRubySelector:@selector(clockTick)]; > > break; > > } > > } > > } > > > > - (void) clockTick { > > } > > > > @end > > > > -------------------------------------------------------- > > > > Then, I have a ruby subclass of MidiReceiver that overrides clockTick, > etc.: > > > > class LiveMidiReceiver < MidiReceiver > > def clockTick > > puts "tick!" > > end > > end > > > > And then, in my Ruby ApplicationController, I'm finding the MIDI > > source and adding an instance of LiveMidiReceiver as a MIDI receiver: > > > > @src = PYMIDIManager.sharedInstance.realSources.find{ |s| > > s.displayName == 'KONTROL49 PORT A' } > > receiver = LiveMidiReceiver.new > > @src.addReceiver(receiver) > > > > The LiveMidiReceiver instance, upon receiving a midi packet, is called > > properly up to the point of the performRubySelector, but thereafter it > > launches into the debugger with EXC_BAD_ACCESS messages or other > > unsightly stack dumps. > > > > --- > > > > An even *better* interface would be to have the "clockTick" and other > > calls be performable on an arbitrary ruby object without having to > > subclass MidiReceiver (e.g., have MidiReceiver send "clockTick", etc. > > to a delegate object which has been created solely in Ruby). I tried > > that and it gave me similar results, although strangely it only > > crashed the first time on a clean build - thereafter I saw no crashes, > > but still no confirmation of ruby method calls either. > > > > To test that, I just added a delegate object to MidiReceiver, and then > > I changed the clockTick recipient from self to delegate: > > > > [delegate performRubySelector:@selector(clockTick)]; > > > > Then set receiver.delegate = self in my ApplicationController. I'll > > bet I need some more hooks than that, although it sure would be nice > > to send ruby messages from obj-c willy-nilly :-) > > > > --- > > > > I hope I'm making some sense here! I greatly appreciate any info that > > you can send my way. Hopefully when I get this all figured out I can > > write a nice, fat blog post about it :-) > > > > Regards, > > Mike Laurence > > > > On Wed, May 27, 2009 at 8:18 PM, Laurent Sansonetti > > <lsansone...@apple.com> wrote: > >> Hi Mike, > >> > >> On May 26, 2009, at 5:45 PM, Mike Laurence wrote: > >> > >>> Hello, > >>> > >>> I'm trying to get some obj-c code to talk back to my ruby. After > >>> encountering some "EXC_BAD_ACCESS" messages and scouring the web, I've > >>> concluded that I'm probably supposed to use performRubySelector > >>> instead of just expecting selectors to work when overridden by ruby > >>> subclasses, etc. > >>> > >>> What is the preferred way to get this to work? I looked through some > >>> of Elysium's old code (which used performRubySelector), but I'm having > >>> trouble wrapping my head around how you're supposed to use the MacRuby > >>> sharedRuntime to get things to happen. If someone could give me a > >>> quick example of how to call arbitrary ruby methods, I would highly > >>> appreciate it. > >>> > >>> Of course, if I'm completely off base and there's some other way to > >>> call ruby code, please let me know! > >> > >> Calling Ruby from Objective-C can be problematic, depending if you want > to > >> call a pure Ruby method or a Ruby method that overrides an Objective-C > one. > >> If you want to dispatch the method by yourself (and if it's a Ruby > method > >> that overrides a specialized Objective-C method), you may want to be > very > >> careful about the types of the arguments you are passing to, as well as > the > >> return value. > >> > >> In any case, using performRubySelector: is better because arguments will > be > >> converted from Objective-C objects (id) into the expected type, and the > >> return value will be converted into an Objective-C object. Also, > >> performRubySelector: can deal with Ruby methods that have optional or > splat > >> arguments. > >> > >> $ cat t.m > >> #import <Foundation/Foundation.h> > >> #import <MacRuby/MacRuby.h> > >> > >> @interface Foo : NSObject > >> @end > >> > >> @implementation Foo > >> - (int)aMethodReturningInt > >> { > >> return 123; > >> } > >> @end > >> > >> int main(void) > >> { > >> [[MacRuby sharedRuntime] evaluateString:@"class X; def foo(x=1, *a); > p x, > >> a; end; end"]; > >> Class k = NSClassFromString(@"X"); > >> id o = [k new]; > >> > >> [o performRubySelector:@selector(foo)]; > >> [o performRubySelector:@selector(foo:) withArguments:@"1", NULL]; > >> [o performRubySelector:@selector(foo:) withArguments:@"1", @"2", > @"3", > >> NULL]; > >> > >> [[MacRuby sharedRuntime] evaluateString:@"class Bar < Foo; def > >> aMethodReturningInt; 42; end; end"]; > >> k = NSClassFromString(@"Bar"); > >> o = [k new]; > >> > >> NSLog(@"%d", [(Foo *)o aMethodReturningInt]); > >> NSLog(@"%@", [o performRubySelector:@selector > (aMethodReturningInt)]); > >> > >> return 0; > >> } > >> $ gcc t.m -o t -framework Foundation -framework MacRuby -fobjc-gc > >> $ ./t > >> 1 > >> [] > >> "1" > >> [] > >> "1" > >> ["2", "3"] > >> 2009-05-27 18:16:36.092 t[11922:10b] 42 > >> 2009-05-27 18:16:36.095 t[11922:10b] 42 > >> $ > >> > >> If you still have problems, it would be easier if you could paste some > code, > >> this way I can try to help you more. > >> > >> HTH, > >> Laurent > >> _______________________________________________ > >> MacRuby-devel mailing list > >> MacRuby-devel@lists.macosforge.org > >> http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel > >> > > _______________________________________________ > > MacRuby-devel mailing list > > MacRuby-devel@lists.macosforge.org > > http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel > > > _______________________________________________ > MacRuby-devel mailing list > MacRuby-devel@lists.macosforge.org > http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel >
_______________________________________________ MacRuby-devel mailing list MacRuby-devel@lists.macosforge.org http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel