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