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