[Python-checkins] python/dist/src/Modules ossaudiodev.c,1.7,1.8

gward@users.sourceforge.net gward@users.sourceforge.net
2002年12月11日 07:12:04 -0800


Update of /cvsroot/python/python/dist/src/Modules
In directory sc8-pr-cvs1:/tmp/cvs-serv9539/Modules
Modified Files:
	ossaudiodev.c 
Log Message:
Add OSS mixer interface (from Nicholas FitzRoy-Dale <wzdd@lardcave.net>):
 * add oss_mixer_t and OSSMixerType
 * add newossmixerobject(), oss_mixer_dealloc(), ossopenmixer()
 * add _do_ioctl_1_internal() to support mixer ioctls
 * add mixer methods: oss_mixer_{close,fileno,channels,stereo_channels,
 rec_channels,getvol,setvol,getrecsrc,setrecsrc}()
 * add oss_mixer_methods list
 * add oss_mixer_getattr() (why?!)
 * export SOUND_MIXER_* constants from soundcard.h
Index: ossaudiodev.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Modules/ossaudiodev.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -C2 -d -r1.7 -r1.8
*** ossaudiodev.c	11 Dec 2002 14:49:59 -0000	1.7
--- ossaudiodev.c	11 Dec 2002 15:12:01 -0000	1.8
***************
*** 9,12 ****
--- 9,13 ----
 * Renamed to ossaudiodev and rearranged/revised/hacked up
 * by Greg Ward <gward@python.net>, November 2002.
+ * Mixer interface by Nicholas FitzRoy-Dale <wzdd@lardcave.net>, Dec 2002.
 * 
 * (c) 2000 Peter Bosch. All Rights Reserved.
***************
*** 54,57 ****
--- 55,63 ----
 } oss_t;
 
+ typedef struct {
+ PyObject_HEAD;
+ int	x_fd;	/* The open mixer device */
+ } oss_mixer_t;
+ 
 /* XXX several format defined in soundcard.h are not supported,
 including _NE (native endian) options and S32 options
***************
*** 77,80 ****
--- 83,87 ----
 
 static PyTypeObject OSSType;
+ static PyTypeObject OSSMixerType;
 
 static PyObject *OSSAudioError;
***************
*** 155,158 ****
--- 162,217 ----
 }
 
+ static oss_mixer_t *
+ newossmixerobject(PyObject *arg)
+ {
+ char *basedev = NULL, *mode = NULL;
+ int fd, imode;
+ oss_mixer_t *xp;
+ 
+ if (!PyArg_ParseTuple (arg, "|ss", &basedev, &mode)) {
+ 	return NULL;
+ }
+ 
+ if (basedev == NULL) {
+ 	basedev = getenv("MIXERDEV");
+ 	if (basedev == NULL)	 	/* MIXERDEV not set */
+ 	 basedev = "/dev/mixer";
+ }
+ 
+ if (mode == NULL || strcmp(mode, "r") == 0)
+ imode = O_RDONLY;
+ else if (strcmp(mode, "w") == 0)
+ imode = O_WRONLY;
+ else if (strcmp(mode, "rw") == 0)
+ imode = O_RDWR;
+ else {
+ PyErr_SetString(OSSAudioError, "mode must be 'r', 'w', or 'rw'");
+ return NULL;
+ }
+ 
+ if ((fd = open (basedev, imode)) == -1) {
+ PyErr_SetFromErrnoWithFilename(PyExc_IOError, basedev);
+ return NULL;
+ }
+ 
+ if ((xp = PyObject_New(oss_mixer_t, &OSSMixerType)) == NULL) {
+ close(fd);
+ return NULL;
+ }
+ 
+ xp->x_fd = fd;
+ 
+ return xp;
+ }
+ 
+ static void
+ oss_mixer_dealloc(oss_mixer_t *xp)
+ {
+ /* if already closed, don't reclose it */
+ if (xp->x_fd != -1)
+ 	close(xp->x_fd);
+ PyObject_Del(xp);
+ }
+ 
 
 /* Methods to wrap the OSS ioctls. The calling convention is pretty
***************
*** 189,192 ****
--- 248,278 ----
 }
 
+ /* _do_ioctl_1_internal() is a wrapper for ioctls that take no inputs
+ but return an output -- ie. we need to pass a pointer to a local C
+ variable so the driver can write its output there, but from Python
+ all we see is the return value. For example,
+ SOUND_MIXER_READ_DEVMASK returns a bitmask of available mixer
+ devices, but does not use the value of the parameter passed-in in any
+ way.
+ */
+ 
+ static PyObject *
+ _do_ioctl_1_internal(int fd, PyObject *args, char *fname, int cmd)
+ {
+ char argfmt[32] = ":";
+ int arg = 0;
+ 
+ assert(strlen(fname) <= 30);
+ strcat(argfmt, fname);
+ if (!PyArg_ParseTuple(args, argfmt, &arg))
+ 	return NULL;
+ 
+ if (ioctl(fd, cmd, &arg) == -1)
+ return PyErr_SetFromErrno(PyExc_IOError);
+ return PyInt_FromLong(arg);
+ }
+ 
+ 
+ 
 /* _do_ioctl_0() is a private helper for the no-argument ioctls:
 SNDCTL_DSP_{SYNC,RESET,POST}. */
