blob: 6b1dde37d4bc01a347de99cfcd72da14de28c55d [file] [log] [blame]
Guido van Rossume3db8621991-09-09 23:33:34 +00001/**********************************************************
Guido van Rossumbab9d031992-04-05 14:26:55 +00002Copyright 1991, 1992 by Stichting Mathematisch Centrum, Amsterdam, The
Guido van Rossume3db8621991-09-09 23:33:34 +00003Netherlands.
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 Rossum57737981992-05-15 11:06:29 +000025/* AL module -- interface to Mark Callow's 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"
Jack Jansen743db361992-08-13 14:13:11 +000033#include "ceval.h"
Guido van Rossume3db8621991-09-09 23:33:34 +000034
35
36/* Config objects */
37
38typedef struct {
39 OB_HEAD
40 ALconfig ob_config;
41} configobject;
42
43extern typeobject Configtype; /* Forward */
44
45#define is_configobject(v) ((v)->ob_type == &Configtype)
46
Guido van Rossumfc58e581992-01-27 16:45:55 +000047/* Forward */
48static int getconfigarg PROTO((object *, ALconfig *));
49static int getstrstrconfigarg PROTO((object *, char **, char **, ALconfig *));
50
Guido van Rossume3db8621991-09-09 23:33:34 +000051static object *
52setConfig (self, args, func)
53 configobject *self;
54 object *args;
55 void (*func)(ALconfig, long);
56{
57 long par;
58
Guido van Rossumfc58e581992-01-27 16:45:55 +000059 if (!getlongarg (args, &par)) return NULL;
Guido van Rossume3db8621991-09-09 23:33:34 +000060
61 (*func) (self-> ob_config, par);
62
63 INCREF (None);
64 return None;
65}
66
67static object *
68getConfig (self, args, func)
69 configobject *self;
70 object *args;
71 long (*func)(ALconfig);
72{
73 long par;
74
Guido van Rossumfc58e581992-01-27 16:45:55 +000075 if (!getnoarg (args)) return NULL;
Guido van Rossume3db8621991-09-09 23:33:34 +000076
77 par = (*func) (self-> ob_config);
78
79 return newintobject (par);
80}
81
82static object *
83al_setqueuesize (self, args)
84 configobject *self;
85 object *args;
86{
87 return (setConfig (self, args, ALsetqueuesize));
88}
89
90static object *
91al_getqueuesize (self, args)
92 configobject *self;
93 object *args;
94{
95 return (getConfig (self, args, ALgetqueuesize));
96}
97
98static object *
99al_setwidth (self, args)
100 configobject *self;
101 object *args;
102{
103 return (setConfig (self, args, ALsetwidth));
104}
105
106static object *
107al_getwidth (self, args)
108 configobject *self;
109 object *args;
110{
111 return (getConfig (self, args, ALgetwidth));
112}
113
114static object *
115al_getchannels (self, args)
116 configobject *self;
117 object *args;
118{
119 return (getConfig (self, args, ALgetchannels));
120}
121
122static object *
123al_setchannels (self, args)
124 configobject *self;
125 object *args;
126{
127 return (setConfig (self, args, ALsetchannels));
128}
129
130static struct methodlist config_methods[] = {
131 {"getqueuesize", al_getqueuesize},
132 {"setqueuesize", al_setqueuesize},
133 {"getwidth", al_getwidth},
134 {"setwidth", al_setwidth},
135 {"getchannels", al_getchannels},
136 {"setchannels", al_setchannels},
137 {NULL, NULL} /* sentinel */
138};
139
140static void
141config_dealloc(self)
142 configobject *self;
143{
144 ALfreeconfig(self->ob_config);
145 DEL(self);
146}
147
148static object *
149config_getattr(self, name)
150 configobject *self;
151 char *name;
152{
153 return findmethod(config_methods, (object *)self, name);
154}
155
156typeobject Configtype = {
157 OB_HEAD_INIT(&Typetype)
158 0, /*ob_size*/
159 "config", /*tp_name*/
160 sizeof(configobject), /*tp_size*/
161 0, /*tp_itemsize*/
162 /* methods */
163 config_dealloc, /*tp_dealloc*/
164 0, /*tp_print*/
165 config_getattr, /*tp_getattr*/
166 0, /*tp_setattr*/
167 0, /*tp_compare*/
168 0, /*tp_repr*/
169};
170
171static object *
172newconfigobject(config)
173 ALconfig config;
174{
175 configobject *p;
176
177 p = NEWOBJ(configobject, &Configtype);
178 if (p == NULL)
179 return NULL;
180 p->ob_config = config;
181 return (object *)p;
182}
183
184/* Port objects */
185
186typedef struct {
187 OB_HEAD
188 ALport ob_port;
189} portobject;
190
191extern typeobject Porttype; /* Forward */
192
193#define is_portobject(v) ((v)->ob_type == &Porttype)
194
195static object *
196al_closeport (self, args)
197 portobject *self;
198 object *args;
199{
Guido van Rossumfc58e581992-01-27 16:45:55 +0000200 if (!getnoarg (args)) return NULL;
Guido van Rossume3db8621991-09-09 23:33:34 +0000201
202 if (self->ob_port != NULL) {
203 ALcloseport (self-> ob_port);
204 self->ob_port = NULL;
205 /* XXX Using a closed port may dump core! */
206 }
207
208 INCREF (None);
209 return None;
210}
211
212static object *
213al_getfd (self, args)
214 portobject *self;
215 object *args;
216{
217 int fd;
218
Guido van Rossumfc58e581992-01-27 16:45:55 +0000219 if (!getnoarg (args)) return NULL;
Guido van Rossume3db8621991-09-09 23:33:34 +0000220
221 fd = ALgetfd (self-> ob_port);
222
223 return newintobject (fd);
224}
225
226static object *
227al_getfilled (self, args)
228 portobject *self;
229 object *args;
230{
231 long count;
232
Guido van Rossumfc58e581992-01-27 16:45:55 +0000233 if (!getnoarg (args)) return NULL;
Guido van Rossume3db8621991-09-09 23:33:34 +0000234
235 count = ALgetfilled (self-> ob_port);
236
237 return newintobject (count);
238}
239
240static object *
241al_getfillable (self, args)
242 portobject *self;
243 object *args;
244{
245 long count;
246
Guido van Rossumfc58e581992-01-27 16:45:55 +0000247 if (!getnoarg (args)) return NULL;
Guido van Rossume3db8621991-09-09 23:33:34 +0000248
249 count = ALgetfillable (self-> ob_port);
250
251 return newintobject (count);
252}
253
254static object *
255al_readsamps (self, args)
256 portobject *self;
257 object *args;
258{
259 long count;
260 object *v;
Guido van Rossumb3a5b9b1991-09-10 14:54:05 +0000261 ALconfig c;
Guido van Rossume3db8621991-09-09 23:33:34 +0000262 int width;
263
264 if (!getlongarg (args, &count)) return NULL;
265
266 if (count <= 0)
267 {
268 err_setstr (RuntimeError, "al.readsamps : arg <= 0");
269 return NULL;
270 }
271
Guido van Rossumb3a5b9b1991-09-10 14:54:05 +0000272 c = ALgetconfig(self->ob_port);
273 width = ALgetwidth(c);
274 ALfreeconfig(c);
Guido van Rossume3db8621991-09-09 23:33:34 +0000275 v = newsizedstringobject ((char *)NULL, width * count);
276 if (v == NULL) return NULL;
277
Jack Jansen743db361992-08-13 14:13:11 +0000278 BGN_SAVE
Guido van Rossume3db8621991-09-09 23:33:34 +0000279 ALreadsamps (self-> ob_port, (void *) getstringvalue(v), count);
Jack Jansen743db361992-08-13 14:13:11 +0000280 END_SAVE
Guido van Rossume3db8621991-09-09 23:33:34 +0000281
282 return (v);
283}
284
285static object *
286al_writesamps (self, args)
287 portobject *self;
288 object *args;
289{
290 long count;
Guido van Rossumfc58e581992-01-27 16:45:55 +0000291 char *buf;
292 int size, width;
Guido van Rossumb3a5b9b1991-09-10 14:54:05 +0000293 ALconfig c;
Guido van Rossume3db8621991-09-09 23:33:34 +0000294
Guido van Rossumfc58e581992-01-27 16:45:55 +0000295 if (!getargs (args, "s#", &buf, &size)) return NULL;
Guido van Rossume3db8621991-09-09 23:33:34 +0000296
Guido van Rossumb3a5b9b1991-09-10 14:54:05 +0000297 c = ALgetconfig(self->ob_port);
298 width = ALgetwidth(c);
299 ALfreeconfig(c);
Jack Jansen743db361992-08-13 14:13:11 +0000300 BGN_SAVE
Guido van Rossumfc58e581992-01-27 16:45:55 +0000301 ALwritesamps (self-> ob_port, (void *) buf, (long) size / width);
Jack Jansen743db361992-08-13 14:13:11 +0000302 END_SAVE
Guido van Rossume3db8621991-09-09 23:33:34 +0000303
304 INCREF (None);
305 return None;
306}
307
308static object *
309al_getfillpoint (self, args)
310 portobject *self;
311 object *args;
312{
313 long count;
314
Guido van Rossumfc58e581992-01-27 16:45:55 +0000315 if (!getnoarg (args)) return NULL;
Guido van Rossume3db8621991-09-09 23:33:34 +0000316
317 count = ALgetfillpoint (self-> ob_port);
318
319 return newintobject (count);
320}
321
322static object *
323al_setfillpoint (self, args)
324 portobject *self;
325 object *args;
326{
327 long count;
328
Guido van Rossumfc58e581992-01-27 16:45:55 +0000329 if (!getlongarg (args, &count)) return NULL;
Guido van Rossume3db8621991-09-09 23:33:34 +0000330
331 ALsetfillpoint (self-> ob_port, count);
332
333 INCREF (None);
334 return (None);
335}
336
337static object *
338al_setconfig (self, args)
339 portobject *self;
340 object *args;
341{
342 ALconfig config;
343
Guido van Rossumfc58e581992-01-27 16:45:55 +0000344 if (!getconfigarg (args, &config)) return NULL;
Guido van Rossume3db8621991-09-09 23:33:34 +0000345
346 ALsetconfig (self-> ob_port, config);
347
348 INCREF (None);
349 return (None);
350}
351
352static object *
353al_getconfig (self, args)
354 portobject *self;
355 object *args;
356{
357 ALconfig config;
358
Guido van Rossumfc58e581992-01-27 16:45:55 +0000359 if (!getnoarg (args)) return NULL;
Guido van Rossume3db8621991-09-09 23:33:34 +0000360
361 config = ALgetconfig (self-> ob_port);
362
363 return newconfigobject (config);
364}
365
366static struct methodlist port_methods[] = {
367 {"closeport", al_closeport},
368 {"getfd", al_getfd},
Jack Jansen743db361992-08-13 14:13:11 +0000369 {"fileno", al_getfd},
Guido van Rossume3db8621991-09-09 23:33:34 +0000370 {"getfilled", al_getfilled},
371 {"getfillable", al_getfillable},
372 {"readsamps", al_readsamps},
373 {"writesamps", al_writesamps},
374 {"setfillpoint", al_setfillpoint},
375 {"getfillpoint", al_getfillpoint},
376 {"setconfig", al_setconfig},
377 {"getconfig", al_getconfig},
378 {NULL, NULL} /* sentinel */
379};
380
381static void
382port_dealloc(p)
383 portobject *p;
384{
385 if (p->ob_port != NULL)
386 ALcloseport(p->ob_port);
387 DEL(p);
388}
389
390static object *
391port_getattr(p, name)
392 portobject *p;
393 char *name;
394{
395 return findmethod(port_methods, (object *)p, name);
396}
397
398typeobject Porttype = {
399 OB_HEAD_INIT(&Typetype)
400 0, /*ob_size*/
401 "port", /*tp_name*/
402 sizeof(portobject), /*tp_size*/
403 0, /*tp_itemsize*/
404 /* methods */
405 port_dealloc, /*tp_dealloc*/
406 0, /*tp_print*/
407 port_getattr, /*tp_getattr*/
408 0, /*tp_setattr*/
409 0, /*tp_compare*/
410 0, /*tp_repr*/
411};
412
413static object *
414newportobject(port)
415 ALport port;
416{
417 portobject *p;
418
419 p = NEWOBJ(portobject, &Porttype);
420 if (p == NULL)
421 return NULL;
422 p->ob_port = port;
423 return (object *)p;
424}
425
426/* the module al */
427
428static object *
429al_openport (self, args)
430 object *self, *args;
431{
Guido van Rossumfc58e581992-01-27 16:45:55 +0000432 char *name, *dir;
Guido van Rossume3db8621991-09-09 23:33:34 +0000433 ALport port;
434 ALconfig config = NULL;
Guido van Rossumc0aab891991-10-20 20:10:46 +0000435 int size;
Guido van Rossume3db8621991-09-09 23:33:34 +0000436
Guido van Rossumc0aab891991-10-20 20:10:46 +0000437 if (args == NULL || !is_tupleobject(args)) {
Guido van Rossumfc58e581992-01-27 16:45:55 +0000438 err_badarg ();
Guido van Rossumc0aab891991-10-20 20:10:46 +0000439 return NULL;
440 }
441 size = gettuplesize(args);
Guido van Rossume3db8621991-09-09 23:33:34 +0000442 if (size == 2) {
443 if (!getstrstrarg (args, &name, &dir))
444 return NULL;
445 }
446 else if (size == 3) {
447 if (!getstrstrconfigarg (args, &name, &dir, &config))
448 return NULL;
449 }
450 else {
Guido van Rossumfc58e581992-01-27 16:45:55 +0000451 err_badarg ();
Guido van Rossume3db8621991-09-09 23:33:34 +0000452 return NULL;
453 }
454
Guido van Rossumfc58e581992-01-27 16:45:55 +0000455 port = ALopenport(name, dir, config);
Guido van Rossume3db8621991-09-09 23:33:34 +0000456
Guido van Rossumc0aab891991-10-20 20:10:46 +0000457 if (port == NULL) {
458 err_errno(RuntimeError);
459 return NULL;
460 }
461
Guido van Rossume3db8621991-09-09 23:33:34 +0000462 return newportobject (port);
463}
464
465static object *
466al_newconfig (self, args)
467 object *self, *args;
468{
469 ALconfig config;
470
471 if (!getnoarg (args)) return NULL;
472
473 config = ALnewconfig ();
Guido van Rossumc0aab891991-10-20 20:10:46 +0000474 if (config == NULL) {
475 err_errno(RuntimeError);
476 return NULL;
477 }
Guido van Rossume3db8621991-09-09 23:33:34 +0000478
479 return newconfigobject (config);
480}
Guido van Rossumb3a5b9b1991-09-10 14:54:05 +0000481
482static object *
483al_queryparams(self, args)
484 object *self, *args;
485{
486 long device;
487 long length;
488 long *PVbuffer;
489 long PVdummy[2];
490 object *v;
491 object *w;
492
Guido van Rossumfc58e581992-01-27 16:45:55 +0000493 if (!getlongarg (args, &device))
Guido van Rossumb3a5b9b1991-09-10 14:54:05 +0000494 return NULL;
495 length = ALqueryparams(device, PVdummy, 2L);
496 PVbuffer = NEW(long, length);
497 if (PVbuffer == NULL)
498 return err_nomem();
499 (void) ALqueryparams(device, PVbuffer, length);
500 v = newlistobject((int)length);
501 if (v != NULL) {
502 int i;
503 for (i = 0; i < length; i++)
504 setlistitem(v, i, newintobject(PVbuffer[i]));
505 }
506 DEL(PVbuffer);
507 return v;
508}
509
510static object *
511doParams(args, func, modified)
512 object *args;
513 void (*func)(long, long *, long);
514 int modified;
515{
516 long device;
517 object *list, *v;
518 long *PVbuffer;
519 long length;
520 int i;
Guido van Rossume3db8621991-09-09 23:33:34 +0000521
Guido van Rossumfc58e581992-01-27 16:45:55 +0000522 if (!getargs(args, "(lO)", &device, &list))
Guido van Rossumb3a5b9b1991-09-10 14:54:05 +0000523 return NULL;
524 if (!is_listobject(list)) {
525 err_badarg();
526 return NULL;
527 }
528 length = getlistsize(list);
529 PVbuffer = NEW(long, length);
530 if (PVbuffer == NULL)
531 return err_nomem();
532 for (i = 0; i < length; i++) {
533 v = getlistitem(list, i);
534 if (!is_intobject(v)) {
535 DEL(PVbuffer);
536 err_badarg();
537 return NULL;
538 }
539 PVbuffer[i] = getintvalue(v);
540 }
541
Guido van Rossum8db03071991-09-13 15:31:47 +0000542 (*func)(device, PVbuffer, length);
Guido van Rossumb3a5b9b1991-09-10 14:54:05 +0000543
544 if (modified) {
545 for (i = 0; i < length; i++)
546 setlistitem(list, i, newintobject(PVbuffer[i]));
547 }
548
Guido van Rossumc0aab891991-10-20 20:10:46 +0000549 DEL(PVbuffer);
550
Guido van Rossumb3a5b9b1991-09-10 14:54:05 +0000551 INCREF(None);
552 return None;
553}
554
555static object *
556al_getparams(self, args)
557 object *self, *args;
558{
559 return doParams(args, ALgetparams, 1);
560}
561
562static object *
563al_setparams(self, args)
564 object *self, *args;
565{
566 return doParams(args, ALsetparams, 0);
567}
568
Guido van Rossum448f4bf1992-08-19 16:41:15 +0000569static object *
570al_getname(self, args)
571 object *self, *args;
572{
573 long device, descriptor;
574 char *name;
575 if (!getargs(args, "(ll)", &device, &descriptor))
576 return NULL;
577 name = ALgetname(device, descriptor);
578 if (name == NULL) {
579 err_setstr(ValueError, "al.getname: bad descriptor");
580 return NULL;
581 }
582 return newstringobject(name);
583}
584
585static object *
586al_getdefault(self, args)
587 object *self, *args;
588{
589 long device, descriptor, value;
590 if (!getargs(args, "(ll)", &device, &descriptor))
591 return NULL;
592 value = ALgetdefault(device, descriptor);
593 return newlongobject(value);
594}
595
596static object *
597al_getminmax(self, args)
598 object *self, *args;
599{
600 long device, descriptor, min, max;
601 if (!getargs(args, "(ll)", &device, &descriptor))
602 return NULL;
603 min = -1;
604 max = -1;
605 ALgetminmax(device, descriptor, &min, &max);
606 return mkvalue("ll", min, max);
607}
608
Guido van Rossume3db8621991-09-09 23:33:34 +0000609static struct methodlist al_methods[] = {
610 {"openport", al_openport},
611 {"newconfig", al_newconfig},
Guido van Rossumb3a5b9b1991-09-10 14:54:05 +0000612 {"queryparams", al_queryparams},
613 {"getparams", al_getparams},
614 {"setparams", al_setparams},
Guido van Rossum448f4bf1992-08-19 16:41:15 +0000615 {"getname", al_getname},
616 {"getdefault", al_getdefault},
617 {"getminmax", al_getminmax},
Guido van Rossume3db8621991-09-09 23:33:34 +0000618 {NULL, NULL} /* sentinel */
619};
620
621void
622inital()
623{
624 initmodule("al", al_methods);
625}
626
Guido van Rossumfc58e581992-01-27 16:45:55 +0000627static int
628getconfigarg(o, conf)
629 object *o;
Guido van Rossume3db8621991-09-09 23:33:34 +0000630 ALconfig *conf;
631{
632 if (o == NULL || !is_configobject(o))
633 return err_badarg ();
634
Guido van Rossumfc58e581992-01-27 16:45:55 +0000635 *conf = ((configobject *) o) -> ob_config;
Guido van Rossume3db8621991-09-09 23:33:34 +0000636
637 return 1;
638}
639
Guido van Rossumfc58e581992-01-27 16:45:55 +0000640static int
Guido van Rossume3db8621991-09-09 23:33:34 +0000641getstrstrconfigarg(v, a, b, c)
642 object *v;
Guido van Rossumfc58e581992-01-27 16:45:55 +0000643 char **a;
644 char **b;
Guido van Rossume3db8621991-09-09 23:33:34 +0000645 ALconfig *c;
646{
Guido van Rossumfc58e581992-01-27 16:45:55 +0000647 object *o;
648 return getargs(v, "(ssO)", a, b, &o) && getconfigarg(o, c);
Guido van Rossume3db8621991-09-09 23:33:34 +0000649}