Staging
v0.5.1
v0.5.1
https://github.com/python/cpython
Tip revision: 74f4bd53e03ded8408bcc2de67cf0f5a4ac5b1a1 authored by Barry Warsaw on 23 February 2012, 15:59:38 UTC
Bump some more copyright years (as per PEP 101), since this is the first
Bump some more copyright years (as per PEP 101), since this is the first
Tip revision: 74f4bd5
cdmodule.c
/* 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;
if (PyErr_WarnPy3k("the cd module has been removed in "
"Python 3.0", 2) < 0)
return;
m = Py_InitModule("cd", CD_methods);
if (m == NULL)
return;
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
}