***************
*** 568,571 ****
--- 654,765 ----
 }
 
+ /* Mixer methods */
+ static PyObject *
+ oss_mixer_close(oss_mixer_t *self, PyObject *args)
+ {
+ if (!PyArg_ParseTuple(args, ":close"))
+ 	return NULL;
+ 
+ if (self->x_fd >= 0) {
+ close(self->x_fd);
+ self->x_fd = -1;
+ }
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ 
+ static PyObject *
+ oss_mixer_fileno(oss_mixer_t *self, PyObject *args)
+ {
+ if (!PyArg_ParseTuple(args, ":fileno")) 
+ 	return NULL;
+ return PyInt_FromLong(self->x_fd);
+ }
+ 
+ /* Simple mixer interface methods */
+ 
+ static PyObject *
+ oss_mixer_channels (oss_mixer_t *self, PyObject *args)
+ {
+ return _do_ioctl_1_internal(self->x_fd, args, "channels",
+ SOUND_MIXER_READ_DEVMASK);
+ }
+ 
+ static PyObject *
+ oss_mixer_stereo_channels (oss_mixer_t *self, PyObject *args)
+ {
+ return _do_ioctl_1_internal(self->x_fd, args, "stereochannels",
+ SOUND_MIXER_READ_STEREODEVS);
+ }
+ 
+ static PyObject *
+ oss_mixer_rec_channels (oss_mixer_t *self, PyObject *args)
+ {
+ return _do_ioctl_1_internal(self->x_fd, args, "recchannels",
+ SOUND_MIXER_READ_STEREODEVS);
+ }
+ 
+ static PyObject *
+ oss_mixer_getvol (oss_mixer_t *self, PyObject *args)
+ {
+ int channel, volume;
+ 
+ /* Can't use _do_ioctl_1 because of encoded arg thingy. */
+ if (!PyArg_ParseTuple (args, "i:getvol", &channel))
+ 	return NULL;
+ 
+ if (channel < 0 || channel > SOUND_MIXER_NRDEVICES) {
+ 	PyErr_SetString (OSSAudioError, "Invalid mixer channel specified.");
+ 	return NULL;
+ }
+ 
+ if (ioctl (self->x_fd, MIXER_READ(channel), &volume) == -1)
+ 	return PyErr_SetFromErrno(PyExc_IOError);
+ 
+ return Py_BuildValue ("(ii)", volume & 0xff, (volume & 0xff00) >> 8);
+ }
+ 
+ static PyObject *
+ oss_mixer_setvol (oss_mixer_t *self, PyObject *args)
+ {
+ int channel, volume, leftVol, rightVol;
+ 
+ /* Can't use _do_ioctl_1 because of encoded arg thingy. */
+ if (!PyArg_ParseTuple (args, "i(ii):setvol", &channel, &leftVol, &rightVol))
+ 	return NULL;
+ 	 
+ if (channel < 0 || channel > SOUND_MIXER_NRDEVICES) {
+ 	PyErr_SetString (OSSAudioError, "Invalid mixer channel specified.");
+ 	return NULL;
+ }
+ 
+ if (leftVol < 0 || rightVol < 0 || leftVol > 100 || rightVol > 100) {
+ 	PyErr_SetString (OSSAudioError, "Volumes must be between 0 and 100.");
+ 	return NULL;
+ }
+ 
+ volume = (rightVol << 8) | leftVol;
+ 
+ if (ioctl (self->x_fd, MIXER_WRITE(channel), &volume) == -1)
+ 	return PyErr_SetFromErrno(PyExc_IOError);
+ 
+ return Py_BuildValue ("(ii)", volume & 0xff, (volume & 0xff00) >> 8);
+ }
+ 
+ static PyObject *
+ oss_mixer_getrecsrc (oss_mixer_t *self, PyObject *args)
+ {
+ return _do_ioctl_1_internal(self->x_fd, args, "getrecsrc",
+ SOUND_MIXER_READ_RECSRC);
+ }
+ 
+ static PyObject *
+ oss_mixer_setrecsrc (oss_mixer_t *self, PyObject *args)
+ {
+ return _do_ioctl_1(self->x_fd, args, "setrecsrc",
+ SOUND_MIXER_WRITE_RECSRC);
+ }
+ 
+ 
 static PyMethodDef oss_methods[] = {
 /* Regular file methods */
***************
*** 599,602 ****
--- 793,813 ----
 };
 
+ static PyMethodDef oss_mixer_methods[] = {
+ /* Regular file method - OSS mixers are ioctl-only interface */
+ { "close",		(PyCFunction)oss_mixer_close, METH_VARARGS }, 
+ { "fileno", 	(PyCFunction)oss_mixer_fileno, METH_VARARGS },
+ 
+ /* Simple ioctl wrappers */
+ { "channels", 	(PyCFunction)oss_mixer_channels, METH_VARARGS }, 
+ { "stereochannels", (PyCFunction)oss_mixer_stereo_channels, METH_VARARGS},
+ { "recchannels", (PyCFunction)oss_mixer_rec_channels, METH_VARARGS}, 
+ { "getvol", 	(PyCFunction)oss_mixer_getvol, METH_VARARGS },
+ { "setvol", 	(PyCFunction)oss_mixer_setvol, METH_VARARGS },
+ { "getrecsrc", 	(PyCFunction)oss_mixer_getrecsrc, METH_VARARGS },
+ { "setrecsrc", 	(PyCFunction)oss_mixer_setrecsrc, METH_VARARGS },
+ 
+ { NULL, 	 	NULL}
+ };
+ 
 static PyObject *
 oss_getattr(oss_t *xp, char *name)
***************
*** 605,608 ****
--- 816,825 ----
 }
 
