I'll try and post what I was working on to Github, but it's fairly incomplete, as I didn't want to get too far and then find out I couldn't send messages to ruby the way I thought :-)
This little MIDI project of mine was just to get my formerly-RubyCocoa (and thus formerly Midiator / DL / rbcoremidi compatible) app working in MacRuby, but the more I think about it, the more it feels like we should do something about this fragmented ruby MIDI situation. Since that's really a topic for the Ruby-MIDI forum, I posted my thoughts over there: http://groups.google.com/group/ruby-midi/browse_thread/thread/2cacf04770abf242 Let the firestorm begin! Or, maybe just a happy storm. That would be better. Mike On Thu, May 28, 2009 at 1:02 PM, Jeremy Voorhis <jvoor...@gmail.com> wrote: > I'd love to do it in FFI, but getting this far in C was a lot of work! > > ... so here's another crackpot idea of mine. Another project I have > been following is the Pure Language > <http://code.google.com/p/pure-lang>. It aims to be a simple, > interpreted functional language based on term-rewriting, and also has > an LLVM JIT compiler. Using LLVM, they support a literal syntax for > declaring foreign functions. > > To assist in creating wrappers for libraries, they created a tool > called pure-gen that parses C header files and dumps out a .pure file > containing FFI declarations. The tool is written in Haskell using a > module called Language.C, but I wonder if we could bootstrap something > similar by wrapping up Clang's libparse. They've managed to create > wrappers for gsl, gtk+ and some other libraries by starting with the > generated FFI decls, and adding some syntactic sugar and abstraction > within Pure as appropriate. > > Implementing such a tool is probably going to take a lot of effort, > but the benefits are pretty clear – especially since generated > wrappers might be usable in JRuby and MRI. I also don't know how much > this overlaps with BridgeSupport, but I just wanted to put the idea > out there. > > Best, > > Jeremy > > On Thu, May 28, 2009 at 10:38 AM, Matt Aimonetti > <mattaimone...@gmail.com> wrote: >> 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 >> >> > _______________________________________________ > 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