~ubuntu-branches/ubuntu/oneiric/portmidi/oneiric-updates

« back to all changes in this revision

Viewing changes to pm_python/pypmbase.i

  • Committer: Bazaar Package Importer
  • Author(s): Daniel T Chen
  • Date: 2010-02-14 17:30:52 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20100214173052-uraknpxk6m8ogzf8
Tags: 1:200-0ubuntu1
* New upstream release
* debian/patches/: Refresh/rediff

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* pypm.i : interface file for SWIG
 
2
 *
 
3
 * Roger B. Dannenberg, Nov 2009
 
4
 *
 
5
 * created to interface portmidi to Python 3.1
 
6
 * (for Python 2.6, use Pyrex and pypm.pyx)
 
7
 */
 
8
 
 
9
%module pypm
 
10
%{
 
11
#define PDB 1 // debugging on if true
 
12
#define D if(PDB)
 
13
#if PDB
 
14
#include "stdio.h"
 
15
#endif
 
16
 
 
17
#include "portmidi.h"
 
18
#include "porttime.h"
 
19
 
 
20
#define PYPM_INVALID_ARGUMENT (pmHostError + 100)
 
21
 
 
22
int Initialize()
 
23
 
24
    int err = Pm_Initialize();
 
25
    if (err == pmNoError) Pt_Start(1, NULL, NULL);
 
26
    return err;
 
27
}
 
28
 
 
29
int Terminate() { Pt_Stop(); return Pm_Terminate(); }
 
30
 
 
31
int GetDefaultInputDeviceID() { return Pm_GetDefaultInputDeviceID(); }
 
32
 
 
33
int GetDefaultOutputDeviceID() { return Pm_GetDefaultOutputDeviceID(); }
 
34
 
 
35
int CountDevices() { return Pm_CountDevices(); }
 
36
 
 
37
PyObject *GetDeviceInfo(int device_id)
 
38
{
 
39
    PyObject *papi;
 
40
    PyObject *pdev;
 
41
    PyObject *pin;
 
42
    PyObject *pout;
 
43
    PyObject *popened;
 
44
    PyObject *rslt;
 
45
    const PmDeviceInfo *info = Pm_GetDeviceInfo(device_id);
 
46
    if (info) {
 
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);
 
58
    } else {
 
59
        rslt = Py_None;
 
60
        Py_INCREF(Py_None);
 
61
    }
 
62
    return rslt;
 
63
}
 
64
 
 
65
int Time() { return Pt_Time(); }
 
66
 
 
67
const char *GetErrorText(int err)
 
68
 
69
    if (err == PYPM_INVALID_ARGUMENT) {
 
70
        return "pypmbase: `Invalid argumnet'";
 
71
    }
 
72
    return Pm_GetErrorText(err); 
 
73
}
 
74
 
 
75
PmStream **new_Stream() 
 
76
{
 
77
    PmStream **s = (PmStream *) malloc(sizeof(PmStream *)); 
 
78
    D printf("new_Stream returns %p\n", s);
 
79
    return s;
 
80
}
 
81
 
 
82
int OpenOutput(PmStream **midi, int device, int buflen, int latency)
 
83
{
 
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);
 
87
    return rslt;
 
88
}
 
89
 
 
90
 
 
91
int OpenInput(PmStream **midi, int device, int buflen)
 
92
{
 
93
    return Pm_OpenInput(midi, device, NULL, buflen, &Pt_Time, NULL);
 
94
}
 
95
 
 
96
int SetFilter(PmStream **midi, int filters) 
 
97
{
 
98
    return Pm_SetFilter(*midi, filters); 
 
99
}
 
100
 
 
101
int Channel(int chan) { return Pm_Channel(chan); }
 
102
 
 
103
int SetChannelMask(PmStream **midi, int mask)
 
104
{
 
105
    return Pm_SetChannelMask(*midi, mask);
 
106
}
 
107
 
 
108
int Abort(PmStream **midi) { return Pm_Abort(*midi); }
 
109
 
 
110
int Close(PmStream **midi) 
 
111
{
 
112
    int rslt = pmBadPtr;
 
113
    if (midi) {
 
114
        rslt = Pm_Close(*midi);
 
115
        *midi = NULL;
 
116
        free(midi);
 
117
    }
 
118
    return rslt;
 
119
}
 
120
 
 
121
 
 
122
int Write(PmStream **midi, PyObject *data)
 
123
{
 
124
    int i, j, k;
 
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);
 
129
    if (len == -1) {
 
130
        return PYPM_INVALID_ARGUMENT;
 
131
    }
 
132
    j = 0; // message index
 
