You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
794 lines
19 KiB
794 lines
19 KiB
/* CD module -- interface to Mark Callow's and Roger Chickering's */ |
|
/* CD Audio Library (CD). */ |
|
|
|
#include <sys/types.h> |
|
#include <cdaudio.h> |
|
#include "Python.h" |
|
|
|
#define NCALLBACKS 8 |
|
|
|
typedef struct { |
|
PyObject_HEAD |
|
CDPLAYER *ob_cdplayer; |
|
} cdplayerobject; |
|
|
|
static PyObject *CdError; /* exception cd.error */ |
|
|
|
static PyObject * |
|
CD_allowremoval(cdplayerobject *self, PyObject *args) |
|
{ |
|
if (!PyArg_ParseTuple(args, ":allowremoval")) |
|
return NULL; |
|
|
|
CDallowremoval(self->ob_cdplayer); |
|
|
|
Py_INCREF(Py_None); |
|
return Py_None; |
|
} |
|
|
|
static PyObject * |
|
CD_preventremoval(cdplayerobject *self, PyObject *args) |
|
{ |
|
if (!PyArg_ParseTuple(args, ":preventremoval")) |
|
return NULL; |
|
|
|
CDpreventremoval(self->ob_cdplayer); |
|
|
|
Py_INCREF(Py_None); |
|
return Py_None; |
|
} |
|
|
|
static PyObject * |
|
CD_bestreadsize(cdplayerobject *self, PyObject *args) |
|
{ |
|
if (!PyArg_ParseTuple(args, ":bestreadsize")) |
|
return NULL; |
|
|
|
return PyInt_FromLong((long) CDbestreadsize(self->ob_cdplayer)); |
|
} |
|
|
|
static PyObject * |
|
CD_close(cdplayerobject *self, PyObject *args) |
|
{ |
|
if (!PyArg_ParseTuple(args, ":close")) |
|
return NULL; |
|
|
|
if (!CDclose(self->ob_cdplayer)) { |
|
PyErr_SetFromErrno(CdError); /* XXX - ??? */ |
|
return NULL; |
|
} |
|
self->ob_cdplayer = NULL; |
|
|
|
Py_INCREF(Py_None); |
|
return Py_None; |
|
} |
|
|
|
static PyObject * |
|
CD_eject(cdplayerobject *self, PyObject *args) |
|
{ |
|
CDSTATUS status; |
|
|
|
if (!PyArg_ParseTuple(args, ":eject")) |
|
return NULL; |
|
|
|
if (!CDeject(self->ob_cdplayer)) { |
|
if (CDgetstatus(self->ob_cdplayer, &status) && |
|
status.state == CD_NODISC) |
|
PyErr_SetString(CdError, "no disc in player"); |
|
else |
|
PyErr_SetString(CdError, "eject failed"); |
|
return NULL; |
|
} |
|
|
|
Py_INCREF(Py_None); |
|
return Py_None; |
|
} |
|
|
|
static PyObject * |
|
CD_getstatus(cdplayerobject *self, PyObject *args) |
|
{ |
|
CDSTATUS status; |
|
|
|
if (!PyArg_ParseTuple(args, ":getstatus")) |
|
return NULL; |
|
|
|
if (!CDgetstatus(self->ob_cdplayer, &status)) { |
|
PyErr_SetFromErrno(CdError); /* XXX - ??? */ |
|
return NULL; |
|
} |
|
|
|
return Py_BuildValue("(ii(iii)(iii)(iii)iiii)", status.state, |
|
status.track, status.min, status.sec, status.frame, |
|
status.abs_min, status.abs_sec, status.abs_frame, |
|
status.total_min, status.total_sec, status.total_frame, |
|
status.first, status.last, status.scsi_audio, |
|
status.cur_block); |
|
} |
|
|
|
static PyObject * |
|
CD_gettrackinfo(cdplayerobject *self, PyObject *args) |
|
{ |
|
int track; |
|
CDTRACKINFO info; |
|
CDSTATUS status; |
|
|
|
if (!PyArg_ParseTuple(args, "i:gettrackinfo", &track)) |
|
return NULL; |
|
|
|
if (!CDgettrackinfo(self->ob_cdplayer, track, &info)) { |
|
if (CDgetstatus(self->ob_cdplayer, &status) && |
|
status.state == CD_NODISC) |
|
PyErr_SetString(CdError, "no disc in player"); |
|
else |
|
PyErr_SetString(CdError, "gettrackinfo failed"); |
|
return NULL; |
|
} |
|
|
|
return Py_BuildValue("((iii)(iii))", |
|
info.start_min, info.start_sec, info.start_frame, |
|
info.total_min, info.total_sec, info.total_frame); |
|
} |
|
|
|
static PyObject * |
|
CD_msftoblock(cdplayerobject *self, PyObject *args) |
|
{ |
|
int min, sec, frame; |
|
|
|
if (!PyArg_ParseTuple(args, "iii:msftoblock", &min, &sec, &frame)) |
|
return NULL; |
|
|
|
return PyInt_FromLong((long) CDmsftoblock(self->ob_cdplayer, |
|
min, sec, frame)); |
|
} |
|
|
|
static PyObject * |
|
CD_play(cdplayerobject *self, PyObject *args) |
|
{ |
|
int start, play; |
|
CDSTATUS status; |
|
|
|
if (!PyArg_ParseTuple(args, "ii:play", &start, &play)) |
|
return NULL; |
|
|
|
if (!CDplay(self->ob_cdplayer, start, play)) { |
|
if (CDgetstatus(self->ob_cdplayer, &status) && |
|
status.state == CD_NODISC) |
|
PyErr_SetString(CdError, "no disc in player"); |
|
else |
|
PyErr_SetString(CdError, "play failed"); |
|
return NULL; |
|
} |
|
|
|
Py_INCREF(Py_None); |
|
return Py_None; |
|
} |
|
|
|
static PyObject * |
|
CD_playabs(cdplayerobject *self, PyObject *args) |
|
{ |
|
int min, sec, frame, play; |
|
CDSTATUS status; |
|
|
|
if (!PyArg_ParseTuple(args, "iiii:playabs", &min, &sec, &frame, &play)) |
|
return NULL; |
|
|
|
if (!CDplayabs(self->ob_cdplayer, min, sec, frame, play)) { |
|
if (CDgetstatus(self->ob_cdplayer, &status) && |
|
status.state == CD_NODISC) |
|
PyErr_SetString(CdError, "no disc in player"); |
|
else |
|
PyErr_SetString(CdError, "playabs failed"); |
|
return NULL; |
|
} |
|
|
|
Py_INCREF(Py_None); |
|
return Py_None; |
|
} |
|
|
|
static PyObject * |
|
CD_playtrack(cdplayerobject *self, PyObject *args) |
|
{ |
|
int start, play; |
|
CDSTATUS status; |
|
|
|
if (!PyArg_ParseTuple(args, "ii:playtrack", &start, &play)) |
|
return NULL; |
|
|
|
if (!CDplaytrack(self->ob_cdplayer, start, play)) { |
|
if (CDgetstatus(self->ob_cdplayer, &status) && |
|
status.state == CD_NODISC) |
|
PyErr_SetString(CdError, "no disc in player"); |
|
else |
|
PyErr_SetString(CdError, "playtrack failed"); |
|
return NULL; |
|
} |
|
|
|
Py_INCREF(Py_None); |
|
return Py_None; |
|
} |
|
|
|
static PyObject * |
|
CD_playtrackabs(cdplayerobject *self, PyObject *args) |
|
{ |
|
int track, min, sec, frame, play; |
|
CDSTATUS status; |
|
|
|
if (!PyArg_ParseTuple(args, "iiiii:playtrackabs", &track, &min, &sec, |
|
&frame, &play)) |
|
return NULL; |
|
|
|
if (!CDplaytrackabs(self->ob_cdplayer, track, min, sec, frame, play)) { |
|
if (CDgetstatus(self->ob_cdplayer, &status) && |
|
status.state == CD_NODISC) |
|
PyErr_SetString(CdError, "no disc in player"); |
|
else |
|
PyErr_SetString(CdError, "playtrackabs failed"); |
|
return NULL; |
|
} |
|
|
|
Py_INCREF(Py_None); |
|
return Py_None; |
|
} |
|
|
|
static PyObject * |
|
CD_readda(cdplayerobject *self, PyObject *args) |
|
{ |
|
int numframes, n; |
|
PyObject *result; |
|
|
|
if (!PyArg_ParseTuple(args, "i:readda", &numframes)) |
|
return NULL; |
|
|
|
result = PyString_FromStringAndSize(NULL, numframes * sizeof(CDFRAME)); |
|
if (result == NULL) |
|
return NULL; |
|
|
|
n = CDreadda(self->ob_cdplayer, |
|
(CDFRAME *) PyString_AsString(result), numframes); |
|
if (n == -1) { |
|
Py_DECREF(result); |
|
PyErr_SetFromErrno(CdError); |
|
return NULL; |
|
} |
|
if (n < numframes) |
|
_PyString_Resize(&result, n * sizeof(CDFRAME)); |
|
|
|
return result; |
|
} |
|
|
|
static PyObject * |
|
CD_seek(cdplayerobject *self, PyObject *args) |
|
{ |
|
int min, sec, frame; |
|
long PyTryBlock; |
|
|
|
if (!PyArg_ParseTuple(args, "iii:seek", &min, &sec, &frame)) |
|
return NULL; |
|
|
|
PyTryBlock = CDseek(self->ob_cdplayer, min, sec, frame); |
|
if (PyTryBlock == -1) { |
|
PyErr_SetFromErrno(CdError); |
|
return NULL; |
|
} |
|
|
|
return PyInt_FromLong(PyTryBlock); |
|
} |
|
|
|
static PyObject * |
|
CD_seektrack(cdplayerobject *self, PyObject *args) |
|
{ |
|
int track; |
|
long PyTryBlock; |
|
|
|
if (!PyArg_ParseTuple(args, "i:seektrack", &track)) |
|
return NULL; |
|
|
|
PyTryBlock = CDseektrack(self->ob_cdplayer, track); |
|
if (PyTryBlock == -1) { |
|
PyErr_SetFromErrno(CdError); |
|
return NULL; |
|
} |
|
|
|
return PyInt_FromLong(PyTryBlock); |
|
} |
|
|
|
static PyObject * |
|
CD_seekblock(cdplayerobject *self, PyObject *args) |
|
{ |
|
unsigned long PyTryBlock; |
|
|
|
if (!PyArg_ParseTuple(args, "l:seekblock", &PyTryBlock)) |
|
return NULL; |
|
|
|
PyTryBlock = CDseekblock(self->ob_cdplayer, PyTryBlock); |
|
if (PyTryBlock == (unsigned long) -1) { |
|
PyErr_SetFromErrno(CdError); |
|
return NULL; |
|
} |
|
|
|
return PyInt_FromLong(PyTryBlock); |
|
} |
|
|
|
static PyObject * |
|
CD_stop(cdplayerobject *self, PyObject *args) |
|
{ |
|
CDSTATUS status; |
|
|
|
if (!PyArg_ParseTuple(args, ":stop")) |
|
return NULL; |
|
|
|
if (!CDstop(self->ob_cdplayer)) { |
|
if (CDgetstatus(self->ob_cdplayer, &status) && |
|
status.state == CD_NODISC) |
|
PyErr_SetString(CdError, "no disc in player"); |
|
else |
|
PyErr_SetString(CdError, "stop failed"); |
|
return NULL; |
|
} |
|
|
|
Py_INCREF(Py_None); |
|
return Py_None; |
|
} |
|
|
|
static PyObject * |
|
CD_togglepause(cdplayerobject *self, PyObject *args) |
|
{ |
|
CDSTATUS status; |
|
|
|
if (!PyArg_ParseTuple(args, ":togglepause")) |
|
return NULL; |
|
|
|
if (!CDtogglepause(self->ob_cdplayer)) { |
|
if (CDgetstatus(self->ob_cdplayer, &status) && |
|
status.state == CD_NODISC) |
|
PyErr_SetString(CdError, "no disc in player"); |
|
else |
|
PyErr_SetString(CdError, "togglepause failed"); |
|
return NULL; |
|
} |
|
|
|
Py_INCREF(Py_None); |
|
return Py_None; |
|
} |
|
|
|
static PyMethodDef cdplayer_methods[] = { |
|
{"allowremoval", (PyCFunction)CD_allowremoval, METH_VARARGS}, |
|
{"bestreadsize", (PyCFunction)CD_bestreadsize, METH_VARARGS}, |
|
{"close", (PyCFunction)CD_close, METH_VARARGS}, |
|
{"eject", (PyCFunction)CD_eject, METH_VARARGS}, |
|
{"getstatus", (PyCFunction)CD_getstatus, METH_VARARGS}, |
|
{"gettrackinfo", (PyCFunction)CD_gettrackinfo, METH_VARARGS}, |
|
{"msftoblock", (PyCFunction)CD_msftoblock, METH_VARARGS}, |
|
{"play", (PyCFunction)CD_play, METH_VARARGS}, |
|
{"playabs", (PyCFunction)CD_playabs, METH_VARARGS}, |
|
{"playtrack", (PyCFunction)CD_playtrack, METH_VARARGS}, |
|
{"playtrackabs", (PyCFunction)CD_playtrackabs, METH_VARARGS}, |
|
{"preventremoval", (PyCFunction)CD_preventremoval, METH_VARARGS}, |
|
{"readda", (PyCFunction)CD_readda, METH_VARARGS}, |
|
{"seek", (PyCFunction)CD_seek, METH_VARARGS}, |
|
{"seekblock", (PyCFunction)CD_seekblock, METH_VARARGS}, |
|
{"seektrack", (PyCFunction)CD_seektrack, METH_VARARGS}, |
|
{"stop", (PyCFunction)CD_stop, METH_VARARGS}, |
|
{"togglepause", (PyCFunction)CD_togglepause, METH_VARARGS}, |
|
{NULL, NULL} /* sentinel */ |
|
}; |
|
|
|
static void |
|
cdplayer_dealloc(cdplayerobject *self) |
|
{ |
|
if (self->ob_cdplayer != NULL) |
|
CDclose(self->ob_cdplayer); |
|
PyObject_Del(self); |
|
} |
|
|
|
static PyObject * |
|
cdplayer_getattr(cdplayerobject *self, char *name) |
|
{ |
|
if (self->ob_cdplayer == NULL) { |
|
PyErr_SetString(PyExc_RuntimeError, "no player active"); |
|
return NULL; |
|
} |
|
return Py_FindMethod(cdplayer_methods, (PyObject *)self, name); |
|
} |
|
|
|
PyTypeObject CdPlayertype = { |
|
PyObject_HEAD_INIT(&PyType_Type) |
|
0, /*ob_size*/ |
|
"cd.cdplayer", /*tp_name*/ |
|
sizeof(cdplayerobject), /*tp_size*/ |
|
0, /*tp_itemsize*/ |
|
/* methods */ |
|
(destructor)cdplayer_dealloc, /*tp_dealloc*/ |
|
0, /*tp_print*/ |
|
(getattrfunc)cdplayer_getattr, /*tp_getattr*/ |
|
0, /*tp_setattr*/ |
|
0, /*tp_compare*/ |
|
0, /*tp_repr*/ |
|
}; |
|
|
|
static PyObject * |
|
newcdplayerobject(CDPLAYER *cdp) |
|
{ |
|
cdplayerobject *p; |
|
|
|
p = PyObject_New(cdplayerobject, &CdPlayertype); |
|
if (p == NULL) |
|
return NULL; |
|
p->ob_cdplayer = cdp; |
|
return (PyObject *) p; |
|
} |
|
|
|
static PyObject * |
|
CD_open(PyObject *self, PyObject *args) |
|
{ |
|
char *dev, *direction; |
|
CDPLAYER *cdp; |
|
|
|
/* |
|
* Variable number of args. |
|
* First defaults to "None", second defaults to "r". |
|
*/ |
|
dev = NULL; |
|
direction = "r"; |
|
if (!PyArg_ParseTuple(args, "|zs:open", &dev, &direction)) |
|
return NULL; |
|
|
|
cdp = CDopen(dev, direction); |
|
if (cdp == NULL) { |
|
PyErr_SetFromErrno(CdError); |
|
return NULL; |
|
} |
|
|
|
return newcdplayerobject(cdp); |
|
} |
|
|
|
typedef struct { |
|
PyObject_HEAD |
|
CDPARSER *ob_cdparser; |
|
struct { |
|
PyObject *ob_cdcallback; |
|
PyObject *ob_cdcallbackarg; |
|
} ob_cdcallbacks[NCALLBACKS]; |
|
} cdparserobject; |
|
|
|
static void |
|
CD_callback(void *arg, CDDATATYPES type, void *data) |
|
{ |
|
PyObject *result, *args, *v = NULL; |
|
char *p; |
|
int i; |
|
cdparserobject *self; |
|
|
|
self = (cdparserobject *) arg; |
|
args = PyTuple_New(3); |
|
if (args == NULL) |
|
return; |
|
Py_INCREF(self->ob_cdcallbacks[type].ob_cdcallbackarg); |
|
PyTuple_SetItem(args, 0, self->ob_cdcallbacks[type].ob_cdcallbackarg); |
|
PyTuple_SetItem(args, 1, PyInt_FromLong((long) type)); |
|
switch (type) { |
|
case cd_audio: |
|
v = PyString_FromStringAndSize(data, CDDA_DATASIZE); |
|
break; |
|
case cd_pnum: |
|
case cd_index: |
|
v = PyInt_FromLong(((CDPROGNUM *) data)->value); |
|
break; |
|
case cd_ptime: |
|
case cd_atime: |
|
#define ptr ((struct cdtimecode *) data) |
|
v = Py_BuildValue("(iii)", |
|
ptr->mhi * 10 + ptr->mlo, |
|
ptr->shi * 10 + ptr->slo, |
|
ptr->fhi * 10 + ptr->flo); |
|
#undef ptr |
|
break; |
|
case cd_catalog: |
|
v = PyString_FromStringAndSize(NULL, 13); |
|
p = PyString_AsString(v); |
|
for (i = 0; i < 13; i++) |
|
*p++ = ((char *) data)[i] + '0'; |
|
break; |
|
case cd_ident: |
|
#define ptr ((struct cdident *) data) |
|
v = PyString_FromStringAndSize(NULL, 12); |
|
p = PyString_AsString(v); |
|
CDsbtoa(p, ptr->country, 2); |
|
p += 2; |
|
CDsbtoa(p, ptr->owner, 3); |
|
p += 3; |
|
*p++ = ptr->year[0] + '0'; |
|
*p++ = ptr->year[1] + '0'; |
|
*p++ = ptr->serial[0] + '0'; |
|
*p++ = ptr->serial[1] + '0'; |
|
*p++ = ptr->serial[2] + '0'; |
|
*p++ = ptr->serial[3] + '0'; |
|
*p++ = ptr->serial[4] + '0'; |
|
#undef ptr |
|
break; |
|
case cd_control: |
|
v = PyInt_FromLong((long) *((unchar *) data)); |
|
break; |
|
} |
|
PyTuple_SetItem(args, 2, v); |
|
if (PyErr_Occurred()) { |
|
Py_DECREF(args); |
|
return; |
|
} |
|
|
|
result = PyEval_CallObject(self->ob_cdcallbacks[type].ob_cdcallback, |
|
args); |
|
Py_DECREF(args); |
|
Py_XDECREF(result); |
|
} |
|
|
|
static PyObject * |
|
CD_deleteparser(cdparserobject *self, PyObject *args) |
|
{ |
|
int i; |
|
|
|
if (!PyArg_ParseTuple(args, ":deleteparser")) |
|
return NULL; |
|
|
|
CDdeleteparser(self->ob_cdparser); |
|
self->ob_cdparser = NULL; |
|
|
|
/* no sense in keeping the callbacks, so remove them */ |
|
for (i = 0; i < NCALLBACKS; i++) { |
|
Py_XDECREF(self->ob_cdcallbacks[i].ob_cdcallback); |
|
self->ob_cdcallbacks[i].ob_cdcallback = NULL; |
|
Py_XDECREF(self->ob_cdcallbacks[i].ob_cdcallbackarg); |
|
self->ob_cdcallbacks[i].ob_cdcallbackarg = NULL; |
|
} |
|
|
|
Py_INCREF(Py_None); |
|
return Py_None; |
|
} |
|
|
|
static PyObject * |
|
CD_parseframe(cdparserobject *self, PyObject *args) |
|
{ |
|
char *cdfp; |
|
int length; |
|
CDFRAME *p; |
|
|
|
if (!PyArg_ParseTuple(args, "s#:parseframe", &cdfp, &length)) |
|
return NULL; |
|
|
|
if (length % sizeof(CDFRAME) != 0) { |
|
PyErr_SetString(PyExc_TypeError, "bad length"); |
|
return NULL; |
|
} |
|
|
|
p = (CDFRAME *) cdfp; |
|
while (length > 0) { |
|
CDparseframe(self->ob_cdparser, p); |
|
length -= sizeof(CDFRAME); |
|
p++; |
|
if (PyErr_Occurred()) |
|
return NULL; |
|
} |
|
|
|
Py_INCREF(Py_None); |
|
return Py_None; |
|
} |
|
|
|
static PyObject * |
|
CD_removecallback(cdparserobject *self, PyObject *args) |
|
{ |
|
int type; |
|
|
|
if (!PyArg_ParseTuple(args, "i:removecallback", &type)) |
|
return NULL; |
|
|
|
if (type < 0 || type >= NCALLBACKS) { |
|
PyErr_SetString(PyExc_TypeError, "bad type"); |
|
return NULL; |
|
} |
|
|
|
CDremovecallback(self->ob_cdparser, (CDDATATYPES) type); |
|
|
|
Py_XDECREF(self->ob_cdcallbacks[type].ob_cdcallback); |
|
self->ob_cdcallbacks[type].ob_cdcallback = NULL; |
|
|
|
Py_XDECREF(self->ob_cdcallbacks[type].ob_cdcallbackarg); |
|
self->ob_cdcallbacks[type].ob_cdcallbackarg = NULL; |
|
|
|
Py_INCREF(Py_None); |
|
return Py_None; |
|
} |
|
|
|
static PyObject * |
|
CD_resetparser(cdparserobject *self, PyObject *args) |
|
{ |
|
if (!PyArg_ParseTuple(args, ":resetparser")) |
|
return NULL; |
|
|
|
CDresetparser(self->ob_cdparser); |
|
|
|
Py_INCREF(Py_None); |
|
return Py_None; |
|
} |
|
|
|
static PyObject * |
|
CD_addcallback(cdparserobject *self, PyObject *args) |
|
{ |
|
int type; |
|
PyObject *func, *funcarg; |
|
|
|
/* XXX - more work here */ |
|
if (!PyArg_ParseTuple(args, "iOO:addcallback", &type, &func, &funcarg)) |
|
return NULL; |
|
|
|
if (type < 0 || type >= NCALLBACKS) { |
|
PyErr_SetString(PyExc_TypeError, "argument out of range"); |
|
return NULL; |
|
} |
|
|
|
#ifdef CDsetcallback |
|
CDaddcallback(self->ob_cdparser, (CDDATATYPES) type, CD_callback, |
|
(void *) self); |
|
#else |
|
CDsetcallback(self->ob_cdparser, (CDDATATYPES) type, CD_callback, |
|
(void *) self); |
|
#endif |
|
Py_XDECREF(self->ob_cdcallbacks[type].ob_cdcallback); |
|
Py_INCREF(func); |
|
self->ob_cdcallbacks[type].ob_cdcallback = func; |
|
Py_XDECREF(self->ob_cdcallbacks[type].ob_cdcallbackarg); |
|
Py_INCREF(funcarg); |
|
self->ob_cdcallbacks[type].ob_cdcallbackarg = funcarg; |
|
|
|
/* |
|
if (type == cd_audio) { |
|
sigfpe_[_UNDERFL].repls = _ZERO; |
|
handle_sigfpes(_ON, _EN_UNDERFL, NULL, |
|
_ABORT_ON_ERROR, NULL); |
|
} |
|
*/ |
|
|
|
Py_INCREF(Py_None); |
|
return Py_None; |
|
} |
|
|
|
static PyMethodDef cdparser_methods[] = { |
|
{"addcallback", (PyCFunction)CD_addcallback, METH_VARARGS}, |
|
{"deleteparser", (PyCFunction)CD_deleteparser, METH_VARARGS}, |
|
{"parseframe", (PyCFunction)CD_parseframe, METH_VARARGS}, |
|
{"removecallback", (PyCFunction)CD_removecallback, METH_VARARGS}, |
|
{"resetparser", (PyCFunction)CD_resetparser, METH_VARARGS}, |
|
/* backward compatibility */ |
|
{"setcallback", (PyCFunction)CD_addcallback, METH_VARARGS}, |
|
{NULL, NULL} /* sentinel */ |
|
}; |
|
|
|
static void |
|
cdparser_dealloc(cdparserobject *self) |
|
{ |
|
int i; |
|
|
|
for (i = 0; i < NCALLBACKS; i++) { |
|
Py_XDECREF(self->ob_cdcallbacks[i].ob_cdcallback); |
|
self->ob_cdcallbacks[i].ob_cdcallback = NULL; |
|
Py_XDECREF(self->ob_cdcallbacks[i].ob_cdcallbackarg); |
|
self->ob_cdcallbacks[i].ob_cdcallbackarg = NULL; |
|
} |
|
CDdeleteparser(self->ob_cdparser); |
|
PyObject_Del(self); |
|
} |
|
|
|
static PyObject * |
|
cdparser_getattr(cdparserobject *self, char *name) |
|
{ |
|
if (self->ob_cdparser == NULL) { |
|
PyErr_SetString(PyExc_RuntimeError, "no parser active"); |
|
return NULL; |
|
} |
|
|
|
return Py_FindMethod(cdparser_methods, (PyObject *)self, name); |
|
} |
|
|
|
PyTypeObject CdParsertype = { |
|
PyObject_HEAD_INIT(&PyType_Type) |
|
0, /*ob_size*/ |
|
"cd.cdparser", /*tp_name*/ |
|
sizeof(cdparserobject), /*tp_size*/ |
|
0, /*tp_itemsize*/ |
|
/* methods */ |
|
(destructor)cdparser_dealloc, /*tp_dealloc*/ |
|
0, /*tp_print*/ |
|
(getattrfunc)cdparser_getattr, /*tp_getattr*/ |
|
0, /*tp_setattr*/ |
|
0, /*tp_compare*/ |
|
0, /*tp_repr*/ |
|
}; |
|
|
|
static PyObject * |
|
newcdparserobject(CDPARSER *cdp) |
|
{ |
|
cdparserobject *p; |
|
int i; |
|
|
|
p = PyObject_New(cdparserobject, &CdParsertype); |
|
if (p == NULL) |
|
return NULL; |
|
p->ob_cdparser = cdp; |
|
for (i = 0; i < NCALLBACKS; i++) { |
|
p->ob_cdcallbacks[i].ob_cdcallback = NULL; |
|
p->ob_cdcallbacks[i].ob_cdcallbackarg = NULL; |
|
} |
|
return (PyObject *) p; |
|
} |
|
|
|
static PyObject * |
|
CD_createparser(PyObject *self, PyObject *args) |
|
{ |
|
CDPARSER *cdp; |
|
|
|
if (!PyArg_ParseTuple(args, ":createparser")) |
|
return NULL; |
|
cdp = CDcreateparser(); |
|
if (cdp == NULL) { |
|
PyErr_SetString(CdError, "createparser failed"); |
|
return NULL; |
|
} |
|
|
|
return newcdparserobject(cdp); |
|
} |
|
|
|
static PyObject * |
|
CD_msftoframe(PyObject *self, PyObject *args) |
|
{ |
|
int min, sec, frame; |
|
|
|
if (!PyArg_ParseTuple(args, "iii:msftoframe", &min, &sec, &frame)) |
|
return NULL; |
|
|
|
return PyInt_FromLong((long) CDmsftoframe(min, sec, frame)); |
|
} |
|
|
|
static PyMethodDef CD_methods[] = { |
|
{"open", (PyCFunction)CD_open, METH_VARARGS}, |
|
{"createparser", (PyCFunction)CD_createparser, METH_VARARGS}, |
|
{"msftoframe", (PyCFunction)CD_msftoframe, METH_VARARGS}, |
|
{NULL, NULL} /* Sentinel */ |
|
}; |
|
|
|
void |
|
initcd(void) |
|
{ |
|
PyObject *m, *d; |
|
|
|
m = Py_InitModule("cd", CD_methods); |
|
d = PyModule_GetDict(m); |
|
|
|
CdError = PyErr_NewException("cd.error", NULL, NULL); |
|
PyDict_SetItemString(d, "error", CdError); |
|
|
|
/* Identifiers for the different types of callbacks from the parser */ |
|
PyDict_SetItemString(d, "audio", PyInt_FromLong((long) cd_audio)); |
|
PyDict_SetItemString(d, "pnum", PyInt_FromLong((long) cd_pnum)); |
|
PyDict_SetItemString(d, "index", PyInt_FromLong((long) cd_index)); |
|
PyDict_SetItemString(d, "ptime", PyInt_FromLong((long) cd_ptime)); |
|
PyDict_SetItemString(d, "atime", PyInt_FromLong((long) cd_atime)); |
|
PyDict_SetItemString(d, "catalog", PyInt_FromLong((long) cd_catalog)); |
|
PyDict_SetItemString(d, "ident", PyInt_FromLong((long) cd_ident)); |
|
PyDict_SetItemString(d, "control", PyInt_FromLong((long) cd_control)); |
|
|
|
/* Block size information for digital audio data */ |
|
PyDict_SetItemString(d, "DATASIZE", |
|
PyInt_FromLong((long) CDDA_DATASIZE)); |
|
PyDict_SetItemString(d, "BLOCKSIZE", |
|
PyInt_FromLong((long) CDDA_BLOCKSIZE)); |
|
|
|
/* Possible states for the cd player */ |
|
PyDict_SetItemString(d, "ERROR", PyInt_FromLong((long) CD_ERROR)); |
|
PyDict_SetItemString(d, "NODISC", PyInt_FromLong((long) CD_NODISC)); |
|
PyDict_SetItemString(d, "READY", PyInt_FromLong((long) CD_READY)); |
|
PyDict_SetItemString(d, "PLAYING", PyInt_FromLong((long) CD_PLAYING)); |
|
PyDict_SetItemString(d, "PAUSED", PyInt_FromLong((long) CD_PAUSED)); |
|
PyDict_SetItemString(d, "STILL", PyInt_FromLong((long) CD_STILL)); |
|
#ifdef CD_CDROM /* only newer versions of the library */ |
|
PyDict_SetItemString(d, "CDROM", PyInt_FromLong((long) CD_CDROM)); |
|
#endif |
|
}
|
|
|