blob: e6ba1b09bc0f17e364e39561803829c66158e04d [file] [log] [blame]
Guido van Rossume3db8621991-09-09 23:33:34 +00001/**********************************************************
2Copyright 1991 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
Guido van Rossumfc58e581992-01-27 16:45:55 +000025/* AL module -- interface to Mark Callows' Audio Library (AL). */
Guido van Rossume3db8621991-09-09 23:33:34 +000026
27#include "audio.h"
28
29#include "allobjects.h"
30#include "import.h"
31#include "modsupport.h"
32#include "structmember.h"
33
34
35/* Config objects */
36
37typedef struct {
38 OB_HEAD
39 ALconfig ob_config;
40} configobject;
41
42extern typeobject Configtype; /* Forward */
43
44#define is_configobject(v) ((v)->ob_type == &Configtype)
45
Guido van Rossumfc58e581992-01-27 16:45:55 +000046/* Forward */
47static int getconfigarg PROTO((object *, ALconfig *));
48static int getstrstrconfigarg PROTO((object *, char **, char **, ALconfig *));
49
Guido van Rossume3db8621991-09-09 23:33:34 +000050static object *
51setConfig (self, args, func)
52 configobject *self;
53 object *args;
54 void (*func)(ALconfig, long);
55{
56 long par;
57
Guido van Rossumfc58e581992-01-27 16:45:55 +000058 if (!getlongarg (args, &par)) return NULL;
Guido van Rossume3db8621991-09-09 23:33:34 +000059
60 (*func) (self-> ob_config, par);
61
62 INCREF (None);
63 return None;
64}
65
66static object *
67getConfig (self, args, func)
68 configobject *self;
69 object *args;
70 long (*func)(ALconfig);
71{
72 long par;
73
Guido van Rossumfc58e581992-01-27 16:45:55 +000074 if (!getnoarg (args)) return NULL;
Guido van Rossume3db8621991-09-09 23:33:34 +000075
76 par = (*func) (self-> ob_config);
77
78 return newintobject (par);
79}
80
81static object *
82al_setqueuesize (self, args)
83 configobject *self;
84 object *args;
85{
86 return (setConfig (self, args, ALsetqueuesize));
87}
88
89static object *
90al_getqueuesize (self, args)
91 configobject *self;
92 object *args;
93{
94 return (getConfig (self, args, ALgetqueuesize));
95}
96
97static object *
98al_setwidth (self, args)
99 configobject *self;
100 object *args;
101{
102 return (setConfig (self, args, ALsetwidth));
103}
104
105static object *
106al_getwidth (self, args)
107 configobject *self;
108 object *args;
109{
110 return (getConfig (self, args, ALgetwidth));
111}
112
113static object *
114al_getchannels (self, args)
115 configobject *self;
116 object *args;
117{
118 return (getConfig (self, args, ALgetchannels));
119}
120
121static object *
122al_setchannels (self, args)
123 configobject *self;
124 object *args;
125{
126 return (setConfig (self, args, ALsetchannels));
127}
128
129static struct methodlist config_methods[] = {
130 {"getqueuesize", al_getqueuesize},
131 {"setqueuesize", al_setqueuesize},
132 {"getwidth", al_getwidth},
133 {"setwidth", al_setwidth},
134 {"getchannels", al_getchannels},
135 {"setchannels", al_setchannels},
136 {NULL, NULL} /* sentinel */
137};
138
139static void
140config_dealloc(self)
141 configobject *self;
142{
143 ALfreeconfig(self->ob_config);
144 DEL(self);
145}
146
147static object *
148config_getattr(self, name)
149 configobject *self;
150 char *name;
151{
152 return findmethod(config_methods, (object *)self, name);
153}
154
155typeobject Configtype = {
156 OB_HEAD_INIT(&Typetype)
157 0, /*ob_size*/
158 "config", /*tp_name*/
159 sizeof(configobject), /*tp_size*/
160 0, /*tp_itemsize*/
161 /* methods */
162 config_dealloc, /*tp_dealloc*/
163 0, /*tp_print*/
164 config_getattr, /*tp_getattr*/
165 0, /*tp_setattr*/
166 0, /*tp_compare*/
167 0, /*tp_repr*/
168};
169
170static object *
171newconfigobject(config)
172 ALconfig config;
173{
174 configobject *p;
175
176 p = NEWOBJ(configobject, &Configtype);
177 if (p == NULL)
178 return NULL;
179 p->ob_config = config;
180 return (object *)p;
181}
182
183/* Port objects */
184
185typedef struct {
186 OB_HEAD
187 ALport ob_port;
188} portobject;
189
190extern typeobject Porttype; /* Forward */
191
192#define is_portobject(v) ((v)->ob_type == &Porttype)
193
194static object *
195al_closeport (self, args)
196 portobject *self;
197 object *args;
198{
Guido van Rossumfc58e581992-01-27 16:45:55 +0000199 if (!getnoarg (args)) return NULL;
Guido van Rossume3db8621991-09-09 23:33:34 +0000200
201 if (self->ob_port != NULL) {
202 ALcloseport (self-> ob_port);
203 self->ob_port = NULL;
204 /* XXX Using a closed port may dump core! */
205 }
206
207 INCREF (None);
208 return None;
209}
210
211static object *
212al_getfd (self, args)
213 portobject *self;
214 object *args;
215{
216 int fd;
217
Guido van Rossumfc58e581992-01-27 16:45:55 +0000218 if (!getnoarg (args)) return NULL;
Guido van Rossume3db8621991-09-09 23:33:34 +0000219
220 fd = ALgetfd (self-> ob_port);
221
222 return newintobject (fd);
223}
224
225static object *
226al_getfilled (self, args)
227 portobject *self;
228 object *args;
229{
230 long count;
231
Guido van Rossumfc58e581992-01-27 16:45:55 +0000232 if (!getnoarg (args)) return NULL;
Guido van Rossume3db8621991-09-09 23:33:34 +0000233
234 count = ALgetfilled (self-> ob_port);
235
236 return newintobject (count);
237}
238
239static object *
240al_getfillable (self, args)
241 portobject *self;
242 object *args;
243{
244 long count;
245
Guido van Rossumfc58e581992-01-27 16:45:55 +0000246 if (!getnoarg (args)) return NULL;
Guido van Rossume3db8621991-09-09 23:33:34 +0000247
248 count = ALgetfillable (self-> ob_port);
249
250 return newintobject (count);
251}
252
253static object *
254al_readsamps (self, args)
255 portobject *self;
256 object *args;
257{
258 long count;
259 object *v;
Guido van Rossumb3a5b9b1991-09-10 14:54:05 +0000260 ALconfig c;
Guido van Rossume3db8621991-09-09 23:33:34 +0000261 int width;
262
263 if (!getlongarg (args, &count)) return NULL;
264
265 if (count <= 0)
266 {
267 err_setstr (RuntimeError, "al.readsamps : arg <= 0");
268 return NULL;
269 }
270
Guido van Rossumb3a5b9b1991-09-10 14:54:05 +0000271 c = ALgetconfig(self->ob_port);
272 width = ALgetwidth(c);
273 ALfreeconfig(c);
Guido van Rossume3db8621991-09-09 23:33:34 +0000274 v = newsizedstringobject ((char *)NULL, width * count);
275 if (v == NULL) return NULL;
276
277 ALreadsamps (self-> ob_port, (void *) getstringvalue(v), count);
278
279 return (v);
280}
281
282static object *
283al_writesamps (self, args)
284 portobject *self;
285 object *args;
286{
287 long count;
Guido van Rossumfc58e581992-01-27 16:45:55 +0000288 char *buf;
289 int size, width;
Guido van Rossumb3a5b9b1991-09-10 14:54:05 +0000290 ALconfig c;
Guido van Rossume3db8621991-09-09 23:33:34 +0000291
Guido van Rossumfc58e581992-01-27 16:45:55 +0000292 if (!getargs (args, "s#", &buf, &size)) return NULL;
Guido van Rossume3db8621991-09-09 23:33:34 +0000293
Guido van Rossumb3a5b9b1991-09-10 14:54:05 +0000294 c = ALgetconfig(self->ob_port);
295 width = ALgetwidth(c);
296 ALfreeconfig(c);
Guido van Rossumfc58e581992-01-27 16:45:55 +0000297 ALwritesamps (self-> ob_port, (void *) buf, (long) size / width);
Guido van Rossume3db8621991-09-09 23:33:34 +0000298
299 INCREF (None);
300 return None;
301}
302
303static object *
304al_getfillpoint (self, args)
305 portobject *self;
306 object *args;
307{
308 long count;
309
Guido van Rossumfc58e581992-01-27 16:45:55 +0000310 if (!getnoarg (args)) return NULL;
Guido van Rossume3db8621991-09-09 23:33:34 +0000311
312 count = ALgetfillpoint (self-> ob_port);
313
314 return newintobject (count);
315}
316
317static object *
318al_setfillpoint (self, args)
319 portobject *self;
320 object *args;
321{
322 long count;
323
Guido van Rossumfc58e581992-01-27 16:45:55 +0000324 if (!getlongarg (args, &count)) return NULL;
Guido van Rossume3db8621991-09-09 23:33:34 +0000325
326 ALsetfillpoint (self-> ob_port, count);
327
328 INCREF (None);
329 return (None);
330}
331
332static object *
333al_setconfig (self, args)
334 portobject *self;
335 object *args;
336{
337 ALconfig config;
338
Guido van Rossumfc58e581992-01-27 16:45:55 +0000339 if (!getconfigarg (args, &config)) return NULL;
Guido van Rossume3db8621991-09-09 23:33:34 +0000340
341 ALsetconfig (self-> ob_port, config);
342
343 INCREF (None);
344 return (None);
345}
346
347static object *
348al_getconfig (self, args)
349 portobject *self;
350 object *args;
351{
352 ALconfig config;
353
Guido van Rossumfc58e581992-01-27 16:45:55 +0000354 if (!getnoarg (args)) return NULL;
Guido van Rossume3db8621991-09-09 23:33:34 +0000355
356 config = ALgetconfig (self-> ob_port);
357
358 return newconfigobject (config);
359}
360
361static struct methodlist port_methods[] = {
362 {"closeport", al_closeport},
363 {"getfd", al_getfd},
364 {"getfilled", al_getfilled},
365 {"getfillable", al_getfillable},
366 {"readsamps", al_readsamps},
367 {"writesamps", al_writesamps},
368 {"setfillpoint", al_setfillpoint},
369 {"getfillpoint", al_getfillpoint},
370 {"setconfig", al_setconfig},
371 {"getconfig", al_getconfig},
372 {NULL, NULL} /* sentinel */
373};
374
375static void
376port_dealloc(p)
377 portobject *p;
378{
379 if (p->ob_port != NULL)
380 ALcloseport(p->ob_port);
381 DEL(p);
382}
383
384static object *
385port_getattr(p, name)
386 portobject *p;
387 char *name;
388{
389 return findmethod(port_methods, (object *)p, name);
390}
391
392typeobject Porttype = {
393 OB_HEAD_INIT(&Typetype)
394 0, /*ob_size*/
395 "port", /*tp_name*/
396 sizeof(portobject), /*tp_size*/
397 0, /*tp_itemsize*/
398 /* methods */
399 port_dealloc, /*tp_dealloc*/
400 0, /*tp_print*/
401 port_getattr, /*tp_getattr*/
402 0, /*tp_setattr*/
403 0, /*tp_compare*/
404 0, /*tp_repr*/
405};
406
407static object *
408newportobject(port)
409 ALport port;
410{
411 portobject *p;
412
413 p = NEWOBJ(portobject, &Porttype);
414 if (p == NULL)
415 return NULL;
416 p->ob_port = port;
417 return (object *)p;
418}
419
420/* the module al */
421
422static object *
423al_openport (self, args)
424 object *self, *args;
425{
Guido van Rossumfc58e581992-01-27 16:45:55 +0000426 char *name, *dir;
Guido van Rossume3db8621991-09-09 23:33:34 +0000427 ALport port;
428 ALconfig config = NULL;
Guido van Rossumc0aab891991-10-20 20:10:46 +0000429 int size;
Guido van Rossume3db8621991-09-09 23:33:34 +0000430
Guido van Rossumc0aab891991-10-20 20:10:46 +0000431 if (args == NULL || !is_tupleobject(args)) {
Guido van Rossumfc58e581992-01-27 16:45:55 +0000432 err_badarg ();
Guido van Rossumc0aab891991-10-20 20:10:46 +0000433 return NULL;
434 }
435 size = gettuplesize(args);
Guido van Rossume3db8621991-09-09 23:33:34 +0000436 if (size == 2) {
437 if (!getstrstrarg (args, &name, &dir))
438 return NULL;
439 }
440 else if (size == 3) {
441 if (!getstrstrconfigarg (args, &name, &dir, &config))
442 return NULL;
443 }
444 else {
Guido van Rossumfc58e581992-01-27 16:45:55 +0000445 err_badarg ();
Guido van Rossume3db8621991-09-09 23:33:34 +0000446 return NULL;
447 }
448
Guido van Rossumfc58e581992-01-27 16:45:55 +0000449 port = ALopenport(name, dir, config);
Guido van Rossume3db8621991-09-09 23:33:34 +0000450
Guido van Rossumc0aab891991-10-20 20:10:46 +0000451 if (port == NULL) {
452 err_errno(RuntimeError);
453 return NULL;
454 }
455
Guido van Rossume3db8621991-09-09 23:33:34 +0000456 return newportobject (port);
457}
458
459static object *
460al_newconfig (self, args)
461 object *self, *args;
462{
463 ALconfig config;
464
465 if (!getnoarg (args)) return NULL;
466
467 config = ALnewconfig ();
Guido van Rossumc0aab891991-10-20 20:10:46 +0000468 if (config == NULL) {
469 err_errno(RuntimeError);
470 return NULL;
471 }
Guido van Rossume3db8621991-09-09 23:33:34 +0000472
473 return newconfigobject (config);
474}
Guido van Rossumb3a5b9b1991-09-10 14:54:05 +0000475
476static object *
477al_queryparams(self, args)
478 object *self, *args;
479{
480 long device;
481 long length;
482 long *PVbuffer;
483 long PVdummy[2];
484 object *v;
485 object *w;
486
Guido van Rossumfc58e581992-01-27 16:45:55 +0000487 if (!getlongarg (args, &device))
Guido van Rossumb3a5b9b1991-09-10 14:54:05 +0000488 return NULL;
489 length = ALqueryparams(device, PVdummy, 2L);
490 PVbuffer = NEW(long, length);
491 if (PVbuffer == NULL)
492 return err_nomem();
493 (void) ALqueryparams(device, PVbuffer, length);
494 v = newlistobject((int)length);
495 if (v != NULL) {
496 int i;
497 for (i = 0; i < length; i++)
498 setlistitem(v, i, newintobject(PVbuffer[i]));
499 }
500 DEL(PVbuffer);
501 return v;
502}
503
504static object *
505doParams(args, func, modified)
506 object *args;
507 void (*func)(long, long *, long);
508 int modified;
509{
510 long device;
511 object *list, *v;
512 long *PVbuffer;
513 long length;
514 int i;
Guido van Rossume3db8621991-09-09 23:33:34 +0000515
Guido van Rossumfc58e581992-01-27 16:45:55 +0000516 if (!getargs(args, "(lO)", &device, &list))
Guido van Rossumb3a5b9b1991-09-10 14:54:05 +0000517 return NULL;
518 if (!is_listobject(list)) {
519 err_badarg();
520 return NULL;
521 }
522 length = getlistsize(list);
523 PVbuffer = NEW(long, length);
524 if (PVbuffer == NULL)
525 return err_nomem();
526 for (i = 0; i < length; i++) {
527 v = getlistitem(list, i);
528 if (!is_intobject(v)) {
529 DEL(PVbuffer);
530 err_badarg();
531 return NULL;
532 }
533 PVbuffer[i] = getintvalue(v);
534 }
535
Guido van Rossum8db03071991-09-13 15:31:47 +0000536 (*func)(device, PVbuffer, length);
Guido van Rossumb3a5b9b1991-09-10 14:54:05 +0000537
538 if (modified) {
539 for (i = 0; i < length; i++)
540 setlistitem(list, i, newintobject(PVbuffer[i]));
541 }
542
Guido van Rossumc0aab891991-10-20 20:10:46 +0000543 DEL(PVbuffer);
544
Guido van Rossumb3a5b9b1991-09-10 14:54:05 +0000545 INCREF(None);
546 return None;
547}
548
549static object *
550al_getparams(self, args)
551 object *self, *args;
552{
553 return doParams(args, ALgetparams, 1);
554}
555
556static object *
557al_setparams(self, args)
558 object *self, *args;
559{
560 return doParams(args, ALsetparams, 0);
561}
562
Guido van Rossume3db8621991-09-09 23:33:34 +0000563static struct methodlist al_methods[] = {
564 {"openport", al_openport},
565 {"newconfig", al_newconfig},
Guido van Rossumb3a5b9b1991-09-10 14:54:05 +0000566 {"queryparams", al_queryparams},
567 {"getparams", al_getparams},
568 {"setparams", al_setparams},
Guido van Rossume3db8621991-09-09 23:33:34 +0000569 {NULL, NULL} /* sentinel */
570};
571
572void
573inital()
574{
575 initmodule("al", al_methods);
576}
577
Guido van Rossumfc58e581992-01-27 16:45:55 +0000578static int
579getconfigarg(o, conf)
580 object *o;
Guido van Rossume3db8621991-09-09 23:33:34 +0000581 ALconfig *conf;
582{
583 if (o == NULL || !is_configobject(o))
584 return err_badarg ();
585
Guido van Rossumfc58e581992-01-27 16:45:55 +0000586 *conf = ((configobject *) o) -> ob_config;
Guido van Rossume3db8621991-09-09 23:33:34 +0000587
588 return 1;
589}
590
Guido van Rossumfc58e581992-01-27 16:45:55 +0000591static int
Guido van Rossume3db8621991-09-09 23:33:34 +0000592getstrstrconfigarg(v, a, b, c)
593 object *v;
Guido van Rossumfc58e581992-01-27 16:45:55 +0000594 char **a;
595 char **b;
Guido van Rossume3db8621991-09-09 23:33:34 +0000596 ALconfig *c;
597{
Guido van Rossumfc58e581992-01-27 16:45:55 +0000598 object *o;
599 return getargs(v, "(ssO)", a, b, &o) && getconfigarg(o, c);
Guido van Rossume3db8621991-09-09 23:33:34 +0000600}