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_CLEAR(self->ob_cdcallbacks[i].ob_cdcallback); 539 Py_CLEAR(self->ob_cdcallbacks[i].ob_cdcallbackarg); 540 } 541 542 Py_INCREF(Py_None); 543 return Py_None; 544 } 545 546 static PyObject * 547 CD_parseframe(cdparserobject *self, PyObject *args) 548 { 549 char *cdfp; 550 int length; 551 CDFRAME *p; 552 553 if (!PyArg_ParseTuple(args, "s#:parseframe", &cdfp, &length)) 554 return NULL; 555 556 if (length % sizeof(CDFRAME) != 0) { 557 PyErr_SetString(PyExc_TypeError, "bad length"); 558 return NULL; 559 } 560 561 p = (CDFRAME *) cdfp; 562 while (length > 0) { 563 CDparseframe(self->ob_cdparser, p); 564 length -= sizeof(CDFRAME); 565 p++; 566 if (PyErr_Occurred()) 567 return NULL; 568 } 569 570 Py_INCREF(Py_None); 571 return Py_None; 572 } 573 574 static PyObject * 575 CD_removecallback(cdparserobject *self, PyObject *args) 576 { 577 int type; 578 579 if (!PyArg_ParseTuple(args, "i:removecallback", &type)) 580 return NULL; 581 582 if (type < 0 || type >= NCALLBACKS) { 583 PyErr_SetString(PyExc_TypeError, "bad type"); 584 return NULL; 585 } 586 587 CDremovecallback(self->ob_cdparser, (CDDATATYPES) type); 588 589 Py_CLEAR(self->ob_cdcallbacks[type].ob_cdcallback); 590 591 Py_CLEAR(self->ob_cdcallbacks[type].ob_cdcallbackarg); 592 593 Py_INCREF(Py_None); 594 return Py_None; 595 } 596 597 static PyObject * 598 CD_resetparser(cdparserobject *self, PyObject *args) 599 { 600 if (!PyArg_ParseTuple(args, ":resetparser")) 601 return NULL; 602 603 CDresetparser(self->ob_cdparser); 604 605 Py_INCREF(Py_None); 606 return Py_None; 607 } 608 609 static PyObject * 610 CD_addcallback(cdparserobject *self, PyObject *args) 611 { 612 int type; 613 PyObject *func, *funcarg; 614 615 /* XXX - more work here */ 616 if (!PyArg_ParseTuple(args, "iOO:addcallback", &type, &func, &funcarg)) 617 return NULL; 618 619 if (type < 0 || type >= NCALLBACKS) { 620 PyErr_SetString(PyExc_TypeError, "argument out of range"); 621 return NULL; 622 } 623 624 #ifdef CDsetcallback 625 CDaddcallback(self->ob_cdparser, (CDDATATYPES) type, CD_callback, 626 (void *) self); 627 #else 628 CDsetcallback(self->ob_cdparser, (CDDATATYPES) type, CD_callback, 629 (void *) self); 630 #endif 631 Py_INCREF(func); 632 Py_XSETREF(self->ob_cdcallbacks[type].ob_cdcallback, func); 633 Py_INCREF(funcarg); 634 Py_XSETREF(self->ob_cdcallbacks[type].ob_cdcallbackarg, funcarg); 635 636 /* 637 if (type == cd_audio) { 638 sigfpe_[_UNDERFL].repls = _ZERO; 639 handle_sigfpes(_ON, _EN_UNDERFL, NULL, 640 _ABORT_ON_ERROR, NULL); 641 } 642 */ 643 644 Py_INCREF(Py_None); 645 return Py_None; 646 } 647 648 static PyMethodDef cdparser_methods[] = { 649 {"addcallback", (PyCFunction)CD_addcallback, METH_VARARGS}, 650 {"deleteparser", (PyCFunction)CD_deleteparser, METH_VARARGS}, 651 {"parseframe", (PyCFunction)CD_parseframe, METH_VARARGS}, 652 {"removecallback", (PyCFunction)CD_removecallback, METH_VARARGS}, 653 {"resetparser", (PyCFunction)CD_resetparser, METH_VARARGS}, 654 /* backward compatibility */ 655 {"setcallback", (PyCFunction)CD_addcallback, METH_VARARGS}, 656 {NULL, NULL} /* sentinel */ 657 }; 658 659 static void 660 cdparser_dealloc(cdparserobject *self) 661 { 662 int i; 663 664 for (i = 0; i < NCALLBACKS; i++) { 665 Py_CLEAR(self->ob_cdcallbacks[i].ob_cdcallback); 666 Py_CLEAR(self->ob_cdcallbacks[i].ob_cdcallbackarg); 667 } 668 CDdeleteparser(self->ob_cdparser); 669 PyObject_Del(self); 670 } 671 672 static PyObject * 673 cdparser_getattr(cdparserobject *self, char *name) 674 { 675 if (self->ob_cdparser == NULL) { 676 PyErr_SetString(PyExc_RuntimeError, "no parser active"); 677 return NULL; 678 } 679 680 return Py_FindMethod(cdparser_methods, (PyObject *)self, name); 681 } 682 683 PyTypeObject CdParsertype = { 684 PyObject_HEAD_INIT(&PyType_Type) 685 0, /*ob_size*/ 686 "cd.cdparser", /*tp_name*/ 687 sizeof(cdparserobject), /*tp_size*/ 688 0, /*tp_itemsize*/ 689 /* methods */ 690 (destructor)cdparser_dealloc, /*tp_dealloc*/ 691 0, /*tp_print*/ 692 (getattrfunc)cdparser_getattr, /*tp_getattr*/ 693 0, /*tp_setattr*/ 694 0, /*tp_compare*/ 695 0, /*tp_repr*/ 696 }; 697 698 static PyObject * 699 newcdparserobject(CDPARSER *cdp) 700 { 701 cdparserobject *p; 702 int i; 703 704 p = PyObject_New(cdparserobject, &CdParsertype); 705 if (p == NULL) 706 return NULL; 707 p->ob_cdparser = cdp; 708 for (i = 0; i < NCALLBACKS; i++) { 709 p->ob_cdcallbacks[i].ob_cdcallback = NULL; 710 p->ob_cdcallbacks[i].ob_cdcallbackarg = NULL; 711 } 712 return (PyObject *) p; 713 } 714 715 static PyObject * 716 CD_createparser(PyObject *self, PyObject *args) 717 { 718 CDPARSER *cdp; 719 720 if (!PyArg_ParseTuple(args, ":createparser")) 721 return NULL; 722 cdp = CDcreateparser(); 723 if (cdp == NULL) { 724 PyErr_SetString(CdError, "createparser failed"); 725 return NULL; 726 } 727 728 return newcdparserobject(cdp); 729 } 730 731 static PyObject * 732 CD_msftoframe(PyObject *self, PyObject *args) 733 { 734 int min, sec, frame; 735 736 if (!PyArg_ParseTuple(args, "iii:msftoframe", &min, &sec, &frame)) 737 return NULL; 738 739 return PyInt_FromLong((long) CDmsftoframe(min, sec, frame)); 740 } 741 742 static PyMethodDef CD_methods[] = { 743 {"open", (PyCFunction)CD_open, METH_VARARGS}, 744 {"createparser", (PyCFunction)CD_createparser, METH_VARARGS}, 745 {"msftoframe", (PyCFunction)CD_msftoframe, METH_VARARGS}, 746 {NULL, NULL} /* Sentinel */ 747 }; 748 749 void 750 initcd(void) 751 { 752 PyObject *m, *d; 753 754 if (PyErr_WarnPy3k("the cd module has been removed in " 755 "Python 3.0", 2) < 0) 756 return; 757 758 m = Py_InitModule("cd", CD_methods); 759 if (m == NULL) 760 return; 761 d = PyModule_GetDict(m); 762 763 CdError = PyErr_NewException("cd.error", NULL, NULL); 764 PyDict_SetItemString(d, "error", CdError); 765 766 /* Identifiers for the different types of callbacks from the parser */ 767 PyDict_SetItemString(d, "audio", PyInt_FromLong((long) cd_audio)); 768 PyDict_SetItemString(d, "pnum", PyInt_FromLong((long) cd_pnum)); 769 PyDict_SetItemString(d, "index", PyInt_FromLong((long) cd_index)); 770 PyDict_SetItemString(d, "ptime", PyInt_FromLong((long) cd_ptime)); 771 PyDict_SetItemString(d, "atime", PyInt_FromLong((long) cd_atime)); 772 PyDict_SetItemString(d, "catalog", PyInt_FromLong((long) cd_catalog)); 773 PyDict_SetItemString(d, "ident", PyInt_FromLong((long) cd_ident)); 774 PyDict_SetItemString(d, "control", PyInt_FromLong((long) cd_control)); 775 776 /* Block size information for digital audio data */ 777 PyDict_SetItemString(d, "DATASIZE", 778 PyInt_FromLong((long) CDDA_DATASIZE)); 779 PyDict_SetItemString(d, "BLOCKSIZE", 780 PyInt_FromLong((long) CDDA_BLOCKSIZE)); 781 782 /* Possible states for the cd player */ 783 PyDict_SetItemString(d, "ERROR", PyInt_FromLong((long) CD_ERROR)); 784 PyDict_SetItemString(d, "NODISC", PyInt_FromLong((long) CD_NODISC)); 785 PyDict_SetItemString(d, "READY", PyInt_FromLong((long) CD_READY)); 786 PyDict_SetItemString(d, "PLAYING", PyInt_FromLong((long) CD_PLAYING)); 787 PyDict_SetItemString(d, "PAUSED", PyInt_FromLong((long) CD_PAUSED)); 788 PyDict_SetItemString(d, "STILL", PyInt_FromLong((long) CD_STILL)); 789 #ifdef CD_CDROM /* only newer versions of the library */ 790 PyDict_SetItemString(d, "CDROM", PyInt_FromLong((long) CD_CDROM)); 791 #endif 792 } 793