2

我只是尝试进行一些基本的 Windows 调用来打印来自 MIDI 输入设备(键盘)的信息。这些调用似乎有效,但对 midiInOpen 和 midiInStart 的前两个调用返回MMSYSERR_NOMEMand MMSYSERR_INVALHANDLE。我相信这与它有关,ptr = FFI::MemoryPointer.new(:pointer)但我对 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 {}
4

2 回答 2

1

没有明确的答案,因为您的代码看起来大部分是正确的,但我怀疑您传递给 midiInOpen() 的 dwFlags (最后一个参数)是问题所在。查看http://msdn.microsoft.com/en-us/library/dd798458(v=vs.85).aspx,它似乎需要非零。

尝试在 winmm 头文件中查找 CALLBACK_FUNCTION 的值,并在模块中声明一个类似的常量,然后将其用作标志参数。

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

您对 midiInOpen 和回调的签名略有错误(但不会导致此问题)。他们应该是:

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

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

即使用 :pointer API 文档使用 DWORD_PTR

于 2011-01-07T06:54:38.830 回答
0

看看https://github.com/arirusso/midi-winmm/blob/master/lib/midi-winmm/map.rb

哦!那是你的一些。凉爽的。有用。

我知道这在 Windows 中有效,因为我已经尝试过了。我最大的愿望是从 Microsoft 那里找到有关 winmm.dll api 的文档。由于user186057回答了您的问题,我认为我已经找到了。

谢谢。

于 2016-12-17T22:44:16.333 回答