133
    for (i = 0; i < len; i++) {
 
134
        int bytes_len;
 
135
        int msg;
 
136
        PyObject *bytes;
 
137
        PyObject *timestamp;
 
138
        PyObject *message = PySequence_GetItem(data, i);
 
139
        if (!message) return PYPM_INVALID_ARGUMENT;
 
140
        bytes = PySequence_GetItem(message, 0);
 
141
        if (!bytes) {
 
142
            Py_DECREF(message);
 
143
            return PYPM_INVALID_ARGUMENT;
 
144
        }
 
145
        bytes_len = PyObject_Length(bytes);
 
146
        if (bytes_len <= 0 || bytes_len > 4) return PYPM_INVALID_ARGUMENT;
 
147
        msg = 0;
 
148
        k = 0;
 
149
        for (k = 0; k < bytes_len; k++) {
 
150
            PyObject *byte = PySequence_GetItem(bytes, k);
 
151
            if (!byte) {
 
152
                Py_DECREF(message);
 
153
                Py_DECREF(bytes);
 
154
                return PYPM_INVALID_ARGUMENT;
 
155
            }
 
156
            msg = msg + ((PyInt_AsLong(byte) & 0xFF) << (8 * k));
 
157
            if (PyErr_Occurred()) {
 
158
                Py_DECREF(message);
 
159
                Py_DECREF(bytes);
 
160
                Py_DECREF(byte);
 
161
                return PYPM_INVALID_ARGUMENT;
 
162
            } else {
 
163
                Py_DECREF(byte);
 
164
            }
 
165
        }
 
166
        Py_DECREF(bytes);
 
167
        buffer[j].message = msg;
 
168
        timestamp = PySequence_GetItem(message, 1);
 
169
        if (!timestamp) {
 
170
            Py_DECREF(message);
 
171
            return PYPM_INVALID_ARGUMENT;
 
172
        }
 
173
        buffer[j++].timestamp = PyInt_AsLong(timestamp);
 
174
        if (PyErr_Occurred()) {
 
175
            Py_DECREF(message);
 
176
            Py_DECREF(timestamp);
 
177
            return PYPM_INVALID_ARGUMENT;
 
178
        }
 
179
        Py_DECREF(timestamp);
 
180
        Py_DECREF(message);
 
181
        if (j >= PYPM_BUFFER_LEN) {
 
182
            int r;
 
183
            D printf(
 
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;
 
189
            j = 0;
 
190
        }
 
191
    }
 
192
    if (j > 0) {
 
193
        int r;
 
194
        D printf(
 
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);
 
199
        if (r < j) return r;
 
200
    }
 
201
    return i;
 
202
}
 
203
 
 
204
int WriteSysEx(PmStream **midi, int timestamp, PyObject *msg)
 
205
{
 
206
    unsigned char *bytes;
 
207
    int len;
 
208
    if (!PyBytes_Check(msg)) {
 
209
        D printf("WriteSysEx PyBytes_Check failure\n");
 
210
        D printf("Type: ");
 
211
        D PyObject_Print(msg->ob_type, stdout, 0);
 
212
        return PYPM_INVALID_ARGUMENT;
 
213
    }
 
214
    bytes = PyBytes_AsString(msg);
 
215
    if (!bytes) {
 
216
        D printf("WriteSysEx PyBytes_AsString failure\n");
 
217
        return PYPM_INVALID_ARGUMENT;
 
218
    }
 
219
    len = PyBytes_GET_SIZE(msg);
 
220
    // check for valid-looking sysex message
 
221
    if (len < 3 || *bytes != 0xF0 || bytes[len - 1] != 0xF7) {
 
222
        D printf(
 
223
        "WriteSysEx format failure: len %d, *bytes %x, bytes[len - 1] %x\n",
 
224
                 len, *bytes, bytes[len - 1]);
 
225
        return PYPM_INVALID_ARGUMENT;
 
226
    }
 
227
    return Pm_WriteSysEx(*midi, timestamp, bytes);
 
228
}
 
229
 
 
230
 
 
231
int Poll(PmStream **midi) { return Pm_Poll(*midi); }
 
232
 
 
233
PyObject *Read(PmStream **midi)
 
234
{
 
235
    int i, n;
 
236
    PyObject *num;
 
237
    PyObject *msg;
 
238
    PyObject *rslt;
 
239
    PmEvent buffer;
 
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.
 
248
    msg = PyList_New(4);
 
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);
 
255
    }
 
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);
 
260
    return rslt;
 
261
}
 
262
 
 
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;
 
284
 
 
285
const int pypmInvalidArgument = PYPM_INVALID_ARGUMENT;
 
286
 
 
287
%}
 
288
 
 
289
const int FILT_ACTIVE;
 
290
const int FILT_ACTIVE;
 
291
const int FILT_SYSEX;
 
292
const int FILT_CLOCK;
 
293
const int FILT_PLAY;
 
294
const int FILT_F9;
 
295
const int FILT_TICK;
 
296
const int FILT_FD;
 
297
const int FILT_UNDEFINED;
 
298
const int FILT_RESET;
 
299
const int FILT_REALTIME;
 
300
const int FILT_NOTE;
 
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;
 
307
const int FILT_MTC;
 
308
const int FILT_SONG_POSITION;
 
309
const int FILT_SONG_SELECT;
 
310
const int FILT_TUNE;
 
311
 
 
312
const int pypmInvalidArgument;
 
313
 
 
314
const int pmNoError;
 
315
const int pmNoData;
 
316
const int pmGotData;
 
317
const int pmHostError;
 
318
const int pmInvalidDeviceId;
 
319
const int pmInsufficientMemory;
 
320
const int pmBufferTooSmall;
 
321
const int pmBufferOverflow;
 
322
const int pmBadPtr;
 
323
const int pmBadData;
 
324
const int pmInternalError;
 
325
const int pmBufferMaxSize;
 
326
 
 
327
 
 
328
int Initialize();
 
329
int Terminate();
 
330
const char *GetErrorText(int err);
 
331
int GetDefaultInputDeviceID();
 
332
int GetDefaultOutputDeviceID();
 
333
int CountDevices();
 
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);
 
347
int Time();
 
348