blob: 3e095778aeef4e63d9204730015d93a2b9b69505 [file] [log] [blame]
Guido van Rossum16b8f301992-04-13 18:22:53 +00001/**********************************************************
Guido van Rossum524b5881995-01-04 19:10:35 +00002Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
Guido van Rossum16b8f301992-04-13 18:22:53 +00004
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
25/* CD module -- interface to Mark Callow's and Roger Chickering's */
26 /* CD Audio Library (CD). */
27
28#include <sys/types.h>
29#include <cdaudio.h>
30#include "allobjects.h"
31#include "import.h"
32#include "modsupport.h"
Guido van Rossum16b8f301992-04-13 18:22:53 +000033#include "ceval.h"
34
35#define NCALLBACKS 8
36
37typedef struct {
38 OB_HEAD
39 CDPLAYER *ob_cdplayer;
40} cdplayerobject;
41
42#define CheckPlayer(self) if ((self)->ob_cdplayer == NULL) { \
43 err_setstr(RuntimeError, "no player active"); \
44 return NULL; \
45 }
46#define CheckParser(self) if ((self)->ob_cdparser == NULL) { \
47 err_setstr(RuntimeError, "no parser active"); \
48 return NULL; \
49 }
50
Sjoerd Mullender46927ba1992-09-24 10:48:40 +000051static object *CdError; /* exception cd.error */
52
Guido van Rossum16b8f301992-04-13 18:22:53 +000053static object *
54CD_allowremoval(self, args)
55 cdplayerobject *self;
56 object *args;
57{
58 CheckPlayer(self);
59
60 if (!getnoarg(args))
61 return NULL;
62
63 CDallowremoval(self->ob_cdplayer);
64
65 INCREF(None);
66 return None;
67}
68
69static object *
70CD_preventremoval(self, args)
71 cdplayerobject *self;
72 object *args;
73{
74 CheckPlayer(self);
75
76 if (!getnoarg(args))
77 return NULL;
78
79 CDpreventremoval(self->ob_cdplayer);
80
81 INCREF(None);
82 return None;
83}
84
85static object *
Guido van Rossum16b8f301992-04-13 18:22:53 +000086CD_bestreadsize(self, args)
87 cdplayerobject *self;
88 object *args;
89{
90 CheckPlayer(self);
91
92 if (!getnoarg(args))
93 return NULL;
94
95 return newintobject((long) CDbestreadsize(self->ob_cdplayer));
96}
97
98static object *
99CD_close(self, args)
100 cdplayerobject *self;
101 object *args;
102{
103 CheckPlayer(self);
104
105 if (!getnoarg(args))
106 return NULL;
107
108 if (!CDclose(self->ob_cdplayer)) {
Sjoerd Mullender46927ba1992-09-24 10:48:40 +0000109 err_errno(CdError); /* XXX - ??? */
Guido van Rossum16b8f301992-04-13 18:22:53 +0000110 return NULL;
111 }
112 self->ob_cdplayer = NULL;
113
114 INCREF(None);
115 return None;
116}
117
118static object *
119CD_eject(self, args)
120 cdplayerobject *self;
121 object *args;
122{
Guido van Rossumc3c7ac81992-05-06 09:48:30 +0000123 CDSTATUS status;
124
Guido van Rossum16b8f301992-04-13 18:22:53 +0000125 CheckPlayer(self);
126
127 if (!getnoarg(args))
128 return NULL;
129
130 if (!CDeject(self->ob_cdplayer)) {
Guido van Rossumc3c7ac81992-05-06 09:48:30 +0000131 if (CDgetstatus(self->ob_cdplayer, &status) &&
132 status.state == CD_NODISC)
Sjoerd Mullender46927ba1992-09-24 10:48:40 +0000133 err_setstr(CdError, "no disc in player");
Guido van Rossumc3c7ac81992-05-06 09:48:30 +0000134 else
Sjoerd Mullender46927ba1992-09-24 10:48:40 +0000135 err_setstr(CdError, "eject failed");
Guido van Rossum16b8f301992-04-13 18:22:53 +0000136 return NULL;
137 }
138
139 INCREF(None);
140 return None;
141}
142
143static object *
144CD_getstatus(self, args)
145 cdplayerobject *self;
146 object *args;
147{
148 CDSTATUS status;
149
150 CheckPlayer(self);
151
152 if (!getnoarg(args))
153 return NULL;
154
155 if (!CDgetstatus(self->ob_cdplayer, &status)) {
Sjoerd Mullender46927ba1992-09-24 10:48:40 +0000156 err_errno(CdError); /* XXX - ??? */
Guido van Rossum16b8f301992-04-13 18:22:53 +0000157 return NULL;
158 }
159
Guido van Rossumece6efe1992-04-15 15:56:11 +0000160 return mkvalue("(ii(iii)(iii)(iii)iiii(iii))", status.state,
161 status.track, status.min, status.sec, status.frame,
162 status.abs_min, status.abs_sec, status.abs_frame,
163 status.total_min, status.total_sec, status.total_frame,
164 status.first, status.last, status.scsi_audio,
165 status.cur_block, status.polyfilla[0],
166 status.polyfilla[1], status.polyfilla[2]);
Guido van Rossum16b8f301992-04-13 18:22:53 +0000167}
168
169static object *
170CD_gettrackinfo(self, args)
171 cdplayerobject *self;
172 object *args;
173{
174 int track;
175 CDTRACKINFO info;
Guido van Rossumc3c7ac81992-05-06 09:48:30 +0000176 CDSTATUS status;
Guido van Rossum16b8f301992-04-13 18:22:53 +0000177
178 CheckPlayer(self);
179
180 if (!getargs(args, "i", &track))
181 return NULL;
182
183 if (!CDgettrackinfo(self->ob_cdplayer, track, &info)) {
Guido van Rossumc3c7ac81992-05-06 09:48:30 +0000184 if (CDgetstatus(self->ob_cdplayer, &status) &&
185 status.state == CD_NODISC)
Sjoerd Mullender46927ba1992-09-24 10:48:40 +0000186 err_setstr(CdError, "no disc in player");
Guido van Rossumc3c7ac81992-05-06 09:48:30 +0000187 else
Sjoerd Mullender46927ba1992-09-24 10:48:40 +0000188 err_setstr(CdError, "gettrackinfo failed");
Guido van Rossum16b8f301992-04-13 18:22:53 +0000189 return NULL;
190 }
191
Guido van Rossumece6efe1992-04-15 15:56:11 +0000192 return mkvalue("((iii)(iii))",
Guido van Rossum16b8f301992-04-13 18:22:53 +0000193 info.start_min, info.start_sec, info.start_frame,
194 info.total_min, info.total_sec, info.total_frame);
195}
196
197static object *
198CD_msftoblock(self, args)
199 cdplayerobject *self;
200 object *args;
201{
202 int min, sec, frame;
203 unsigned long block;
204
205 CheckPlayer(self);
206
207 if (!getargs(args, "(iii)", &min, &sec, &frame))
208 return NULL;
209
210 block = CDmsftoblock(self->ob_cdplayer, min, sec, frame);
211 return newintobject((long) block);
212}
213
214static object *
215CD_play(self, args)
216 cdplayerobject *self;
217 object *args;
218{
219 int start, play;
Guido van Rossumc3c7ac81992-05-06 09:48:30 +0000220 CDSTATUS status;
Guido van Rossum16b8f301992-04-13 18:22:53 +0000221
222 CheckPlayer(self);
223
224 if (!getargs(args, "(ii)", &start, &play))
225 return NULL;
226
227 if (!CDplay(self->ob_cdplayer, start, play)) {
Guido van Rossumc3c7ac81992-05-06 09:48:30 +0000228 if (CDgetstatus(self->ob_cdplayer, &status) &&
229 status.state == CD_NODISC)
Sjoerd Mullender46927ba1992-09-24 10:48:40 +0000230 err_setstr(CdError, "no disc in player");
Guido van Rossumc3c7ac81992-05-06 09:48:30 +0000231 else
Sjoerd Mullender46927ba1992-09-24 10:48:40 +0000232 err_setstr(CdError, "play failed");
Guido van Rossum16b8f301992-04-13 18:22:53 +0000233 return NULL;
234 }
235
236 INCREF(None);
237 return None;
238}
239
240static object *
241CD_playabs(self, args)
242 cdplayerobject *self;
243 object *args;
244{
245 int min, sec, frame, play;
Guido van Rossumc3c7ac81992-05-06 09:48:30 +0000246 CDSTATUS status;
Guido van Rossum16b8f301992-04-13 18:22:53 +0000247
248 CheckPlayer(self);
249
250 if (!getargs(args, "(iiii)", &min, &sec, &frame, &play))
251 return NULL;
252
253 if (!CDplayabs(self->ob_cdplayer, min, sec, frame, play)) {
Guido van Rossumc3c7ac81992-05-06 09:48:30 +0000254 if (CDgetstatus(self->ob_cdplayer, &status) &&
255 status.state == CD_NODISC)
Sjoerd Mullender46927ba1992-09-24 10:48:40 +0000256 err_setstr(CdError, "no disc in player");
Guido van Rossumc3c7ac81992-05-06 09:48:30 +0000257 else
Sjoerd Mullender46927ba1992-09-24 10:48:40 +0000258 err_setstr(CdError, "playabs failed");
Guido van Rossum16b8f301992-04-13 18:22:53 +0000259 return NULL;
260 }
261
262 INCREF(None);
263 return None;
264}
265
266static object *
267CD_playtrack(self, args)
268 cdplayerobject *self;
269 object *args;
270{
271 int start, play;
Guido van Rossumc3c7ac81992-05-06 09:48:30 +0000272 CDSTATUS status;
Guido van Rossum16b8f301992-04-13 18:22:53 +0000273
274 CheckPlayer(self);
275
276 if (!getargs(args, "(ii)", &start, &play))
277 return NULL;
278
279 if (!CDplaytrack(self->ob_cdplayer, start, play)) {
Guido van Rossumc3c7ac81992-05-06 09:48:30 +0000280 if (CDgetstatus(self->ob_cdplayer, &status) &&
281 status.state == CD_NODISC)
Sjoerd Mullender46927ba1992-09-24 10:48:40 +0000282 err_setstr(CdError, "no disc in player");
Guido van Rossumc3c7ac81992-05-06 09:48:30 +0000283 else
Sjoerd Mullender46927ba1992-09-24 10:48:40 +0000284 err_setstr(CdError, "playtrack failed");
Guido van Rossum16b8f301992-04-13 18:22:53 +0000285 return NULL;
286 }
287
288 INCREF(None);
289 return None;
290}
291
292static object *
293CD_playtrackabs(self, args)
294 cdplayerobject *self;
295 object *args;
296{
297 int track, min, sec, frame, play;
Guido van Rossumc3c7ac81992-05-06 09:48:30 +0000298 CDSTATUS status;
Guido van Rossum16b8f301992-04-13 18:22:53 +0000299
300 CheckPlayer(self);
301
302 if (!getargs(args, "(iiiii)", &track, &min, &sec, &frame, &play))
303 return NULL;
304
305 if (!CDplaytrackabs(self->ob_cdplayer, track, min, sec, frame, play)) {
Guido van Rossumc3c7ac81992-05-06 09:48:30 +0000306 if (CDgetstatus(self->ob_cdplayer, &status) &&
307 status.state == CD_NODISC)
Sjoerd Mullender46927ba1992-09-24 10:48:40 +0000308 err_setstr(CdError, "no disc in player");
Guido van Rossumc3c7ac81992-05-06 09:48:30 +0000309 else
Sjoerd Mullender46927ba1992-09-24 10:48:40 +0000310 err_setstr(CdError, "playtrackabs failed");
Guido van Rossum16b8f301992-04-13 18:22:53 +0000311 return NULL;
312 }
313
314 INCREF(None);
315 return None;
316}
317
318static object *
319CD_readda(self, args)
320 cdplayerobject *self;
321 object *args;
322{
323 int numframes, n;
324 object *result;
325
326 CheckPlayer(self);
327
328 if (!getargs(args, "i", &numframes))
329 return NULL;
330
331 result = newsizedstringobject(NULL, numframes * sizeof(CDFRAME));
332 if (result == NULL)
333 return NULL;
334
335 n = CDreadda(self->ob_cdplayer, (CDFRAME *) getstringvalue(result), numframes);
336 if (n == -1) {
337 DECREF(result);
Sjoerd Mullender46927ba1992-09-24 10:48:40 +0000338 err_errno(CdError);
Guido van Rossum16b8f301992-04-13 18:22:53 +0000339 return NULL;
340 }
341 if (n < numframes)
342 if (resizestring(&result, n * sizeof(CDFRAME)))
343 return NULL;
344
345 return result;
346}
347
348static object *
349CD_seek(self, args)
350 cdplayerobject *self;
351 object *args;
352{
353 int min, sec, frame;
354 long block;
355
356 CheckPlayer(self);
357
358 if (!getargs(args, "(iii)", &min, &sec, &frame))
359 return NULL;
360
361 block = CDseek(self->ob_cdplayer, min, sec, frame);
362 if (block == -1) {
Sjoerd Mullender46927ba1992-09-24 10:48:40 +0000363 err_errno(CdError);
Guido van Rossum16b8f301992-04-13 18:22:53 +0000364 return NULL;
365 }
366
367 return newintobject(block);
368}
369
370static object *
371CD_seektrack(self, args)
372 cdplayerobject *self;
373 object *args;
374{
375 int track;
376 long block;
377
378 CheckPlayer(self);
379
380 if (!getargs(args, "i", &track))
381 return NULL;
382
383 block = CDseektrack(self->ob_cdplayer, track);
384 if (block == -1) {
Sjoerd Mullender46927ba1992-09-24 10:48:40 +0000385 err_errno(CdError);
Guido van Rossum16b8f301992-04-13 18:22:53 +0000386 return NULL;
387 }
388
389 return newintobject(block);
390}
391
392static object *
393CD_stop(self, args)
394 cdplayerobject *self;
395 object *args;
396{
Guido van Rossumc3c7ac81992-05-06 09:48:30 +0000397 CDSTATUS status;
398
Guido van Rossum16b8f301992-04-13 18:22:53 +0000399 CheckPlayer(self);
400
401 if (!getnoarg(args))
402 return NULL;
403
404 if (!CDstop(self->ob_cdplayer)) {
Guido van Rossumc3c7ac81992-05-06 09:48:30 +0000405 if (CDgetstatus(self->ob_cdplayer, &status) &&
406 status.state == CD_NODISC)
Sjoerd Mullender46927ba1992-09-24 10:48:40 +0000407 err_setstr(CdError, "no disc in player");
Guido van Rossumc3c7ac81992-05-06 09:48:30 +0000408 else
Sjoerd Mullender46927ba1992-09-24 10:48:40 +0000409 err_setstr(CdError, "stop failed");
Guido van Rossum16b8f301992-04-13 18:22:53 +0000410 return NULL;
411 }
412
413 INCREF(None);
414 return None;
415}
416
417static object *
418CD_togglepause(self, args)
419 cdplayerobject *self;
420 object *args;
421{
Guido van Rossumc3c7ac81992-05-06 09:48:30 +0000422 CDSTATUS status;
423
Guido van Rossum16b8f301992-04-13 18:22:53 +0000424 CheckPlayer(self);
425
426 if (!getnoarg(args))
427 return NULL;
428
429 if (!CDtogglepause(self->ob_cdplayer)) {
Guido van Rossumc3c7ac81992-05-06 09:48:30 +0000430 if (CDgetstatus(self->ob_cdplayer, &status) &&
431 status.state == CD_NODISC)
Sjoerd Mullender46927ba1992-09-24 10:48:40 +0000432 err_setstr(CdError, "no disc in player");
Guido van Rossumc3c7ac81992-05-06 09:48:30 +0000433 else
Sjoerd Mullender46927ba1992-09-24 10:48:40 +0000434 err_setstr(CdError, "togglepause failed");
Guido van Rossum16b8f301992-04-13 18:22:53 +0000435 return NULL;
436 }
437
438 INCREF(None);
439 return None;
440}
441
442static struct methodlist cdplayer_methods[] = {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000443 {"allowremoval", (method)CD_allowremoval},
444 {"bestreadsize", (method)CD_bestreadsize},
445 {"close", (method)CD_close},
446 {"eject", (method)CD_eject},
447 {"getstatus", (method)CD_getstatus},
448 {"gettrackinfo", (method)CD_gettrackinfo},
449 {"msftoblock", (method)CD_msftoblock},
450 {"play", (method)CD_play},
451 {"playabs", (method)CD_playabs},
452 {"playtrack", (method)CD_playtrack},
453 {"playtrackabs", (method)CD_playtrackabs},
454 {"preventremoval", (method)CD_preventremoval},
455 {"readda", (method)CD_readda},
456 {"seek", (method)CD_seek},
457 {"seektrack", (method)CD_seektrack},
458 {"stop", (method)CD_stop},
459 {"togglepause", (method)CD_togglepause},
Guido van Rossum16b8f301992-04-13 18:22:53 +0000460 {NULL, NULL} /* sentinel */
461};
462
463static void
464cdplayer_dealloc(self)
465 cdplayerobject *self;
466{
467 if (self->ob_cdplayer != NULL)
468 CDclose(self->ob_cdplayer);
469 DEL(self);
470}
471
472static object *
473cdplayer_getattr(cdp, name)
474 cdplayerobject *cdp;
475 char *name;
476{
477 return findmethod(cdplayer_methods, (object *)cdp, name);
478}
479
480typeobject CdPlayertype = {
481 OB_HEAD_INIT(&Typetype)
482 0, /*ob_size*/
483 "cdplayer", /*tp_name*/
484 sizeof(cdplayerobject), /*tp_size*/
485 0, /*tp_itemsize*/
486 /* methods */
Guido van Rossumb6775db1994-08-01 11:34:53 +0000487 (destructor)cdplayer_dealloc, /*tp_dealloc*/
Guido van Rossum16b8f301992-04-13 18:22:53 +0000488 0, /*tp_print*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000489 (getattrfunc)cdplayer_getattr, /*tp_getattr*/
Guido van Rossum16b8f301992-04-13 18:22:53 +0000490 0, /*tp_setattr*/
491 0, /*tp_compare*/
492 0, /*tp_repr*/
493};
494
495static object *
496newcdplayerobject(cdp)
497 CDPLAYER *cdp;
498{
499 cdplayerobject *p;
500
501 p = NEWOBJ(cdplayerobject, &CdPlayertype);
502 if (p == NULL)
503 return NULL;
504 p->ob_cdplayer = cdp;
505 return (object *) p;
506}
507
508static object *
509CD_open(self, args)
510 object *self, *args;
511{
512 char *dev, *direction;
513 CDPLAYER *cdp;
514
515 /*
516 * Variable number of args.
517 * First defaults to "None", second defaults to "r".
518 */
519 dev = NULL;
520 direction = "r";
521 if (!getnoarg(args)) {
522 err_clear();
523 if (!getargs(args, "z", &dev)) {
524 err_clear();
525 if (!getargs(args, "(zs)", &dev, &direction))
526 return NULL;
527 }
528 }
529
530 cdp = CDopen(dev, direction);
531 if (cdp == NULL) {
Sjoerd Mullender46927ba1992-09-24 10:48:40 +0000532 err_errno(CdError);
Guido van Rossum16b8f301992-04-13 18:22:53 +0000533 return NULL;
534 }
535
536 return newcdplayerobject(cdp);
537}
538
539typedef struct {
540 OB_HEAD
541 CDPARSER *ob_cdparser;
542 struct {
543 object *ob_cdcallback;
544 object *ob_cdcallbackarg;
545 } ob_cdcallbacks[NCALLBACKS];
546} cdparserobject;
547
548static void
549CD_callback(arg, type, data)
550 void *arg;
551 CDDATATYPES type;
552 void *data;
553{
554 object *result, *args, *v;
555 char *p;
556 int i;
557 cdparserobject *self;
558
559 self = (cdparserobject *) arg;
560 args = newtupleobject(3);
561 if (args == NULL)
562 return;
563 INCREF(self->ob_cdcallbacks[type].ob_cdcallbackarg);
564 settupleitem(args, 0, self->ob_cdcallbacks[type].ob_cdcallbackarg);
565 settupleitem(args, 1, newintobject((long) type));
566 switch (type) {
567 case cd_audio:
568 v = newsizedstringobject(data, CDDA_DATASIZE);
569 break;
570 case cd_pnum:
571 case cd_index:
572 v = newintobject(((CDPROGNUM *) data)->value);
573 break;
574 case cd_ptime:
575 case cd_atime:
Guido van Rossumece6efe1992-04-15 15:56:11 +0000576#define ptr ((struct cdtimecode *) data)
577 v = mkvalue("(iii)", ptr->mhi * 10 + ptr->mlo,
578 ptr->shi * 10 + ptr->slo,
579 ptr->fhi * 10 + ptr->flo);
580#undef ptr
Guido van Rossum16b8f301992-04-13 18:22:53 +0000581 break;
582 case cd_catalog:
583 v = newsizedstringobject(NULL, 13);
584 p = getstringvalue(v);
585 for (i = 0; i < 13; i++)
586 *p++ = ((char *) data)[i] + '0';
587 break;
588 case cd_ident:
589 v = newsizedstringobject(NULL, 12);
590 p = getstringvalue(v);
591 CDsbtoa(p, ((struct cdident *) data)->country, 2);
592 p += 2;
593 CDsbtoa(p, ((struct cdident *) data)->owner, 3);
594 p += 3;
595 *p++ = ((struct cdident *) data)->year[0] + '0';
596 *p++ = ((struct cdident *) data)->year[1] + '0';
597 *p++ = ((struct cdident *) data)->serial[0] + '0';
598 *p++ = ((struct cdident *) data)->serial[1] + '0';
599 *p++ = ((struct cdident *) data)->serial[2] + '0';
600 *p++ = ((struct cdident *) data)->serial[3] + '0';
601 *p++ = ((struct cdident *) data)->serial[4] + '0';
602 break;
603 case cd_control:
604 v = newintobject((long) *((unchar *) data));
605 break;
606 }
607 settupleitem(args, 2, v);
608 if (err_occurred()) {
609 DECREF(args);
610 return;
611 }
612
613 result = call_object(self->ob_cdcallbacks[type].ob_cdcallback, args);
614 DECREF(args);
615 XDECREF(result);
616}
617
618static object *
619CD_deleteparser(self, args)
620 cdparserobject *self;
621 object *args;
622{
623 int i;
624
625 CheckParser(self);
626
627 if (!getnoarg(args))
628 return NULL;
629
630 CDdeleteparser(self->ob_cdparser);
631 self->ob_cdparser = NULL;
632
633 /* no sense in keeping the callbacks, so remove them */
634 for (i = 0; i < NCALLBACKS; i++) {
635 XDECREF(self->ob_cdcallbacks[i].ob_cdcallback);
636 self->ob_cdcallbacks[i].ob_cdcallback = NULL;
637 XDECREF(self->ob_cdcallbacks[i].ob_cdcallbackarg);
638 self->ob_cdcallbacks[i].ob_cdcallbackarg = NULL;
639 }
640
641 INCREF(None);
642 return None;
643}
644
645static object *
646CD_parseframe(self, args)
647 cdparserobject *self;
648 object *args;
649{
650 char *cdfp;
651 int length;
652 CDFRAME *p;
653
654 CheckParser(self);
655
656 if (!getargs(args, "s#", &cdfp, &length))
657 return NULL;
658
659 if (length % sizeof(CDFRAME) != 0) {
Sjoerd Mullender46927ba1992-09-24 10:48:40 +0000660 err_setstr(TypeError, "bad length");
Guido van Rossum16b8f301992-04-13 18:22:53 +0000661 return NULL;
662 }
663
664 p = (CDFRAME *) cdfp;
665 while (length > 0) {
666 CDparseframe(self->ob_cdparser, p);
667 length -= sizeof(CDFRAME);
668 p++;
669 if (err_occurred())
670 return NULL;
671 }
672
673 INCREF(None);
674 return None;
675}
676
677static object *
678CD_removecallback(self, args)
679 cdparserobject *self;
680 object *args;
681{
682 int type;
683
684 CheckParser(self);
685
686 if (!getargs(args, "i", &type))
687 return NULL;
688
Guido van Rossumf16eda51992-08-03 19:06:59 +0000689 if (type < 0 || type >= NCALLBACKS) {
Sjoerd Mullender46927ba1992-09-24 10:48:40 +0000690 err_setstr(TypeError, "bad type");
Guido van Rossumf16eda51992-08-03 19:06:59 +0000691 return NULL;
692 }
693
Guido van Rossum16b8f301992-04-13 18:22:53 +0000694 CDremovecallback(self->ob_cdparser, (CDDATATYPES) type);
695
696 XDECREF(self->ob_cdcallbacks[type].ob_cdcallback);
697 self->ob_cdcallbacks[type].ob_cdcallback = NULL;
698
699 XDECREF(self->ob_cdcallbacks[type].ob_cdcallbackarg);
700 self->ob_cdcallbacks[type].ob_cdcallbackarg = NULL;
701
702 INCREF(None);
703 return None;
704}
705
706static object *
707CD_resetparser(self, args)
708 cdparserobject *self;
709 object *args;
710{
711 CheckParser(self);
712
713 if (!getnoarg(args))
714 return NULL;
715
716 CDresetparser(self->ob_cdparser);
717
718 INCREF(None);
719 return None;
720}
721
722static object *
Guido van Rossumf16eda51992-08-03 19:06:59 +0000723CD_addcallback(self, args)
Guido van Rossum16b8f301992-04-13 18:22:53 +0000724 cdparserobject *self;
725 object *args;
726{
727 int type;
Guido van Rossum234f9421993-06-17 12:35:49 +0000728 object *func, *funcarg;
Guido van Rossum16b8f301992-04-13 18:22:53 +0000729
730 CheckParser(self);
731
732 /* XXX - more work here */
Guido van Rossum234f9421993-06-17 12:35:49 +0000733 if (!getargs(args, "(iOO)", &type, &func, &funcarg))
Guido van Rossum16b8f301992-04-13 18:22:53 +0000734 return NULL;
735
736 if (type < 0 || type >= NCALLBACKS) {
Sjoerd Mullender46927ba1992-09-24 10:48:40 +0000737 err_setstr(TypeError, "argument out of range");
Guido van Rossum16b8f301992-04-13 18:22:53 +0000738 return NULL;
739 }
740
Sjoerd Mullender7c4eb401992-09-25 11:15:58 +0000741#ifdef CDsetcallback
Guido van Rossumf16eda51992-08-03 19:06:59 +0000742 CDaddcallback(self->ob_cdparser, (CDDATATYPES) type, CD_callback, (void *) self);
743#else
Guido van Rossum16b8f301992-04-13 18:22:53 +0000744 CDsetcallback(self->ob_cdparser, (CDDATATYPES) type, CD_callback, (void *) self);
Guido van Rossumf16eda51992-08-03 19:06:59 +0000745#endif
Guido van Rossum16b8f301992-04-13 18:22:53 +0000746 XDECREF(self->ob_cdcallbacks[type].ob_cdcallback);
Guido van Rossum234f9421993-06-17 12:35:49 +0000747 INCREF(func);
748 self->ob_cdcallbacks[type].ob_cdcallback = func;
Guido van Rossum16b8f301992-04-13 18:22:53 +0000749 XDECREF(self->ob_cdcallbacks[type].ob_cdcallbackarg);
Guido van Rossum234f9421993-06-17 12:35:49 +0000750 INCREF(funcarg);
751 self->ob_cdcallbacks[type].ob_cdcallbackarg = funcarg;
Guido van Rossum16b8f301992-04-13 18:22:53 +0000752
753 INCREF(None);
754 return None;
755}
756
757static struct methodlist cdparser_methods[] = {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000758 {"addcallback", (method)CD_addcallback},
759 {"deleteparser", (method)CD_deleteparser},
760 {"parseframe", (method)CD_parseframe},
761 {"removecallback", (method)CD_removecallback},
762 {"resetparser", (method)CD_resetparser},
763 {"setcallback", (method)CD_addcallback}, /* backward compatibility */
Guido van Rossum16b8f301992-04-13 18:22:53 +0000764 {NULL, NULL} /* sentinel */
765};
766
767static void
768cdparser_dealloc(self)
769 cdparserobject *self;
770{
771 int i;
772
773 for (i = 0; i < NCALLBACKS; i++) {
774 XDECREF(self->ob_cdcallbacks[i].ob_cdcallback);
775 self->ob_cdcallbacks[i].ob_cdcallback = NULL;
776 XDECREF(self->ob_cdcallbacks[i].ob_cdcallbackarg);
777 self->ob_cdcallbacks[i].ob_cdcallbackarg = NULL;
778 }
779 CDdeleteparser(self->ob_cdparser);
780 DEL(self);
781}
782
783static object *
784cdparser_getattr(cdp, name)
785 cdparserobject *cdp;
786 char *name;
787{
788 return findmethod(cdparser_methods, (object *)cdp, name);
789}
790
791typeobject CdParsertype = {
792 OB_HEAD_INIT(&Typetype)
793 0, /*ob_size*/
794 "cdparser", /*tp_name*/
795 sizeof(cdparserobject), /*tp_size*/
796 0, /*tp_itemsize*/
797 /* methods */
Guido van Rossumb6775db1994-08-01 11:34:53 +0000798 (destructor)cdparser_dealloc, /*tp_dealloc*/
Guido van Rossum16b8f301992-04-13 18:22:53 +0000799 0, /*tp_print*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000800 (getattrfunc)cdparser_getattr, /*tp_getattr*/
Guido van Rossum16b8f301992-04-13 18:22:53 +0000801 0, /*tp_setattr*/
802 0, /*tp_compare*/
803 0, /*tp_repr*/
804};
805
806static object *
807newcdparserobject(cdp)
808 CDPARSER *cdp;
809{
810 cdparserobject *p;
811 int i;
812
813 p = NEWOBJ(cdparserobject, &CdParsertype);
814 if (p == NULL)
815 return NULL;
816 p->ob_cdparser = cdp;
817 for (i = 0; i < NCALLBACKS; i++) {
818 p->ob_cdcallbacks[i].ob_cdcallback = NULL;
819 p->ob_cdcallbacks[i].ob_cdcallbackarg = NULL;
820 }
821 return (object *) p;
822}
823
824static object *
825CD_createparser(self, args)
826 object *self, *args;
827{
828 CDPARSER *cdp;
829
830 if (!getnoarg(args))
831 return NULL;
832 cdp = CDcreateparser();
833 if (cdp == NULL) {
Sjoerd Mullender46927ba1992-09-24 10:48:40 +0000834 err_setstr(CdError, "createparser failed");
Guido van Rossum16b8f301992-04-13 18:22:53 +0000835 return NULL;
836 }
837
838 return newcdparserobject(cdp);
839}
840
841static object *
842CD_sbtoa(self, args)
843 object *self;
844 object *args;
845{
846 char *sb;
847 int length;
848 object *result;
849
850 if (!getargs(args, "s#", &sb, &length))
851 return NULL;
852 result = newsizedstringobject(NULL, length);
853 CDsbtoa(getstringvalue(result), (unchar *) sb, length);
854 return result;
855}
856
857static object *
858CD_timetoa(self, args)
859 object *self;
860 object *args;
861{
862 char *tc;
863 int length;
864 object *result;
865
866 if (!getargs(args, "s#", &tc, &length))
867 return NULL;
868
869 if (length != sizeof(struct cdtimecode)) {
Sjoerd Mullender46927ba1992-09-24 10:48:40 +0000870 err_setstr(TypeError, "bad length");
Guido van Rossum16b8f301992-04-13 18:22:53 +0000871 return NULL;
872 }
873
874 result = newsizedstringobject(NULL, 8);
875 CDtimetoa(getstringvalue(result), (struct cdtimecode *) tc);
876 return result;
877}
878
879static struct methodlist CD_methods[] = {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000880 {"sbtoa", (method)CD_sbtoa},
881 {"open", (method)CD_open},
882 {"createparser",(method)CD_createparser},
883 {"timetoa", (method)CD_timetoa},
Guido van Rossum16b8f301992-04-13 18:22:53 +0000884 {NULL, NULL} /* Sentinel */
885};
886
887void
888initcd()
889{
Sjoerd Mullender46927ba1992-09-24 10:48:40 +0000890 object *m, *d;
891
892 m = initmodule("cd", CD_methods);
893 d = getmoduledict(m);
894
895 CdError = newstringobject("cd.error");
896 if (CdError == NULL || dictinsert(d, "error", CdError) != 0)
897 fatal("can't define cd.error");
Guido van Rossum16b8f301992-04-13 18:22:53 +0000898}