おーぷんMIDIぷろじぇくと、なるもの発見
おーぷんMIDIぷろじぇくと を先日発見。これ Python から使えると便利な気がしてきた。気のせいかも? DLL の形式でも公開されているため、とりあえず ctypes つかえばベタなラッパーは何も考えずに書ける。たとえば MIDIIOライブラリならこんな感じ。
でもベタなままだと C と大差ない、なら C から使おうよってことにもなる。 Python らしくするためにも一工夫加える必要あり。整数 1, 0 返して正常異常を知らせる関数は失敗時に例外を送出にしたりとか(これは ctypes のみで可能)、ポインタ複数渡して値を複数受け取るための関数は普通にリストに値まとめて返すようにしたり(これも)。入出力マクロはそのままではなく Python 標準のファイルオブジェクト風にしてみたり。MIDIData ライブラリは OOP っぽくするのもありかも。今後の課題。
- 使ってみる。 MIDIIO.dll と下記の自作 midiio パッケージを使用。起立、礼!
# coding: utf-8 import time from ctypes import * from midiio import midiout def main(): c_s = create_string_buffer(32) ret = midiout.GetDeviceName(0, c_s, 32) if not ret: u'MIDIデバイスが見つかりません' return s0 = c_s.value print s0 mo = midiout.Open(s0) if mo: try: print u'MIDIデバイスオープンしました' grand_piano = '\xc0\x00' midiout.PutMIDIMessage(mo, grand_piano, len(grand_piano)) time.sleep(0.1) code_c = ('\x24', '\x30', '\x3c', '\x40', '\x43', '\x48') code_g = ('\x2b', '\x37', '\x3b', '\x3e', '\x43', '\x47') for c in code_c: message = '\x90%s\x64' % c midiout.PutMIDIMessage(mo, message, len(message)) time.sleep(2) for c in code_c: message = '\x90%s\x00' % c midiout.PutMIDIMessage(mo, message, len(message)) for c in code_g: message = '\x90%s\x64' % c midiout.PutMIDIMessage(mo, message, len(message)) time.sleep(2) for c in code_g: message = '\x90%s\x00' % c midiout.PutMIDIMessage(mo, message, len(message)) for c in code_c: message = '\x90%s\x64' % c midiout.PutMIDIMessage(mo, message, len(message)) time.sleep(4) finally: ret = midiout.Close(mo) if ret: print u'MIDIデバイスクローズしました' else: print u'MIDIデバイスクローズ失敗' else: print 'MIDIデバイスが開けません' if __name__ == '__main__': main()
- midiio/__init__.py
# coding: utf-8 u"""おーぷんMIDIぷろじぇくと MIDIIOLib0.4 対応 """ from ctypes import * __all__ = ['midiin', 'midiout'] midiio_dll = windll.MIDIIO class MIDI(Structure): _fields_ = [ ('m_pDeviceHandle', c_void_p), ('m_szDeviceName', c_char * 32), ('m_lMode', c_long), ('m_pBuf', POINTER(c_ubyte)), ('m_lBufSize', c_long), ('m_lReadPosition', c_long), ('m_lWritePosition', c_long), ]
- midiio/midiin.py
# coding: utf-8 u"""おーぷんMIDIぷろじぇくと MIDIIn 系 """ from ctypes import * from midiio import MIDI, midiio_dll __all__ = [ 'MIDIIn', 'GetDeviceNum', 'GetDeviceName', 'Open', 'Reopen', 'Close', 'Reset', 'GetMIDIMessage', 'GetByte', 'GetBytes'] MIDIIn = MIDI GetDeviceNum = WINFUNCTYPE(c_long)( ('MIDIIn_GetDeviceNum', midiio_dll), ) GetDeviceName = WINFUNCTYPE(c_long, c_long, c_char_p, c_long)( ('MIDIIn_GetDeviceName', midiio_dll), ( (1, 'lIndex'), (1, 'pszDeviceName'), (1, 'lLen'), ) ) Open = WINFUNCTYPE(POINTER(MIDIIn), c_char_p)( ('MIDIIn_Open', midiio_dll), ( (1, 'pszDeviceName'), ) ) Reopen = WINFUNCTYPE(POINTER(MIDIIn), POINTER(MIDIIn), c_char_p)( ('MIDIIn_Reopen', midiio_dll), ( (1, 'pMIDIIn'), (1, 'pszDeviceName'), ) ) Close = WINFUNCTYPE(c_long, POINTER(MIDIIn))( ('MIDIIn_Close', midiio_dll), ( (1, 'pMIDIIn'), ) ) Reset = WINFUNCTYPE(c_long, POINTER(MIDIIn))( ('MIDIIn_Reset', midiio_dll), ( (1, 'pMIDIIn'), ) ) GetMIDIMessage = WINFUNCTYPE(c_long, POINTER(MIDIIn), c_char_p, c_long)( ('MIDIIn_GetMIDIMessage', midiio_dll), ( (1, 'pMIDIIn'), (1, 'pMessage'), (1, 'lLen'), ) ) GetByte = WINFUNCTYPE(c_long, POINTER(MIDIIn), c_ubyte)( ('MIDIIn_GetByte', midiio_dll), ( (1, 'pMIDIIn'), (1, 'ucByte'), ) ) GetBytes = WINFUNCTYPE(c_long, POINTER(MIDIIn), c_char_p, c_long)( ('MIDIIn_GetBytes', midiio_dll), ( (1, 'pMIDIIn'), (1, 'pBuf'), (1, 'lLen'), ) )
- midiio/midiout.py
# coding: utf-8 u"""おーぷんMIDIぷろじぇくと MIDIOut 系 """ from ctypes import * from midiio import MIDI, midiio_dll __all__ = [ 'MIDIOut', 'GetDeviceNum', 'GetDeviceName', 'Open', 'Reopen', 'Close', 'Reset', 'PutMIDIMessage', 'PutByte', 'PutBytes'] MIDIOut = MIDI GetDeviceNum = WINFUNCTYPE(c_long)( ('MIDIOut_GetDeviceNum', midiio_dll), ) GetDeviceName = WINFUNCTYPE(c_long, c_long, c_char_p, c_long)( ('MIDIOut_GetDeviceName', midiio_dll), ( (1, 'lIndex'), (1, 'pszDeviceName'), (1, 'lLen'), ) ) Open = WINFUNCTYPE(POINTER(MIDIOut), c_char_p)( ('MIDIOut_Open', midiio_dll), ( (1, 'pszDeviceName'), ) ) Reopen = WINFUNCTYPE(POINTER(MIDIOut), POINTER(MIDIOut), c_char_p)( ('MIDIOut_Reopen', midiio_dll), ( (1, 'pMIDIOut'), (1, 'pszDeviceName'), ) ) Close = WINFUNCTYPE(c_long, POINTER(MIDIOut))( ('MIDIOut_Close', midiio_dll), ( (1, 'pMIDIOut'), ) ) Reset = WINFUNCTYPE(c_long, POINTER(MIDIOut))( ('MIDIOut_Reset', midiio_dll), ( (1, 'pMIDIOut'), ) ) PutMIDIMessage = WINFUNCTYPE(c_long, POINTER(MIDIOut), c_char_p, c_long)( ('MIDIOut_PutMIDIMessage', midiio_dll), ( (1, 'pMIDIOut'), (1, 'pMessage'), (1, 'lLen'), ) ) PutByte = WINFUNCTYPE(c_long, POINTER(MIDIOut), c_ubyte)( ('MIDIOut_PutByte', midiio_dll), ( (1, 'pMIDIOut'), (1, 'ucByte'), ) ) PutBytes = WINFUNCTYPE(c_long, POINTER(MIDIOut), c_char_p, c_long)( ('MIDIOut_PutBytes', midiio_dll), ( (1, 'pMIDIOut'), (1, 'pBuf'), (1, 'lLen'), ) )