blob: 5bd7249e6b7b8bad39d6beca50d4a66912f98d0a [file] [log] [blame]
Guido van Rossum9c52e0f1992-06-03 17:06:14 +00001/***********************************************************
Guido van Rossum9bfef441993-03-29 10:43:31 +00002Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
3Amsterdam, The 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 Rossum234f9421993-06-17 12:35:49 +000031#include <stropts.h>
Guido van Rossum9c52e0f1992-06-03 17:06:14 +000032#include <sys/ioctl.h>
Sjoerd Mullender66bca321993-12-03 16:54:45 +000033#ifdef SOLARIS
34#include <multimedia/libaudio.h>
35#else
Guido van Rossum9c52e0f1992-06-03 17:06:14 +000036#include <sun/audioio.h>
Sjoerd Mullender66bca321993-12-03 16:54:45 +000037#endif
Guido van Rossum9c52e0f1992-06-03 17:06:14 +000038
39/* #define offsetof(str,mem) ((int)(((str *)0)->mem)) */
40
41typedef struct {
42 OB_HEAD
43 int x_fd; /* The open file */
44 int x_icount; /* # samples read */
45 int x_ocount; /* # samples written */
46 int x_isctl; /* True if control device */
47
48} sadobject;
49
50typedef struct {
51 OB_HEAD
52 audio_info_t ai;
53} sadstatusobject;
54
55extern typeobject Sadtype; /* Really static, forward */
56extern typeobject Sadstatustype; /* Really static, forward */
Sjoerd Mullender66bca321993-12-03 16:54:45 +000057static sadstatusobject *sads_alloc(); /* Forward */
Guido van Rossum9c52e0f1992-06-03 17:06:14 +000058
59static object *SunAudioError;
60
61static int dummy_for_dl;
62
63#define is_sadobject(v) ((v)->ob_type == &Sadtype)
64#define is_sadstatusobject(v) ((v)->ob_type == &Sadstatustype)
65
66static sadobject *
67newsadobject(arg)
68 object *arg;
69{
70 sadobject *xp;
71 int fd;
72 char *mode;
73 int imode;
74
75 /* Check arg for r/w/rw */
76 if ( !getargs(arg, "s", &mode) )
77 return 0;
78 if ( strcmp(mode, "r") == 0 )
79 imode = 0;
80 else if ( strcmp(mode, "w") == 0 )
81 imode = 1;
82 else if ( strcmp(mode, "rw") == 0 )
83 imode = 2;
84 else if ( strcmp(mode, "control") == 0 )
85 imode = -1;
86 else {
87 err_setstr(SunAudioError,
88 "Mode should be one of 'r', 'w', 'rw' or 'control'");
89 return 0;
90 }
91
92 /* Open the correct device */
93 if ( imode < 0 )
94 fd = open("/dev/audioctl", 2); /* XXXX Chaeck that this works */
95 else
96 fd = open("/dev/audio", imode);
97 if ( fd < 0 ) {
98 err_errno(SunAudioError);
99 return NULL;
100 }
101
102 /* Create and initialize the object */
103 xp = NEWOBJ(sadobject, &Sadtype);
104 if (xp == NULL)
105 return NULL;
106 xp->x_fd = fd;
107 xp->x_icount = xp->x_ocount = 0;
108 xp->x_isctl = (imode < 0);
109
110 return xp;
111}
112
113/* Sad methods */
114
115static void
116sad_dealloc(xp)
117 sadobject *xp;
118{
119 close(xp->x_fd);
120 DEL(xp);
121}
122
123static object *
124sad_read(self, args)
125 sadobject *self;
126 object *args;
127{
128 int size, count;
129 char *cp;
130 object *rv;
131
132 if ( !getargs(args, "i", &size) )
133 return 0;
134 rv = newsizedstringobject(NULL, size);
135 if ( rv == NULL )
136 return 0;
137
138 cp = getstringvalue(rv);
139
140 count = read(self->x_fd, cp, size);
141 if ( count < 0 ) {
142 DECREF(rv);
143 err_errno(SunAudioError);
144 return NULL;
145 }
146 if ( count != size )
147 printf("sunaudio: funny read rv %d wtd %d\n", count, size);
148 self->x_icount += count;
149 return rv;
150}
151
152static object *
153sad_write(self, args)
154 sadobject *self;
155 object *args;
156{
157 char *cp;
158 int count, size;
159
160 if ( !getargs(args, "s#", &cp, &size) )
161 return 0;
162
163 count = write(self->x_fd, cp, size);
164 if ( count < 0 ) {
165 err_errno(SunAudioError);
166 return NULL;
167 }
168 if ( count != size )
169 printf("sunaudio: funny write rv %d wanted %d\n", count, size);
170 self->x_ocount += count;
171
172 INCREF(None);
173 return None;
174}
175
176static object *
177sad_getinfo(self, args)
178 sadobject *self;
179 object *args;
180{
181 sadstatusobject *rv;
182
183 if ( !getargs(args, "") )
184 return NULL;
185 rv = sads_alloc();
186 if ( ioctl(self->x_fd, AUDIO_GETINFO, &rv->ai) < 0 ) {
187 err_errno(SunAudioError);
188 DECREF(rv);
189 return NULL;
190 }
191 return (object *)rv;
192}
193
194static object *
195sad_setinfo(self, arg)
196 sadobject *self;
197 sadstatusobject *arg;
198{
199 if ( !is_sadstatusobject(arg) ) {
200 err_setstr(TypeError, "Must be sun audio status object");
201 return NULL;
202 }
203 if ( ioctl(self->x_fd, AUDIO_SETINFO, &arg->ai) < 0 ) {
204 err_errno(SunAudioError);
205 return NULL;
206 }
207 INCREF(None);
208 return None;
209}
210
211static object *
212sad_ibufcount(self, args)
213 sadobject *self;
214 object *args;
215{
216 audio_info_t ai;
217 object *rv;
218
219 if ( !getargs(args, "") )
220 return 0;
221 if ( ioctl(self->x_fd, AUDIO_GETINFO, &ai) < 0 ) {
222 err_errno(SunAudioError);
223 return NULL;
224 }
225 rv = newintobject(ai.record.samples - self->x_icount);
226 return rv;
227}
228
229static object *
230sad_obufcount(self, args)
231 sadobject *self;
232 object *args;
233{
234 audio_info_t ai;
235 object *rv;
236
237 if ( !getargs(args, "") )
238 return 0;
239 if ( ioctl(self->x_fd, AUDIO_GETINFO, &ai) < 0 ) {
240 err_errno(SunAudioError);
241 return NULL;
242 }
243 rv = newintobject(self->x_ocount - ai.play.samples);
244 return rv;
245}
246
247static object *
248sad_drain(self, args)
249 sadobject *self;
250 object *args;
251{
252
253 if ( !getargs(args, "") )
254 return 0;
255 if ( ioctl(self->x_fd, AUDIO_DRAIN, 0) < 0 ) {
256 err_errno(SunAudioError);
257 return NULL;
258 }
259 INCREF(None);
260 return None;
261}
262
Sjoerd Mullender66bca321993-12-03 16:54:45 +0000263#ifdef SOLARIS
264static object *
265sad_getdev(self, args)
266 sadobject *self;
267 object *args;
268{
269 struct audio_device ad;
270
271 if ( !getargs(args, "") )
272 return 0;
273 if ( ioctl(self->x_fd, AUDIO_GETDEV, &ad) < 0 ) {
274 err_errno(SunAudioError);
275 return NULL;
276 }
277 return mkvalue("(sss)", ad.name, ad.version, ad.config);
278}
279#endif
280
Guido van Rossum234f9421993-06-17 12:35:49 +0000281static object *
282sad_flush(self, args)
283 sadobject *self;
284 object *args;
285{
286
287 if ( !getargs(args, "") )
288 return 0;
289 if ( ioctl(self->x_fd, I_FLUSH, FLUSHW) < 0 ) {
290 err_errno(SunAudioError);
291 return NULL;
292 }
293 INCREF(None);
294 return None;
295}
296
297static object *
298sad_close(self, args)
299 sadobject *self;
300 object *args;
301{
302
303 if ( !getargs(args, "") )
304 return 0;
305 if ( self->x_fd >= 0 ) {
306 close(self->x_fd);
307 self->x_fd = -1;
308 }
309 INCREF(None);
310 return None;
311}
312
Guido van Rossum9c52e0f1992-06-03 17:06:14 +0000313static struct methodlist sad_methods[] = {
314 { "read", sad_read },
315 { "write", sad_write },
316 { "ibufcount", sad_ibufcount },
317 { "obufcount", sad_obufcount },
318#define CTL_METHODS 4
319 { "getinfo", sad_getinfo },
320 { "setinfo", sad_setinfo },
321 { "drain", sad_drain },
Guido van Rossum234f9421993-06-17 12:35:49 +0000322 { "flush", sad_flush },
Sjoerd Mullender66bca321993-12-03 16:54:45 +0000323#ifdef SOLARIS
324 { "getdev", sad_getdev },
325#endif
Guido van Rossum234f9421993-06-17 12:35:49 +0000326 { "close", sad_close },
Guido van Rossum9c52e0f1992-06-03 17:06:14 +0000327 {NULL, NULL} /* sentinel */
328};
329
330static object *
331sad_getattr(xp, name)
332 sadobject *xp;
333 char *name;
334{
335 if ( xp->x_isctl )
336 return findmethod(sad_methods+CTL_METHODS, (object *)xp, name);
337 else
338 return findmethod(sad_methods, (object *)xp, name);
339}
340
341/* ----------------------------------------------------------------- */
342
343static sadstatusobject *
344sads_alloc() {
345 sadstatusobject *rv;
346
347 rv = NEWOBJ(sadstatusobject, &Sadstatustype);
348 return rv;
349}
350
351static void
352sads_dealloc(xp)
353 sadstatusobject *xp;
354{
355 DEL(xp);
356}
357
358#define OFF(x) offsetof(audio_info_t,x)
359static struct memberlist sads_ml[] = {
360 { "i_sample_rate", T_UINT, OFF(record.sample_rate) },
361 { "i_channels", T_UINT, OFF(record.channels) },
362 { "i_precision", T_UINT, OFF(record.precision) },
363 { "i_encoding", T_UINT, OFF(record.encoding) },
364 { "i_gain", T_UINT, OFF(record.gain) },
365 { "i_port", T_UINT, OFF(record.port) },
366 { "i_samples", T_UINT, OFF(record.samples) },
367 { "i_eof", T_UINT, OFF(record.eof) },
368 { "i_pause", T_UBYTE, OFF(record.pause) },
369 { "i_error", T_UBYTE, OFF(record.error) },
370 { "i_waiting", T_UBYTE, OFF(record.waiting) },
371 { "i_open", T_UBYTE, OFF(record.open) , RO},
372 { "i_active", T_UBYTE, OFF(record.active) , RO},
Sjoerd Mullender66bca321993-12-03 16:54:45 +0000373#ifdef SOLARIS
374 { "i_buffer_size", T_UINT, OFF(record.buffer_size) },
375 { "i_balance", T_UBYTE, OFF(record.balance) },
376 { "i_avail_ports", T_UINT, OFF(record.avail_ports) },
377#endif
Guido van Rossum9c52e0f1992-06-03 17:06:14 +0000378
379 { "o_sample_rate", T_UINT, OFF(play.sample_rate) },
380 { "o_channels", T_UINT, OFF(play.channels) },
381 { "o_precision", T_UINT, OFF(play.precision) },
382 { "o_encoding", T_UINT, OFF(play.encoding) },
383 { "o_gain", T_UINT, OFF(play.gain) },
384 { "o_port", T_UINT, OFF(play.port) },
385 { "o_samples", T_UINT, OFF(play.samples) },
386 { "o_eof", T_UINT, OFF(play.eof) },
387 { "o_pause", T_UBYTE, OFF(play.pause) },
388 { "o_error", T_UBYTE, OFF(play.error) },
389 { "o_waiting", T_UBYTE, OFF(play.waiting) },
390 { "o_open", T_UBYTE, OFF(play.open) , RO},
391 { "o_active", T_UBYTE, OFF(play.active) , RO},
Sjoerd Mullender66bca321993-12-03 16:54:45 +0000392#ifdef SOLARIS
393 { "o_buffer_size", T_UINT, OFF(play.buffer_size) },
394 { "o_balance", T_UBYTE, OFF(play.balance) },
395 { "o_avail_ports", T_UINT, OFF(play.avail_ports) },
396#endif
Guido van Rossum9c52e0f1992-06-03 17:06:14 +0000397
398 { "monitor_gain", T_UINT, OFF(monitor_gain) },
399 { NULL, 0, 0},
400};
401
402static object *
403sads_getattr(xp, name)
404 sadstatusobject *xp;
405 char *name;
406{
407 return getmember((char *)&xp->ai, sads_ml, name);
408}
409
410static int
411sads_setattr(xp, name, v)
412 sadstatusobject *xp;
413 char *name;
414 object *v;
415{
Guido van Rossum94472a01992-09-04 09:45:18 +0000416
417 if (v == NULL) {
418 err_setstr(TypeError,
419 "can't delete sun audio status attributes");
Sjoerd Mullender66bca321993-12-03 16:54:45 +0000420 return 0;
Guido van Rossum94472a01992-09-04 09:45:18 +0000421 }
Guido van Rossum9c52e0f1992-06-03 17:06:14 +0000422 return setmember((char *)&xp->ai, sads_ml, name, v);
423}
424
425/* ------------------------------------------------------------------- */
426
427
428static typeobject Sadtype = {
429 OB_HEAD_INIT(&Typetype)
430 0, /*ob_size*/
431 "sun_audio_device", /*tp_name*/
432 sizeof(sadobject), /*tp_size*/
433 0, /*tp_itemsize*/
434 /* methods */
435 sad_dealloc, /*tp_dealloc*/
436 0, /*tp_print*/
437 sad_getattr, /*tp_getattr*/
438 0, /*tp_setattr*/
439 0, /*tp_compare*/
440 0, /*tp_repr*/
441};
442
443static typeobject Sadstatustype = {
444 OB_HEAD_INIT(&Typetype)
445 0, /*ob_size*/
446 "sun_audio_device_status", /*tp_name*/
447 sizeof(sadstatusobject), /*tp_size*/
448 0, /*tp_itemsize*/
449 /* methods */
450 sads_dealloc, /*tp_dealloc*/
451 0, /*tp_print*/
452 sads_getattr, /*tp_getattr*/
453 sads_setattr, /*tp_setattr*/
454 0, /*tp_compare*/
455 0, /*tp_repr*/
456};
457/* ------------------------------------------------------------------- */
458
459static object *
460sadopen(self, args)
461 object *self;
462 object *args;
463{
464 object *rv;
465
466 rv = (object *)newsadobject(args);
467 return rv;
468}
469
470static struct methodlist sunaudiodev_methods[] = {
471 { "open", sadopen },
472 { 0, 0 },
473};
474
475void
476initsunaudiodev() {
477 object *m, *d;
478
479 m = initmodule("sunaudiodev", sunaudiodev_methods);
480 d = getmoduledict(m);
481 SunAudioError = newstringobject("sunaudiodev.error");
482 if ( SunAudioError == NULL || dictinsert(d, "error", SunAudioError) )
483 fatal("can't define sunaudiodev.error");
484}