Added 'list_only' option (and modified 'run()' to respect it).
[python/dscho.git] / Modules / cdmodule.c
blob71598d7cd7d15222b074c0902f1b9e660bd56298
1 /**********************************************************
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3 The Netherlands.
5 All Rights Reserved
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Stichting Mathematisch
12 Centrum or CWI or Corporation for National Research Initiatives or
13 CNRI not be used in advertising or publicity pertaining to
14 distribution of the software without specific, written prior
15 permission.
17 While CWI is the initial source for this software, a modified version
18 is made available by the Corporation for National Research Initiatives
19 (CNRI) at the Internet address ftp://ftp.python.org.
21 STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22 REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23 MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24 CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26 PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28 PERFORMANCE OF THIS SOFTWARE.
30 ******************************************************************/
32 /* CD module -- interface to Mark Callow's and Roger Chickering's */
33 /* CD Audio Library (CD). */
35 #include <sys/types.h>
36 #include <cdaudio.h>
37 #include "Python.h"
39 #define NCALLBACKS 8
41 typedef struct {
42 PyObject_HEAD
43 CDPLAYER *ob_cdplayer;
44 } cdplayerobject;
46 static PyObject *CdError; /* exception cd.error */
48 static PyObject *
49 CD_allowremoval(self, args)
50 cdplayerobject *self;
51 PyObject *args;
53 if (!PyArg_ParseTuple(args, ""))
54 return NULL;
56 CDallowremoval(self->ob_cdplayer);
58 Py_INCREF(Py_None);
59 return Py_None;
62 static PyObject *
63 CD_preventremoval(self, args)
64 cdplayerobject *self;
65 PyObject *args;
67 if (!PyArg_ParseTuple(args, ""))
68 return NULL;
70 CDpreventremoval(self->ob_cdplayer);
72 Py_INCREF(Py_None);
73 return Py_None;
76 static PyObject *
77 CD_bestreadsize(self, args)
78 cdplayerobject *self;
79 PyObject *args;
81 if (!PyArg_ParseTuple(args, ""))
82 return NULL;
84 return PyInt_FromLong((long) CDbestreadsize(self->ob_cdplayer));
87 static PyObject *
88 CD_close(self, args)
89 cdplayerobject *self;
90 PyObject *args;
92 if (!PyArg_ParseTuple(args, ""))
93 return NULL;
95 if (!CDclose(self->ob_cdplayer)) {
96 PyErr_SetFromErrno(CdError); /* XXX - ??? */
97 return NULL;
99 self->ob_cdplayer = NULL;
101 Py_INCREF(Py_None);
102 return Py_None;
105 static PyObject *
106 CD_eject(self, args)
107 cdplayerobject *self;
108 PyObject *args;
110 CDSTATUS status;
112 if (!PyArg_ParseTuple(args, ""))
113 return NULL;
115 if (!CDeject(self->ob_cdplayer)) {
116 if (CDgetstatus(self->ob_cdplayer, &status) &&
117 status.state == CD_NODISC)
118 PyErr_SetString(CdError, "no disc in player");
119 else
120 PyErr_SetString(CdError, "eject failed");
121 return NULL;
124 Py_INCREF(Py_None);
125 return Py_None;
128 static PyObject *
129 CD_getstatus(self, args)
130 cdplayerobject *self;
131 PyObject *args;
133 CDSTATUS status;
135 if (!PyArg_ParseTuple(args, ""))
136 return NULL;
138 if (!CDgetstatus(self->ob_cdplayer, &status)) {
139 PyErr_SetFromErrno(CdError); /* XXX - ??? */
140 return NULL;
143 return Py_BuildValue("(ii(iii)(iii)(iii)iiii)", status.state,
144 status.track, status.min, status.sec, status.frame,
145 status.abs_min, status.abs_sec, status.abs_frame,
146 status.total_min, status.total_sec, status.total_frame,
147 status.first, status.last, status.scsi_audio,
148 status.cur_block);
151 static PyObject *
152 CD_gettrackinfo(self, args)
153 cdplayerobject *self;
154 PyObject *args;
156 int track;
157 CDTRACKINFO info;
158 CDSTATUS status;
160 if (!PyArg_ParseTuple(args, "i", &track))
161 return NULL;
163 if (!CDgettrackinfo(self->ob_cdplayer, track, &info)) {
164 if (CDgetstatus(self->ob_cdplayer, &status) &&
165 status.state == CD_NODISC)
166 PyErr_SetString(CdError, "no disc in player");
167 else
168 PyErr_SetString(CdError, "gettrackinfo failed");
169 return NULL;
172 return Py_BuildValue("((iii)(iii))",
173 info.start_min, info.start_sec, info.start_frame,
174 info.total_min, info.total_sec, info.total_frame);
177 static PyObject *
178 CD_msftoblock(self, args)
179 cdplayerobject *self;
180 PyObject *args;
182 int min, sec, frame;
184 if (!PyArg_ParseTuple(args, "iii", &min, &sec, &frame))
185 return NULL;
187 return PyInt_FromLong((long) CDmsftoblock(self->ob_cdplayer,
188 min, sec, frame));
191 static PyObject *
192 CD_play(self, args)
193 cdplayerobject *self;
194 PyObject *args;
196 int start, play;
197 CDSTATUS status;
199 if (!PyArg_ParseTuple(args, "ii", &start, &play))
200 return NULL;
202 if (!CDplay(self->ob_cdplayer, start, play)) {
203 if (CDgetstatus(self->ob_cdplayer, &status) &&
204 status.state == CD_NODISC)
205 PyErr_SetString(CdError, "no disc in player");
206 else
207 PyErr_SetString(CdError, "play failed");
208 return NULL;
211 Py_INCREF(Py_None);
212 return Py_None;
215 static PyObject *
216 CD_playabs(self, args)
217 cdplayerobject *self;
218 PyObject *args;
220 int min, sec, frame, play;
221 CDSTATUS status;
223 if (!PyArg_ParseTuple(args, "iiii", &min, &sec, &frame, &play))
224 return NULL;
226 if (!CDplayabs(self->ob_cdplayer, min, sec, frame, play)) {
227 if (CDgetstatus(self->ob_cdplayer, &status) &&
228 status.state == CD_NODISC)
229 PyErr_SetString(CdError, "no disc in player");
230 else
231 PyErr_SetString(CdError, "playabs failed");
232 return NULL;
235 Py_INCREF(Py_None);
236 return Py_None;
239 static PyObject *
240 CD_playtrack(self, args)
241 cdplayerobject *self;
242 PyObject *args;
244 int start, play;
245 CDSTATUS status;
247 if (!PyArg_ParseTuple(args, "ii", &start, &play))
248 return NULL;
250 if (!CDplaytrack(self->ob_cdplayer, start, play)) {
251 if (CDgetstatus(self->ob_cdplayer, &status) &&
252 status.state == CD_NODISC)
253 PyErr_SetString(CdError, "no disc in player");
254 else
255 PyErr_SetString(CdError, "playtrack failed");
256 return NULL;
259 Py_INCREF(Py_None);
260 return Py_None;
263 static PyObject *
264 CD_playtrackabs(self, args)
265 cdplayerobject *self;
266 PyObject *args;
268 int track, min, sec, frame, play;
269 CDSTATUS status;
271 if (!PyArg_ParseTuple(args, "iiiii", &track, &min, &sec,
272 &frame, &play))
273 return NULL;
275 if (!CDplaytrackabs(self->ob_cdplayer, track, min, sec, frame, play)) {
276 if (CDgetstatus(self->ob_cdplayer, &status) &&
277 status.state == CD_NODISC)
278 PyErr_SetString(CdError, "no disc in player");
279 else
280 PyErr_SetString(CdError, "playtrackabs failed");
281 return NULL;
284 Py_INCREF(Py_None);
285 return Py_None;
288 static PyObject *
289 CD_readda(self, args)
290 cdplayerobject *self;
291 PyObject *args;
293 int numframes, n;
294 PyObject *result;
296 if (!PyArg_ParseTuple(args, "i", &numframes))
297 return NULL;
299 result = PyString_FromStringAndSize(NULL, numframes * sizeof(CDFRAME));
300 if (result == NULL)
301 return NULL;
303 n = CDreadda(self->ob_cdplayer,
304 (CDFRAME *) PyString_AsString(result), numframes);
305 if (n == -1) {
306 Py_DECREF(result);
307 PyErr_SetFromErrno(CdError);
308 return NULL;
310 if (n < numframes)
311 if (_PyString_Resize(&result, n * sizeof(CDFRAME)))
312 return NULL;
314 return result;
317 static PyObject *
318 CD_seek(self, args)
319 cdplayerobject *self;
320 PyObject *args;
322 int min, sec, frame;
323 long PyTryBlock;
325 if (!PyArg_ParseTuple(args, "iii", &min, &sec, &frame))
326 return NULL;
328 PyTryBlock = CDseek(self->ob_cdplayer, min, sec, frame);
329 if (PyTryBlock == -1) {
330 PyErr_SetFromErrno(CdError);
331 return NULL;
334 return PyInt_FromLong(PyTryBlock);
337 static PyObject *
338 CD_seektrack(self, args)
339 cdplayerobject *self;
340 PyObject *args;
342 int track;
343 long PyTryBlock;
345 if (!PyArg_ParseTuple(args, "i", &track))
346 return NULL;
348 PyTryBlock = CDseektrack(self->ob_cdplayer, track);
349 if (PyTryBlock == -1) {
350 PyErr_SetFromErrno(CdError);
351 return NULL;
354 return PyInt_FromLong(PyTryBlock);
357 static PyObject *
358 CD_seekblock(self, args)
359 cdplayerobject *self;
360 PyObject *args;
362 unsigned long PyTryBlock;
364 if (!PyArg_ParseTuple(args, "l", &PyTryBlock))
365 return NULL;
367 PyTryBlock = CDseekblock(self->ob_cdplayer, PyTryBlock);
368 if (PyTryBlock == (unsigned long) -1) {
369 PyErr_SetFromErrno(CdError);
370 return NULL;
373 return PyInt_FromLong(PyTryBlock);
376 static PyObject *
377 CD_stop(self, args)
378 cdplayerobject *self;
379 PyObject *args;
381 CDSTATUS status;
383 if (!PyArg_ParseTuple(args, ""))
384 return NULL;
386 if (!CDstop(self->ob_cdplayer)) {
387 if (CDgetstatus(self->ob_cdplayer, &status) &&
388 status.state == CD_NODISC)
389 PyErr_SetString(CdError, "no disc in player");
390 else
391 PyErr_SetString(CdError, "stop failed");
392 return NULL;
395 Py_INCREF(Py_None);
396 return Py_None;
399 static PyObject *
400 CD_togglepause(self, args)
401 cdplayerobject *self;
402 PyObject *args;
404 CDSTATUS status;
406 if (!PyArg_ParseTuple(args, ""))
407 return NULL;
409 if (!CDtogglepause(self->ob_cdplayer)) {
410 if (CDgetstatus(self->ob_cdplayer, &status) &&
411 status.state == CD_NODISC)
412 PyErr_SetString(CdError, "no disc in player");
413 else
414 PyErr_SetString(CdError, "togglepause failed");
415 return NULL;
418 Py_INCREF(Py_None);
419 return Py_None;
422 static PyMethodDef cdplayer_methods[] = {
423 {"allowremoval", (PyCFunction)CD_allowremoval, 1},
424 {"bestreadsize", (PyCFunction)CD_bestreadsize, 1},
425 {"close", (PyCFunction)CD_close, 1},
426 {"eject", (PyCFunction)CD_eject, 1},
427 {"getstatus", (PyCFunction)CD_getstatus, 1},
428 {"gettrackinfo", (PyCFunction)CD_gettrackinfo, 1},
429 {"msftoblock", (PyCFunction)CD_msftoblock, 1},
430 {"play", (PyCFunction)CD_play, 1},
431 {"playabs", (PyCFunction)CD_playabs, 1},
432 {"playtrack", (PyCFunction)CD_playtrack, 1},
433 {"playtrackabs", (PyCFunction)CD_playtrackabs, 1},
434 {"preventremoval", (PyCFunction)CD_preventremoval, 1},
435 {"readda", (PyCFunction)CD_readda, 1},
436 {"seek", (PyCFunction)CD_seek, 1},
437 {"seekblock", (PyCFunction)CD_seekblock, 1},
438 {"seektrack", (PyCFunction)CD_seektrack, 1},
439 {"stop", (PyCFunction)CD_stop, 1},
440 {"togglepause", (PyCFunction)CD_togglepause, 1},
441 {NULL, NULL} /* sentinel */
444 static void
445 cdplayer_dealloc(self)
446 cdplayerobject *self;
448 if (self->ob_cdplayer != NULL)
449 CDclose(self->ob_cdplayer);
450 PyMem_DEL(self);
453 static PyObject *
454 cdplayer_getattr(self, name)
455 cdplayerobject *self;
456 char *name;
458 if (self->ob_cdplayer == NULL) {
459 PyErr_SetString(PyExc_RuntimeError, "no player active");
460 return NULL;
462 return Py_FindMethod(cdplayer_methods, (PyObject *)self, name);
465 PyTypeObject CdPlayertype = {
466 PyObject_HEAD_INIT(&PyType_Type)
467 0, /*ob_size*/
468 "cdplayer", /*tp_name*/
469 sizeof(cdplayerobject), /*tp_size*/
470 0, /*tp_itemsize*/
471 /* methods */
472 (destructor)cdplayer_dealloc, /*tp_dealloc*/
473 0, /*tp_print*/
474 (getattrfunc)cdplayer_getattr, /*tp_getattr*/
475 0, /*tp_setattr*/
476 0, /*tp_compare*/
477 0, /*tp_repr*/
480 static PyObject *
481 newcdplayerobject(cdp)
482 CDPLAYER *cdp;
484 cdplayerobject *p;
486 p = PyObject_NEW(cdplayerobject, &CdPlayertype);
487 if (p == NULL)
488 return NULL;
489 p->ob_cdplayer = cdp;
490 return (PyObject *) p;
493 static PyObject *
494 CD_open(self, args)
495 PyObject *self, *args;
497 char *dev, *direction;
498 CDPLAYER *cdp;
501 * Variable number of args.
502 * First defaults to "None", second defaults to "r".
504 dev = NULL;
505 direction = "r";
506 if (!PyArg_ParseTuple(args, "|zs", &dev, &direction))
507 return NULL;
509 cdp = CDopen(dev, direction);
510 if (cdp == NULL) {
511 PyErr_SetFromErrno(CdError);
512 return NULL;
515 return newcdplayerobject(cdp);
518 typedef struct {
519 PyObject_HEAD
520 CDPARSER *ob_cdparser;
521 struct {
522 PyObject *ob_cdcallback;
523 PyObject *ob_cdcallbackarg;
524 } ob_cdcallbacks[NCALLBACKS];
525 } cdparserobject;
527 static void
528 CD_callback(arg, type, data)
529 void *arg;
530 CDDATATYPES type;
531 void *data;
533 PyObject *result, *args, *v = NULL;
534 char *p;
535 int i;
536 cdparserobject *self;
538 self = (cdparserobject *) arg;
539 args = PyTuple_New(3);
540 if (args == NULL)
541 return;
542 Py_INCREF(self->ob_cdcallbacks[type].ob_cdcallbackarg);
543 PyTuple_SetItem(args, 0, self->ob_cdcallbacks[type].ob_cdcallbackarg);
544 PyTuple_SetItem(args, 1, PyInt_FromLong((long) type));
545 switch (type) {
546 case cd_audio:
547 v = PyString_FromStringAndSize(data, CDDA_DATASIZE);
548 break;
549 case cd_pnum:
550 case cd_index:
551 v = PyInt_FromLong(((CDPROGNUM *) data)->value);
552 break;
553 case cd_ptime:
554 case cd_atime:
555 #define ptr ((struct cdtimecode *) data)
556 v = Py_BuildValue("(iii)",
557 ptr->mhi * 10 + ptr->mlo,
558 ptr->shi * 10 + ptr->slo,
559 ptr->fhi * 10 + ptr->flo);
560 #undef ptr
561 break;
562 case cd_catalog:
563 v = PyString_FromStringAndSize(NULL, 13);
564 p = PyString_AsString(v);
565 for (i = 0; i < 13; i++)
566 *p++ = ((char *) data)[i] + '0';
567 break;
568 case cd_ident:
569 #define ptr ((struct cdident *) data)
570 v = PyString_FromStringAndSize(NULL, 12);
571 p = PyString_AsString(v);
572 CDsbtoa(p, ptr->country, 2);
573 p += 2;
574 CDsbtoa(p, ptr->owner, 3);
575 p += 3;
576 *p++ = ptr->year[0] + '0';
577 *p++ = ptr->year[1] + '0';
578 *p++ = ptr->serial[0] + '0';
579 *p++ = ptr->serial[1] + '0';
580 *p++ = ptr->serial[2] + '0';
581 *p++ = ptr->serial[3] + '0';
582 *p++ = ptr->serial[4] + '0';
583 #undef ptr
584 break;
585 case cd_control:
586 v = PyInt_FromLong((long) *((unchar *) data));
587 break;
589 PyTuple_SetItem(args, 2, v);
590 if (PyErr_Occurred()) {
591 Py_DECREF(args);
592 return;
595 result = PyEval_CallObject(self->ob_cdcallbacks[type].ob_cdcallback,
596 args);
597 Py_DECREF(args);
598 Py_XDECREF(result);
601 static PyObject *
602 CD_deleteparser(self, args)
603 cdparserobject *self;
604 PyObject *args;
606 int i;
608 if (!PyArg_ParseTuple(args, ""))
609 return NULL;
611 CDdeleteparser(self->ob_cdparser);
612 self->ob_cdparser = NULL;
614 /* no sense in keeping the callbacks, so remove them */
615 for (i = 0; i < NCALLBACKS; i++) {
616 Py_XDECREF(self->ob_cdcallbacks[i].ob_cdcallback);
617 self->ob_cdcallbacks[i].ob_cdcallback = NULL;
618 Py_XDECREF(self->ob_cdcallbacks[i].ob_cdcallbackarg);
619 self->ob_cdcallbacks[i].ob_cdcallbackarg = NULL;
622 Py_INCREF(Py_None);
623 return Py_None;
626 static PyObject *
627 CD_parseframe(self, args)
628 cdparserobject *self;
629 PyObject *args;
631 char *cdfp;
632 int length;
633 CDFRAME *p;
635 if (!PyArg_ParseTuple(args, "s#", &cdfp, &length))
636 return NULL;
638 if (length % sizeof(CDFRAME) != 0) {
639 PyErr_SetString(PyExc_TypeError, "bad length");
640 return NULL;
643 p = (CDFRAME *) cdfp;
644 while (length > 0) {
645 CDparseframe(self->ob_cdparser, p);
646 length -= sizeof(CDFRAME);
647 p++;
648 if (PyErr_Occurred())
649 return NULL;
652 Py_INCREF(Py_None);
653 return Py_None;
656 static PyObject *
657 CD_removecallback(self, args)
658 cdparserobject *self;
659 PyObject *args;
661 int type;
663 if (!PyArg_ParseTuple(args, "i", &type))
664 return NULL;
666 if (type < 0 || type >= NCALLBACKS) {
667 PyErr_SetString(PyExc_TypeError, "bad type");
668 return NULL;
671 CDremovecallback(self->ob_cdparser, (CDDATATYPES) type);
673 Py_XDECREF(self->ob_cdcallbacks[type].ob_cdcallback);
674 self->ob_cdcallbacks[type].ob_cdcallback = NULL;
676 Py_XDECREF(self->ob_cdcallbacks[type].ob_cdcallbackarg);
677 self->ob_cdcallbacks[type].ob_cdcallbackarg = NULL;
679 Py_INCREF(Py_None);
680 return Py_None;
683 static PyObject *
684 CD_resetparser(self, args)
685 cdparserobject *self;
686 PyObject *args;
688 if (!PyArg_ParseTuple(args, ""))
689 return NULL;
691 CDresetparser(self->ob_cdparser);
693 Py_INCREF(Py_None);
694 return Py_None;
697 static PyObject *
698 CD_addcallback(self, args)
699 cdparserobject *self;
700 PyObject *args;
702 int type;
703 PyObject *func, *funcarg;
705 /* XXX - more work here */
706 if (!PyArg_ParseTuple(args, "iOO", &type, &func, &funcarg))
707 return NULL;
709 if (type < 0 || type >= NCALLBACKS) {
710 PyErr_SetString(PyExc_TypeError, "argument out of range");
711 return NULL;
714 #ifdef CDsetcallback
715 CDaddcallback(self->ob_cdparser, (CDDATATYPES) type, CD_callback,
716 (void *) self);
717 #else
718 CDsetcallback(self->ob_cdparser, (CDDATATYPES) type, CD_callback,
719 (void *) self);
720 #endif
721 Py_XDECREF(self->ob_cdcallbacks[type].ob_cdcallback);
722 Py_INCREF(func);
723 self->ob_cdcallbacks[type].ob_cdcallback = func;
724 Py_XDECREF(self->ob_cdcallbacks[type].ob_cdcallbackarg);
725 Py_INCREF(funcarg);
726 self->ob_cdcallbacks[type].ob_cdcallbackarg = funcarg;
729 if (type == cd_audio) {
730 sigfpe_[_UNDERFL].repls = _ZERO;
731 handle_sigfpes(_ON, _EN_UNDERFL, NULL,
732 _ABORT_ON_ERROR, NULL);
736 Py_INCREF(Py_None);
737 return Py_None;
740 static PyMethodDef cdparser_methods[] = {
741 {"addcallback", (PyCFunction)CD_addcallback, 1},
742 {"deleteparser", (PyCFunction)CD_deleteparser, 1},
743 {"parseframe", (PyCFunction)CD_parseframe, 1},
744 {"removecallback", (PyCFunction)CD_removecallback, 1},
745 {"resetparser", (PyCFunction)CD_resetparser, 1},
746 /* backward compatibility */
747 {"setcallback", (PyCFunction)CD_addcallback, 1},
748 {NULL, NULL} /* sentinel */
751 static void
752 cdparser_dealloc(self)
753 cdparserobject *self;
755 int i;
757 for (i = 0; i < NCALLBACKS; i++) {
758 Py_XDECREF(self->ob_cdcallbacks[i].ob_cdcallback);
759 self->ob_cdcallbacks[i].ob_cdcallback = NULL;
760 Py_XDECREF(self->ob_cdcallbacks[i].ob_cdcallbackarg);
761 self->ob_cdcallbacks[i].ob_cdcallbackarg = NULL;
763 CDdeleteparser(self->ob_cdparser);
764 PyMem_DEL(self);
767 static PyObject *
768 cdparser_getattr(self, name)
769 cdparserobject *self;
770 char *name;
772 if (self->ob_cdparser == NULL) {
773 PyErr_SetString(PyExc_RuntimeError, "no parser active");
774 return NULL;
777 return Py_FindMethod(cdparser_methods, (PyObject *)self, name);
780 PyTypeObject CdParsertype = {
781 PyObject_HEAD_INIT(&PyType_Type)
782 0, /*ob_size*/
783 "cdparser", /*tp_name*/
784 sizeof(cdparserobject), /*tp_size*/
785 0, /*tp_itemsize*/
786 /* methods */
787 (destructor)cdparser_dealloc, /*tp_dealloc*/
788 0, /*tp_print*/
789 (getattrfunc)cdparser_getattr, /*tp_getattr*/
790 0, /*tp_setattr*/
791 0, /*tp_compare*/
792 0, /*tp_repr*/
795 static PyObject *
796 newcdparserobject(cdp)
797 CDPARSER *cdp;
799 cdparserobject *p;
800 int i;
802 p = PyObject_NEW(cdparserobject, &CdParsertype);
803 if (p == NULL)
804 return NULL;
805 p->ob_cdparser = cdp;
806 for (i = 0; i < NCALLBACKS; i++) {
807 p->ob_cdcallbacks[i].ob_cdcallback = NULL;
808 p->ob_cdcallbacks[i].ob_cdcallbackarg = NULL;
810 return (PyObject *) p;
813 static PyObject *
814 CD_createparser(self, args)
815 PyObject *self, *args;
817 CDPARSER *cdp;
819 if (!PyArg_ParseTuple(args, ""))
820 return NULL;
821 cdp = CDcreateparser();
822 if (cdp == NULL) {
823 PyErr_SetString(CdError, "createparser failed");
824 return NULL;
827 return newcdparserobject(cdp);
830 static PyObject *
831 CD_msftoframe(self, args)
832 PyObject *self, *args;
834 int min, sec, frame;
836 if (!PyArg_ParseTuple(args, "iii", &min, &sec, &frame))
837 return NULL;
839 return PyInt_FromLong((long) CDmsftoframe(min, sec, frame));
842 static PyMethodDef CD_methods[] = {
843 {"open", (PyCFunction)CD_open, 1},
844 {"createparser", (PyCFunction)CD_createparser, 1},
845 {"msftoframe", (PyCFunction)CD_msftoframe, 1},
846 {NULL, NULL} /* Sentinel */
849 void
850 initcd()
852 PyObject *m, *d;
854 m = Py_InitModule("cd", CD_methods);
855 d = PyModule_GetDict(m);
857 CdError = PyErr_NewException("cd.error", NULL, NULL);
858 PyDict_SetItemString(d, "error", CdError);
860 /* Identifiers for the different types of callbacks from the parser */
861 PyDict_SetItemString(d, "audio", PyInt_FromLong((long) cd_audio));
862 PyDict_SetItemString(d, "pnum", PyInt_FromLong((long) cd_pnum));
863 PyDict_SetItemString(d, "index", PyInt_FromLong((long) cd_index));
864 PyDict_SetItemString(d, "ptime", PyInt_FromLong((long) cd_ptime));
865 PyDict_SetItemString(d, "atime", PyInt_FromLong((long) cd_atime));
866 PyDict_SetItemString(d, "catalog", PyInt_FromLong((long) cd_catalog));
867 PyDict_SetItemString(d, "ident", PyInt_FromLong((long) cd_ident));
868 PyDict_SetItemString(d, "control", PyInt_FromLong((long) cd_control));
870 /* Block size information for digital audio data */
871 PyDict_SetItemString(d, "DATASIZE",
872 PyInt_FromLong((long) CDDA_DATASIZE));
873 PyDict_SetItemString(d, "BLOCKSIZE",
874 PyInt_FromLong((long) CDDA_BLOCKSIZE));
876 /* Possible states for the cd player */
877 PyDict_SetItemString(d, "ERROR", PyInt_FromLong((long) CD_ERROR));
878 PyDict_SetItemString(d, "NODISC", PyInt_FromLong((long) CD_NODISC));
879 PyDict_SetItemString(d, "READY", PyInt_FromLong((long) CD_READY));
880 PyDict_SetItemString(d, "PLAYING", PyInt_FromLong((long) CD_PLAYING));
881 PyDict_SetItemString(d, "PAUSED", PyInt_FromLong((long) CD_PAUSED));
882 PyDict_SetItemString(d, "STILL", PyInt_FromLong((long) CD_STILL));
883 #ifdef CD_CDROM /* only newer versions of the library */
884 PyDict_SetItemString(d, "CDROM", PyInt_FromLong((long) CD_CDROM));
885 #endif
887 if (PyErr_Occurred())
888 Py_FatalError("can't initialize module cd");