improve treatment of multi-line replies, ignore empty lines
[python/dscho.git] / Modules / sunaudiodev.c
blob49022240b5865594c7b6c80941613a8ca7f8ce4d
1 /***********************************************************
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3 The Netherlands.
5 All Rights Reserved
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Stichting Mathematisch
12 Centrum or CWI not be used in advertising or publicity pertaining to
13 distribution of the software without specific, written prior permission.
15 STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16 THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18 FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21 OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 ******************************************************************/
25 /* Sad objects */
27 #include "allobjects.h"
28 #include "modsupport.h"
29 #include "structmember.h"
31 #ifdef HAVE_SYS_AUDIOIO_H
32 #define SOLARIS
33 #endif
35 #include <stropts.h>
36 #include <sys/ioctl.h>
37 #ifdef SOLARIS
38 #include <sys/audioio.h>
39 #else
40 #include <sun/audioio.h>
41 #endif
43 /* #define offsetof(str,mem) ((int)(((str *)0)->mem)) */
45 typedef 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 */
52 } sadobject;
54 typedef struct {
55 OB_HEAD
56 audio_info_t ai;
57 } sadstatusobject;
59 staticforward typeobject Sadtype;
60 staticforward typeobject Sadstatustype;
61 static sadstatusobject *sads_alloc(); /* Forward */
63 static object *SunAudioError;
65 static int dummy_for_dl;
67 #define is_sadobject(v) ((v)->ob_type == &Sadtype)
68 #define is_sadstatusobject(v) ((v)->ob_type == &Sadstatustype)
70 static sadobject *
71 newsadobject(arg)
72 object *arg;
74 sadobject *xp;
75 int fd;
76 char *mode;
77 int imode;
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;
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;
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);
114 return xp;
117 /* Sad methods */
119 static void
120 sad_dealloc(xp)
121 sadobject *xp;
123 close(xp->x_fd);
124 DEL(xp);
127 static object *
128 sad_read(self, args)
129 sadobject *self;
130 object *args;
132 int size, count;
133 char *cp;
134 object *rv;
136 if ( !getargs(args, "i", &size) )
137 return 0;
138 rv = newsizedstringobject(NULL, size);
139 if ( rv == NULL )
140 return 0;
142 cp = getstringvalue(rv);
144 count = read(self->x_fd, cp, size);
145 if ( count < 0 ) {
146 DECREF(rv);
147 err_errno(SunAudioError);
148 return NULL;
150 if ( count != size )
151 printf("sunaudio: funny read rv %d wtd %d\n", count, size);
152 self->x_icount += count;
153 return rv;
156 static object *
157 sad_write(self, args)
158 sadobject *self;
159 object *args;
161 char *cp;
162 int count, size;
164 if ( !getargs(args, "s#", &cp, &size) )
165 return 0;
167 count = write(self->x_fd, cp, size);
168 if ( count < 0 ) {
169 err_errno(SunAudioError);
170 return NULL;
172 if ( count != size )
173 printf("sunaudio: funny write rv %d wanted %d\n", count, size);
174 self->x_ocount += count;
176 INCREF(None);
177 return None;
180 static object *
181 sad_getinfo(self, args)
182 sadobject *self;
183 object *args;
185 sadstatusobject *rv;
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;
195 return (object *)rv;
198 static object *
199 sad_setinfo(self, arg)
200 sadobject *self;
201 sadstatusobject *arg;
203 if ( !is_sadstatusobject(arg) ) {
204 err_setstr(TypeError, "Must be sun audio status object");
205 return NULL;
207 if ( ioctl(self->x_fd, AUDIO_SETINFO, &arg->ai) < 0 ) {
208 err_errno(SunAudioError);
209 return NULL;
211 INCREF(None);
212 return None;
215 static object *
216 sad_ibufcount(self, args)
217 sadobject *self;
218 object *args;
220 audio_info_t ai;
221 object *rv;
223 if ( !getargs(args, "") )
224 return 0;
225 if ( ioctl(self->x_fd, AUDIO_GETINFO, &ai) < 0 ) {
226 err_errno(SunAudioError);
227 return NULL;
229 rv = newintobject(ai.record.samples - self->x_icount);
230 return rv;
233 static object *
234 sad_obufcount(self, args)
235 sadobject *self;
236 object *args;
238 audio_info_t ai;
239 object *rv;
241 if ( !getargs(args, "") )
242 return 0;
243 if ( ioctl(self->x_fd, AUDIO_GETINFO, &ai) < 0 ) {
244 err_errno(SunAudioError);
245 return NULL;
247 rv = newintobject(self->x_ocount - ai.play.samples);
248 return rv;
251 static object *
252 sad_drain(self, args)
253 sadobject *self;
254 object *args;
257 if ( !getargs(args, "") )
258 return 0;
259 if ( ioctl(self->x_fd, AUDIO_DRAIN, 0) < 0 ) {
260 err_errno(SunAudioError);
261 return NULL;
263 INCREF(None);
264 return None;
267 #ifdef SOLARIS
268 static object *
269 sad_getdev(self, args)
270 sadobject *self;
271 object *args;
273 struct audio_device ad;
275 if ( !getargs(args, "") )
276 return 0;
277 if ( ioctl(self->x_fd, AUDIO_GETDEV, &ad) < 0 ) {
278 err_errno(SunAudioError);
279 return NULL;
281 return mkvalue("(sss)", ad.name, ad.version, ad.config);
283 #endif
285 static object *
286 sad_flush(self, args)
287 sadobject *self;
288 object *args;
291 if ( !getargs(args, "") )
292 return 0;
293 if ( ioctl(self->x_fd, I_FLUSH, FLUSHW) < 0 ) {
294 err_errno(SunAudioError);
295 return NULL;
297 INCREF(None);
298 return None;
301 static object *
302 sad_close(self, args)
303 sadobject *self;
304 object *args;
307 if ( !getargs(args, "") )
308 return 0;
309 if ( self->x_fd >= 0 ) {
310 close(self->x_fd);
311 self->x_fd = -1;
313 INCREF(None);
314 return None;
317 static 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 },
326 { "flush", sad_flush },
327 #ifdef SOLARIS
328 { "getdev", sad_getdev },
329 #endif
330 { "close", sad_close },
331 {NULL, NULL} /* sentinel */
334 static object *
335 sad_getattr(xp, name)
336 sadobject *xp;
337 char *name;
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);
345 /* ----------------------------------------------------------------- */
347 static sadstatusobject *
348 sads_alloc() {
349 sadstatusobject *rv;
351 rv = NEWOBJ(sadstatusobject, &Sadstatustype);
352 return rv;
355 static void
356 sads_dealloc(xp)
357 sadstatusobject *xp;
359 DEL(xp);
362 #define OFF(x) offsetof(audio_info_t,x)
363 static 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},
377 #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
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},
396 #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
402 { "monitor_gain", T_UINT, OFF(monitor_gain) },
403 { NULL, 0, 0},
406 static object *
407 sads_getattr(xp, name)
408 sadstatusobject *xp;
409 char *name;
411 return getmember((char *)&xp->ai, sads_ml, name);
414 static int
415 sads_setattr(xp, name, v)
416 sadstatusobject *xp;
417 char *name;
418 object *v;
421 if (v == NULL) {
422 err_setstr(TypeError,
423 "can't delete sun audio status attributes");
424 return 0;
426 return setmember((char *)&xp->ai, sads_ml, name, v);
429 /* ------------------------------------------------------------------- */
432 static typeobject Sadtype = {
433 OB_HEAD_INIT(&Typetype)
434 0, /*ob_size*/
435 "sun_audio_device", /*tp_name*/
436 sizeof(sadobject), /*tp_size*/
437 0, /*tp_itemsize*/
438 /* methods */
439 (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*/
447 static 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 */
454 (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*/
461 /* ------------------------------------------------------------------- */
463 static object *
464 sadopen(self, args)
465 object *self;
466 object *args;
468 object *rv;
470 rv = (object *)newsadobject(args);
471 return rv;
474 static struct methodlist sunaudiodev_methods[] = {
475 { "open", sadopen },
476 { 0, 0 },
479 void
480 initsunaudiodev() {
481 object *m, *d;
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");