我使用MacOSX的CoreMIDI函数访问计算机中的MIDI设备。此外,我想用Python和ctypes来做。
为了做到这一点,我必须创建一个回调函数,只要我的计算机收到MIDI消息就会调用它。回调原型(在C中)是:
typedef void ( *MIDIReadProc)(
const MIDIPacketList *pktlist,
void *readProcRefCon,
void *srcConnRefCon);
MIDIPacketList定义为:
struct MIDIPacketList {
UInt32 numPackets;
MIDIPacket packet[1];
};
MIDIPacket定义为:
struct MIDIPacket {
MIDITimeStamp timeStamp;
UInt16 length;
Byte data[256];
};
MIDITimeStamp定义为:
typedef UInt64 MIDITimeStamp;
好的,我的定义回调和自定义结构的代码如下:
MIDITimeStamp = c_ulonglong
class MIDIPacket(Structure):
_fields_ = [("timeStamp", MIDITimeStamp),
("length", c_ushort),
("data", c_char_p)]
class MIDIPacketList(Structure):
_fields_ = [("numPackets", c_uint),
("packet", POINTER(MIDIPacket))]
def callback(midi_packet_list, proc_ref, src_ref):
m_pack_list = midi_packet_list.contents
packet = m_pack_list.packet.contents
print packet.length # This line crashes the program
CALLBACKFUNC = CFUNCTYPE(None, POINTER(MIDIPacketList), c_void_p, c_void_p)
midi_input_callback = CALLBACKFUNC(callback)
# I omitted the MIDI setup code because I don't think it is relevant here
# MIDIInputPortCreate associates the callback function to the midi endpoint and input port
result = core_midi.MIDIInputPortCreate(midi_client, input_port_name, midi_input_callback, None, byref(input_port));
我不知道为什么,但我无法正确访问回调函数中midi_packet_list指向的数据。这应该是指向MIDIPacketList结构的指针,我将其与midi_packet_list.contents取消引用。然后我尝试获取参数packet [0],它应该是MIDIPacketObject。但是当我尝试访问MIDIPacket数据(packet.length)时,程序崩溃了。
我知道回调被正确调用,因为当我的MIDI设备关闭时,它永远不会被调用,但是当MIDI设备打开时,我可以在屏幕上打印信息。但是我无法从MIDIPacketList访问数据,这是回调例程中最重要的部分。我需要有人帮我指出访问这些数据的正确方法。
谢谢!