-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathrtmidi_python.pyx
More file actions
121 lines (84 loc) · 3.65 KB
/
rtmidi_python.pyx
File metadata and controls
121 lines (84 loc) · 3.65 KB
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
from cython.operator import dereference
from libcpp.string cimport string
from libcpp.vector cimport vector
# Init Python threads and GIL, because RtMidi calls Python from native threads.
# See http://permalink.gmane.org/gmane.comp.python.cython.user/5837
cdef extern from "Python.h":
void PyEval_InitThreads()
PyEval_InitThreads()
cdef extern from "RtMidi/RtMidi.h":
ctypedef void (*RtMidiCallback)(double timeStamp, vector[unsigned char]* message, void* userData)
enum Api "RtMidi::Api":
UNSPECIFIED "RtMidi::UNSPECIFIED"
cdef cppclass RtMidi:
void openPort(unsigned int portNumber)
void openVirtualPort(string portName)
unsigned int getPortCount()
string getPortName(unsigned int portNumber)
void closePort()
cdef cppclass RtMidiIn(RtMidi):
RtMidiIn(Api api, string clientName, unsigned int queueSizeLimit)
void setCallback(RtMidiCallback callback, void* userData)
void cancelCallback()
void ignoreTypes(bint midiSysex, bint midiTime, bint midiSense)
double getMessage(vector[unsigned char]* message)
cdef cppclass RtMidiOut(RtMidi):
RtMidiOut(Api api, string clientName)
void sendMessage(vector[unsigned char]* message)
cdef class MidiBase:
cdef RtMidi* baseptr(self):
return NULL
def open_port(self, port=0):
if isinstance(port, int):
port_number = port
else:
port_number = self.ports.index(port)
self.baseptr().openPort(port_number)
def open_virtual_port(self, port_name="RtMidi"):
self.baseptr().openVirtualPort(string(<char*>port_name))
property ports:
def __get__(self):
return [self.baseptr().getPortName(i).c_str() for i in range(self.baseptr().getPortCount())]
def close_port(self):
self.baseptr().closePort()
cdef void midi_in_callback(double time_stamp, vector[unsigned char]* message_vector, void* py_callback) with gil:
(<object>py_callback)(dereference(message_vector), time_stamp)
cdef class MidiIn(MidiBase):
cdef RtMidiIn* thisptr
cdef object py_callback
def __cinit__(self, client_name="RtMidi Input Client", queue_size_limit=100):
self.thisptr = new RtMidiIn(UNSPECIFIED, string(<char*>client_name), queue_size_limit)
self.py_callback = None
def __dealloc__(self):
del self.thisptr
cdef RtMidi* baseptr(self):
return self.thisptr
property callback:
def __get__(self):
return self.py_callback
def __set__(self, callback):
if self.py_callback is not None:
self.thisptr.cancelCallback()
self.py_callback = callback
if self.py_callback is not None:
self.thisptr.setCallback(midi_in_callback, <void*>self.py_callback)
def ignore_types(self, midi_sysex=True, midi_time=True, midi_sense=True):
self.thisptr.ignoreTypes(midi_sysex, midi_time, midi_sense)
def get_message(self):
cdef vector[unsigned char] message_vector
delta_time = self.thisptr.getMessage(&message_vector)
if message_vector.empty():
return None, None
else:
return message_vector, delta_time
cdef class MidiOut(MidiBase):
cdef RtMidiOut* thisptr
def __cinit__(self, client_name="RtMidi Output Client"):
self.thisptr = new RtMidiOut(UNSPECIFIED, string(<char*>client_name))
def __dealloc__(self):
del self.thisptr
cdef RtMidi* baseptr(self):
return self.thisptr
def send_message(self, message):
cdef vector[unsigned char] message_vector = message
self.thisptr.sendMessage(&message_vector)