2011-01-07 188 views
2

我只是想做一些基本的Windows調用來打印來自MIDI輸入設備(鍵盤)的信息。這些調用似乎有效,但前兩個調用midiInOpen和midiInStart返回MMSYSERR_NOMEMMMSYSERR_INVALHANDLE。我相信這與ptr = FFI::MemoryPointer.new(:pointer)有關,但我對FFI瞭解不多。任何幫助表示讚賞。幫助紅寶石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

Ryan問題:我在這裏有同樣的問題。 midiInOpen的結果是MMSYSERR_NOERROR,並且在midiInOpen之後一次調用回調函數。然後我打電話給midiInStart,結果是MMSYSERR_INVALHANDLE。你有沒有發現,問題是什麼或在midiInOpen中設置的正確標誌是什麼,錯誤消失了? – Michael 2015-04-13 19:05:47

回答

1

沒有確切的答案,因爲你的代碼看起來大多是正確的,但我懷疑它是dwFlags中(最後PARAM)要傳遞到midiInOpen()這就是問題所在。看看http://msdn.microsoft.com/en-us/library/dd798458(v=vs.85).aspx,它似乎需要非零。

嘗試在winmm頭文件中查找CALLBACK_FUNCTION的值,並在模塊中聲明一個類似的常量,然後將其用作標誌參數。

有一個C#包裝器http://powersdr-iq.googlecode.com/svn/trunk/Source/Console/midi.cs可能是其他人使用C#P/Invoke接口包裝相同API的有用示例。

您對midiInOpen和回調的簽名有點不對(但不會導致此問題)。他們應該是:

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

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

即使用:指針在API文檔使用DWORD_PTR

+0

這似乎已經停止了「MMSYSERR_NOMEM」和「MMSYSERR_INVALHANDLE」錯誤。回調函數似乎沒有工作。 – RyanScottLewis 2011-01-07 07:01:32