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