1 | /* CD module -- interface to Mark Callow's and Roger Chickering's */
|
---|
2 | /* CD Audio Library (CD). */
|
---|
3 |
|
---|
4 | #include <sys/types.h>
|
---|
5 | #include <cdaudio.h>
|
---|
6 | #include "Python.h"
|
---|
7 |
|
---|
8 | #define NCALLBACKS 8
|
---|
9 |
|
---|
10 | typedef struct {
|
---|
11 | PyObject_HEAD
|
---|
12 | CDPLAYER *ob_cdplayer;
|
---|
13 | } cdplayerobject;
|
---|
14 |
|
---|
15 | static PyObject *CdError; /* exception cd.error */
|
---|
16 |
|
---|
17 | static PyObject *
|
---|
18 | CD_allowremoval(cdplayerobject *self, PyObject *args)
|
---|
19 | {
|
---|
20 | if (!PyArg_ParseTuple(args, ":allowremoval"))
|
---|
21 | return NULL;
|
---|
22 |
|
---|
23 | CDallowremoval(self->ob_cdplayer);
|
---|
24 |
|
---|
25 | Py_INCREF(Py_None);
|
---|
26 | return Py_None;
|
---|
27 | }
|
---|
28 |
|
---|
29 | static PyObject *
|
---|
30 | CD_preventremoval(cdplayerobject *self, PyObject *args)
|
---|
31 | {
|
---|
32 | if (!PyArg_ParseTuple(args, ":preventremoval"))
|
---|
33 | return NULL;
|
---|
34 |
|
---|
35 | CDpreventremoval(self->ob_cdplayer);
|
---|
36 |
|
---|
37 | Py_INCREF(Py_None);
|
---|
38 | return Py_None;
|
---|
39 | }
|
---|
40 |
|
---|
41 | static PyObject *
|
---|
42 | CD_bestreadsize(cdplayerobject *self, PyObject *args)
|
---|
43 | {
|
---|
44 | if (!PyArg_ParseTuple(args, ":bestreadsize"))
|
---|
45 | return NULL;
|
---|
46 |
|
---|
47 | return PyInt_FromLong((long) CDbestreadsize(self->ob_cdplayer));
|
---|
48 | }
|
---|
49 |
|
---|
50 | static PyObject *
|
---|
51 | CD_close(cdplayerobject *self, PyObject *args)
|
---|
52 | {
|
---|
53 | if (!PyArg_ParseTuple(args, ":close"))
|
---|
54 | return NULL;
|
---|
55 |
|
---|
56 | if (!CDclose(self->ob_cdplayer)) {
|
---|
57 | PyErr_SetFromErrno(CdError); /* XXX - ??? */
|
---|
58 | return NULL;
|
---|
59 | }
|
---|
60 | self->ob_cdplayer = NULL;
|
---|
61 |
|
---|
62 | Py_INCREF(Py_None);
|
---|
63 | return Py_None;
|
---|
64 | }
|
---|
65 |
|
---|
66 | static PyObject *
|
---|
67 | CD_eject(cdplayerobject *self, PyObject *args)
|
---|
68 | {
|
---|
69 | CDSTATUS status;
|
---|
70 |
|
---|
71 | if (!PyArg_ParseTuple(args, ":eject"))
|
---|
72 | return NULL;
|
---|
73 |
|
---|
74 | if (!CDeject(self->ob_cdplayer)) {
|
---|
75 | if (CDgetstatus(self->ob_cdplayer, &status) &&
|
---|
76 | status.state == CD_NODISC)
|
---|
77 | PyErr_SetString(CdError, "no disc in player");
|
---|
78 | else
|
---|
79 | PyErr_SetString(CdError, "eject failed");
|
---|
80 | return NULL;
|
---|
81 | }
|
---|
82 |
|
---|
83 | Py_INCREF(Py_None);
|
---|
84 | return Py_None;
|
---|
85 | }
|
---|
86 |
|
---|
87 | static PyObject *
|
---|
88 | CD_getstatus(cdplayerobject *self, PyObject *args)
|
---|
89 | {
|
---|
90 | CDSTATUS status;
|
---|
91 |
|
---|
92 | if (!PyArg_ParseTuple(args, ":getstatus"))
|
---|
93 | return NULL;
|
---|
94 |
|
---|
95 | if (!CDgetstatus(self->ob_cdplayer, &status)) {
|
---|
96 | PyErr_SetFromErrno(CdError); /* XXX - ??? */
|
---|
97 | return NULL;
|
---|
98 | }
|
---|
99 |
|
---|
100 | return Py_BuildValue("(ii(iii)(iii)(iii)iiii)", status.state,
|
---|
101 | status.track, status.min, status.sec, status.frame,
|
---|
102 | status.abs_min, status.abs_sec, status.abs_frame,
|
---|
103 | status.total_min, status.total_sec, status.total_frame,
|
---|
104 | status.first, status.last, status.scsi_audio,
|
---|
105 | status.cur_block);
|
---|
106 | }
|
---|
107 |
|
---|
108 | static PyObject *
|
---|
109 | CD_gettrackinfo(cdplayerobject *self, PyObject *args)
|
---|
110 | {
|
---|
111 | int track;
|
---|
112 | CDTRACKINFO info;
|
---|
113 | CDSTATUS status;
|
---|
114 |
|
---|
115 | if (!PyArg_ParseTuple(args, "i:gettrackinfo", &track))
|
---|
116 | return NULL;
|
---|
117 |
|
---|
118 | if (!CDgettrackinfo(self->ob_cdplayer, track, &info)) {
|
---|
119 | if (CDgetstatus(self->ob_cdplayer, &status) &&
|
---|
120 | status.state == CD_NODISC)
|
---|
121 | PyErr_SetString(CdError, "no disc in player");
|
---|
122 | else
|
---|
123 | PyErr_SetString(CdError, "gettrackinfo failed");
|
---|
124 | return NULL;
|
---|
125 | }
|
---|
126 |
|
---|
127 | return Py_BuildValue("((iii)(iii))",
|
---|
128 | info.start_min, info.start_sec, info.start_frame,
|
---|
129 | info.total_min, info.total_sec, info.total_frame);
|
---|
130 | }
|
---|
131 |
|
---|
132 | static PyObject *
|
---|
133 | CD_msftoblock(cdplayerobject *self, PyObject *args)
|
---|
134 | {
|
---|
135 | int min, sec, frame;
|
---|
136 |
|
---|
137 | if (!PyArg_ParseTuple(args, "iii:msftoblock", &min, &sec, &frame))
|
---|
138 | return NULL;
|
---|
139 |
|
---|
140 | return PyInt_FromLong((long) CDmsftoblock(self->ob_cdplayer,
|
---|
141 | min, sec, frame));
|
---|
142 | }
|
---|
143 |
|
---|
144 | static PyObject *
|
---|
145 | CD_play(cdplayerobject *self, PyObject *args)
|
---|
146 | {
|
---|
147 | int start, play;
|
---|
148 | CDSTATUS status;
|
---|
149 |
|
---|
150 | if (!PyArg_ParseTuple(args, "ii:play", &start, &play))
|
---|
151 | return NULL;
|
---|
152 |
|
---|
153 | if (!CDplay(self->ob_cdplayer, start, play)) {
|
---|
154 | if (CDgetstatus(self->ob_cdplayer, &status) &&
|
---|
155 | status.state == CD_NODISC)
|
---|
156 | PyErr_SetString(CdError, "no disc in player");
|
---|
157 | else
|
---|
158 | PyErr_SetString(CdError, "play failed");
|
---|
159 | return NULL;
|
---|
160 | }
|
---|
161 |
|
---|
162 | Py_INCREF(Py_None);
|
---|
163 | return Py_None;
|
---|
164 | }
|
---|
165 |
|
---|
166 | static PyObject *
|
---|
167 | CD_playabs(cdplayerobject *self, PyObject *args)
|
---|
168 | {
|
---|
169 | int min, sec, frame, play;
|
---|
170 | CDSTATUS status;
|
---|
171 |
|
---|
172 | if (!PyArg_ParseTuple(args, "iiii:playabs", &min, &sec, &frame, &play))
|
---|
173 | return NULL;
|
---|
174 |
|
---|
175 | if (!CDplayabs(self->ob_cdplayer, min, sec, frame, play)) {
|
---|
176 | if (CDgetstatus(self->ob_cdplayer, &status) &&
|
---|
177 | status.state == CD_NODISC)
|
---|
178 | PyErr_SetString(CdError, "no disc in player");
|
---|
179 | else
|
---|
180 | PyErr_SetString(CdError, "playabs failed");
|
---|
181 | return NULL;
|
---|
182 | }
|
---|
183 |
|
---|
184 | Py_INCREF(Py_None);
|
---|
185 | return Py_None;
|
---|
186 | }
|
---|
187 |
|
---|
188 | static PyObject *
|
---|
189 | CD_playtrack(cdplayerobject *self, PyObject *args)
|
---|
190 | {
|
---|
191 | int start, play;
|
---|
192 | CDSTATUS status;
|
---|
193 |
|
---|
194 | if (!PyArg_ParseTuple(args, "ii:playtrack", &start, &play))
|
---|
195 | return NULL;
|
---|
196 |
|
---|
197 | if (!CDplaytrack(self->ob_cdplayer, start, play)) {
|
---|
198 | if (CDgetstatus(self->ob_cdplayer, &status) &&
|
---|
199 | status.state == CD_NODISC)
|
---|
200 | PyErr_SetString(CdError, "no disc in player");
|
---|
201 | else
|
---|
202 | PyErr_SetString(CdError, "playtrack failed");
|
---|
203 | return NULL;
|
---|
204 | }
|
---|
205 |
|
---|
206 | Py_INCREF(Py_None);
|
---|
207 | return Py_None;
|
---|
208 | }
|
---|
209 |
|
---|
210 | static PyObject *
|
---|
211 | CD_playtrackabs(cdplayerobject *self, PyObject *args)
|
---|
212 | {
|
---|
213 | int track, min, sec, frame, play;
|
---|
214 | CDSTATUS status;
|
---|
215 |
|
---|
216 | if (!PyArg_ParseTuple(args, "iiiii:playtrackabs", &track, &min, &sec,
|
---|
217 | &frame, &play))
|
---|
218 | return NULL;
|
---|
219 |
|
---|
220 | if (!CDplaytrackabs(self->ob_cdplayer, track, min, sec, frame, play)) {
|
---|
221 | if (CDgetstatus(self->ob_cdplayer, &status) &&
|
---|
222 | status.state == CD_NODISC)
|
---|
223 | PyErr_SetString(CdError, "no disc in player");
|
---|
224 | else
|
---|
225 | PyErr_SetString(CdError, "playtrackabs failed");
|
---|
226 | return NULL;
|
---|
227 | }
|
---|
228 |
|
---|
229 | Py_INCREF(Py_None);
|
---|
230 | return Py_None;
|
---|
231 | }
|
---|
232 |
|
---|
233 | static PyObject *
|
---|
234 | CD_readda(cdplayerobject *self, PyObject *args)
|
---|
235 | {
|
---|
236 | int numframes, n;
|
---|
237 | PyObject *result;
|
---|
238 |
|
---|
239 | if (!PyArg_ParseTuple(args, "i:readda", &numframes))
|
---|
240 | return NULL;
|
---|
241 |
|
---|
242 | result = PyString_FromStringAndSize(NULL, numframes * sizeof(CDFRAME));
|
---|
243 | if (result == NULL)
|
---|
244 | return NULL;
|
---|
245 |
|
---|
246 | n = CDreadda(self->ob_cdplayer,
|
---|
247 | (CDFRAME *) PyString_AsString(result), numframes);
|
---|
248 | if (n == -1) {
|
---|
249 | Py_DECREF(result);
|
---|
250 | PyErr_SetFromErrno(CdError);
|
---|
251 | return NULL;
|
---|
252 | }
|
---|
253 | if (n < numframes)
|
---|
254 | _PyString_Resize(&result, n * sizeof(CDFRAME));
|
---|
255 |
|
---|
256 | return result;
|
---|
257 | }
|
---|
258 |
|
---|
259 | static PyObject *
|
---|
260 | CD_seek(cdplayerobject *self, PyObject *args)
|
---|
261 | {
|
---|
262 | int min, sec, frame;
|
---|
263 | long PyTryBlock;
|
---|
264 |
|
---|
265 | if (!PyArg_ParseTuple(args, "iii:seek", &min, &sec, &frame))
|
---|
266 | return NULL;
|
---|
267 |
|
---|
268 | PyTryBlock = CDseek(self->ob_cdplayer, min, sec, frame);
|
---|
269 | if (PyTryBlock == -1) {
|
---|
270 | PyErr_SetFromErrno(CdError);
|
---|
271 | return NULL;
|
---|
272 | }
|
---|
273 |
|
---|
274 | return PyInt_FromLong(PyTryBlock);
|
---|
275 | }
|
---|
276 |
|
---|
277 | static PyObject *
|
---|
278 | CD_seektrack(cdplayerobject *self, PyObject *args)
|
---|
279 | {
|
---|
280 | int track;
|
---|
281 | long PyTryBlock;
|
---|
282 |
|
---|
283 | if (!PyArg_ParseTuple(args, "i:seektrack", &track))
|
---|
284 | return NULL;
|
---|
285 |
|
---|
286 | PyTryBlock = CDseektrack(self->ob_cdplayer, track);
|
---|
287 | if (PyTryBlock == -1) {
|
---|
288 | PyErr_SetFromErrno(CdError);
|
---|
289 | return NULL;
|
---|
290 | }
|
---|
291 |
|
---|
292 | return PyInt_FromLong(PyTryBlock);
|
---|
293 | }
|
---|
294 |
|
---|
295 | static PyObject *
|
---|
296 | CD_seekblock(cdplayerobject *self, PyObject *args)
|
---|
297 | {
|
---|
298 | unsigned long PyTryBlock;
|
---|
299 |
|
---|
300 | if (!PyArg_ParseTuple(args, "l:seekblock", &PyTryBlock))
|
---|
301 | return NULL;
|
---|
302 |
|
---|
303 | PyTryBlock = CDseekblock(self->ob_cdplayer, PyTryBlock);
|
---|
304 | if (PyTryBlock == (unsigned long) -1) {
|
---|
305 | PyErr_SetFromErrno(CdError);
|
---|
306 | return NULL;
|
---|
307 | }
|
---|
308 |
|
---|
309 | return PyInt_FromLong(PyTryBlock);
|
---|
310 | }
|
---|
311 |
|
---|
312 | static PyObject *
|
---|
313 | CD_stop(cdplayerobject *self, PyObject *args)
|
---|
314 | {
|
---|
315 | CDSTATUS status;
|
---|
316 |
|
---|
317 | if (!PyArg_ParseTuple(args, ":stop"))
|
---|
318 | return NULL;
|
---|
319 |
|
---|
320 | if (!CDstop(self->ob_cdplayer)) {
|
---|
321 | if (CDgetstatus(self->ob_cdplayer, &status) &&
|
---|
322 | status.state == CD_NODISC)
|
---|
323 | PyErr_SetString(CdError, "no disc in player");
|
---|
324 | else
|
---|
325 | PyErr_SetString(CdError, "stop failed");
|
---|
326 | return NULL;
|
---|
327 | }
|
---|
328 |
|
---|
329 | Py_INCREF(Py_None);
|
---|
330 | return Py_None;
|
---|
331 | }
|
---|
332 |
|
---|
333 | static PyObject *
|
---|
334 | CD_togglepause(cdplayerobject *self, PyObject *args)
|
---|
335 | {
|
---|
336 | CDSTATUS status;
|
---|
337 |
|
---|
338 | if (!PyArg_ParseTuple(args, ":togglepause"))
|
---|
339 | return NULL;
|
---|
340 |
|
---|
341 | if (!CDtogglepause(self->ob_cdplayer)) {
|
---|
342 | if (CDgetstatus(self->ob_cdplayer, &status) &&
|
---|
343 | status.state == CD_NODISC)
|
---|
344 | PyErr_SetString(CdError, "no disc in player");
|
---|
345 | else
|
---|
346 | PyErr_SetString(CdError, "togglepause failed");
|
---|
347 | return NULL;
|
---|
348 | }
|
---|
349 |
|
---|
350 | Py_INCREF(Py_None);
|
---|
351 | return Py_None;
|
---|
352 | }
|
---|
353 |
|
---|
354 | static PyMethodDef cdplayer_methods[] = {
|
---|
355 | {"allowremoval", (PyCFunction)CD_allowremoval, METH_VARARGS},
|
---|
356 | {"bestreadsize", (PyCFunction)CD_bestreadsize, METH_VARARGS},
|
---|
357 | {"close", (PyCFunction)CD_close, METH_VARARGS},
|
---|
358 | {"eject", (PyCFunction)CD_eject, METH_VARARGS},
|
---|
359 | {"getstatus", (PyCFunction)CD_getstatus, METH_VARARGS},
|
---|
360 | {"gettrackinfo", (PyCFunction)CD_gettrackinfo, METH_VARARGS},
|
---|
361 | {"msftoblock", (PyCFunction)CD_msftoblock, METH_VARARGS},
|
---|
362 | {"play", (PyCFunction)CD_play, METH_VARARGS},
|
---|
363 | {"playabs", (PyCFunction)CD_playabs, METH_VARARGS},
|
---|
364 | {"playtrack", (PyCFunction)CD_playtrack, METH_VARARGS},
|
---|
365 | {"playtrackabs", (PyCFunction)CD_playtrackabs, METH_VARARGS},
|
---|
366 | {"preventremoval", (PyCFunction)CD_preventremoval, METH_VARARGS},
|
---|
367 | {"readda", (PyCFunction)CD_readda, METH_VARARGS},
|
---|
368 | {"seek", (PyCFunction)CD_seek, METH_VARARGS},
|
---|
369 | {"seekblock", (PyCFunction)CD_seekblock, METH_VARARGS},
|
---|
370 | {"seektrack", (PyCFunction)CD_seektrack, METH_VARARGS},
|
---|
371 | {"stop", (PyCFunction)CD_stop, METH_VARARGS},
|
---|
372 | {"togglepause", (PyCFunction)CD_togglepause, METH_VARARGS},
|
---|
373 | {NULL, NULL} /* sentinel */
|
---|
374 | };
|
---|
375 |
|
---|
376 | static void
|
---|
377 | cdplayer_dealloc(cdplayerobject *self)
|
---|
378 | {
|
---|
379 | if (self->ob_cdplayer != NULL)
|
---|
380 | CDclose(self->ob_cdplayer);
|
---|
381 | PyObject_Del(self);
|
---|
382 | }
|
---|
383 |
|
---|
384 | static PyObject *
|
---|
385 | cdplayer_getattr(cdplayerobject *self, char *name)
|
---|
386 | {
|
---|
387 | if (self->ob_cdplayer == NULL) {
|
---|
388 | PyErr_SetString(PyExc_RuntimeError, "no player active");
|
---|
389 | return NULL;
|
---|
390 | }
|
---|
391 | return Py_FindMethod(cdplayer_methods, (PyObject *)self, name);
|
---|
392 | }
|
---|
393 |
|
---|
394 | PyTypeObject CdPlayertype = {
|
---|
395 | PyObject_HEAD_INIT(&PyType_Type)
|
---|
396 | 0, /*ob_size*/
|
---|
397 | "cd.cdplayer", /*tp_name*/
|
---|
398 | sizeof(cdplayerobject), /*tp_size*/
|
---|
399 | 0, /*tp_itemsize*/
|
---|
400 | /* methods */
|
---|
401 | (destructor)cdplayer_dealloc, /*tp_dealloc*/
|
---|
402 | 0, /*tp_print*/
|
---|
403 | (getattrfunc)cdplayer_getattr, /*tp_getattr*/
|
---|
404 | 0, /*tp_setattr*/
|
---|
405 | 0, /*tp_compare*/
|
---|
406 | 0, /*tp_repr*/
|
---|
407 | };
|
---|
408 |
|
---|
409 | static PyObject *
|
---|
410 | newcdplayerobject(CDPLAYER *cdp)
|
---|
411 | {
|
---|
412 | cdplayerobject *p;
|
---|
413 |
|
---|
414 | p = PyObject_New(cdplayerobject, &CdPlayertype);
|
---|
415 | if (p == NULL)
|
---|
416 | return NULL;
|
---|
417 | p->ob_cdplayer = cdp;
|
---|
418 | return (PyObject *) p;
|
---|
419 | }
|
---|
420 |
|
---|
421 | static PyObject *
|
---|
422 | CD_open(PyObject *self, PyObject *args)
|
---|
423 | {
|
---|
424 | char *dev, *direction;
|
---|
425 | CDPLAYER *cdp;
|
---|
426 |
|
---|
427 | /*
|
---|
428 | * Variable number of args.
|
---|
429 | * First defaults to "None", second defaults to "r".
|
---|
430 | */
|
---|
431 | dev = NULL;
|
---|
432 | direction = "r";
|
---|
433 | if (!PyArg_ParseTuple(args, "|zs:open", &dev, &direction))
|
---|
434 | return NULL;
|
---|
435 |
|
---|
436 | cdp = CDopen(dev, direction);
|
---|
437 | if (cdp == NULL) {
|
---|
438 | PyErr_SetFromErrno(CdError);
|
---|
439 | return NULL;
|
---|
440 | }
|
---|
441 |
|
---|
442 | return newcdplayerobject(cdp);
|
---|
443 | }
|
---|
444 |
|
---|
445 | typedef struct {
|
---|
446 | PyObject_HEAD
|
---|
447 | CDPARSER *ob_cdparser;
|
---|
448 | struct {
|
---|
449 | PyObject *ob_cdcallback;
|
---|
450 | PyObject *ob_cdcallbackarg;
|
---|
451 | } ob_cdcallbacks[NCALLBACKS];
|
---|
452 | } cdparserobject;
|
---|
453 |
|
---|
454 | static void
|
---|
455 | CD_callback(void *arg, CDDATATYPES type, void *data)
|
---|
456 | {
|
---|
457 | PyObject *result, *args, *v = NULL;
|
---|
458 | char *p;
|
---|
459 | int i;
|
---|
460 | cdparserobject *self;
|
---|
461 |
|
---|
462 | self = (cdparserobject *) arg;
|
---|
463 | args = PyTuple_New(3);
|
---|
464 | if (args == NULL)
|
---|
465 | return;
|
---|
466 | Py_INCREF(self->ob_cdcallbacks[type].ob_cdcallbackarg);
|
---|
467 | PyTuple_SetItem(args, 0, self->ob_cdcallbacks[type].ob_cdcallbackarg);
|
---|
468 | PyTuple_SetItem(args, 1, PyInt_FromLong((long) type));
|
---|
469 | switch (type) {
|
---|
470 | case cd_audio:
|
---|
471 | v = PyString_FromStringAndSize(data, CDDA_DATASIZE);
|
---|
472 | break;
|
---|
473 | case cd_pnum:
|
---|
474 | case cd_index:
|
---|
475 | v = PyInt_FromLong(((CDPROGNUM *) data)->value);
|
---|
476 | break;
|
---|
477 | case cd_ptime:
|
---|
478 | case cd_atime:
|
---|
479 | #define ptr ((struct cdtimecode *) data)
|
---|
480 | v = Py_BuildValue("(iii)",
|
---|
481 | ptr->mhi * 10 + ptr->mlo,
|
---|
482 | ptr->shi * 10 + ptr->slo,
|
---|
483 | ptr->fhi * 10 + ptr->flo);
|
---|
484 | #undef ptr
|
---|
485 | break;
|
---|
486 | case cd_catalog:
|
---|
487 | v = PyString_FromStringAndSize(NULL, 13);
|
---|
488 | p = PyString_AsString(v);
|
---|
489 | for (i = 0; i < 13; i++)
|
---|
490 | *p++ = ((char *) data)[i] + '0';
|
---|
491 | break;
|
---|
492 | case cd_ident:
|
---|
493 | #define ptr ((struct cdident *) data)
|
---|
494 | v = PyString_FromStringAndSize(NULL, 12);
|
---|
495 | p = PyString_AsString(v);
|
---|
496 | CDsbtoa(p, ptr->country, 2);
|
---|
497 | p += 2;
|
---|
498 | CDsbtoa(p, ptr->owner, 3);
|
---|
499 | p += 3;
|
---|
500 | *p++ = ptr->year[0] + '0';
|
---|
501 | *p++ = ptr->year[1] + '0';
|
---|
502 | *p++ = ptr->serial[0] + '0';
|
---|
503 | *p++ = ptr->serial[1] + '0';
|
---|
504 | *p++ = ptr->serial[2] + '0';
|
---|
505 | *p++ = ptr->serial[3] + '0';
|
---|
506 | *p++ = ptr->serial[4] + '0';
|
---|
507 | #undef ptr
|
---|
508 | break;
|
---|
509 | case cd_control:
|
---|
510 | v = PyInt_FromLong((long) *((unchar *) data));
|
---|
511 | break;
|
---|
512 | }
|
---|
513 | PyTuple_SetItem(args, 2, v);
|
---|
514 | if (PyErr_Occurred()) {
|
---|
515 | Py_DECREF(args);
|
---|
516 | return;
|
---|
517 | }
|
---|
518 |
|
---|
519 | result = PyEval_CallObject(self->ob_cdcallbacks[type].ob_cdcallback,
|
---|
520 | args);
|
---|
521 | Py_DECREF(args);
|
---|
522 | Py_XDECREF(result);
|
---|
523 | }
|
---|
524 |
|
---|
525 | static PyObject *
|
---|
526 | CD_deleteparser(cdparserobject *self, PyObject *args)
|
---|
527 | {
|
---|
528 | int i;
|
---|
529 |
|
---|
530 | if (!PyArg_ParseTuple(args, ":deleteparser"))
|
---|
531 | return NULL;
|
---|
532 |
|
---|
533 | CDdeleteparser(self->ob_cdparser);
|
---|
534 | self->ob_cdparser = NULL;
|
---|
535 |
|
---|
536 | /* no sense in keeping the callbacks, so remove them */
|
---|
537 | for (i = 0; i < NCALLBACKS; i++) {
|
---|
538 | Py_XDECREF(self->ob_cdcallbacks[i].ob_cdcallback);
|
---|
539 | self->ob_cdcallbacks[i].ob_cdcallback = NULL;
|
---|
540 | Py_XDECREF(self->ob_cdcallbacks[i].ob_cdcallbackarg);
|
---|
541 | self->ob_cdcallbacks[i].ob_cdcallbackarg = NULL;
|
---|
542 | }
|
---|
543 |
|
---|
544 | Py_INCREF(Py_None);
|
---|
545 | return Py_None;
|
---|
546 | }
|
---|
547 |
|
---|
548 | static PyObject *
|
---|
549 | CD_parseframe(cdparserobject *self, PyObject *args)
|
---|
550 | {
|
---|
551 | char *cdfp;
|
---|
552 | int length;
|
---|
553 | CDFRAME *p;
|
---|
554 |
|
---|
555 | if (!PyArg_ParseTuple(args, "s#:parseframe", &cdfp, &length))
|
---|
556 | return NULL;
|
---|
557 |
|
---|
558 | if (length % sizeof(CDFRAME) != 0) {
|
---|
559 | PyErr_SetString(PyExc_TypeError, "bad length");
|
---|
560 | return NULL;
|
---|
561 | }
|
---|
562 |
|
---|
563 | p = (CDFRAME *) cdfp;
|
---|
564 | while (length > 0) {
|
---|
565 | CDparseframe(self->ob_cdparser, p);
|
---|
566 | length -= sizeof(CDFRAME);
|
---|
567 | p++;
|
---|
568 | if (PyErr_Occurred())
|
---|
569 | return NULL;
|
---|
570 | }
|
---|
571 |
|
---|
572 | Py_INCREF(Py_None);
|
---|
573 | return Py_None;
|
---|
574 | }
|
---|
575 |
|
---|
576 | static PyObject *
|
---|
577 | CD_removecallback(cdparserobject *self, PyObject *args)
|
---|
578 | {
|
---|
579 | int type;
|
---|
580 |
|
---|
581 | if (!PyArg_ParseTuple(args, "i:removecallback", &type))
|
---|
582 | return NULL;
|
---|
583 |
|
---|
584 | if (type < 0 || type >= NCALLBACKS) {
|
---|
585 | PyErr_SetString(PyExc_TypeError, "bad type");
|
---|
586 | return NULL;
|
---|
587 | }
|
---|
588 |
|
---|
589 | CDremovecallback(self->ob_cdparser, (CDDATATYPES) type);
|
---|
590 |
|
---|
591 | Py_XDECREF(self->ob_cdcallbacks[type].ob_cdcallback);
|
---|
592 | self->ob_cdcallbacks[type].ob_cdcallback = NULL;
|
---|
593 |
|
---|
594 | Py_XDECREF(self->ob_cdcallbacks[type].ob_cdcallbackarg);
|
---|
595 | self->ob_cdcallbacks[type].ob_cdcallbackarg = NULL;
|
---|
596 |
|
---|
597 | Py_INCREF(Py_None);
|
---|
598 | return Py_None;
|
---|
599 | }
|
---|
600 |
|
---|
601 | static PyObject *
|
---|
602 | CD_resetparser(cdparserobject *self, PyObject *args)
|
---|
603 | {
|
---|
604 | if (!PyArg_ParseTuple(args, ":resetparser"))
|
---|
605 | return NULL;
|
---|
606 |
|
---|
607 | CDresetparser(self->ob_cdparser);
|
---|
608 |
|
---|
609 | Py_INCREF(Py_None);
|
---|
610 | return Py_None;
|
---|
611 | }
|
---|
612 |
|
---|
613 | static PyObject *
|
---|
614 | CD_addcallback(cdparserobject *self, PyObject *args)
|
---|
615 | {
|
---|
616 | int type;
|
---|
617 | PyObject *func, *funcarg;
|
---|
618 |
|
---|
619 | /* XXX - more work here */
|
---|
620 | if (!PyArg_ParseTuple(args, "iOO:addcallback", &type, &func, &funcarg))
|
---|
621 | return NULL;
|
---|
622 |
|
---|
623 | if (type < 0 || type >= NCALLBACKS) {
|
---|
624 | PyErr_SetString(PyExc_TypeError, "argument out of range");
|
---|
625 | return NULL;
|
---|
626 | }
|
---|
627 |
|
---|
628 | #ifdef CDsetcallback
|
---|
629 | CDaddcallback(self->ob_cdparser, (CDDATATYPES) type, CD_callback,
|
---|
630 | (void *) self);
|
---|
631 | #else
|
---|
632 | CDsetcallback(self->ob_cdparser, (CDDATATYPES) type, CD_callback,
|
---|
633 | (void *) self);
|
---|
634 | #endif
|
---|
635 | Py_XDECREF(self->ob_cdcallbacks[type].ob_cdcallback);
|
---|
636 | Py_INCREF(func);
|
---|
637 | self->ob_cdcallbacks[type].ob_cdcallback = func;
|
---|
638 | Py_XDECREF(self->ob_cdcallbacks[type].ob_cdcallbackarg);
|
---|
639 | Py_INCREF(funcarg);
|
---|
640 | self->ob_cdcallbacks[type].ob_cdcallbackarg = funcarg;
|
---|
641 |
|
---|
642 | /*
|
---|
643 | if (type == cd_audio) {
|
---|
644 | sigfpe_[_UNDERFL].repls = _ZERO;
|
---|
645 | handle_sigfpes(_ON, _EN_UNDERFL, NULL,
|
---|
646 | _ABORT_ON_ERROR, NULL);
|
---|
647 | }
|
---|
648 | */
|
---|
649 |
|
---|
650 | Py_INCREF(Py_None);
|
---|
651 | return Py_None;
|
---|
652 | }
|
---|
653 |
|
---|
654 | static PyMethodDef cdparser_methods[] = {
|
---|
655 | {"addcallback", (PyCFunction)CD_addcallback, METH_VARARGS},
|
---|
656 | {"deleteparser", (PyCFunction)CD_deleteparser, METH_VARARGS},
|
---|
657 | {"parseframe", (PyCFunction)CD_parseframe, METH_VARARGS},
|
---|
658 | {"removecallback", (PyCFunction)CD_removecallback, METH_VARARGS},
|
---|
659 | {"resetparser", (PyCFunction)CD_resetparser, METH_VARARGS},
|
---|
660 | /* backward compatibility */
|
---|
661 | {"setcallback", (PyCFunction)CD_addcallback, METH_VARARGS},
|
---|
662 | {NULL, NULL} /* sentinel */
|
---|
663 | };
|
---|
664 |
|
---|
665 | static void
|
---|
666 | cdparser_dealloc(cdparserobject *self)
|
---|
667 | {
|
---|
668 | int i;
|
---|
669 |
|
---|
670 | for (i = 0; i < NCALLBACKS; i++) {
|
---|
671 | Py_XDECREF(self->ob_cdcallbacks[i].ob_cdcallback);
|
---|
672 | self->ob_cdcallbacks[i].ob_cdcallback = NULL;
|
---|
673 | Py_XDECREF(self->ob_cdcallbacks[i].ob_cdcallbackarg);
|
---|
674 | self->ob_cdcallbacks[i].ob_cdcallbackarg = NULL;
|
---|
675 | }
|
---|
676 | CDdeleteparser(self->ob_cdparser);
|
---|
677 | PyObject_Del(self);
|
---|
678 | }
|
---|
679 |
|
---|
680 | static PyObject *
|
---|
681 | cdparser_getattr(cdparserobject *self, char *name)
|
---|
682 | {
|
---|
683 | if (self->ob_cdparser == NULL) {
|
---|
684 | PyErr_SetString(PyExc_RuntimeError, "no parser active");
|
---|
685 | return NULL;
|
---|
686 | }
|
---|
687 |
|
---|
688 | return Py_FindMethod(cdparser_methods, (PyObject *)self, name);
|
---|
689 | }
|
---|
690 |
|
---|
691 | PyTypeObject CdParsertype = {
|
---|
692 | PyObject_HEAD_INIT(&PyType_Type)
|
---|
693 | 0, /*ob_size*/
|
---|
694 | "cd.cdparser", /*tp_name*/
|
---|
695 | sizeof(cdparserobject), /*tp_size*/
|
---|
696 | 0, /*tp_itemsize*/
|
---|
697 | /* methods */
|
---|
698 | (destructor)cdparser_dealloc, /*tp_dealloc*/
|
---|
699 | 0, /*tp_print*/
|
---|
700 | (getattrfunc)cdparser_getattr, /*tp_getattr*/
|
---|
701 | 0, /*tp_setattr*/
|
---|
702 | 0, /*tp_compare*/
|
---|
703 | 0, /*tp_repr*/
|
---|
704 | };
|
---|
705 |
|
---|
706 | static PyObject *
|
---|
707 | newcdparserobject(CDPARSER *cdp)
|
---|
708 | {
|
---|
709 | cdparserobject *p;
|
---|
710 | int i;
|
---|
711 |
|
---|
712 | p = PyObject_New(cdparserobject, &CdParsertype);
|
---|
713 | if (p == NULL)
|
---|
714 | return NULL;
|
---|
715 | p->ob_cdparser = cdp;
|
---|
716 | for (i = 0; i < NCALLBACKS; i++) {
|
---|
717 | p->ob_cdcallbacks[i].ob_cdcallback = NULL;
|
---|
718 | p->ob_cdcallbacks[i].ob_cdcallbackarg = NULL;
|
---|
719 | }
|
---|
720 | return (PyObject *) p;
|
---|
721 | }
|
---|
722 |
|
---|
723 | static PyObject *
|
---|
724 | CD_createparser(PyObject *self, PyObject *args)
|
---|
725 | {
|
---|
726 | CDPARSER *cdp;
|
---|
727 |
|
---|
728 | if (!PyArg_ParseTuple(args, ":createparser"))
|
---|
729 | return NULL;
|
---|
730 | cdp = CDcreateparser();
|
---|
731 | if (cdp == NULL) {
|
---|
732 | PyErr_SetString(CdError, "createparser failed");
|
---|
733 | return NULL;
|
---|
734 | }
|
---|
735 |
|
---|
736 | return newcdparserobject(cdp);
|
---|
737 | }
|
---|
738 |
|
---|
739 | static PyObject *
|
---|
740 | CD_msftoframe(PyObject *self, PyObject *args)
|
---|
741 | {
|
---|
742 | int min, sec, frame;
|
---|
743 |
|
---|
744 | if (!PyArg_ParseTuple(args, "iii:msftoframe", &min, &sec, &frame))
|
---|
745 | return NULL;
|
---|
746 |
|
---|
747 | return PyInt_FromLong((long) CDmsftoframe(min, sec, frame));
|
---|
748 | }
|
---|
749 |
|
---|
750 | static PyMethodDef CD_methods[] = {
|
---|
751 | {"open", (PyCFunction)CD_open, METH_VARARGS},
|
---|
752 | {"createparser", (PyCFunction)CD_createparser, METH_VARARGS},
|
---|
753 | {"msftoframe", (PyCFunction)CD_msftoframe, METH_VARARGS},
|
---|
754 | {NULL, NULL} /* Sentinel */
|
---|
755 | };
|
---|
756 |
|
---|
757 | void
|
---|
758 | initcd(void)
|
---|
759 | {
|
---|
760 | PyObject *m, *d;
|
---|
761 |
|
---|
762 | if (PyErr_WarnPy3k("the cd module has been removed in "
|
---|
763 | "Python 3.0", 2) < 0)
|
---|
764 | return;
|
---|
765 |
|
---|
766 | m = Py_InitModule("cd", CD_methods);
|
---|
767 | if (m == NULL)
|
---|
768 | return;
|
---|
769 | d = PyModule_GetDict(m);
|
---|
770 |
|
---|
771 | CdError = PyErr_NewException("cd.error", NULL, NULL);
|
---|
772 | PyDict_SetItemString(d, "error", CdError);
|
---|
773 |
|
---|
774 | /* Identifiers for the different types of callbacks from the parser */
|
---|
775 | PyDict_SetItemString(d, "audio", PyInt_FromLong((long) cd_audio));
|
---|
776 | PyDict_SetItemString(d, "pnum", PyInt_FromLong((long) cd_pnum));
|
---|
777 | PyDict_SetItemString(d, "index", PyInt_FromLong((long) cd_index));
|
---|
778 | PyDict_SetItemString(d, "ptime", PyInt_FromLong((long) cd_ptime));
|
---|
779 | PyDict_SetItemString(d, "atime", PyInt_FromLong((long) cd_atime));
|
---|
780 | PyDict_SetItemString(d, "catalog", PyInt_FromLong((long) cd_catalog));
|
---|
781 | PyDict_SetItemString(d, "ident", PyInt_FromLong((long) cd_ident));
|
---|
782 | PyDict_SetItemString(d, "control", PyInt_FromLong((long) cd_control));
|
---|
783 |
|
---|
784 | /* Block size information for digital audio data */
|
---|
785 | PyDict_SetItemString(d, "DATASIZE",
|
---|
786 | PyInt_FromLong((long) CDDA_DATASIZE));
|
---|
787 | PyDict_SetItemString(d, "BLOCKSIZE",
|
---|
788 | PyInt_FromLong((long) CDDA_BLOCKSIZE));
|
---|
789 |
|
---|
790 | /* Possible states for the cd player */
|
---|
791 | PyDict_SetItemString(d, "ERROR", PyInt_FromLong((long) CD_ERROR));
|
---|
792 | PyDict_SetItemString(d, "NODISC", PyInt_FromLong((long) CD_NODISC));
|
---|
793 | PyDict_SetItemString(d, "READY", PyInt_FromLong((long) CD_READY));
|
---|
794 | PyDict_SetItemString(d, "PLAYING", PyInt_FromLong((long) CD_PLAYING));
|
---|
795 | PyDict_SetItemString(d, "PAUSED", PyInt_FromLong((long) CD_PAUSED));
|
---|
796 | PyDict_SetItemString(d, "STILL", PyInt_FromLong((long) CD_STILL));
|
---|
797 | #ifdef CD_CDROM /* only newer versions of the library */
|
---|
798 | PyDict_SetItemString(d, "CDROM", PyInt_FromLong((long) CD_CDROM));
|
---|
799 | #endif
|
---|
800 | }
|
---|