1
/* pypm.i : interface file for SWIG
3
* Roger B. Dannenberg, Nov 2009
5
* created to interface portmidi to Python 3.1
6
* (for Python 2.6, use Pyrex and pypm.pyx)
11
#define PDB 1 // debugging on if true
20
#define PYPM_INVALID_ARGUMENT (pmHostError + 100)
24
int err = Pm_Initialize();
25
if (err == pmNoError) Pt_Start(1, NULL, NULL);
29
int Terminate() { Pt_Stop(); return Pm_Terminate(); }
31
int GetDefaultInputDeviceID() { return Pm_GetDefaultInputDeviceID(); }
33
int GetDefaultOutputDeviceID() { return Pm_GetDefaultOutputDeviceID(); }
35
int CountDevices() { return Pm_CountDevices(); }
37
PyObject *GetDeviceInfo(int device_id)
45
const PmDeviceInfo *info = Pm_GetDeviceInfo(device_id);
47
papi = PyUnicode_FromStringAndSize(info->interf, strlen(info->interf));
48
pdev = PyUnicode_FromStringAndSize(info->name, strlen(info->name));
49
pin = PyInt_FromLong(info->input);
50
pout = PyInt_FromLong(info->output);
51
popened = PyInt_FromLong(info->opened);
52
rslt = PyTuple_New(5);
53
PyTuple_SET_ITEM(rslt, 0, papi);
54
PyTuple_SET_ITEM(rslt, 1, pdev);
55
PyTuple_SET_ITEM(rslt, 2, pin);
56
PyTuple_SET_ITEM(rslt, 3, pout);
57
PyTuple_SET_ITEM(rslt, 4, popened);
65
int Time() { return Pt_Time(); }
67
const char *GetErrorText(int err)
69
if (err == PYPM_INVALID_ARGUMENT) {
70
return "pypmbase: `Invalid argumnet'";
72
return Pm_GetErrorText(err);
75
PmStream **new_Stream()
77
PmStream **s = (PmStream *) malloc(sizeof(PmStream *));
78
D printf("new_Stream returns %p\n", s);
82
int OpenOutput(PmStream **midi, int device, int buflen, int latency)
84
int rslt = Pm_OpenOutput(midi, device, NULL, buflen,
85
(latency ? &Pt_Time : NULL), NULL, latency);
86
D printf("OpenOutput midi %p *midi %p rslt %d\n", midi, *midi, rslt);
91
int OpenInput(PmStream **midi, int device, int buflen)
93
return Pm_OpenInput(midi, device, NULL, buflen, &Pt_Time, NULL);
96
int SetFilter(PmStream **midi, int filters)
98
return Pm_SetFilter(*midi, filters);
101
int Channel(int chan) { return Pm_Channel(chan); }
103
int SetChannelMask(PmStream **midi, int mask)
105
return Pm_SetChannelMask(*midi, mask);
108
int Abort(PmStream **midi) { return Pm_Abort(*midi); }
110
int Close(PmStream **midi)
114
rslt = Pm_Close(*midi);
122
int Write(PmStream **midi, PyObject *data)
125
// we'll send data in chunks of 16 messages
126
#define PYPM_BUFFER_LEN 16
127
PmEvent buffer[PYPM_BUFFER_LEN];
128
int len = PyObject_Length(data);
130
return PYPM_INVALID_ARGUMENT;
132
j = 0; // message index
133
for (i = 0; i < len; i++) {
138
PyObject *message = PySequence_GetItem(data, i);
139
if (!message) return PYPM_INVALID_ARGUMENT;
140
bytes = PySequence_GetItem(message, 0);
143
return PYPM_INVALID_ARGUMENT;
145
bytes_len = PyObject_Length(bytes);
146
if (bytes_len <= 0 || bytes_len > 4) return PYPM_INVALID_ARGUMENT;
149
for (k = 0; k < bytes_len; k++) {
150
PyObject *byte = PySequence_GetItem(bytes, k);
154
return PYPM_INVALID_ARGUMENT;
156
msg = msg + ((PyInt_AsLong(byte) & 0xFF) << (8 * k));
157
if (PyErr_Occurred()) {
161
return PYPM_INVALID_ARGUMENT;
167
buffer[j].message = msg;
168
timestamp = PySequence_GetItem(message, 1);
171
return PYPM_INVALID_ARGUMENT;
173
buffer[j++].timestamp = PyInt_AsLong(timestamp);
174
if (PyErr_Occurred()) {
176
Py_DECREF(timestamp);
177
return PYPM_INVALID_ARGUMENT;
179
Py_DECREF(timestamp);
181
if (j >= PYPM_BUFFER_LEN) {
184
"Write about to write buffer, *midi %p i %d buffer[1] %x@%d\n",
185
*midi, i, buffer[0].message, buffer[0].timestamp);
186
r = Pm_Write(*midi, buffer, PYPM_BUFFER_LEN);
187
D printf("Write returns %d\n", r);
188
if (r < PYPM_BUFFER_LEN) return r;
195
"Write about to write buffer, *midi %p j %d buffer[1] %x@%d\n",
196
*midi, j, buffer[0].message, buffer[0].timestamp);
197
r = Pm_Write(*midi, buffer, j);
198
D printf("Write returns %d\n", r);
204
int WriteSysEx(PmStream **midi, int timestamp, PyObject *msg)
206
unsigned char *bytes;
208
if (!PyBytes_Check(msg)) {
209
D printf("WriteSysEx PyBytes_Check failure\n");
211
D PyObject_Print(msg->ob_type, stdout, 0);
212
return PYPM_INVALID_ARGUMENT;
214
bytes = PyBytes_AsString(msg);
216
D printf("WriteSysEx PyBytes_AsString failure\n");
217
return PYPM_INVALID_ARGUMENT;
219
len = PyBytes_GET_SIZE(msg);
220
// check for valid-looking sysex message
221
if (len < 3 || *bytes != 0xF0 || bytes[len - 1] != 0xF7) {
223
"WriteSysEx format failure: len %d, *bytes %x, bytes[len - 1] %x\n",
224
len, *bytes, bytes[len - 1]);
225
return PYPM_INVALID_ARGUMENT;
227
return Pm_WriteSysEx(*midi, timestamp, bytes);
231
int Poll(PmStream **midi) { return Pm_Poll(*midi); }
233
PyObject *Read(PmStream **midi)
240
n = Pm_Read(*midi, &buffer, 1);
241
if (n <= 0) return PyInt_FromLong(n);
242
// I'm not really sure how to do error recovery when allocation
243
// fails. If allocation fails here, I think Python is not going
244
// to get much further, so I'll just return. This may leak some
245
// previously allocated objects. I'm also not sure what happens
246
// if I return NULL, but I can't return an error number because
247
// that would require PyInt_FromLong() which is sure to fail.
249
rslt = PyList_New(2);
250
if (!msg || !rslt) return NULL;
251
for (i = 0; i < 4; i++) {
252
num = PyInt_FromLong((buffer.message >> (i * 8)) & 0xFF);
253
if (!num) return NULL;
254
PyList_SET_ITEM(msg, i, num);
256
PyList_SET_ITEM(rslt, 0, msg);
257
msg = PyInt_FromLong(buffer.timestamp);
258
if (!msg) return NULL;
259
PyList_SET_ITEM(rslt, 1, msg);
263
const int FILT_ACTIVE = PM_FILT_ACTIVE;
264
const int FILT_SYSEX = PM_FILT_SYSEX;
265
const int FILT_CLOCK = PM_FILT_CLOCK;
266
const int FILT_PLAY = PM_FILT_PLAY;
267
const int FILT_F9 = PM_FILT_TICK;
268
const int FILT_TICK = PM_FILT_TICK;
269
const int FILT_FD = PM_FILT_FD;
270
const int FILT_UNDEFINED = PM_FILT_UNDEFINED;
271
const int FILT_RESET = PM_FILT_RESET;
272
const int FILT_REALTIME = PM_FILT_REALTIME;
273
const int FILT_NOTE = PM_FILT_NOTE;
274
const int FILT_CHANNEL_AFTERTOUCH = PM_FILT_CHANNEL_AFTERTOUCH;
275
const int FILT_POLY_AFTERTOUCH = PM_FILT_POLY_AFTERTOUCH;
276
const int FILT_AFTERTOUCH = PM_FILT_AFTERTOUCH;
277
const int FILT_PROGRAM = PM_FILT_PROGRAM;
278
const int FILT_CONTROL = PM_FILT_CONTROL;
279
const int FILT_PITCHBEND = PM_FILT_PITCHBEND;
280
const int FILT_MTC = PM_FILT_MTC;
281
const int FILT_SONG_POSITION = PM_FILT_SONG_POSITION;
282
const int FILT_SONG_SELECT = PM_FILT_SONG_SELECT;
283
const int FILT_TUNE = PM_FILT_TUNE;
285
const int pypmInvalidArgument = PYPM_INVALID_ARGUMENT;
289
const int FILT_ACTIVE;
290
const int FILT_ACTIVE;
291
const int FILT_SYSEX;
292
const int FILT_CLOCK;
297
const int FILT_UNDEFINED;
298
const int FILT_RESET;
299
const int FILT_REALTIME;
301
const int FILT_CHANNEL_AFTERTOUCH;
302
const int FILT_POLY_AFTERTOUCH;
303
const int FILT_AFTERTOUCH;
304
const int FILT_PROGRAM;
305
const int FILT_CONTROL;
306
const int FILT_PITCHBEND;
308
const int FILT_SONG_POSITION;
309
const int FILT_SONG_SELECT;
312
const int pypmInvalidArgument;
317
const int pmHostError;
318
const int pmInvalidDeviceId;
319
const int pmInsufficientMemory;
320
const int pmBufferTooSmall;
321
const int pmBufferOverflow;
324
const int pmInternalError;
325
const int pmBufferMaxSize;
330
const char *GetErrorText(int err);
331
int GetDefaultInputDeviceID();
332
int GetDefaultOutputDeviceID();
334
PyObject *GetDeviceInfo(int device_id);
335
PmStream **new_Stream();
336
int OpenOutput(PmStream **midi, int device, int buflen, int latency);
337
int OpenInput(PmStream **midi, int device, int buflen);
338
int SetFilter(PmStream **midi, int filters);
339
int Channel(int chan);
340
int SetChannelMask(PmStream **midi, int mask);
341
int Abort(PmStream **midi);
342
int Close(PmStream **midi);
343
int Write(PmStream **midi, PyObject *data);
344
int WriteSysEx(PmStream **midi, int timestamp, PyObject *msg);
345
int Poll(PmStream **midi);
346
PyObject *Read(PmStream **midi);