History

add hg and python

cinap_lenrek committed 15 years ago

Commit 4bb9e221 parent 987265c3706 files · +1228772 −-233Browse files

Showing the changes to sys/src/cmd/python/Modules/cdmodule.c (1 of 3706 files). Show all

Unified · Split

sys/src/cmd/python/Modules/cdmodule.c+796−0
@@ -0,0 +1,796 @@
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+ m = Py_InitModule("cd", CD_methods);
763+ if (m == NULL)
764+ return;
765+ d = PyModule_GetDict(m);
766+
767+ CdError = PyErr_NewException("cd.error", NULL, NULL);
768+ PyDict_SetItemString(d, "error", CdError);
769+
770+ /* Identifiers for the different types of callbacks from the parser */
771+ PyDict_SetItemString(d, "audio", PyInt_FromLong((long) cd_audio));
772+ PyDict_SetItemString(d, "pnum", PyInt_FromLong((long) cd_pnum));
773+ PyDict_SetItemString(d, "index", PyInt_FromLong((long) cd_index));
774+ PyDict_SetItemString(d, "ptime", PyInt_FromLong((long) cd_ptime));
775+ PyDict_SetItemString(d, "atime", PyInt_FromLong((long) cd_atime));
776+ PyDict_SetItemString(d, "catalog", PyInt_FromLong((long) cd_catalog));
777+ PyDict_SetItemString(d, "ident", PyInt_FromLong((long) cd_ident));
778+ PyDict_SetItemString(d, "control", PyInt_FromLong((long) cd_control));
779+
780+ /* Block size information for digital audio data */
781+ PyDict_SetItemString(d, "DATASIZE",
782+ PyInt_FromLong((long) CDDA_DATASIZE));
783+ PyDict_SetItemString(d, "BLOCKSIZE",
784+ PyInt_FromLong((long) CDDA_BLOCKSIZE));
785+
786+ /* Possible states for the cd player */
787+ PyDict_SetItemString(d, "ERROR", PyInt_FromLong((long) CD_ERROR));
788+ PyDict_SetItemString(d, "NODISC", PyInt_FromLong((long) CD_NODISC));
789+ PyDict_SetItemString(d, "READY", PyInt_FromLong((long) CD_READY));
790+ PyDict_SetItemString(d, "PLAYING", PyInt_FromLong((long) CD_PLAYING));
791+ PyDict_SetItemString(d, "PAUSED", PyInt_FromLong((long) CD_PAUSED));
792+ PyDict_SetItemString(d, "STILL", PyInt_FromLong((long) CD_STILL));
793+#ifdef CD_CDROM /* only newer versions of the library */
794+ PyDict_SetItemString(d, "CDROM", PyInt_FromLong((long) CD_CDROM));
795+#endif
796+}