2011-01-07 8 views
2

Ich versuche einfach, ein paar grundlegende Windows-Aufrufe zu machen, um die Informationen von einem MIDI-Eingabegerät (Tastatur) zu drucken. Die Anrufe scheinen zu funktionieren, aber die ersten beiden Aufrufe von MidiInOpen und MidiInStart geben MMSYSERR_NOMEM und MMSYSERR_INVALHANDLE zurück. Ich glaube, es hat etwas mit ptr = FFI::MemoryPointer.new(:pointer) zu tun, aber ich weiß nicht genug über FFI, um es herauszufinden. Jede Hilfe wird geschätzt.Hilfe mit Ruby FFI

require 'ffi' 

module MIDI; end 

module MIDI::Input 
    extend FFI::Library 

    ffi_lib 'winmm' 
    ffi_convention :stdcall 

    callback :midiInProc, [ :pointer, :uint, :int, :int, :int ], :void 

    attach_function :midiInOpen, [ :pointer, :uint, :midiInProc, :int, :int ], :int 
    attach_function :midiInClose, [ :long ], :int 

    attach_function :midiInStart, [ :long ], :int 
    attach_function :midiInStop, [ :long ], :int 
    attach_function :midiInReset, [ :long ], :int 

    MidiInProcCallback = Proc.new do |hmidiin, wmsg, dwintance, dwparam1, dwparam2| 
    p hmidiin, wmsg, dwintance, dwparam1, dwparam2 
    end 
end 

require 'pp' 
ptr = FFI::MemoryPointer.new(:pointer) 
p MIDI::Input.midiInOpen(ptr, 0, MIDI::Input::MidiInProcCallback, 0, 0) 
p MIDI::Input.midiInStart(ptr.read_long) 

trap("INT") do 
    p MIDI::Input.midiInStart(ptr.read_long) 
    p MIDI::Input.midiInClose(ptr.read_long) 
    p ptr.free 
    exit 
end 

loop {} 
+0

Eine Frage an Ryan: Ich habe das gleiche Problem hier. Das Ergebnis von midiInOpen ist MMSYSERR_NOERROR und die Callback-Funktion wird genau einmal nach midiInOpen aufgerufen. Dann rufe ich midiInStart auf und das Ergebnis ist MMSYSERR_INVALHANDLE. Haben Sie herausgefunden, was das Problem ist oder welche Flags müssen Sie in midiInOpen setzen, damit der Fehler verschwindet? – Michael

Antwort

1

keine definitive Antwort, wie Ihr Code sieht meistens richtig, aber ich vermute, dass es die dwFlags ist (die letzte param) Sie midiInOpen sind vorbei(), die das Problem ist. Mit Blick auf http://msdn.microsoft.com/en-us/library/dd798458(v=vs.85).aspx scheint es, dass es nicht Null sein muss.

Versuchen Sie, in der Winmm-Header-Datei nach dem Wert von CALLBACK_FUNCTION zu suchen, und deklarieren Sie eine ähnliche Konstante in Ihrem Modul, und verwenden Sie sie als Flags-Parameter.

Es gibt einen C# -Wrapper unter http://powersdr-iq.googlecode.com/svn/trunk/Source/Console/midi.cs, der ein nützliches Beispiel für eine andere Person sein könnte, die die gleiche API mit der C# P/Invoke-Schnittstelle umschließt.

Ihre Signaturen für midiInOpen und den Rückruf sind leicht falsch (wird aber dieses Problem nicht verursachen). Sie sollten sein:

callback :midiInProc, [ :pointer, :uint, :pointer, :pointer, :pointer ], :void 

attach_function :midiInOpen, [ :pointer, :uint, :midiInProc, :pointer, :int ], :int 

das heißt Verwendung: Zeiger, wo die API-Dokumentation DWORD_PTR verwenden

+0

Dies scheint die Fehler "MMSYSERR_NOMEM" und "MMSYSERR_INVALHANDLE" gestoppt zu haben. Die Callback-Funktion scheint jedoch nicht zu funktionieren. – RyanScottLewis

+0

Müssen Sie die Windows-Meldungsschleife pumpen, wie in http://en.wikipedia.org/wiki/Message_loop_in_Microsoft_Windows? –

0

Werfen Sie einen Blick auf https://github.com/arirusso/midi-winmm/blob/master/lib/midi-winmm/map.rb

Oh! Das ist etwas von dir. Cool. Es klappt.

Ich weiß, das funktioniert in Windows, weil ich es ausprobiert habe. Mein größter Wunsch ist es, die Dokumentation von Microsoft für die winmm.dll API zu finden. Ich denke, dass ich dank Ihrer Frage von user186057 gefunden habe.

Danke.

Verwandte Themen