+ static PyObject *
+ oss_mixer_getattr(oss_mixer_t *xp, char *name)
+ {
+ return Py_FindMethod(oss_mixer_methods, (PyObject *)xp, name);
+ }
+ 
 static PyTypeObject OSSType = {
 PyObject_HEAD_INIT(&PyType_Type)
***************
*** 620,623 ****
--- 837,856 ----
 };
 
+ static PyTypeObject OSSMixerType = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,				 /*ob_size*/
+ "ossaudiodev.oss_mixer_device", /*tp_name*/
+ sizeof(oss_mixer_t),	 /*tp_size*/
+ 0,				 /*tp_itemsize*/
+ /* methods */
+ (destructor)oss_mixer_dealloc, /*tp_dealloc*/
+ 0,			 	 /*tp_print*/
+ (getattrfunc)oss_mixer_getattr, /*tp_getattr*/
+ 0,		 		 /*tp_setattr*/
+ 0,				 /*tp_compare*/
+ 0,				 /*tp_repr*/
+ };
+ 
+ 
 static PyObject *
 ossopen(PyObject *self, PyObject *args)
***************
*** 626,631 ****
--- 859,871 ----
 }
 
+ static PyObject *
+ ossopenmixer(PyObject *self, PyObject *args)
+ {
+ return (PyObject *)newossmixerobject(args);
+ }
+ 
 static PyMethodDef ossaudiodev_methods[] = {
 { "open", ossopen, METH_VARARGS },
+ { "openmixer", ossopenmixer, METH_VARARGS },
 { 0, 0 },
 };
***************
*** 660,663 ****
--- 900,930 ----
 _EXPORT_INT(m, AFMT_AC3);
 _EXPORT_INT(m, AFMT_S16_NE);
+ 	
+ /* Expose the sound mixer channels. */
+ _EXPORT_INT(m, SOUND_MIXER_VOLUME);
+ _EXPORT_INT(m, SOUND_MIXER_BASS);
+ _EXPORT_INT(m, SOUND_MIXER_TREBLE);
+ _EXPORT_INT(m, SOUND_MIXER_SYNTH);
+ _EXPORT_INT(m, SOUND_MIXER_PCM);
+ _EXPORT_INT(m, SOUND_MIXER_SPEAKER);
+ _EXPORT_INT(m, SOUND_MIXER_LINE);
+ _EXPORT_INT(m, SOUND_MIXER_MIC);
+ _EXPORT_INT(m, SOUND_MIXER_CD);
+ _EXPORT_INT(m, SOUND_MIXER_IMIX);
+ _EXPORT_INT(m, SOUND_MIXER_ALTPCM);
+ _EXPORT_INT(m, SOUND_MIXER_RECLEV);
+ _EXPORT_INT(m, SOUND_MIXER_IGAIN);
+ _EXPORT_INT(m, SOUND_MIXER_OGAIN);
+ _EXPORT_INT(m, SOUND_MIXER_LINE1);
+ _EXPORT_INT(m, SOUND_MIXER_LINE2);
+ _EXPORT_INT(m, SOUND_MIXER_LINE3);
+ _EXPORT_INT(m, SOUND_MIXER_DIGITAL1);
+ _EXPORT_INT(m, SOUND_MIXER_DIGITAL2);
+ _EXPORT_INT(m, SOUND_MIXER_DIGITAL3);
+ _EXPORT_INT(m, SOUND_MIXER_PHONEIN);
+ _EXPORT_INT(m, SOUND_MIXER_PHONEOUT);
+ _EXPORT_INT(m, SOUND_MIXER_VIDEO);
+ _EXPORT_INT(m, SOUND_MIXER_RADIO);
+ _EXPORT_INT(m, SOUND_MIXER_MONITOR);
 
 /* Expose all the ioctl numbers for masochists who like to do this

AltStyle によって変換されたページ (->オリジナル) /