1 /***********************************************************
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Stichting Mathematisch
12 Centrum or CWI or Corporation for National Research Initiatives or
13 CNRI not be used in advertising or publicity pertaining to
14 distribution of the software without specific, written prior
17 While CWI is the initial source for this software, a modified version
18 is made available by the Corporation for National Research Initiatives
19 (CNRI) at the Internet address ftp://ftp.python.org.
21 STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22 REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23 MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24 CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26 PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28 PERFORMANCE OF THIS SOFTWARE.
30 ******************************************************************/
35 #include "structmember.h"
37 #ifdef HAVE_SYS_AUDIOIO_H
50 #include <sys/ioctl.h>
52 #include <sys/audioio.h>
54 #include <sun/audioio.h>
57 /* #define offsetof(str,mem) ((int)(((str *)0)->mem)) */
61 int x_fd
; /* The open file */
62 int x_icount
; /* # samples read */
63 int x_ocount
; /* # samples written */
64 int x_isctl
; /* True if control device */
73 staticforward PyTypeObject Sadtype
;
74 staticforward PyTypeObject Sadstatustype
;
75 static sadstatusobject
*sads_alloc(); /* Forward */
77 static PyObject
*SunAudioError
;
79 #define is_sadobject(v) ((v)->ob_type == &Sadtype)
80 #define is_sadstatusobject(v) ((v)->ob_type == &Sadstatustype)
95 /* Check arg for r/w/rw */
96 if (!PyArg_Parse(arg
, "s", &mode
))
98 if (strcmp(mode
, "r") == 0)
100 else if (strcmp(mode
, "w") == 0)
102 else if (strcmp(mode
, "rw") == 0)
104 else if (strcmp(mode
, "control") == 0)
107 PyErr_SetString(SunAudioError
,
108 "Mode should be one of 'r', 'w', 'rw' or 'control'");
112 /* Open the correct device. The base device name comes from the
113 * AUDIODEV environment variable first, then /dev/audio. The
114 * control device tacks "ctl" onto the base device name.
116 basedev
= getenv("AUDIODEV");
118 basedev
= "/dev/audio";
119 ctldev
= PyMem_NEW(char, strlen(basedev
) + 4);
124 strcpy(ctldev
, basedev
);
125 strcat(ctldev
, "ctl");
129 fd
= open(ctldev
, 2);
133 fd
= open(basedev
, imode
);
136 PyErr_SetFromErrnoWithFilename(SunAudioError
, opendev
);
141 /* Create and initialize the object */
142 xp
= PyObject_NEW(sadobject
, &Sadtype
);
148 xp
->x_icount
= xp
->x_ocount
= 0;
149 xp
->x_isctl
= (imode
< 0);
173 if (!PyArg_Parse(args
, "i", &size
))
175 rv
= PyString_FromStringAndSize(NULL
, size
);
179 if (!(cp
= PyString_AsString(rv
)))
182 count
= read(self
->x_fd
, cp
, size
);
184 PyErr_SetFromErrno(SunAudioError
);
188 /* TBD: why print this message if you can handle the condition?
189 * assume it's debugging info which we can just as well get rid
190 * of. in any case this message should *not* be using printf!
193 printf("sunaudio: funny read rv %d wtd %d\n", count
, size
);
195 self
->x_icount
+= count
;
204 sad_write(self
, args
)
211 if (!PyArg_Parse(args
, "s#", &cp
, &size
))
214 count
= write(self
->x_fd
, cp
, size
);
216 PyErr_SetFromErrno(SunAudioError
);
221 printf("sunaudio: funny write rv %d wanted %d\n", count
, size
);
223 self
->x_ocount
+= count
;
230 sad_getinfo(self
, args
)
236 if (!PyArg_Parse(args
, ""))
238 if (!(rv
= sads_alloc()))
241 if (ioctl(self
->x_fd
, AUDIO_GETINFO
, &rv
->ai
) < 0) {
242 PyErr_SetFromErrno(SunAudioError
);
246 return (PyObject
*)rv
;
250 sad_setinfo(self
, arg
)
252 sadstatusobject
*arg
;
254 if (!is_sadstatusobject(arg
)) {
255 PyErr_SetString(PyExc_TypeError
,
256 "Must be sun audio status object");
259 if (ioctl(self
->x_fd
, AUDIO_SETINFO
, &arg
->ai
) < 0) {
260 PyErr_SetFromErrno(SunAudioError
);
268 sad_ibufcount(self
, args
)
274 if (!PyArg_Parse(args
, ""))
276 if (ioctl(self
->x_fd
, AUDIO_GETINFO
, &ai
) < 0) {
277 PyErr_SetFromErrno(SunAudioError
);
280 return PyInt_FromLong(ai
.record
.samples
- self
->x_icount
);
284 sad_obufcount(self
, args
)
290 if (!PyArg_Parse(args
, ""))
292 if (ioctl(self
->x_fd
, AUDIO_GETINFO
, &ai
) < 0) {
293 PyErr_SetFromErrno(SunAudioError
);
296 /* x_ocount is in bytes, wheras play.samples is in frames */
298 return PyInt_FromLong(self
->x_ocount
/ (ai
.play
.channels
*
299 ai
.play
.precision
/ 8) -
304 sad_drain(self
, args
)
309 if (!PyArg_Parse(args
, ""))
311 if (ioctl(self
->x_fd
, AUDIO_DRAIN
, 0) < 0) {
312 PyErr_SetFromErrno(SunAudioError
);
321 sad_getdev(self
, args
)
325 struct audio_device ad
;
327 if (!PyArg_Parse(args
, ""))
329 if (ioctl(self
->x_fd
, AUDIO_GETDEV
, &ad
) < 0) {
330 PyErr_SetFromErrno(SunAudioError
);
333 return Py_BuildValue("(sss)", ad
.name
, ad
.version
, ad
.config
);
338 sad_flush(self
, args
)
343 if (!PyArg_Parse(args
, ""))
345 if (ioctl(self
->x_fd
, I_FLUSH
, FLUSHW
) < 0) {
346 PyErr_SetFromErrno(SunAudioError
);
354 sad_close(self
, args
)
359 if (!PyArg_Parse(args
, ""))
361 if (self
->x_fd
>= 0) {
370 sad_fileno(self
, args
)
374 if (!PyArg_Parse(args
, ""))
377 return PyInt_FromLong(self
->x_fd
);
381 static PyMethodDef sad_methods
[] = {
382 { "read", (PyCFunction
)sad_read
},
383 { "write", (PyCFunction
)sad_write
},
384 { "ibufcount", (PyCFunction
)sad_ibufcount
},
385 { "obufcount", (PyCFunction
)sad_obufcount
},
386 #define CTL_METHODS 4
387 { "getinfo", (PyCFunction
)sad_getinfo
},
388 { "setinfo", (PyCFunction
)sad_setinfo
},
389 { "drain", (PyCFunction
)sad_drain
},
390 { "flush", (PyCFunction
)sad_flush
},
392 { "getdev", (PyCFunction
)sad_getdev
},
394 { "close", (PyCFunction
)sad_close
},
395 { "fileno", (PyCFunction
)sad_fileno
},
396 {NULL
, NULL
} /* sentinel */
400 sad_getattr(xp
, name
)
405 return Py_FindMethod(sad_methods
+CTL_METHODS
,
406 (PyObject
*)xp
, name
);
408 return Py_FindMethod(sad_methods
, (PyObject
*)xp
, name
);
411 /* ----------------------------------------------------------------- */
413 static sadstatusobject
*
415 return PyObject_NEW(sadstatusobject
, &Sadstatustype
);
425 #define OFF(x) offsetof(audio_info_t,x)
426 static struct memberlist sads_ml
[] = {
427 { "i_sample_rate", T_UINT
, OFF(record
.sample_rate
) },
428 { "i_channels", T_UINT
, OFF(record
.channels
) },
429 { "i_precision", T_UINT
, OFF(record
.precision
) },
430 { "i_encoding", T_UINT
, OFF(record
.encoding
) },
431 { "i_gain", T_UINT
, OFF(record
.gain
) },
432 { "i_port", T_UINT
, OFF(record
.port
) },
433 { "i_samples", T_UINT
, OFF(record
.samples
) },
434 { "i_eof", T_UINT
, OFF(record
.eof
) },
435 { "i_pause", T_UBYTE
, OFF(record
.pause
) },
436 { "i_error", T_UBYTE
, OFF(record
.error
) },
437 { "i_waiting", T_UBYTE
, OFF(record
.waiting
) },
438 { "i_open", T_UBYTE
, OFF(record
.open
) , RO
},
439 { "i_active", T_UBYTE
, OFF(record
.active
) , RO
},
441 { "i_buffer_size", T_UINT
, OFF(record
.buffer_size
) },
442 { "i_balance", T_UBYTE
, OFF(record
.balance
) },
443 { "i_avail_ports", T_UINT
, OFF(record
.avail_ports
) },
446 { "o_sample_rate", T_UINT
, OFF(play
.sample_rate
) },
447 { "o_channels", T_UINT
, OFF(play
.channels
) },
448 { "o_precision", T_UINT
, OFF(play
.precision
) },
449 { "o_encoding", T_UINT
, OFF(play
.encoding
) },
450 { "o_gain", T_UINT
, OFF(play
.gain
) },
451 { "o_port", T_UINT
, OFF(play
.port
) },
452 { "o_samples", T_UINT
, OFF(play
.samples
) },
453 { "o_eof", T_UINT
, OFF(play
.eof
) },
454 { "o_pause", T_UBYTE
, OFF(play
.pause
) },
455 { "o_error", T_UBYTE
, OFF(play
.error
) },
456 { "o_waiting", T_UBYTE
, OFF(play
.waiting
) },
457 { "o_open", T_UBYTE
, OFF(play
.open
) , RO
},
458 { "o_active", T_UBYTE
, OFF(play
.active
) , RO
},
460 { "o_buffer_size", T_UINT
, OFF(play
.buffer_size
) },
461 { "o_balance", T_UBYTE
, OFF(play
.balance
) },
462 { "o_avail_ports", T_UINT
, OFF(play
.avail_ports
) },
465 { "monitor_gain", T_UINT
, OFF(monitor_gain
) },
470 sads_getattr(xp
, name
)
474 return PyMember_Get((char *)&xp
->ai
, sads_ml
, name
);
478 sads_setattr(xp
, name
, v
)
485 PyErr_SetString(PyExc_TypeError
,
486 "can't delete sun audio status attributes");
489 return PyMember_Set((char *)&xp
->ai
, sads_ml
, name
, v
);
492 /* ------------------------------------------------------------------- */
495 static PyTypeObject Sadtype
= {
496 PyObject_HEAD_INIT(&PyType_Type
)
498 "sun_audio_device", /*tp_name*/
499 sizeof(sadobject
), /*tp_size*/
502 (destructor
)sad_dealloc
, /*tp_dealloc*/
504 (getattrfunc
)sad_getattr
, /*tp_getattr*/
510 static PyTypeObject Sadstatustype
= {
511 PyObject_HEAD_INIT(&PyType_Type
)
513 "sun_audio_device_status", /*tp_name*/
514 sizeof(sadstatusobject
), /*tp_size*/
517 (destructor
)sads_dealloc
, /*tp_dealloc*/
519 (getattrfunc
)sads_getattr
, /*tp_getattr*/
520 (setattrfunc
)sads_setattr
, /*tp_setattr*/
524 /* ------------------------------------------------------------------- */
531 return (PyObject
*)newsadobject(args
);
534 static PyMethodDef sunaudiodev_methods
[] = {
544 m
= Py_InitModule("sunaudiodev", sunaudiodev_methods
);
545 d
= PyModule_GetDict(m
);
546 SunAudioError
= PyErr_NewException("sunaudiodev.error", NULL
, NULL
);
548 PyDict_SetItemString(d
, "error", SunAudioError
);