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