mirror of https://github.com/python/cpython
899 lines
18 KiB
C
899 lines
18 KiB
C
/**********************************************************
|
|
Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
|
|
The Netherlands.
|
|
|
|
All Rights Reserved
|
|
|
|
Permission to use, copy, modify, and distribute this software and its
|
|
documentation for any purpose and without fee is hereby granted,
|
|
provided that the above copyright notice appear in all copies and that
|
|
both that copyright notice and this permission notice appear in
|
|
supporting documentation, and that the names of Stichting Mathematisch
|
|
Centrum or CWI not be used in advertising or publicity pertaining to
|
|
distribution of the software without specific, written prior permission.
|
|
|
|
STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
|
|
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
|
|
FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
|
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
******************************************************************/
|
|
|
|
/* CD module -- interface to Mark Callow's and Roger Chickering's */
|
|
/* CD Audio Library (CD). */
|
|
|
|
#include <sys/types.h>
|
|
#include <cdaudio.h>
|
|
#include "allobjects.h"
|
|
#include "import.h"
|
|
#include "modsupport.h"
|
|
#include "ceval.h"
|
|
|
|
#define NCALLBACKS 8
|
|
|
|
typedef struct {
|
|
OB_HEAD
|
|
CDPLAYER *ob_cdplayer;
|
|
} cdplayerobject;
|
|
|
|
#define CheckPlayer(self) if ((self)->ob_cdplayer == NULL) { \
|
|
err_setstr(RuntimeError, "no player active"); \
|
|
return NULL; \
|
|
}
|
|
#define CheckParser(self) if ((self)->ob_cdparser == NULL) { \
|
|
err_setstr(RuntimeError, "no parser active"); \
|
|
return NULL; \
|
|
}
|
|
|
|
static object *CdError; /* exception cd.error */
|
|
|
|
static object *
|
|
CD_allowremoval(self, args)
|
|
cdplayerobject *self;
|
|
object *args;
|
|
{
|
|
CheckPlayer(self);
|
|
|
|
if (!getnoarg(args))
|
|
return NULL;
|
|
|
|
CDallowremoval(self->ob_cdplayer);
|
|
|
|
INCREF(None);
|
|
return None;
|
|
}
|
|
|
|
static object *
|
|
CD_preventremoval(self, args)
|
|
cdplayerobject *self;
|
|
object *args;
|
|
{
|
|
CheckPlayer(self);
|
|
|
|
if (!getnoarg(args))
|
|
return NULL;
|
|
|
|
CDpreventremoval(self->ob_cdplayer);
|
|
|
|
INCREF(None);
|
|
return None;
|
|
}
|
|
|
|
static object *
|
|
CD_bestreadsize(self, args)
|
|
cdplayerobject *self;
|
|
object *args;
|
|
{
|
|
CheckPlayer(self);
|
|
|
|
if (!getnoarg(args))
|
|
return NULL;
|
|
|
|
return newintobject((long) CDbestreadsize(self->ob_cdplayer));
|
|
}
|
|
|
|
static object *
|
|
CD_close(self, args)
|
|
cdplayerobject *self;
|
|
object *args;
|
|
{
|
|
CheckPlayer(self);
|
|
|
|
if (!getnoarg(args))
|
|
return NULL;
|
|
|
|
if (!CDclose(self->ob_cdplayer)) {
|
|
err_errno(CdError); /* XXX - ??? */
|
|
return NULL;
|
|
}
|
|
self->ob_cdplayer = NULL;
|
|
|
|
INCREF(None);
|
|
return None;
|
|
}
|
|
|
|
static object *
|
|
CD_eject(self, args)
|
|
cdplayerobject *self;
|
|
object *args;
|
|
{
|
|
CDSTATUS status;
|
|
|
|
CheckPlayer(self);
|
|
|
|
if (!getnoarg(args))
|
|
return NULL;
|
|
|
|
if (!CDeject(self->ob_cdplayer)) {
|
|
if (CDgetstatus(self->ob_cdplayer, &status) &&
|
|
status.state == CD_NODISC)
|
|
err_setstr(CdError, "no disc in player");
|
|
else
|
|
err_setstr(CdError, "eject failed");
|
|
return NULL;
|
|
}
|
|
|
|
INCREF(None);
|
|
return None;
|
|
}
|
|
|
|
static object *
|
|
CD_getstatus(self, args)
|
|
cdplayerobject *self;
|
|
object *args;
|
|
{
|
|
CDSTATUS status;
|
|
|
|
CheckPlayer(self);
|
|
|
|
if (!getnoarg(args))
|
|
return NULL;
|
|
|
|
if (!CDgetstatus(self->ob_cdplayer, &status)) {
|
|
err_errno(CdError); /* XXX - ??? */
|
|
return NULL;
|
|
}
|
|
|
|
return mkvalue("(ii(iii)(iii)(iii)iiii(iii))", 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, status.polyfilla[0],
|
|
status.polyfilla[1], status.polyfilla[2]);
|
|
}
|
|
|
|
static object *
|
|
CD_gettrackinfo(self, args)
|
|
cdplayerobject *self;
|
|
object *args;
|
|
{
|
|
int track;
|
|
CDTRACKINFO info;
|
|
CDSTATUS status;
|
|
|
|
CheckPlayer(self);
|
|
|
|
if (!getargs(args, "i", &track))
|
|
return NULL;
|
|
|
|
if (!CDgettrackinfo(self->ob_cdplayer, track, &info)) {
|
|
if (CDgetstatus(self->ob_cdplayer, &status) &&
|
|
status.state == CD_NODISC)
|
|
err_setstr(CdError, "no disc in player");
|
|
else
|
|
err_setstr(CdError, "gettrackinfo failed");
|
|
return NULL;
|
|
}
|
|
|
|
return mkvalue("((iii)(iii))",
|
|
info.start_min, info.start_sec, info.start_frame,
|
|
info.total_min, info.total_sec, info.total_frame);
|
|
}
|
|
|
|
static object *
|
|
CD_msftoblock(self, args)
|
|
cdplayerobject *self;
|
|
object *args;
|
|
{
|
|
int min, sec, frame;
|
|
unsigned long block;
|
|
|
|
CheckPlayer(self);
|
|
|
|
if (!getargs(args, "(iii)", &min, &sec, &frame))
|
|
return NULL;
|
|
|
|
block = CDmsftoblock(self->ob_cdplayer, min, sec, frame);
|
|
return newintobject((long) block);
|
|
}
|
|
|
|
static object *
|
|
CD_play(self, args)
|
|
cdplayerobject *self;
|
|
object *args;
|
|
{
|
|
int start, play;
|
|
CDSTATUS status;
|
|
|
|
CheckPlayer(self);
|
|
|
|
if (!getargs(args, "(ii)", &start, &play))
|
|
return NULL;
|
|
|
|
if (!CDplay(self->ob_cdplayer, start, play)) {
|
|
if (CDgetstatus(self->ob_cdplayer, &status) &&
|
|
status.state == CD_NODISC)
|
|
err_setstr(CdError, "no disc in player");
|
|
else
|
|
err_setstr(CdError, "play failed");
|
|
return NULL;
|
|
}
|
|
|
|
INCREF(None);
|
|
return None;
|
|
}
|
|
|
|
static object *
|
|
CD_playabs(self, args)
|
|
cdplayerobject *self;
|
|
object *args;
|
|
{
|
|
int min, sec, frame, play;
|
|
CDSTATUS status;
|
|
|
|
CheckPlayer(self);
|
|
|
|
if (!getargs(args, "(iiii)", &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)
|
|
err_setstr(CdError, "no disc in player");
|
|
else
|
|
err_setstr(CdError, "playabs failed");
|
|
return NULL;
|
|
}
|
|
|
|
INCREF(None);
|
|
return None;
|
|
}
|
|
|
|
static object *
|
|
CD_playtrack(self, args)
|
|
cdplayerobject *self;
|
|
object *args;
|
|
{
|
|
int start, play;
|
|
CDSTATUS status;
|
|
|
|
CheckPlayer(self);
|
|
|
|
if (!getargs(args, "(ii)", &start, &play))
|
|
return NULL;
|
|
|
|
if (!CDplaytrack(self->ob_cdplayer, start, play)) {
|
|
if (CDgetstatus(self->ob_cdplayer, &status) &&
|
|
status.state == CD_NODISC)
|
|
err_setstr(CdError, "no disc in player");
|
|
else
|
|
err_setstr(CdError, "playtrack failed");
|
|
return NULL;
|
|
}
|
|
|
|
INCREF(None);
|
|
return None;
|
|
}
|
|
|
|
static object *
|
|
CD_playtrackabs(self, args)
|
|
cdplayerobject *self;
|
|
object *args;
|
|
{
|
|
int track, min, sec, frame, play;
|
|
CDSTATUS status;
|
|
|
|
CheckPlayer(self);
|
|
|
|
if (!getargs(args, "(iiiii)", &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)
|
|
err_setstr(CdError, "no disc in player");
|
|
else
|
|
err_setstr(CdError, "playtrackabs failed");
|
|
return NULL;
|
|
}
|
|
|
|
INCREF(None);
|
|
return None;
|
|
}
|
|
|
|
static object *
|
|
CD_readda(self, args)
|
|
cdplayerobject *self;
|
|
object *args;
|
|
{
|
|
int numframes, n;
|
|
object *result;
|
|
|
|
CheckPlayer(self);
|
|
|
|
if (!getargs(args, "i", &numframes))
|
|
return NULL;
|
|
|
|
result = newsizedstringobject(NULL, numframes * sizeof(CDFRAME));
|
|
if (result == NULL)
|
|
return NULL;
|
|
|
|
n = CDreadda(self->ob_cdplayer, (CDFRAME *) getstringvalue(result), numframes);
|
|
if (n == -1) {
|
|
DECREF(result);
|
|
err_errno(CdError);
|
|
return NULL;
|
|
}
|
|
if (n < numframes)
|
|
if (resizestring(&result, n * sizeof(CDFRAME)))
|
|
return NULL;
|
|
|
|
return result;
|
|
}
|
|
|
|
static object *
|
|
CD_seek(self, args)
|
|
cdplayerobject *self;
|
|
object *args;
|
|
{
|
|
int min, sec, frame;
|
|
long block;
|
|
|
|
CheckPlayer(self);
|
|
|
|
if (!getargs(args, "(iii)", &min, &sec, &frame))
|
|
return NULL;
|
|
|
|
block = CDseek(self->ob_cdplayer, min, sec, frame);
|
|
if (block == -1) {
|
|
err_errno(CdError);
|
|
return NULL;
|
|
}
|
|
|
|
return newintobject(block);
|
|
}
|
|
|
|
static object *
|
|
CD_seektrack(self, args)
|
|
cdplayerobject *self;
|
|
object *args;
|
|
{
|
|
int track;
|
|
long block;
|
|
|
|
CheckPlayer(self);
|
|
|
|
if (!getargs(args, "i", &track))
|
|
return NULL;
|
|
|
|
block = CDseektrack(self->ob_cdplayer, track);
|
|
if (block == -1) {
|
|
err_errno(CdError);
|
|
return NULL;
|
|
}
|
|
|
|
return newintobject(block);
|
|
}
|
|
|
|
static object *
|
|
CD_stop(self, args)
|
|
cdplayerobject *self;
|
|
object *args;
|
|
{
|
|
CDSTATUS status;
|
|
|
|
CheckPlayer(self);
|
|
|
|
if (!getnoarg(args))
|
|
return NULL;
|
|
|
|
if (!CDstop(self->ob_cdplayer)) {
|
|
if (CDgetstatus(self->ob_cdplayer, &status) &&
|
|
status.state == CD_NODISC)
|
|
err_setstr(CdError, "no disc in player");
|
|
else
|
|
err_setstr(CdError, "stop failed");
|
|
return NULL;
|
|
}
|
|
|
|
INCREF(None);
|
|
return None;
|
|
}
|
|
|
|
static object *
|
|
CD_togglepause(self, args)
|
|
cdplayerobject *self;
|
|
object *args;
|
|
{
|
|
CDSTATUS status;
|
|
|
|
CheckPlayer(self);
|
|
|
|
if (!getnoarg(args))
|
|
return NULL;
|
|
|
|
if (!CDtogglepause(self->ob_cdplayer)) {
|
|
if (CDgetstatus(self->ob_cdplayer, &status) &&
|
|
status.state == CD_NODISC)
|
|
err_setstr(CdError, "no disc in player");
|
|
else
|
|
err_setstr(CdError, "togglepause failed");
|
|
return NULL;
|
|
}
|
|
|
|
INCREF(None);
|
|
return None;
|
|
}
|
|
|
|
static struct methodlist cdplayer_methods[] = {
|
|
{"allowremoval", (method)CD_allowremoval},
|
|
{"bestreadsize", (method)CD_bestreadsize},
|
|
{"close", (method)CD_close},
|
|
{"eject", (method)CD_eject},
|
|
{"getstatus", (method)CD_getstatus},
|
|
{"gettrackinfo", (method)CD_gettrackinfo},
|
|
{"msftoblock", (method)CD_msftoblock},
|
|
{"play", (method)CD_play},
|
|
{"playabs", (method)CD_playabs},
|
|
{"playtrack", (method)CD_playtrack},
|
|
{"playtrackabs", (method)CD_playtrackabs},
|
|
{"preventremoval", (method)CD_preventremoval},
|
|
{"readda", (method)CD_readda},
|
|
{"seek", (method)CD_seek},
|
|
{"seektrack", (method)CD_seektrack},
|
|
{"stop", (method)CD_stop},
|
|
{"togglepause", (method)CD_togglepause},
|
|
{NULL, NULL} /* sentinel */
|
|
};
|
|
|
|
static void
|
|
cdplayer_dealloc(self)
|
|
cdplayerobject *self;
|
|
{
|
|
if (self->ob_cdplayer != NULL)
|
|
CDclose(self->ob_cdplayer);
|
|
DEL(self);
|
|
}
|
|
|
|
static object *
|
|
cdplayer_getattr(cdp, name)
|
|
cdplayerobject *cdp;
|
|
char *name;
|
|
{
|
|
return findmethod(cdplayer_methods, (object *)cdp, name);
|
|
}
|
|
|
|
typeobject CdPlayertype = {
|
|
OB_HEAD_INIT(&Typetype)
|
|
0, /*ob_size*/
|
|
"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 object *
|
|
newcdplayerobject(cdp)
|
|
CDPLAYER *cdp;
|
|
{
|
|
cdplayerobject *p;
|
|
|
|
p = NEWOBJ(cdplayerobject, &CdPlayertype);
|
|
if (p == NULL)
|
|
return NULL;
|
|
p->ob_cdplayer = cdp;
|
|
return (object *) p;
|
|
}
|
|
|
|
static object *
|
|
CD_open(self, args)
|
|
object *self, *args;
|
|
{
|
|
char *dev, *direction;
|
|
CDPLAYER *cdp;
|
|
|
|
/*
|
|
* Variable number of args.
|
|
* First defaults to "None", second defaults to "r".
|
|
*/
|
|
dev = NULL;
|
|
direction = "r";
|
|
if (!getnoarg(args)) {
|
|
err_clear();
|
|
if (!getargs(args, "z", &dev)) {
|
|
err_clear();
|
|
if (!getargs(args, "(zs)", &dev, &direction))
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
cdp = CDopen(dev, direction);
|
|
if (cdp == NULL) {
|
|
err_errno(CdError);
|
|
return NULL;
|
|
}
|
|
|
|
return newcdplayerobject(cdp);
|
|
}
|
|
|
|
typedef struct {
|
|
OB_HEAD
|
|
CDPARSER *ob_cdparser;
|
|
struct {
|
|
object *ob_cdcallback;
|
|
object *ob_cdcallbackarg;
|
|
} ob_cdcallbacks[NCALLBACKS];
|
|
} cdparserobject;
|
|
|
|
static void
|
|
CD_callback(arg, type, data)
|
|
void *arg;
|
|
CDDATATYPES type;
|
|
void *data;
|
|
{
|
|
object *result, *args, *v;
|
|
char *p;
|
|
int i;
|
|
cdparserobject *self;
|
|
|
|
self = (cdparserobject *) arg;
|
|
args = newtupleobject(3);
|
|
if (args == NULL)
|
|
return;
|
|
INCREF(self->ob_cdcallbacks[type].ob_cdcallbackarg);
|
|
settupleitem(args, 0, self->ob_cdcallbacks[type].ob_cdcallbackarg);
|
|
settupleitem(args, 1, newintobject((long) type));
|
|
switch (type) {
|
|
case cd_audio:
|
|
v = newsizedstringobject(data, CDDA_DATASIZE);
|
|
break;
|
|
case cd_pnum:
|
|
case cd_index:
|
|
v = newintobject(((CDPROGNUM *) data)->value);
|
|
break;
|
|
case cd_ptime:
|
|
case cd_atime:
|
|
#define ptr ((struct cdtimecode *) data)
|
|
v = mkvalue("(iii)", ptr->mhi * 10 + ptr->mlo,
|
|
ptr->shi * 10 + ptr->slo,
|
|
ptr->fhi * 10 + ptr->flo);
|
|
#undef ptr
|
|
break;
|
|
case cd_catalog:
|
|
v = newsizedstringobject(NULL, 13);
|
|
p = getstringvalue(v);
|
|
for (i = 0; i < 13; i++)
|
|
*p++ = ((char *) data)[i] + '0';
|
|
break;
|
|
case cd_ident:
|
|
v = newsizedstringobject(NULL, 12);
|
|
p = getstringvalue(v);
|
|
CDsbtoa(p, ((struct cdident *) data)->country, 2);
|
|
p += 2;
|
|
CDsbtoa(p, ((struct cdident *) data)->owner, 3);
|
|
p += 3;
|
|
*p++ = ((struct cdident *) data)->year[0] + '0';
|
|
*p++ = ((struct cdident *) data)->year[1] + '0';
|
|
*p++ = ((struct cdident *) data)->serial[0] + '0';
|
|
*p++ = ((struct cdident *) data)->serial[1] + '0';
|
|
*p++ = ((struct cdident *) data)->serial[2] + '0';
|
|
*p++ = ((struct cdident *) data)->serial[3] + '0';
|
|
*p++ = ((struct cdident *) data)->serial[4] + '0';
|
|
break;
|
|
case cd_control:
|
|
v = newintobject((long) *((unchar *) data));
|
|
break;
|
|
}
|
|
settupleitem(args, 2, v);
|
|
if (err_occurred()) {
|
|
DECREF(args);
|
|
return;
|
|
}
|
|
|
|
result = call_object(self->ob_cdcallbacks[type].ob_cdcallback, args);
|
|
DECREF(args);
|
|
XDECREF(result);
|
|
}
|
|
|
|
static object *
|
|
CD_deleteparser(self, args)
|
|
cdparserobject *self;
|
|
object *args;
|
|
{
|
|
int i;
|
|
|
|
CheckParser(self);
|
|
|
|
if (!getnoarg(args))
|
|
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++) {
|
|
XDECREF(self->ob_cdcallbacks[i].ob_cdcallback);
|
|
self->ob_cdcallbacks[i].ob_cdcallback = NULL;
|
|
XDECREF(self->ob_cdcallbacks[i].ob_cdcallbackarg);
|
|
self->ob_cdcallbacks[i].ob_cdcallbackarg = NULL;
|
|
}
|
|
|
|
INCREF(None);
|
|
return None;
|
|
}
|
|
|
|
static object *
|
|
CD_parseframe(self, args)
|
|
cdparserobject *self;
|
|
object *args;
|
|
{
|
|
char *cdfp;
|
|
int length;
|
|
CDFRAME *p;
|
|
|
|
CheckParser(self);
|
|
|
|
if (!getargs(args, "s#", &cdfp, &length))
|
|
return NULL;
|
|
|
|
if (length % sizeof(CDFRAME) != 0) {
|
|
err_setstr(TypeError, "bad length");
|
|
return NULL;
|
|
}
|
|
|
|
p = (CDFRAME *) cdfp;
|
|
while (length > 0) {
|
|
CDparseframe(self->ob_cdparser, p);
|
|
length -= sizeof(CDFRAME);
|
|
p++;
|
|
if (err_occurred())
|
|
return NULL;
|
|
}
|
|
|
|
INCREF(None);
|
|
return None;
|
|
}
|
|
|
|
static object *
|
|
CD_removecallback(self, args)
|
|
cdparserobject *self;
|
|
object *args;
|
|
{
|
|
int type;
|
|
|
|
CheckParser(self);
|
|
|
|
if (!getargs(args, "i", &type))
|
|
return NULL;
|
|
|
|
if (type < 0 || type >= NCALLBACKS) {
|
|
err_setstr(TypeError, "bad type");
|
|
return NULL;
|
|
}
|
|
|
|
CDremovecallback(self->ob_cdparser, (CDDATATYPES) type);
|
|
|
|
XDECREF(self->ob_cdcallbacks[type].ob_cdcallback);
|
|
self->ob_cdcallbacks[type].ob_cdcallback = NULL;
|
|
|
|
XDECREF(self->ob_cdcallbacks[type].ob_cdcallbackarg);
|
|
self->ob_cdcallbacks[type].ob_cdcallbackarg = NULL;
|
|
|
|
INCREF(None);
|
|
return None;
|
|
}
|
|
|
|
static object *
|
|
CD_resetparser(self, args)
|
|
cdparserobject *self;
|
|
object *args;
|
|
{
|
|
CheckParser(self);
|
|
|
|
if (!getnoarg(args))
|
|
return NULL;
|
|
|
|
CDresetparser(self->ob_cdparser);
|
|
|
|
INCREF(None);
|
|
return None;
|
|
}
|
|
|
|
static object *
|
|
CD_addcallback(self, args)
|
|
cdparserobject *self;
|
|
object *args;
|
|
{
|
|
int type;
|
|
object *func, *funcarg;
|
|
|
|
CheckParser(self);
|
|
|
|
/* XXX - more work here */
|
|
if (!getargs(args, "(iOO)", &type, &func, &funcarg))
|
|
return NULL;
|
|
|
|
if (type < 0 || type >= NCALLBACKS) {
|
|
err_setstr(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
|
|
XDECREF(self->ob_cdcallbacks[type].ob_cdcallback);
|
|
INCREF(func);
|
|
self->ob_cdcallbacks[type].ob_cdcallback = func;
|
|
XDECREF(self->ob_cdcallbacks[type].ob_cdcallbackarg);
|
|
INCREF(funcarg);
|
|
self->ob_cdcallbacks[type].ob_cdcallbackarg = funcarg;
|
|
|
|
INCREF(None);
|
|
return None;
|
|
}
|
|
|
|
static struct methodlist cdparser_methods[] = {
|
|
{"addcallback", (method)CD_addcallback},
|
|
{"deleteparser", (method)CD_deleteparser},
|
|
{"parseframe", (method)CD_parseframe},
|
|
{"removecallback", (method)CD_removecallback},
|
|
{"resetparser", (method)CD_resetparser},
|
|
{"setcallback", (method)CD_addcallback}, /* backward compatibility */
|
|
{NULL, NULL} /* sentinel */
|
|
};
|
|
|
|
static void
|
|
cdparser_dealloc(self)
|
|
cdparserobject *self;
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < NCALLBACKS; i++) {
|
|
XDECREF(self->ob_cdcallbacks[i].ob_cdcallback);
|
|
self->ob_cdcallbacks[i].ob_cdcallback = NULL;
|
|
XDECREF(self->ob_cdcallbacks[i].ob_cdcallbackarg);
|
|
self->ob_cdcallbacks[i].ob_cdcallbackarg = NULL;
|
|
}
|
|
CDdeleteparser(self->ob_cdparser);
|
|
DEL(self);
|
|
}
|
|
|
|
static object *
|
|
cdparser_getattr(cdp, name)
|
|
cdparserobject *cdp;
|
|
char *name;
|
|
{
|
|
return findmethod(cdparser_methods, (object *)cdp, name);
|
|
}
|
|
|
|
typeobject CdParsertype = {
|
|
OB_HEAD_INIT(&Typetype)
|
|
0, /*ob_size*/
|
|
"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 object *
|
|
newcdparserobject(cdp)
|
|
CDPARSER *cdp;
|
|
{
|
|
cdparserobject *p;
|
|
int i;
|
|
|
|
p = NEWOBJ(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 (object *) p;
|
|
}
|
|
|
|
static object *
|
|
CD_createparser(self, args)
|
|
object *self, *args;
|
|
{
|
|
CDPARSER *cdp;
|
|
|
|
if (!getnoarg(args))
|
|
return NULL;
|
|
cdp = CDcreateparser();
|
|
if (cdp == NULL) {
|
|
err_setstr(CdError, "createparser failed");
|
|
return NULL;
|
|
}
|
|
|
|
return newcdparserobject(cdp);
|
|
}
|
|
|
|
static object *
|
|
CD_sbtoa(self, args)
|
|
object *self;
|
|
object *args;
|
|
{
|
|
char *sb;
|
|
int length;
|
|
object *result;
|
|
|
|
if (!getargs(args, "s#", &sb, &length))
|
|
return NULL;
|
|
result = newsizedstringobject(NULL, length);
|
|
CDsbtoa(getstringvalue(result), (unchar *) sb, length);
|
|
return result;
|
|
}
|
|
|
|
static object *
|
|
CD_timetoa(self, args)
|
|
object *self;
|
|
object *args;
|
|
{
|
|
char *tc;
|
|
int length;
|
|
object *result;
|
|
|
|
if (!getargs(args, "s#", &tc, &length))
|
|
return NULL;
|
|
|
|
if (length != sizeof(struct cdtimecode)) {
|
|
err_setstr(TypeError, "bad length");
|
|
return NULL;
|
|
}
|
|
|
|
result = newsizedstringobject(NULL, 8);
|
|
CDtimetoa(getstringvalue(result), (struct cdtimecode *) tc);
|
|
return result;
|
|
}
|
|
|
|
static struct methodlist CD_methods[] = {
|
|
{"sbtoa", (method)CD_sbtoa},
|
|
{"open", (method)CD_open},
|
|
{"createparser",(method)CD_createparser},
|
|
{"timetoa", (method)CD_timetoa},
|
|
{NULL, NULL} /* Sentinel */
|
|
};
|
|
|
|
void
|
|
initcd()
|
|
{
|
|
object *m, *d;
|
|
|
|
m = initmodule("cd", CD_methods);
|
|
d = getmoduledict(m);
|
|
|
|
CdError = newstringobject("cd.error");
|
|
if (CdError == NULL || dictinsert(d, "error", CdError) != 0)
|
|
fatal("can't define cd.error");
|
|
}
|