blob: d8b04ffe0c0e8c6f4380f4f7990aeffbed7f6c54 [file] [log] [blame]
Guido van Rossum9c52e0f1992-06-03 17:06:14 +00001/***********************************************************
Guido van Rossum524b5881995-01-04 19:10:35 +00002Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
Guido van Rossum9c52e0f1992-06-03 17:06:14 +00004
5 All Rights Reserved
6
Guido van Rossumd266eb41996-10-25 14:44:06 +00007Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
Guido van Rossum9c52e0f1992-06-03 17:06:14 +00009provided that the above copyright notice appear in all copies and that
Guido van Rossumd266eb41996-10-25 14:44:06 +000010both that copyright notice and this permission notice appear in
Guido van Rossum9c52e0f1992-06-03 17:06:14 +000011supporting documentation, and that the names of Stichting Mathematisch
Guido van Rossumd266eb41996-10-25 14:44:06 +000012Centrum or CWI or Corporation for National Research Initiatives or
13CNRI not be used in advertising or publicity pertaining to
14distribution of the software without specific, written prior
15permission.
Guido van Rossum9c52e0f1992-06-03 17:06:14 +000016
Guido van Rossumd266eb41996-10-25 14:44:06 +000017While CWI is the initial source for this software, a modified version
18is made available by the Corporation for National Research Initiatives
19(CNRI) at the Internet address ftp://ftp.python.org.
20
21STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28PERFORMANCE OF THIS SOFTWARE.
Guido van Rossum9c52e0f1992-06-03 17:06:14 +000029
30******************************************************************/
31
32/* Sad objects */
33
34#include "allobjects.h"
35#include "modsupport.h"
36#include "structmember.h"
37
Guido van Rossumb6775db1994-08-01 11:34:53 +000038#ifdef HAVE_SYS_AUDIOIO_H
39#define SOLARIS
40#endif
41
Guido van Rossum234f9421993-06-17 12:35:49 +000042#include <stropts.h>
Guido van Rossum9c52e0f1992-06-03 17:06:14 +000043#include <sys/ioctl.h>
Sjoerd Mullender66bca321993-12-03 16:54:45 +000044#ifdef SOLARIS
Guido van Rossumb6775db1994-08-01 11:34:53 +000045#include <sys/audioio.h>
Sjoerd Mullender66bca321993-12-03 16:54:45 +000046#else
Guido van Rossum9c52e0f1992-06-03 17:06:14 +000047#include <sun/audioio.h>
Sjoerd Mullender66bca321993-12-03 16:54:45 +000048#endif
Guido van Rossum9c52e0f1992-06-03 17:06:14 +000049
50/* #define offsetof(str,mem) ((int)(((str *)0)->mem)) */
51
52typedef struct {
53 OB_HEAD
54 int x_fd; /* The open file */
55 int x_icount; /* # samples read */
56 int x_ocount; /* # samples written */
57 int x_isctl; /* True if control device */
58
59} sadobject;
60
61typedef struct {
62 OB_HEAD
63 audio_info_t ai;
64} sadstatusobject;
65
Guido van Rossumb6775db1994-08-01 11:34:53 +000066staticforward typeobject Sadtype;
67staticforward typeobject Sadstatustype;
Sjoerd Mullender66bca321993-12-03 16:54:45 +000068static sadstatusobject *sads_alloc(); /* Forward */
Guido van Rossum9c52e0f1992-06-03 17:06:14 +000069
70static object *SunAudioError;
71
72static int dummy_for_dl;
73
74#define is_sadobject(v) ((v)->ob_type == &Sadtype)
75#define is_sadstatusobject(v) ((v)->ob_type == &Sadstatustype)
76
77static sadobject *
78newsadobject(arg)
79 object *arg;
80{
81 sadobject *xp;
82 int fd;
83 char *mode;
84 int imode;
85
86 /* Check arg for r/w/rw */
87 if ( !getargs(arg, "s", &mode) )
88 return 0;
89 if ( strcmp(mode, "r") == 0 )
90 imode = 0;
91 else if ( strcmp(mode, "w") == 0 )
92 imode = 1;
93 else if ( strcmp(mode, "rw") == 0 )
94 imode = 2;
95 else if ( strcmp(mode, "control") == 0 )
96 imode = -1;
97 else {
98 err_setstr(SunAudioError,
99 "Mode should be one of 'r', 'w', 'rw' or 'control'");
100 return 0;
101 }
102
103 /* Open the correct device */
104 if ( imode < 0 )
105 fd = open("/dev/audioctl", 2); /* XXXX Chaeck that this works */
106 else
107 fd = open("/dev/audio", imode);
108 if ( fd < 0 ) {
109 err_errno(SunAudioError);
110 return NULL;
111 }
112
113 /* Create and initialize the object */
114 xp = NEWOBJ(sadobject, &Sadtype);
115 if (xp == NULL)
116 return NULL;
117 xp->x_fd = fd;
118 xp->x_icount = xp->x_ocount = 0;
119 xp->x_isctl = (imode < 0);
120
121 return xp;
122}
123
124/* Sad methods */
125
126static void
127sad_dealloc(xp)
128 sadobject *xp;
129{
130 close(xp->x_fd);
131 DEL(xp);
132}
133
134static object *
135sad_read(self, args)
136 sadobject *self;
137 object *args;
138{
139 int size, count;
140 char *cp;
141 object *rv;
142
143 if ( !getargs(args, "i", &size) )
144 return 0;
145 rv = newsizedstringobject(NULL, size);
146 if ( rv == NULL )
147 return 0;
148
149 cp = getstringvalue(rv);
150
151 count = read(self->x_fd, cp, size);
152 if ( count < 0 ) {
153 DECREF(rv);
154 err_errno(SunAudioError);
155 return NULL;
156 }
157 if ( count != size )
158 printf("sunaudio: funny read rv %d wtd %d\n", count, size);
159 self->x_icount += count;
160 return rv;
161}
162
163static object *
164sad_write(self, args)
165 sadobject *self;
166 object *args;
167{
168 char *cp;
169 int count, size;
170
171 if ( !getargs(args, "s#", &cp, &size) )
172 return 0;
173
174 count = write(self->x_fd, cp, size);
175 if ( count < 0 ) {
176 err_errno(SunAudioError);
177 return NULL;
178 }
179 if ( count != size )
180 printf("sunaudio: funny write rv %d wanted %d\n", count, size);
181 self->x_ocount += count;
182
183 INCREF(None);
184 return None;
185}
186
187static object *
188sad_getinfo(self, args)
189 sadobject *self;
190 object *args;
191{
192 sadstatusobject *rv;
193
194 if ( !getargs(args, "") )
195 return NULL;
196 rv = sads_alloc();
197 if ( ioctl(self->x_fd, AUDIO_GETINFO, &rv->ai) < 0 ) {
198 err_errno(SunAudioError);
199 DECREF(rv);
200 return NULL;
201 }
202 return (object *)rv;
203}
204
205static object *
206sad_setinfo(self, arg)
207 sadobject *self;
208 sadstatusobject *arg;
209{
210 if ( !is_sadstatusobject(arg) ) {
211 err_setstr(TypeError, "Must be sun audio status object");
212 return NULL;
213 }
214 if ( ioctl(self->x_fd, AUDIO_SETINFO, &arg->ai) < 0 ) {
215 err_errno(SunAudioError);
216 return NULL;
217 }
218 INCREF(None);
219 return None;
220}
221
222static object *
223sad_ibufcount(self, args)
224 sadobject *self;
225 object *args;
226{
227 audio_info_t ai;
228 object *rv;
229
230 if ( !getargs(args, "") )
231 return 0;
232 if ( ioctl(self->x_fd, AUDIO_GETINFO, &ai) < 0 ) {
233 err_errno(SunAudioError);
234 return NULL;
235 }
236 rv = newintobject(ai.record.samples - self->x_icount);
237 return rv;
238}
239
240static object *
241sad_obufcount(self, args)
242 sadobject *self;
243 object *args;
244{
245 audio_info_t ai;
246 object *rv;
247
248 if ( !getargs(args, "") )
249 return 0;
250 if ( ioctl(self->x_fd, AUDIO_GETINFO, &ai) < 0 ) {
251 err_errno(SunAudioError);
252 return NULL;
253 }
254 rv = newintobject(self->x_ocount - ai.play.samples);
255 return rv;
256}
257
258static object *
259sad_drain(self, args)
260 sadobject *self;
261 object *args;
262{
263
264 if ( !getargs(args, "") )
265 return 0;
266 if ( ioctl(self->x_fd, AUDIO_DRAIN, 0) < 0 ) {
267 err_errno(SunAudioError);
268 return NULL;
269 }
270 INCREF(None);
271 return None;
272}
273
Sjoerd Mullender66bca321993-12-03 16:54:45 +0000274#ifdef SOLARIS
275static object *
276sad_getdev(self, args)
277 sadobject *self;
278 object *args;
279{
280 struct audio_device ad;
281
282 if ( !getargs(args, "") )
283 return 0;
284 if ( ioctl(self->x_fd, AUDIO_GETDEV, &ad) < 0 ) {
285 err_errno(SunAudioError);
286 return NULL;
287 }
288 return mkvalue("(sss)", ad.name, ad.version, ad.config);
289}
290#endif
291
Guido van Rossum234f9421993-06-17 12:35:49 +0000292static object *
293sad_flush(self, args)
294 sadobject *self;
295 object *args;
296{
297
298 if ( !getargs(args, "") )
299 return 0;
300 if ( ioctl(self->x_fd, I_FLUSH, FLUSHW) < 0 ) {
301 err_errno(SunAudioError);
302 return NULL;
303 }
304 INCREF(None);
305 return None;
306}
307
308static object *
309sad_close(self, args)
310 sadobject *self;
311 object *args;
312{
313
314 if ( !getargs(args, "") )
315 return 0;
316 if ( self->x_fd >= 0 ) {
317 close(self->x_fd);
318 self->x_fd = -1;
319 }
320 INCREF(None);
321 return None;
322}
323
Guido van Rossum9c52e0f1992-06-03 17:06:14 +0000324static struct methodlist sad_methods[] = {
Sjoerd Mullender14ece161995-03-17 12:18:38 +0000325 { "read", (method)sad_read },
326 { "write", (method)sad_write },
327 { "ibufcount", (method)sad_ibufcount },
328 { "obufcount", (method)sad_obufcount },
Guido van Rossum9c52e0f1992-06-03 17:06:14 +0000329#define CTL_METHODS 4
Sjoerd Mullender14ece161995-03-17 12:18:38 +0000330 { "getinfo", (method)sad_getinfo },
331 { "setinfo", (method)sad_setinfo },
332 { "drain", (method)sad_drain },
333 { "flush", (method)sad_flush },
Sjoerd Mullender66bca321993-12-03 16:54:45 +0000334#ifdef SOLARIS
Sjoerd Mullender14ece161995-03-17 12:18:38 +0000335 { "getdev", (method)sad_getdev },
Sjoerd Mullender66bca321993-12-03 16:54:45 +0000336#endif
Sjoerd Mullender14ece161995-03-17 12:18:38 +0000337 { "close", (method)sad_close },
Guido van Rossum9c52e0f1992-06-03 17:06:14 +0000338 {NULL, NULL} /* sentinel */
339};
340
341static object *
342sad_getattr(xp, name)
343 sadobject *xp;
344 char *name;
345{
346 if ( xp->x_isctl )
347 return findmethod(sad_methods+CTL_METHODS, (object *)xp, name);
348 else
349 return findmethod(sad_methods, (object *)xp, name);
350}
351
352/* ----------------------------------------------------------------- */
353
354static sadstatusobject *
355sads_alloc() {
356 sadstatusobject *rv;
357
358 rv = NEWOBJ(sadstatusobject, &Sadstatustype);
359 return rv;
360}
361
362static void
363sads_dealloc(xp)
364 sadstatusobject *xp;
365{
366 DEL(xp);
367}
368
369#define OFF(x) offsetof(audio_info_t,x)
370static struct memberlist sads_ml[] = {
371 { "i_sample_rate", T_UINT, OFF(record.sample_rate) },
372 { "i_channels", T_UINT, OFF(record.channels) },
373 { "i_precision", T_UINT, OFF(record.precision) },
374 { "i_encoding", T_UINT, OFF(record.encoding) },
375 { "i_gain", T_UINT, OFF(record.gain) },
376 { "i_port", T_UINT, OFF(record.port) },
377 { "i_samples", T_UINT, OFF(record.samples) },
378 { "i_eof", T_UINT, OFF(record.eof) },
379 { "i_pause", T_UBYTE, OFF(record.pause) },
380 { "i_error", T_UBYTE, OFF(record.error) },
381 { "i_waiting", T_UBYTE, OFF(record.waiting) },
382 { "i_open", T_UBYTE, OFF(record.open) , RO},
383 { "i_active", T_UBYTE, OFF(record.active) , RO},
Sjoerd Mullender66bca321993-12-03 16:54:45 +0000384#ifdef SOLARIS
385 { "i_buffer_size", T_UINT, OFF(record.buffer_size) },
386 { "i_balance", T_UBYTE, OFF(record.balance) },
387 { "i_avail_ports", T_UINT, OFF(record.avail_ports) },
388#endif
Guido van Rossum9c52e0f1992-06-03 17:06:14 +0000389
390 { "o_sample_rate", T_UINT, OFF(play.sample_rate) },
391 { "o_channels", T_UINT, OFF(play.channels) },
392 { "o_precision", T_UINT, OFF(play.precision) },
393 { "o_encoding", T_UINT, OFF(play.encoding) },
394 { "o_gain", T_UINT, OFF(play.gain) },
395 { "o_port", T_UINT, OFF(play.port) },
396 { "o_samples", T_UINT, OFF(play.samples) },
397 { "o_eof", T_UINT, OFF(play.eof) },
398 { "o_pause", T_UBYTE, OFF(play.pause) },
399 { "o_error", T_UBYTE, OFF(play.error) },
400 { "o_waiting", T_UBYTE, OFF(play.waiting) },
401 { "o_open", T_UBYTE, OFF(play.open) , RO},
402 { "o_active", T_UBYTE, OFF(play.active) , RO},
Sjoerd Mullender66bca321993-12-03 16:54:45 +0000403#ifdef SOLARIS
404 { "o_buffer_size", T_UINT, OFF(play.buffer_size) },
405 { "o_balance", T_UBYTE, OFF(play.balance) },
406 { "o_avail_ports", T_UINT, OFF(play.avail_ports) },
407#endif
Guido van Rossum9c52e0f1992-06-03 17:06:14 +0000408
409 { "monitor_gain", T_UINT, OFF(monitor_gain) },
410 { NULL, 0, 0},
411};
412
413static object *
414sads_getattr(xp, name)
415 sadstatusobject *xp;
416 char *name;
417{
418 return getmember((char *)&xp->ai, sads_ml, name);
419}
420
421static int
422sads_setattr(xp, name, v)
423 sadstatusobject *xp;
424 char *name;
425 object *v;
426{
Guido van Rossum94472a01992-09-04 09:45:18 +0000427
428 if (v == NULL) {
429 err_setstr(TypeError,
430 "can't delete sun audio status attributes");
Guido van Rossumf156f501996-09-11 23:31:23 +0000431 return -1;
Guido van Rossum94472a01992-09-04 09:45:18 +0000432 }
Guido van Rossum9c52e0f1992-06-03 17:06:14 +0000433 return setmember((char *)&xp->ai, sads_ml, name, v);
434}
435
436/* ------------------------------------------------------------------- */
437
438
439static typeobject Sadtype = {
440 OB_HEAD_INIT(&Typetype)
Guido van Rossumb6775db1994-08-01 11:34:53 +0000441 0, /*ob_size*/
442 "sun_audio_device", /*tp_name*/
443 sizeof(sadobject), /*tp_size*/
444 0, /*tp_itemsize*/
Guido van Rossum9c52e0f1992-06-03 17:06:14 +0000445 /* methods */
Guido van Rossumb6775db1994-08-01 11:34:53 +0000446 (destructor)sad_dealloc, /*tp_dealloc*/
447 0, /*tp_print*/
448 (getattrfunc)sad_getattr, /*tp_getattr*/
449 0, /*tp_setattr*/
450 0, /*tp_compare*/
451 0, /*tp_repr*/
Guido van Rossum9c52e0f1992-06-03 17:06:14 +0000452};
453
454static typeobject Sadstatustype = {
455 OB_HEAD_INIT(&Typetype)
456 0, /*ob_size*/
457 "sun_audio_device_status", /*tp_name*/
458 sizeof(sadstatusobject), /*tp_size*/
459 0, /*tp_itemsize*/
460 /* methods */
Guido van Rossumb6775db1994-08-01 11:34:53 +0000461 (destructor)sads_dealloc, /*tp_dealloc*/
462 0, /*tp_print*/
463 (getattrfunc)sads_getattr, /*tp_getattr*/
464 (setattrfunc)sads_setattr, /*tp_setattr*/
465 0, /*tp_compare*/
466 0, /*tp_repr*/
Guido van Rossum9c52e0f1992-06-03 17:06:14 +0000467};
468/* ------------------------------------------------------------------- */
469
470static object *
471sadopen(self, args)
472 object *self;
473 object *args;
474{
475 object *rv;
476
477 rv = (object *)newsadobject(args);
478 return rv;
479}
480
481static struct methodlist sunaudiodev_methods[] = {
482 { "open", sadopen },
483 { 0, 0 },
484};
485
486void
487initsunaudiodev() {
488 object *m, *d;
489
490 m = initmodule("sunaudiodev", sunaudiodev_methods);
491 d = getmoduledict(m);
492 SunAudioError = newstringobject("sunaudiodev.error");
493 if ( SunAudioError == NULL || dictinsert(d, "error", SunAudioError) )
494 fatal("can't define sunaudiodev.error");
495}