1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
|
# SPDX-FileCopyrightText: 2013 Ole Martin Bjorndalen <ombdalen@gmail.com>
#
# SPDX-License-Identifier: MIT
"""
Low-level wrapper for PortMidi library
Copied straight from Grant Yoshida's portmidizero, with slight
modifications.
"""
import ctypes
import ctypes.util
import sys
dll_name = ''
if sys.platform == 'darwin':
dll_name = ctypes.util.find_library('libportmidi.dylib')
elif sys.platform in ('win32', 'cygwin'):
dll_name = 'portmidi.dll'
else:
dll_name = 'libportmidi.so'
lib = ctypes.CDLL(dll_name)
null = None
false = 0
true = 1
# portmidi.h
# From portmidi.h
PM_HOST_ERROR_MSG_LEN = 256
def get_host_error_message():
"""Return host error message."""
buf = ctypes.create_string_buffer(PM_HOST_ERROR_MSG_LEN)
lib.Pm_GetHostErrorText(buf, PM_HOST_ERROR_MSG_LEN)
return buf.raw.decode().rstrip('\0')
PmError = ctypes.c_int
# PmError enum
pmNoError = 0
pmHostError = -10000
pmInvalidDeviceId = -9999
pmInsufficientMemory = -9989
pmBufferTooSmall = -9979
pmBufferOverflow = -9969
pmBadPtr = -9959
pmBadData = -9994
pmInternalError = -9993
pmBufferMaxSize = -9992
lib.Pm_Initialize.restype = PmError
lib.Pm_Terminate.restype = PmError
PmDeviceID = ctypes.c_int
PortMidiStreamPtr = ctypes.c_void_p
PmStreamPtr = PortMidiStreamPtr
PortMidiStreamPtrPtr = ctypes.POINTER(PortMidiStreamPtr)
lib.Pm_HasHostError.restype = ctypes.c_int
lib.Pm_HasHostError.argtypes = [PortMidiStreamPtr]
lib.Pm_GetErrorText.restype = ctypes.c_char_p
lib.Pm_GetErrorText.argtypes = [PmError]
lib.Pm_GetHostErrorText.argtypes = [ctypes.c_char_p, ctypes.c_uint]
pmNoDevice = -1
class PmDeviceInfo(ctypes.Structure):
_fields_ = [("structVersion", ctypes.c_int),
("interface", ctypes.c_char_p),
("name", ctypes.c_char_p),
("is_input", ctypes.c_int),
("is_output", ctypes.c_int),
("opened", ctypes.c_int)]
PmDeviceInfoPtr = ctypes.POINTER(PmDeviceInfo)
lib.Pm_CountDevices.restype = ctypes.c_int
lib.Pm_GetDefaultOutputDeviceID.restype = PmDeviceID
lib.Pm_GetDefaultInputDeviceID.restype = PmDeviceID
PmTimestamp = ctypes.c_long
PmTimeProcPtr = ctypes.CFUNCTYPE(PmTimestamp, ctypes.c_void_p)
NullTimeProcPtr = ctypes.cast(null, PmTimeProcPtr)
# PmBefore is not defined
lib.Pm_GetDeviceInfo.argtypes = [PmDeviceID]
lib.Pm_GetDeviceInfo.restype = PmDeviceInfoPtr
lib.Pm_OpenInput.restype = PmError
lib.Pm_OpenInput.argtypes = [PortMidiStreamPtrPtr,
PmDeviceID,
ctypes.c_void_p,
ctypes.c_long,
PmTimeProcPtr,
ctypes.c_void_p]
lib.Pm_OpenOutput.restype = PmError
lib.Pm_OpenOutput.argtypes = [PortMidiStreamPtrPtr,
PmDeviceID,
ctypes.c_void_p,
ctypes.c_long,
PmTimeProcPtr,
ctypes.c_void_p,
ctypes.c_long]
lib.Pm_SetFilter.restype = PmError
lib.Pm_SetFilter.argtypes = [PortMidiStreamPtr, ctypes.c_long]
lib.Pm_SetChannelMask.restype = PmError
lib.Pm_SetChannelMask.argtypes = [PortMidiStreamPtr, ctypes.c_int]
lib.Pm_Abort.restype = PmError
lib.Pm_Abort.argtypes = [PortMidiStreamPtr]
lib.Pm_Close.restype = PmError
lib.Pm_Close.argtypes = [PortMidiStreamPtr]
PmMessage = ctypes.c_long
class PmEvent(ctypes.Structure):
_fields_ = [("message", PmMessage),
("timestamp", PmTimestamp)]
PmEventPtr = ctypes.POINTER(PmEvent)
lib.Pm_Read.restype = PmError
lib.Pm_Read.argtypes = [PortMidiStreamPtr, PmEventPtr, ctypes.c_long]
lib.Pm_Poll.restype = PmError
lib.Pm_Poll.argtypes = [PortMidiStreamPtr]
lib.Pm_Write.restype = PmError
lib.Pm_Write.argtypes = [PortMidiStreamPtr, PmEventPtr, ctypes.c_long]
lib.Pm_WriteShort.restype = PmError
lib.Pm_WriteShort.argtypes = [PortMidiStreamPtr, PmTimestamp, ctypes.c_long]
lib.Pm_WriteSysEx.restype = PmError
lib.Pm_WriteSysEx.argtypes = [PortMidiStreamPtr, PmTimestamp, ctypes.c_char_p]
# porttime.h
# PtError enum
PtError = ctypes.c_int
ptNoError = 0
ptHostError = -10000
ptAlreadyStarted = -9999
ptAlreadyStopped = -9998
ptInsufficientMemory = -9997
PtTimestamp = ctypes.c_long
PtCallback = ctypes.CFUNCTYPE(PmTimestamp, ctypes.c_void_p)
lib.Pt_Start.restype = PtError
lib.Pt_Start.argtypes = [ctypes.c_int, PtCallback, ctypes.c_void_p]
lib.Pt_Stop.restype = PtError
lib.Pt_Started.restype = ctypes.c_int
lib.Pt_Time.restype = PtTimestamp
|