summaryrefslogtreecommitdiff
path: root/apps/plugins/pdbox/PDa/src/s_audio.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/pdbox/PDa/src/s_audio.c')
-rw-r--r--apps/plugins/pdbox/PDa/src/s_audio.c1746
1 files changed, 1746 insertions, 0 deletions
diff --git a/apps/plugins/pdbox/PDa/src/s_audio.c b/apps/plugins/pdbox/PDa/src/s_audio.c
new file mode 100644
index 0000000000..4cb93307b0
--- /dev/null
+++ b/apps/plugins/pdbox/PDa/src/s_audio.c
@@ -0,0 +1,1746 @@
1/* Copyright (c) 2003, Miller Puckette and others.
2* For information on usage and redistribution, and for a DISCLAIMER OF ALL
3* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
4
5/* machine-independent (well, mostly!) audio layer. Stores and recalls
6 audio settings from argparse routine and from dialog window.
7*/
8
9#include "m_pd.h"
10#include "s_stuff.h"
11#include <stdio.h>
12#ifdef UNIX
13#include <unistd.h>
14#include <sys/time.h>
15#include <sys/resource.h>
16#endif
17#include <stdlib.h>
18#include <string.h>
19#include <errno.h>
20
21#define SYS_DEFAULTCH 2
22#define SYS_MAXCH 100
23#define SYS_DEFAULTSRATE 44100
24typedef long t_pa_sample;
25#define SYS_SAMPLEWIDTH sizeof(t_pa_sample)
26#define SYS_BYTESPERCHAN (DEFDACBLKSIZE * SYS_SAMPLEWIDTH)
27#define SYS_XFERSAMPS (SYS_DEFAULTCH*DEFDACBLKSIZE)
28#define SYS_XFERSIZE (SYS_SAMPLEWIDTH * SYS_XFERSAMPS)
29
30 /* these are set in this file when opening audio, but then may be reduced,
31 even to zero, in the system dependent open_audio routines. */
32int sys_inchannels;
33int sys_outchannels;
34int sys_advance_samples; /* scheduler advance in samples */
35int sys_blocksize = 0; /* audio I/O block size in sample frames */
36int sys_audioapi = API_DEFAULT;
37
38static int sys_meters; /* true if we're metering */
39static float sys_inmax; /* max input amplitude */
40static float sys_outmax; /* max output amplitude */
41
42 /* exported variables */
43int sys_schedadvance; /* scheduler advance in microseconds */
44float sys_dacsr;
45
46#ifdef MACOSX
47int sys_hipriority = 1;
48#else
49int sys_hipriority = 0;
50#endif
51
52t_sample *sys_soundout;
53t_sample *sys_soundin;
54
55 /* the "state" is normally one if we're open and zero otherwise;
56 but if the state is one, we still haven't necessarily opened the
57 audio hardware; see audio_isopen() below. */
58static int audio_state;
59
60 /* last requested parameters */
61static int audio_naudioindev;
62static int audio_audioindev[MAXAUDIOINDEV];
63static int audio_audiochindev[MAXAUDIOINDEV];
64static int audio_naudiooutdev;
65static int audio_audiooutdev[MAXAUDIOOUTDEV];
66static int audio_audiochoutdev[MAXAUDIOOUTDEV];
67static int audio_rate;
68static int audio_advance;
69
70static int audio_isopen(void)
71{
72 return (audio_state &&
73 ((audio_naudioindev > 0 && audio_audiochindev[0] > 0)
74 || (audio_naudiooutdev > 0 && audio_audiochoutdev[0] > 0)));
75}
76
77static void sys_get_audio_params(
78 int *pnaudioindev, int *paudioindev, int *chindev,
79 int *pnaudiooutdev, int *paudiooutdev, int *choutdev,
80 int *prate, int *padvance)
81{
82 int i;
83 *pnaudioindev = audio_naudioindev;
84 for (i = 0; i < MAXAUDIOINDEV; i++)
85 paudioindev[i] = audio_audioindev[i],
86 chindev[i] = audio_audiochindev[i];
87 *pnaudiooutdev = audio_naudiooutdev;
88 for (i = 0; i < MAXAUDIOOUTDEV; i++)
89 paudiooutdev[i] = audio_audiooutdev[i],
90 choutdev[i] = audio_audiochoutdev[i];
91 *prate = audio_rate;
92 *padvance = audio_advance;
93}
94
95static void sys_save_audio_params(
96 int naudioindev, int *audioindev, int *chindev,
97 int naudiooutdev, int *audiooutdev, int *choutdev,
98 int rate, int advance)
99{
100 int i;
101 audio_naudioindev = naudioindev;
102 for (i = 0; i < MAXAUDIOINDEV; i++)
103 audio_audioindev[i] = audioindev[i],
104 audio_audiochindev[i] = chindev[i];
105 audio_naudiooutdev = naudiooutdev;
106 for (i = 0; i < MAXAUDIOOUTDEV; i++)
107 audio_audiooutdev[i] = audiooutdev[i],
108 audio_audiochoutdev[i] = choutdev[i];
109 audio_rate = rate;
110 audio_advance = advance;
111}
112
113 /* init routines for any API which needs to set stuff up before
114 any other API gets used. This is only true of OSS so far. */
115#ifdef USEAPI_OSS
116void oss_init(void);
117#endif
118
119static void audio_init( void)
120{
121 static int initted = 0;
122 if (initted)
123 return;
124 initted = 1;
125#ifdef USEAPI_OSS
126 oss_init();
127#endif
128}
129
130 /* set channels and sample rate. */
131
132static void sys_setchsr(int chin, int chout, int sr)
133{
134 int nblk;
135 int inbytes = (chin ? chin : 2) * (DEFDACBLKSIZE*sizeof(float));
136 int outbytes = (chout ? chout : 2) * (DEFDACBLKSIZE*sizeof(float));
137
138 sys_inchannels = chin;
139 sys_outchannels = chout;
140 sys_dacsr = sr;
141 sys_advance_samples = (sys_schedadvance * sys_dacsr) / (1000000.);
142 if (sys_advance_samples < 3 * DEFDACBLKSIZE)
143 sys_advance_samples = 3 * DEFDACBLKSIZE;
144
145 if (sys_soundin)
146 free(sys_soundin);
147 sys_soundin = (t_float *)malloc(inbytes);
148 memset(sys_soundin, 0, inbytes);
149
150 if (sys_soundout)
151 free(sys_soundout);
152 sys_soundout = (t_float *)malloc(outbytes);
153 memset(sys_soundout, 0, outbytes);
154
155 if (sys_verbose)
156 post("input channels = %d, output channels = %d",
157 sys_inchannels, sys_outchannels);
158 canvas_resume_dsp(canvas_suspend_dsp());
159}
160
161/* ----------------------- public routines ----------------------- */
162
163 /* open audio devices (after cleaning up the specified device and channel
164 vectors). The audio devices are "zero based" (i.e. "0" means the first
165 one.) We also save the cleaned-up device specification so that we
166 can later re-open audio and/or show the settings on a dialog window. */
167
168void sys_open_audio(int naudioindev, int *audioindev, int nchindev,
169 int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev,
170 int *choutdev, int rate, int advance, int enable)
171{
172 int i, *ip;
173 int defaultchannels = SYS_DEFAULTCH;
174 int inchans, outchans;
175 if (rate < 1)
176 rate = SYS_DEFAULTSRATE;
177 audio_init();
178 /* Since the channel vector might be longer than the
179 audio device vector, or vice versa, we fill the shorter one
180 in to match the longer one. Also, if both are empty, we fill in
181 one device (the default) and two channels. */
182 if (naudioindev == -1)
183 { /* no input audio devices specified */
184 if (nchindev == -1)
185 {
186 nchindev=1;
187 chindev[0] = defaultchannels;
188 naudioindev = 1;
189 audioindev[0] = DEFAULTAUDIODEV;
190 }
191 else
192 {
193 for (i = 0; i < MAXAUDIOINDEV; i++)
194 audioindev[i] = i;
195 naudioindev = nchindev;
196 }
197 }
198 else
199 {
200 if (nchindev == -1)
201 {
202 nchindev = naudioindev;
203 for (i = 0; i < naudioindev; i++)
204 chindev[i] = defaultchannels;
205 }
206 else if (nchindev > naudioindev)
207 {
208 for (i = naudioindev; i < nchindev; i++)
209 {
210 if (i == 0)
211 audioindev[0] = DEFAULTAUDIODEV;
212 else audioindev[i] = audioindev[i-1] + 1;
213 }
214 naudioindev = nchindev;
215 }
216 else if (nchindev < naudioindev)
217 {
218 for (i = nchindev; i < naudioindev; i++)
219 {
220 if (i == 0)
221 chindev[0] = defaultchannels;
222 else chindev[i] = chindev[i-1];
223 }
224 naudioindev = nchindev;
225 }
226 }
227
228 if (naudiooutdev == -1)
229 { /* not set */
230 if (nchoutdev == -1)
231 {
232 nchoutdev=1;
233 choutdev[0]=defaultchannels;
234 naudiooutdev=1;
235 audiooutdev[0] = DEFAULTAUDIODEV;
236 }
237 else
238 {
239 for (i = 0; i < MAXAUDIOOUTDEV; i++)
240 audiooutdev[i] = i;
241 naudiooutdev = nchoutdev;
242 }
243 }
244 else
245 {
246 if (nchoutdev == -1)
247 {
248 nchoutdev = naudiooutdev;
249 for (i = 0; i < naudiooutdev; i++)
250 choutdev[i] = defaultchannels;
251 }
252 else if (nchoutdev > naudiooutdev)
253 {
254 for (i = naudiooutdev; i < nchoutdev; i++)
255 {
256 if (i == 0)
257 audiooutdev[0] = DEFAULTAUDIODEV;
258 else audiooutdev[i] = audiooutdev[i-1] + 1;
259 }
260 naudiooutdev = nchoutdev;
261 }
262 else if (nchoutdev < naudiooutdev)
263 {
264 for (i = nchoutdev; i < naudiooutdev; i++)
265 {
266 if (i == 0)
267 choutdev[0] = defaultchannels;
268 else choutdev[i] = choutdev[i-1];
269 }
270 naudiooutdev = nchoutdev;
271 }
272 }
273
274 /* count total number of input and output channels */
275 for (i = inchans = 0; i < naudioindev; i++)
276 inchans += chindev[i];
277 for (i = outchans = 0; i < naudiooutdev; i++)
278 outchans += choutdev[i];
279 /* if no input or output devices seem to have been specified,
280 this really means just disable audio, which we now do. Meanwhile,
281 we can set audio input and output devices to their defaults. */
282 if (!inchans && !outchans)
283 {
284 enable = 0;
285 naudioindev = nchindev = naudiooutdev = nchoutdev = 1;
286 audioindev[0] = audiooutdev[0] = DEFAULTAUDIODEV;
287 chindev[0] = choutdev[0] = 0;
288 }
289 sys_schedadvance = advance * 1000;
290 sys_setchsr(inchans, outchans, rate);
291 sys_log_error(ERR_NOTHING);
292
293 if (enable && (inchans > 0 || outchans > 0))
294 {
295#ifdef USEAPI_PORTAUDIO
296 if (sys_audioapi == API_PORTAUDIO)
297 {
298 int blksize = (sys_blocksize ? sys_blocksize : 64);
299 pa_open_audio(inchans, outchans, rate, sys_soundin, sys_soundout,
300 blksize, sys_advance_samples/blksize,
301 (naudiooutdev > 0 ? audioindev[0] : 0),
302 (naudiooutdev > 0 ? audiooutdev[0] : 0));
303 }
304else
305#endif
306#ifdef USEAPI_JACK
307 if (sys_audioapi == API_JACK)
308 jack_open_audio((naudioindev > 0 ? chindev[0] : 0),
309 (naudiooutdev > 0 ? choutdev[0] : 0), rate);
310
311 else
312#endif
313#ifdef USEAPI_OSS
314 if (sys_audioapi == API_OSS)
315 oss_open_audio(naudioindev, audioindev, nchindev, chindev,
316 naudiooutdev, audiooutdev, nchoutdev, choutdev, rate);
317 else
318#endif
319#ifdef USEAPI_ALSA
320 /* for alsa, only one device is supported; it may
321 be open for both input and output. */
322 if (sys_audioapi == API_ALSA)
323 alsa_open_audio(naudioindev, audioindev, nchindev, chindev,
324 naudiooutdev, audiooutdev, nchoutdev, choutdev, rate);
325 else
326#endif
327#ifdef USEAPI_MMIO
328 if (sys_audioapi == API_MMIO)
329 mmio_open_audio(naudioindev, audioindev, nchindev, chindev,
330 naudiooutdev, audiooutdev, nchoutdev, choutdev, rate);
331 else
332#endif
333 post("unknown audio API specified");
334 }
335 sys_save_audio_params(naudioindev, audioindev, chindev,
336 naudiooutdev, audiooutdev, choutdev, rate, advance);
337 if (sys_inchannels == 0 && sys_outchannels == 0)
338 enable = 0;
339 audio_state = enable;
340 sys_vgui("set pd_whichapi %d\n", (audio_isopen() ? sys_audioapi : 0));
341 sched_set_using_dacs(enable);
342}
343
344void sys_close_audio(void)
345{
346 if (!audio_isopen())
347 return;
348#ifdef USEAPI_PORTAUDIO
349 if (sys_audioapi == API_PORTAUDIO)
350 pa_close_audio();
351 else
352#endif
353#ifdef USEAPI_JACK
354 if (sys_audioapi == API_JACK)
355 jack_close_audio();
356 else
357#endif
358#ifdef USEAPI_OSS
359 if (sys_audioapi == API_OSS)
360 oss_close_audio();
361 else
362#endif
363#ifdef USEAPI_ALSA
364 if (sys_audioapi == API_ALSA)
365 alsa_close_audio();
366 else
367#endif
368#ifdef USEAPI_MMIO
369 if (sys_audioapi == API_MMIO)
370 mmio_close_audio();
371 else
372#endif
373 post("sys_close_audio: unknown API %d", sys_audioapi);
374 sys_inchannels = sys_outchannels = 0;
375}
376
377 /* open audio using whatever parameters were last used */
378void sys_reopen_audio( void)
379{
380 int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV];
381 int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV];
382 int rate, advance;
383 sys_get_audio_params(&naudioindev, audioindev, chindev,
384 &naudiooutdev, audiooutdev, choutdev, &rate, &advance);
385 sys_open_audio(naudioindev, audioindev, naudioindev, chindev,
386 naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate, advance, 1);
387}
388
389int sys_send_dacs(void)
390{
391 if (sys_meters)
392 {
393 int i, n;
394 float maxsamp;
395 for (i = 0, n = sys_inchannels * DEFDACBLKSIZE, maxsamp = sys_inmax;
396 i < n; i++)
397 {
398 float f = sys_soundin[i];
399 if (f > maxsamp) maxsamp = f;
400 else if (-f > maxsamp) maxsamp = -f;
401 }
402 sys_inmax = maxsamp;
403 for (i = 0, n = sys_outchannels * DEFDACBLKSIZE, maxsamp = sys_outmax;
404 i < n; i++)
405 {
406 float f = sys_soundout[i];
407 if (f > maxsamp) maxsamp = f;
408 else if (-f > maxsamp) maxsamp = -f;
409 }
410 sys_outmax = maxsamp;
411 }
412
413#ifdef USEAPI_PORTAUDIO
414 if (sys_audioapi == API_PORTAUDIO)
415 return (pa_send_dacs());
416 else
417#endif
418#ifdef USEAPI_JACK
419 if (sys_audioapi == API_JACK)
420 return (jack_send_dacs());
421 else
422#endif
423#ifdef USEAPI_OSS
424 if (sys_audioapi == API_OSS)
425 return (oss_send_dacs());
426 else
427#endif
428#ifdef USEAPI_ALSA
429 if (sys_audioapi == API_ALSA)
430 return (alsa_send_dacs());
431 else
432#endif
433#ifdef USEAPI_MMIO
434 if (sys_audioapi == API_MMIO)
435 return (mmio_send_dacs());
436 else
437#endif
438 post("unknown API");
439 return (0);
440}
441
442float sys_getsr(void)
443{
444 return (sys_dacsr);
445}
446
447int sys_get_outchannels(void)
448{
449 return (sys_outchannels);
450}
451
452int sys_get_inchannels(void)
453{
454 return (sys_inchannels);
455}
456
457void sys_audiobuf(int n)
458{
459 /* set the size, in milliseconds, of the audio FIFO */
460 if (n < 5) n = 5;
461 else if (n > 5000) n = 5000;
462 sys_schedadvance = n * 1000;
463}
464
465void sys_getmeters(float *inmax, float *outmax)
466{
467 if (inmax)
468 {
469 sys_meters = 1;
470 *inmax = sys_inmax;
471 *outmax = sys_outmax;
472 }
473 else
474 sys_meters = 0;
475 sys_inmax = sys_outmax = 0;
476}
477
478void sys_reportidle(void)
479{
480}
481
482#define MAXNDEV 20
483#define DEVDESCSIZE 80
484
485static void audio_getdevs(char *indevlist, int *nindevs,
486 char *outdevlist, int *noutdevs, int *canmulti,
487 int maxndev, int devdescsize)
488{
489 audio_init();
490#ifdef USEAPI_OSS
491 if (sys_audioapi == API_OSS)
492 {
493 oss_getdevs(indevlist, nindevs, outdevlist, noutdevs, canmulti,
494 maxndev, devdescsize);
495 }
496 else
497#endif
498#ifdef USEAPI_ALSA
499 if (sys_audioapi == API_ALSA)
500 {
501 alsa_getdevs(indevlist, nindevs, outdevlist, noutdevs, canmulti,
502 maxndev, devdescsize);
503 }
504 else
505#endif
506#ifdef USEAPI_PORTAUDIO
507 if (sys_audioapi == API_PORTAUDIO)
508 {
509 pa_getdevs(indevlist, nindevs, outdevlist, noutdevs, canmulti,
510 maxndev, devdescsize);
511 }
512 else
513#endif
514#ifdef USEAPI_MMIO
515 if (sys_audioapi == API_MMIO)
516 {
517 mmio_getdevs(indevlist, nindevs, outdevlist, noutdevs, canmulti,
518 maxndev, devdescsize);
519 }
520 else
521#endif
522 {
523 /* this shouldn't happen once all the above get filled in. */
524 int i;
525 *nindevs = *noutdevs = 3;
526 for (i = 0; i < 3; i++)
527 {
528 sprintf(indevlist + i * devdescsize, "input device #%d", i+1);
529 sprintf(outdevlist + i * devdescsize, "output device #%d", i+1);
530 }
531 *canmulti = 0;
532 }
533}
534
535#ifdef MSW
536#define DEVONSET 0 /* microsoft device list starts at 0 (the "mapper"). */
537#else /* (see also MSW ifdef in sys_parsedevlist(), s_main.c) */
538#define DEVONSET 1 /* To agree with command line flags, normally start at 1 */
539#endif
540
541static void sys_listaudiodevs(void )
542{
543 char indevlist[MAXNDEV*DEVDESCSIZE], outdevlist[MAXNDEV*DEVDESCSIZE];
544 int nindevs = 0, noutdevs = 0, i, canmulti = 0;
545
546 audio_getdevs(indevlist, &nindevs, outdevlist, &noutdevs, &canmulti,
547 MAXNDEV, DEVDESCSIZE);
548
549 if (!nindevs)
550 post("no audio input devices found");
551 else
552 {
553 post("input devices:");
554 for (i = 0; i < nindevs; i++)
555 post("%d. %s", i+1, indevlist + i * DEVDESCSIZE);
556 }
557 if (!noutdevs)
558 post("no audio output devices found");
559 else
560 {
561 post("output devices:");
562 for (i = 0; i < noutdevs; i++)
563 post("%d. %s", i + DEVONSET, outdevlist + i * DEVDESCSIZE);
564 }
565 post("API number %d\n", sys_audioapi);
566}
567
568 /* start an audio settings dialog window */
569void glob_audio_properties(t_pd *dummy, t_floatarg flongform)
570{
571 char buf[1024 + 2 * MAXNDEV*(DEVDESCSIZE+4)];
572 /* these are the devices you're using: */
573 int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV];
574 int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV];
575 int audioindev1, audioindev2, audioindev3, audioindev4,
576 audioinchan1, audioinchan2, audioinchan3, audioinchan4,
577 audiooutdev1, audiooutdev2, audiooutdev3, audiooutdev4,
578 audiooutchan1, audiooutchan2, audiooutchan3, audiooutchan4;
579 int rate, advance;
580 /* these are all the devices on your system: */
581 char indevlist[MAXNDEV*DEVDESCSIZE], outdevlist[MAXNDEV*DEVDESCSIZE];
582 int nindevs = 0, noutdevs = 0, canmulti = 0, i;
583
584 char indevliststring[MAXNDEV*(DEVDESCSIZE+4)+80],
585 outdevliststring[MAXNDEV*(DEVDESCSIZE+4)+80];
586
587 audio_getdevs(indevlist, &nindevs, outdevlist, &noutdevs, &canmulti,
588 MAXNDEV, DEVDESCSIZE);
589
590 strcpy(indevliststring, "{");
591 for (i = 0; i < nindevs; i++)
592 {
593 strcat(indevliststring, "\"");
594 strcat(indevliststring, indevlist + i * DEVDESCSIZE);
595 strcat(indevliststring, "\" ");
596 }
597 strcat(indevliststring, "}");
598
599 strcpy(outdevliststring, "{");
600 for (i = 0; i < noutdevs; i++)
601 {
602 strcat(outdevliststring, "\"");
603 strcat(outdevliststring, outdevlist + i * DEVDESCSIZE);
604 strcat(outdevliststring, "\" ");
605 }
606 strcat(outdevliststring, "}");
607
608 sys_get_audio_params(&naudioindev, audioindev, chindev,
609 &naudiooutdev, audiooutdev, choutdev, &rate, &advance);
610
611 /* post("naudioindev %d naudiooutdev %d longform %f",
612 naudioindev, naudiooutdev, flongform); */
613 if (naudioindev > 1 || naudiooutdev > 1)
614 flongform = 1;
615
616
617 audioindev1 = (naudioindev > 0 && audioindev[0]>= 0 ? audioindev[0] : 0);
618 audioindev2 = (naudioindev > 1 && audioindev[1]>= 0 ? audioindev[1] : 0);
619 audioindev3 = (naudioindev > 2 && audioindev[2]>= 0 ? audioindev[2] : 0);
620 audioindev4 = (naudioindev > 3 && audioindev[3]>= 0 ? audioindev[3] : 0);
621 audioinchan1 = (naudioindev > 0 ? chindev[0] : 0);
622 audioinchan2 = (naudioindev > 1 ? chindev[1] : 0);
623 audioinchan3 = (naudioindev > 2 ? chindev[2] : 0);
624 audioinchan4 = (naudioindev > 3 ? chindev[3] : 0);
625 audiooutdev1 = (naudiooutdev > 0 && audiooutdev[0]>=0 ? audiooutdev[0] : 0);
626 audiooutdev2 = (naudiooutdev > 1 && audiooutdev[1]>=0 ? audiooutdev[1] : 0);
627 audiooutdev3 = (naudiooutdev > 2 && audiooutdev[2]>=0 ? audiooutdev[2] : 0);
628 audiooutdev4 = (naudiooutdev > 3 && audiooutdev[3]>=0 ? audiooutdev[3] : 0);
629 audiooutchan1 = (naudiooutdev > 0 ? choutdev[0] : 0);
630 audiooutchan2 = (naudiooutdev > 1 ? choutdev[1] : 0);
631 audiooutchan3 = (naudiooutdev > 2 ? choutdev[2] : 0);
632 audiooutchan4 = (naudiooutdev > 3 ? choutdev[3] : 0);
633 sprintf(buf,
634"pdtk_audio_dialog %%s \
635%s %d %d %d %d %d %d %d %d \
636%s %d %d %d %d %d %d %d %d \
637%d %d %d %d\n",
638 indevliststring,
639 audioindev1, audioindev2, audioindev3, audioindev4,
640 audioinchan1, audioinchan2, audioinchan3, audioinchan4,
641 outdevliststring,
642 audiooutdev1, audiooutdev2, audiooutdev3, audiooutdev4,
643 audiooutchan1, audiooutchan2, audiooutchan3, audiooutchan4,
644 rate, advance, canmulti, (flongform != 0));
645 gfxstub_deleteforkey(0);
646 gfxstub_new(&glob_pdobject, glob_audio_properties, buf);
647}
648
649 /* new values from dialog window */
650void glob_audio_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv)
651{
652 int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV];
653 int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV];
654 int rate, advance, audioon, i, nindev, noutdev;
655 int audioindev1, audioinchan1, audiooutdev1, audiooutchan1;
656 int newaudioindev[4], newaudioinchan[4],
657 newaudiooutdev[4], newaudiooutchan[4];
658 /* the new values the dialog came back with: */
659 int newrate = atom_getintarg(16, argc, argv);
660 int newadvance = atom_getintarg(17, argc, argv);
661 int statewas;
662
663 for (i = 0; i < 4; i++)
664 {
665 newaudioindev[i] = atom_getintarg(i, argc, argv);
666 newaudioinchan[i] = atom_getintarg(i+4, argc, argv);
667 newaudiooutdev[i] = atom_getintarg(i+8, argc, argv);
668 newaudiooutchan[i] = atom_getintarg(i+12, argc, argv);
669 }
670
671 for (i = 0, nindev = 0; i < 4; i++)
672 {
673 if (newaudioinchan[i] > 0)
674 {
675 newaudioindev[nindev] = newaudioindev[i];
676 newaudioinchan[nindev] = newaudioinchan[i];
677 /* post("in %d %d %d", nindev,
678 newaudioindev[nindev] , newaudioinchan[nindev]); */
679 nindev++;
680 }
681 }
682 for (i = 0, noutdev = 0; i < 4; i++)
683 {
684 if (newaudiooutchan[i] > 0)
685 {
686 newaudiooutdev[noutdev] = newaudiooutdev[i];
687 newaudiooutchan[noutdev] = newaudiooutchan[i];
688 /* post("out %d %d %d", noutdev,
689 newaudiooutdev[noutdev] , newaudioinchan[noutdev]); */
690 noutdev++;
691 }
692 }
693
694 sys_close_audio();
695 sys_open_audio(nindev, newaudioindev, nindev, newaudioinchan,
696 noutdev, newaudiooutdev, noutdev, newaudiooutchan,
697 newrate, newadvance, 1);
698}
699
700void sys_listdevs(void )
701{
702#ifdef USEAPI_PORTAUDIO
703 if (sys_audioapi == API_PORTAUDIO)
704 sys_listaudiodevs();
705 else
706#endif
707#ifdef USEAPI_JACK
708 if (sys_audioapi == API_JACK)
709 jack_listdevs();
710 else
711#endif
712#ifdef USEAPI_OSS
713 if (sys_audioapi == API_OSS)
714 sys_listaudiodevs();
715 else
716#endif
717#ifdef USEAPI_MMIO
718 if (sys_audioapi == API_MMIO)
719 sys_listaudiodevs();
720 else
721#endif
722#ifdef USEAPI_ALSA
723 if (sys_audioapi == API_ALSA)
724 sys_listaudiodevs();
725 else
726#endif
727 post("unknown API");
728
729 sys_listmididevs();
730}
731
732void sys_setblocksize(int n)
733{
734 if (n < 1)
735 n = 1;
736 if (n != (1 << ilog2(n)))
737 post("warning: adjusting blocksize to power of 2: %d",
738 (n = (1 << ilog2(n))));
739 sys_blocksize = n;
740}
741
742void sys_set_audio_api(int which)
743{
744 sys_audioapi = which;
745 if (sys_verbose)
746 post("sys_audioapi %d", sys_audioapi);
747}
748
749void glob_audio_setapi(void *dummy, t_floatarg f)
750{
751 int newapi = f;
752 if (newapi)
753 {
754 if (newapi == sys_audioapi)
755 {
756 if (!audio_isopen())
757 sys_reopen_audio();
758 }
759 else
760 {
761 sys_close_audio();
762 sys_audioapi = newapi;
763 /* bash device params back to default */
764 audio_naudioindev = audio_naudiooutdev = 1;
765 audio_audioindev[0] = audio_audiooutdev[0] = DEFAULTAUDIODEV;
766 audio_audiochindev[0] = audio_audiochoutdev[0] = SYS_DEFAULTCH;
767 sys_reopen_audio();
768 }
769 glob_audio_properties(0, 0);
770 }
771 else if (audio_isopen())
772 {
773 sys_close_audio();
774 audio_state = 0;
775 sched_set_using_dacs(0);
776 }
777}
778
779 /* start or stop the audio hardware */
780void sys_set_audio_state(int onoff)
781{
782 if (onoff) /* start */
783 {
784 if (!audio_isopen())
785 sys_reopen_audio();
786 }
787 else
788 {
789 if (audio_isopen())
790 {
791 sys_close_audio();
792 sched_set_using_dacs(0);
793 }
794 }
795 audio_state = onoff;
796}
797
798void sys_get_audio_apis(char *buf)
799{
800 int n = 0;
801 strcpy(buf, "{ ");
802#ifdef USEAPI_OSS
803 sprintf(buf + strlen(buf), "{OSS %d} ", API_OSS); n++;
804#endif
805#ifdef USEAPI_MMIO
806 sprintf(buf + strlen(buf), "{\"standard (MMIO)\" %d} ", API_MMIO); n++;
807#endif
808#ifdef USEAPI_ALSA
809 sprintf(buf + strlen(buf), "{ALSA %d} ", API_ALSA); n++;
810#endif
811#ifdef USEAPI_PORTAUDIO
812#ifdef MSW
813 sprintf(buf + strlen(buf),
814 "{\"ASIO (via portaudio)\" %d} ", API_PORTAUDIO);
815#else
816#ifdef OSX
817 sprintf(buf + strlen(buf),
818 "{\"standard (portaudio)\" %d} ", API_PORTAUDIO);
819#else
820 sprintf(buf + strlen(buf), "{portaudio %d} ", API_PORTAUDIO);
821#endif
822#endif
823 n++;
824#endif
825#ifdef USEAPI_JACK
826 sprintf(buf + strlen(buf), "{jack %d} ", API_JACK); n++;
827#endif
828 strcat(buf, "}");
829 /* then again, if only one API (or none) we don't offer any choice. */
830 if (n < 2)
831 strcpy(buf, "{}");
832
833}
834
835#ifdef USEAPI_ALSA
836void alsa_putzeros(int n);
837void alsa_getzeros(int n);
838void alsa_printstate( void);
839#endif
840
841 /* debugging */
842void glob_foo(void *dummy, t_symbol *s, int argc, t_atom *argv)
843{
844 t_symbol *arg = atom_getsymbolarg(0, argc, argv);
845 if (arg == gensym("restart"))
846 {
847 int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV];
848 int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV];
849 int rate, advance;
850 sys_get_audio_params(&naudioindev, audioindev, chindev,
851 &naudiooutdev, audiooutdev, choutdev, &rate, &advance);
852 sys_close_audio();
853 sys_open_audio(naudioindev, audioindev, naudioindev, chindev,
854 naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate, advance,
855 1);
856 }
857#ifdef USEAPI_ALSA
858 else if (arg == gensym("alsawrite"))
859 {
860 int n = atom_getintarg(1, argc, argv);
861 alsa_putzeros(n);
862 }
863 else if (arg == gensym("alsaread"))
864 {
865 int n = atom_getintarg(1, argc, argv);
866 alsa_getzeros(n);
867 }
868 else if (arg == gensym("print"))
869 {
870 alsa_printstate();
871 }
872#endif
873}
874/* Copyright (c) 2003, Miller Puckette and others.
875* For information on usage and redistribution, and for a DISCLAIMER OF ALL
876* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
877
878/* machine-independent (well, mostly!) audio layer. Stores and recalls
879 audio settings from argparse routine and from dialog window.
880*/
881
882#include "m_pd.h"
883#include "s_stuff.h"
884#include <stdio.h>
885#ifdef UNIX
886#include <unistd.h>
887#include <sys/time.h>
888#include <sys/resource.h>
889#endif
890#include <stdlib.h>
891#include <string.h>
892#include <errno.h>
893
894#define SYS_DEFAULTCH 2
895#define SYS_MAXCH 100
896#define SYS_DEFAULTSRATE 44100
897typedef long t_pa_sample;
898#define SYS_SAMPLEWIDTH sizeof(t_pa_sample)
899#define SYS_BYTESPERCHAN (DEFDACBLKSIZE * SYS_SAMPLEWIDTH)
900#define SYS_XFERSAMPS (SYS_DEFAULTCH*DEFDACBLKSIZE)
901#define SYS_XFERSIZE (SYS_SAMPLEWIDTH * SYS_XFERSAMPS)
902
903 /* these are set in this file when opening audio, but then may be reduced,
904 even to zero, in the system dependent open_audio routines. */
905int sys_inchannels;
906int sys_outchannels;
907int sys_advance_samples; /* scheduler advance in samples */
908int sys_blocksize = 0; /* audio I/O block size in sample frames */
909int sys_audioapi = API_DEFAULT;
910
911static int sys_meters; /* true if we're metering */
912static float sys_inmax; /* max input amplitude */
913static float sys_outmax; /* max output amplitude */
914
915 /* exported variables */
916int sys_schedadvance; /* scheduler advance in microseconds */
917float sys_dacsr;
918
919#ifdef MACOSX
920int sys_hipriority = 1;
921#else
922int sys_hipriority = 0;
923#endif
924
925t_sample *sys_soundout;
926t_sample *sys_soundin;
927
928 /* the "state" is normally one if we're open and zero otherwise;
929 but if the state is one, we still haven't necessarily opened the
930 audio hardware; see audio_isopen() below. */
931static int audio_state;
932
933 /* last requested parameters */
934static int audio_naudioindev;
935static int audio_audioindev[MAXAUDIOINDEV];
936static int audio_audiochindev[MAXAUDIOINDEV];
937static int audio_naudiooutdev;
938static int audio_audiooutdev[MAXAUDIOOUTDEV];
939static int audio_audiochoutdev[MAXAUDIOOUTDEV];
940static int audio_rate;
941static int audio_advance;
942
943static int audio_isopen(void)
944{
945 return (audio_state &&
946 ((audio_naudioindev > 0 && audio_audiochindev[0] > 0)
947 || (audio_naudiooutdev > 0 && audio_audiochoutdev[0] > 0)));
948}
949
950static void sys_get_audio_params(
951 int *pnaudioindev, int *paudioindev, int *chindev,
952 int *pnaudiooutdev, int *paudiooutdev, int *choutdev,
953 int *prate, int *padvance)
954{
955 int i;
956 *pnaudioindev = audio_naudioindev;
957 for (i = 0; i < MAXAUDIOINDEV; i++)
958 paudioindev[i] = audio_audioindev[i],
959 chindev[i] = audio_audiochindev[i];
960 *pnaudiooutdev = audio_naudiooutdev;
961 for (i = 0; i < MAXAUDIOOUTDEV; i++)
962 paudiooutdev[i] = audio_audiooutdev[i],
963 choutdev[i] = audio_audiochoutdev[i];
964 *prate = audio_rate;
965 *padvance = audio_advance;
966}
967
968static void sys_save_audio_params(
969 int naudioindev, int *audioindev, int *chindev,
970 int naudiooutdev, int *audiooutdev, int *choutdev,
971 int rate, int advance)
972{
973 int i;
974 audio_naudioindev = naudioindev;
975 for (i = 0; i < MAXAUDIOINDEV; i++)
976 audio_audioindev[i] = audioindev[i],
977 audio_audiochindev[i] = chindev[i];
978 audio_naudiooutdev = naudiooutdev;
979 for (i = 0; i < MAXAUDIOOUTDEV; i++)
980 audio_audiooutdev[i] = audiooutdev[i],
981 audio_audiochoutdev[i] = choutdev[i];
982 audio_rate = rate;
983 audio_advance = advance;
984}
985
986 /* init routines for any API which needs to set stuff up before
987 any other API gets used. This is only true of OSS so far. */
988#ifdef USEAPI_OSS
989void oss_init(void);
990#endif
991
992static void audio_init( void)
993{
994 static int initted = 0;
995 if (initted)
996 return;
997 initted = 1;
998#ifdef USEAPI_OSS
999 oss_init();
1000#endif
1001}
1002
1003 /* set channels and sample rate. */
1004
1005static void sys_setchsr(int chin, int chout, int sr)
1006{
1007 int nblk;
1008 int inbytes = (chin ? chin : 2) * (DEFDACBLKSIZE*sizeof(float));
1009 int outbytes = (chout ? chout : 2) * (DEFDACBLKSIZE*sizeof(float));
1010
1011 sys_inchannels = chin;
1012 sys_outchannels = chout;
1013 sys_dacsr = sr;
1014 sys_advance_samples = (sys_schedadvance * sys_dacsr) / (1000000.);
1015 if (sys_advance_samples < 3 * DEFDACBLKSIZE)
1016 sys_advance_samples = 3 * DEFDACBLKSIZE;
1017
1018 if (sys_soundin)
1019 free(sys_soundin);
1020 sys_soundin = (t_float *)malloc(inbytes);
1021 memset(sys_soundin, 0, inbytes);
1022
1023 if (sys_soundout)
1024 free(sys_soundout);
1025 sys_soundout = (t_float *)malloc(outbytes);
1026 memset(sys_soundout, 0, outbytes);
1027
1028 if (sys_verbose)
1029 post("input channels = %d, output channels = %d",
1030 sys_inchannels, sys_outchannels);
1031 canvas_resume_dsp(canvas_suspend_dsp());
1032}
1033
1034/* ----------------------- public routines ----------------------- */
1035
1036 /* open audio devices (after cleaning up the specified device and channel
1037 vectors). The audio devices are "zero based" (i.e. "0" means the first
1038 one.) We also save the cleaned-up device specification so that we
1039 can later re-open audio and/or show the settings on a dialog window. */
1040
1041void sys_open_audio(int naudioindev, int *audioindev, int nchindev,
1042 int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev,
1043 int *choutdev, int rate, int advance, int enable)
1044{
1045 int i, *ip;
1046 int defaultchannels = SYS_DEFAULTCH;
1047 int inchans, outchans;
1048 if (rate < 1)
1049 rate = SYS_DEFAULTSRATE;
1050 audio_init();
1051 /* Since the channel vector might be longer than the
1052 audio device vector, or vice versa, we fill the shorter one
1053 in to match the longer one. Also, if both are empty, we fill in
1054 one device (the default) and two channels. */
1055 if (naudioindev == -1)
1056 { /* no input audio devices specified */
1057 if (nchindev == -1)
1058 {
1059 nchindev=1;
1060 chindev[0] = defaultchannels;
1061 naudioindev = 1;
1062 audioindev[0] = DEFAULTAUDIODEV;
1063 }
1064 else
1065 {
1066 for (i = 0; i < MAXAUDIOINDEV; i++)
1067 audioindev[i] = i;
1068 naudioindev = nchindev;
1069 }
1070 }
1071 else
1072 {
1073 if (nchindev == -1)
1074 {
1075 nchindev = naudioindev;
1076 for (i = 0; i < naudioindev; i++)
1077 chindev[i] = defaultchannels;
1078 }
1079 else if (nchindev > naudioindev)
1080 {
1081 for (i = naudioindev; i < nchindev; i++)
1082 {
1083 if (i == 0)
1084 audioindev[0] = DEFAULTAUDIODEV;
1085 else audioindev[i] = audioindev[i-1] + 1;
1086 }
1087 naudioindev = nchindev;
1088 }
1089 else if (nchindev < naudioindev)
1090 {
1091 for (i = nchindev; i < naudioindev; i++)
1092 {
1093 if (i == 0)
1094 chindev[0] = defaultchannels;
1095 else chindev[i] = chindev[i-1];
1096 }
1097 naudioindev = nchindev;
1098 }
1099 }
1100
1101 if (naudiooutdev == -1)
1102 { /* not set */
1103 if (nchoutdev == -1)
1104 {
1105 nchoutdev=1;
1106 choutdev[0]=defaultchannels;
1107 naudiooutdev=1;
1108 audiooutdev[0] = DEFAULTAUDIODEV;
1109 }
1110 else
1111 {
1112 for (i = 0; i < MAXAUDIOOUTDEV; i++)
1113 audiooutdev[i] = i;
1114 naudiooutdev = nchoutdev;
1115 }
1116 }
1117 else
1118 {
1119 if (nchoutdev == -1)
1120 {
1121 nchoutdev = naudiooutdev;
1122 for (i = 0; i < naudiooutdev; i++)
1123 choutdev[i] = defaultchannels;
1124 }
1125 else if (nchoutdev > naudiooutdev)
1126 {
1127 for (i = naudiooutdev; i < nchoutdev; i++)
1128 {
1129 if (i == 0)
1130 audiooutdev[0] = DEFAULTAUDIODEV;
1131 else audiooutdev[i] = audiooutdev[i-1] + 1;
1132 }
1133 naudiooutdev = nchoutdev;
1134 }
1135 else if (nchoutdev < naudiooutdev)
1136 {
1137 for (i = nchoutdev; i < naudiooutdev; i++)
1138 {
1139 if (i == 0)
1140 choutdev[0] = defaultchannels;
1141 else choutdev[i] = choutdev[i-1];
1142 }
1143 naudiooutdev = nchoutdev;
1144 }
1145 }
1146
1147 /* count total number of input and output channels */
1148 for (i = inchans = 0; i < naudioindev; i++)
1149 inchans += chindev[i];
1150 for (i = outchans = 0; i < naudiooutdev; i++)
1151 outchans += choutdev[i];
1152 /* if no input or output devices seem to have been specified,
1153 this really means just disable audio, which we now do. Meanwhile,
1154 we can set audio input and output devices to their defaults. */
1155 if (!inchans && !outchans)
1156 {
1157 enable = 0;
1158 naudioindev = nchindev = naudiooutdev = nchoutdev = 1;
1159 audioindev[0] = audiooutdev[0] = DEFAULTAUDIODEV;
1160 chindev[0] = choutdev[0] = 0;
1161 }
1162 sys_schedadvance = advance * 1000;
1163 sys_setchsr(inchans, outchans, rate);
1164 sys_log_error(ERR_NOTHING);
1165
1166 if (enable && (inchans > 0 || outchans > 0))
1167 {
1168#ifdef USEAPI_PORTAUDIO
1169 if (sys_audioapi == API_PORTAUDIO)
1170 {
1171 int blksize = (sys_blocksize ? sys_blocksize : 64);
1172 pa_open_audio(inchans, outchans, rate, sys_soundin, sys_soundout,
1173 blksize, sys_advance_samples/blksize,
1174 (naudiooutdev > 0 ? audioindev[0] : 0),
1175 (naudiooutdev > 0 ? audiooutdev[0] : 0));
1176 }
1177else
1178#endif
1179#ifdef USEAPI_JACK
1180 if (sys_audioapi == API_JACK)
1181 jack_open_audio((naudioindev > 0 ? chindev[0] : 0),
1182 (naudiooutdev > 0 ? choutdev[0] : 0), rate);
1183
1184 else
1185#endif
1186#ifdef USEAPI_OSS
1187 if (sys_audioapi == API_OSS)
1188 oss_open_audio(naudioindev, audioindev, nchindev, chindev,
1189 naudiooutdev, audiooutdev, nchoutdev, choutdev, rate);
1190 else
1191#endif
1192#ifdef USEAPI_ALSA
1193 /* for alsa, only one device is supported; it may
1194 be open for both input and output. */
1195 if (sys_audioapi == API_ALSA)
1196 alsa_open_audio(naudioindev, audioindev, nchindev, chindev,
1197 naudiooutdev, audiooutdev, nchoutdev, choutdev, rate);
1198 else
1199#endif
1200#ifdef USEAPI_MMIO
1201 if (sys_audioapi == API_MMIO)
1202 mmio_open_audio(naudioindev, audioindev, nchindev, chindev,
1203 naudiooutdev, audiooutdev, nchoutdev, choutdev, rate);
1204 else
1205#endif
1206 post("unknown audio API specified");
1207 }
1208 sys_save_audio_params(naudioindev, audioindev, chindev,
1209 naudiooutdev, audiooutdev, choutdev, rate, advance);
1210 if (sys_inchannels == 0 && sys_outchannels == 0)
1211 enable = 0;
1212 audio_state = enable;
1213 sys_vgui("set pd_whichapi %d\n", (audio_isopen() ? sys_audioapi : 0));
1214 sched_set_using_dacs(enable);
1215}
1216
1217void sys_close_audio(void)
1218{
1219 if (!audio_isopen())
1220 return;
1221#ifdef USEAPI_PORTAUDIO
1222 if (sys_audioapi == API_PORTAUDIO)
1223 pa_close_audio();
1224 else
1225#endif
1226#ifdef USEAPI_JACK
1227 if (sys_audioapi == API_JACK)
1228 jack_close_audio();
1229 else
1230#endif
1231#ifdef USEAPI_OSS
1232 if (sys_audioapi == API_OSS)
1233 oss_close_audio();
1234 else
1235#endif
1236#ifdef USEAPI_ALSA
1237 if (sys_audioapi == API_ALSA)
1238 alsa_close_audio();
1239 else
1240#endif
1241#ifdef USEAPI_MMIO
1242 if (sys_audioapi == API_MMIO)
1243 mmio_close_audio();
1244 else
1245#endif
1246 post("sys_close_audio: unknown API %d", sys_audioapi);
1247 sys_inchannels = sys_outchannels = 0;
1248}
1249
1250 /* open audio using whatever parameters were last used */
1251void sys_reopen_audio( void)
1252{
1253 int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV];
1254 int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV];
1255 int rate, advance;
1256 sys_get_audio_params(&naudioindev, audioindev, chindev,
1257 &naudiooutdev, audiooutdev, choutdev, &rate, &advance);
1258 sys_open_audio(naudioindev, audioindev, naudioindev, chindev,
1259 naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate, advance, 1);
1260}
1261
1262int sys_send_dacs(void)
1263{
1264 if (sys_meters)
1265 {
1266 int i, n;
1267 float maxsamp;
1268 for (i = 0, n = sys_inchannels * DEFDACBLKSIZE, maxsamp = sys_inmax;
1269 i < n; i++)
1270 {
1271 float f = sys_soundin[i];
1272 if (f > maxsamp) maxsamp = f;
1273 else if (-f > maxsamp) maxsamp = -f;
1274 }
1275 sys_inmax = maxsamp;
1276 for (i = 0, n = sys_outchannels * DEFDACBLKSIZE, maxsamp = sys_outmax;
1277 i < n; i++)
1278 {
1279 float f = sys_soundout[i];
1280 if (f > maxsamp) maxsamp = f;
1281 else if (-f > maxsamp) maxsamp = -f;
1282 }
1283 sys_outmax = maxsamp;
1284 }
1285
1286#ifdef USEAPI_PORTAUDIO
1287 if (sys_audioapi == API_PORTAUDIO)
1288 return (pa_send_dacs());
1289 else
1290#endif
1291#ifdef USEAPI_JACK
1292 if (sys_audioapi == API_JACK)
1293 return (jack_send_dacs());
1294 else
1295#endif
1296#ifdef USEAPI_OSS
1297 if (sys_audioapi == API_OSS)
1298 return (oss_send_dacs());
1299 else
1300#endif
1301#ifdef USEAPI_ALSA
1302 if (sys_audioapi == API_ALSA)
1303 return (alsa_send_dacs());
1304 else
1305#endif
1306#ifdef USEAPI_MMIO
1307 if (sys_audioapi == API_MMIO)
1308 return (mmio_send_dacs());
1309 else
1310#endif
1311 post("unknown API");
1312 return (0);
1313}
1314
1315float sys_getsr(void)
1316{
1317 return (sys_dacsr);
1318}
1319
1320int sys_get_outchannels(void)
1321{
1322 return (sys_outchannels);
1323}
1324
1325int sys_get_inchannels(void)
1326{
1327 return (sys_inchannels);
1328}
1329
1330void sys_audiobuf(int n)
1331{
1332 /* set the size, in milliseconds, of the audio FIFO */
1333 if (n < 5) n = 5;
1334 else if (n > 5000) n = 5000;
1335 sys_schedadvance = n * 1000;
1336}
1337
1338void sys_getmeters(float *inmax, float *outmax)
1339{
1340 if (inmax)
1341 {
1342 sys_meters = 1;
1343 *inmax = sys_inmax;
1344 *outmax = sys_outmax;
1345 }
1346 else
1347 sys_meters = 0;
1348 sys_inmax = sys_outmax = 0;
1349}
1350
1351void sys_reportidle(void)
1352{
1353}
1354
1355#define MAXNDEV 20
1356#define DEVDESCSIZE 80
1357
1358static void audio_getdevs(char *indevlist, int *nindevs,
1359 char *outdevlist, int *noutdevs, int *canmulti,
1360 int maxndev, int devdescsize)
1361{
1362 audio_init();
1363#ifdef USEAPI_OSS
1364 if (sys_audioapi == API_OSS)
1365 {
1366 oss_getdevs(indevlist, nindevs, outdevlist, noutdevs, canmulti,
1367 maxndev, devdescsize);
1368 }
1369 else
1370#endif
1371#ifdef USEAPI_ALSA
1372 if (sys_audioapi == API_ALSA)
1373 {
1374 alsa_getdevs(indevlist, nindevs, outdevlist, noutdevs, canmulti,
1375 maxndev, devdescsize);
1376 }
1377 else
1378#endif
1379#ifdef USEAPI_PORTAUDIO
1380 if (sys_audioapi == API_PORTAUDIO)
1381 {
1382 pa_getdevs(indevlist, nindevs, outdevlist, noutdevs, canmulti,
1383 maxndev, devdescsize);
1384 }
1385 else
1386#endif
1387#ifdef USEAPI_MMIO
1388 if (sys_audioapi == API_MMIO)
1389 {
1390 mmio_getdevs(indevlist, nindevs, outdevlist, noutdevs, canmulti,
1391 maxndev, devdescsize);
1392 }
1393 else
1394#endif
1395 {
1396 /* this shouldn't happen once all the above get filled in. */
1397 int i;
1398 *nindevs = *noutdevs = 3;
1399 for (i = 0; i < 3; i++)
1400 {
1401 sprintf(indevlist + i * devdescsize, "input device #%d", i+1);
1402 sprintf(outdevlist + i * devdescsize, "output device #%d", i+1);
1403 }
1404 *canmulti = 0;
1405 }
1406}
1407
1408#ifdef MSW
1409#define DEVONSET 0 /* microsoft device list starts at 0 (the "mapper"). */
1410#else /* (see also MSW ifdef in sys_parsedevlist(), s_main.c) */
1411#define DEVONSET 1 /* To agree with command line flags, normally start at 1 */
1412#endif
1413
1414static void sys_listaudiodevs(void )
1415{
1416 char indevlist[MAXNDEV*DEVDESCSIZE], outdevlist[MAXNDEV*DEVDESCSIZE];
1417 int nindevs = 0, noutdevs = 0, i, canmulti = 0;
1418
1419 audio_getdevs(indevlist, &nindevs, outdevlist, &noutdevs, &canmulti,
1420 MAXNDEV, DEVDESCSIZE);
1421
1422 if (!nindevs)
1423 post("no audio input devices found");
1424 else
1425 {
1426 post("input devices:");
1427 for (i = 0; i < nindevs; i++)
1428 post("%d. %s", i+1, indevlist + i * DEVDESCSIZE);
1429 }
1430 if (!noutdevs)
1431 post("no audio output devices found");
1432 else
1433 {
1434 post("output devices:");
1435 for (i = 0; i < noutdevs; i++)
1436 post("%d. %s", i + DEVONSET, outdevlist + i * DEVDESCSIZE);
1437 }
1438 post("API number %d\n", sys_audioapi);
1439}
1440
1441 /* start an audio settings dialog window */
1442void glob_audio_properties(t_pd *dummy, t_floatarg flongform)
1443{
1444 char buf[1024 + 2 * MAXNDEV*(DEVDESCSIZE+4)];
1445 /* these are the devices you're using: */
1446 int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV];
1447 int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV];
1448 int audioindev1, audioindev2, audioindev3, audioindev4,
1449 audioinchan1, audioinchan2, audioinchan3, audioinchan4,
1450 audiooutdev1, audiooutdev2, audiooutdev3, audiooutdev4,
1451 audiooutchan1, audiooutchan2, audiooutchan3, audiooutchan4;
1452 int rate, advance;
1453 /* these are all the devices on your system: */
1454 char indevlist[MAXNDEV*DEVDESCSIZE], outdevlist[MAXNDEV*DEVDESCSIZE];
1455 int nindevs = 0, noutdevs = 0, canmulti = 0, i;
1456
1457 char indevliststring[MAXNDEV*(DEVDESCSIZE+4)+80],
1458 outdevliststring[MAXNDEV*(DEVDESCSIZE+4)+80];
1459
1460 audio_getdevs(indevlist, &nindevs, outdevlist, &noutdevs, &canmulti,
1461 MAXNDEV, DEVDESCSIZE);
1462
1463 strcpy(indevliststring, "{");
1464 for (i = 0; i < nindevs; i++)
1465 {
1466 strcat(indevliststring, "\"");
1467 strcat(indevliststring, indevlist + i * DEVDESCSIZE);
1468 strcat(indevliststring, "\" ");
1469 }
1470 strcat(indevliststring, "}");
1471
1472 strcpy(outdevliststring, "{");
1473 for (i = 0; i < noutdevs; i++)
1474 {
1475 strcat(outdevliststring, "\"");
1476 strcat(outdevliststring, outdevlist + i * DEVDESCSIZE);
1477 strcat(outdevliststring, "\" ");
1478 }
1479 strcat(outdevliststring, "}");
1480
1481 sys_get_audio_params(&naudioindev, audioindev, chindev,
1482 &naudiooutdev, audiooutdev, choutdev, &rate, &advance);
1483
1484 /* post("naudioindev %d naudiooutdev %d longform %f",
1485 naudioindev, naudiooutdev, flongform); */
1486 if (naudioindev > 1 || naudiooutdev > 1)
1487 flongform = 1;
1488
1489
1490 audioindev1 = (naudioindev > 0 && audioindev[0]>= 0 ? audioindev[0] : 0);
1491 audioindev2 = (naudioindev > 1 && audioindev[1]>= 0 ? audioindev[1] : 0);
1492 audioindev3 = (naudioindev > 2 && audioindev[2]>= 0 ? audioindev[2] : 0);
1493 audioindev4 = (naudioindev > 3 && audioindev[3]>= 0 ? audioindev[3] : 0);
1494 audioinchan1 = (naudioindev > 0 ? chindev[0] : 0);
1495 audioinchan2 = (naudioindev > 1 ? chindev[1] : 0);
1496 audioinchan3 = (naudioindev > 2 ? chindev[2] : 0);
1497 audioinchan4 = (naudioindev > 3 ? chindev[3] : 0);
1498 audiooutdev1 = (naudiooutdev > 0 && audiooutdev[0]>=0 ? audiooutdev[0] : 0);
1499 audiooutdev2 = (naudiooutdev > 1 && audiooutdev[1]>=0 ? audiooutdev[1] : 0);
1500 audiooutdev3 = (naudiooutdev > 2 && audiooutdev[2]>=0 ? audiooutdev[2] : 0);
1501 audiooutdev4 = (naudiooutdev > 3 && audiooutdev[3]>=0 ? audiooutdev[3] : 0);
1502 audiooutchan1 = (naudiooutdev > 0 ? choutdev[0] : 0);
1503 audiooutchan2 = (naudiooutdev > 1 ? choutdev[1] : 0);
1504 audiooutchan3 = (naudiooutdev > 2 ? choutdev[2] : 0);
1505 audiooutchan4 = (naudiooutdev > 3 ? choutdev[3] : 0);
1506 sprintf(buf,
1507"pdtk_audio_dialog %%s \
1508%s %d %d %d %d %d %d %d %d \
1509%s %d %d %d %d %d %d %d %d \
1510%d %d %d %d\n",
1511 indevliststring,
1512 audioindev1, audioindev2, audioindev3, audioindev4,
1513 audioinchan1, audioinchan2, audioinchan3, audioinchan4,
1514 outdevliststring,
1515 audiooutdev1, audiooutdev2, audiooutdev3, audiooutdev4,
1516 audiooutchan1, audiooutchan2, audiooutchan3, audiooutchan4,
1517 rate, advance, canmulti, (flongform != 0));
1518 gfxstub_deleteforkey(0);
1519 gfxstub_new(&glob_pdobject, glob_audio_properties, buf);
1520}
1521
1522 /* new values from dialog window */
1523void glob_audio_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv)
1524{
1525 int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV];
1526 int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV];
1527 int rate, advance, audioon, i, nindev, noutdev;
1528 int audioindev1, audioinchan1, audiooutdev1, audiooutchan1;
1529 int newaudioindev[4], newaudioinchan[4],
1530 newaudiooutdev[4], newaudiooutchan[4];
1531 /* the new values the dialog came back with: */
1532 int newrate = atom_getintarg(16, argc, argv);
1533 int newadvance = atom_getintarg(17, argc, argv);
1534 int statewas;
1535
1536 for (i = 0; i < 4; i++)
1537 {
1538 newaudioindev[i] = atom_getintarg(i, argc, argv);
1539 newaudioinchan[i] = atom_getintarg(i+4, argc, argv);
1540 newaudiooutdev[i] = atom_getintarg(i+8, argc, argv);
1541 newaudiooutchan[i] = atom_getintarg(i+12, argc, argv);
1542 }
1543
1544 for (i = 0, nindev = 0; i < 4; i++)
1545 {
1546 if (newaudioinchan[i] > 0)
1547 {
1548 newaudioindev[nindev] = newaudioindev[i];
1549 newaudioinchan[nindev] = newaudioinchan[i];
1550 /* post("in %d %d %d", nindev,
1551 newaudioindev[nindev] , newaudioinchan[nindev]); */
1552 nindev++;
1553 }
1554 }
1555 for (i = 0, noutdev = 0; i < 4; i++)
1556 {
1557 if (newaudiooutchan[i] > 0)
1558 {
1559 newaudiooutdev[noutdev] = newaudiooutdev[i];
1560 newaudiooutchan[noutdev] = newaudiooutchan[i];
1561 /* post("out %d %d %d", noutdev,
1562 newaudiooutdev[noutdev] , newaudioinchan[noutdev]); */
1563 noutdev++;
1564 }
1565 }
1566
1567 sys_close_audio();
1568 sys_open_audio(nindev, newaudioindev, nindev, newaudioinchan,
1569 noutdev, newaudiooutdev, noutdev, newaudiooutchan,
1570 newrate, newadvance, 1);
1571}
1572
1573void sys_listdevs(void )
1574{
1575#ifdef USEAPI_PORTAUDIO
1576 if (sys_audioapi == API_PORTAUDIO)
1577 sys_listaudiodevs();
1578 else
1579#endif
1580#ifdef USEAPI_JACK
1581 if (sys_audioapi == API_JACK)
1582 jack_listdevs();
1583 else
1584#endif
1585#ifdef USEAPI_OSS
1586 if (sys_audioapi == API_OSS)
1587 sys_listaudiodevs();
1588 else
1589#endif
1590#ifdef USEAPI_MMIO
1591 if (sys_audioapi == API_MMIO)
1592 sys_listaudiodevs();
1593 else
1594#endif
1595#ifdef USEAPI_ALSA
1596 if (sys_audioapi == API_ALSA)
1597 sys_listaudiodevs();
1598 else
1599#endif
1600 post("unknown API");
1601
1602 sys_listmididevs();
1603}
1604
1605void sys_setblocksize(int n)
1606{
1607 if (n < 1)
1608 n = 1;
1609 if (n != (1 << ilog2(n)))
1610 post("warning: adjusting blocksize to power of 2: %d",
1611 (n = (1 << ilog2(n))));
1612 sys_blocksize = n;
1613}
1614
1615void sys_set_audio_api(int which)
1616{
1617 sys_audioapi = which;
1618 if (sys_verbose)
1619 post("sys_audioapi %d", sys_audioapi);
1620}
1621
1622void glob_audio_setapi(void *dummy, t_floatarg f)
1623{
1624 int newapi = f;
1625 if (newapi)
1626 {
1627 if (newapi == sys_audioapi)
1628 {
1629 if (!audio_isopen())
1630 sys_reopen_audio();
1631 }
1632 else
1633 {
1634 sys_close_audio();
1635 sys_audioapi = newapi;
1636 /* bash device params back to default */
1637 audio_naudioindev = audio_naudiooutdev = 1;
1638 audio_audioindev[0] = audio_audiooutdev[0] = DEFAULTAUDIODEV;
1639 audio_audiochindev[0] = audio_audiochoutdev[0] = SYS_DEFAULTCH;
1640 sys_reopen_audio();
1641 }
1642 glob_audio_properties(0, 0);
1643 }
1644 else if (audio_isopen())
1645 {
1646 sys_close_audio();
1647 audio_state = 0;
1648 sched_set_using_dacs(0);
1649 }
1650}
1651
1652 /* start or stop the audio hardware */
1653void sys_set_audio_state(int onoff)
1654{
1655 if (onoff) /* start */
1656 {
1657 if (!audio_isopen())
1658 sys_reopen_audio();
1659 }
1660 else
1661 {
1662 if (audio_isopen())
1663 {
1664 sys_close_audio();
1665 sched_set_using_dacs(0);
1666 }
1667 }
1668 audio_state = onoff;
1669}
1670
1671void sys_get_audio_apis(char *buf)
1672{
1673 int n = 0;
1674 strcpy(buf, "{ ");
1675#ifdef USEAPI_OSS
1676 sprintf(buf + strlen(buf), "{OSS %d} ", API_OSS); n++;
1677#endif
1678#ifdef USEAPI_MMIO
1679 sprintf(buf + strlen(buf), "{\"standard (MMIO)\" %d} ", API_MMIO); n++;
1680#endif
1681#ifdef USEAPI_ALSA
1682 sprintf(buf + strlen(buf), "{ALSA %d} ", API_ALSA); n++;
1683#endif
1684#ifdef USEAPI_PORTAUDIO
1685#ifdef MSW
1686 sprintf(buf + strlen(buf),
1687 "{\"ASIO (via portaudio)\" %d} ", API_PORTAUDIO);
1688#else
1689#ifdef OSX
1690 sprintf(buf + strlen(buf),
1691 "{\"standard (portaudio)\" %d} ", API_PORTAUDIO);
1692#else
1693 sprintf(buf + strlen(buf), "{portaudio %d} ", API_PORTAUDIO);
1694#endif
1695#endif
1696 n++;
1697#endif
1698#ifdef USEAPI_JACK
1699 sprintf(buf + strlen(buf), "{jack %d} ", API_JACK); n++;
1700#endif
1701 strcat(buf, "}");
1702 /* then again, if only one API (or none) we don't offer any choice. */
1703 if (n < 2)
1704 strcpy(buf, "{}");
1705
1706}
1707
1708#ifdef USEAPI_ALSA
1709void alsa_putzeros(int n);
1710void alsa_getzeros(int n);
1711void alsa_printstate( void);
1712#endif
1713
1714 /* debugging */
1715void glob_foo(void *dummy, t_symbol *s, int argc, t_atom *argv)
1716{
1717 t_symbol *arg = atom_getsymbolarg(0, argc, argv);
1718 if (arg == gensym("restart"))
1719 {
1720 int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV];
1721 int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV];
1722 int rate, advance;
1723 sys_get_audio_params(&naudioindev, audioindev, chindev,
1724 &naudiooutdev, audiooutdev, choutdev, &rate, &advance);
1725 sys_close_audio();
1726 sys_open_audio(naudioindev, audioindev, naudioindev, chindev,
1727 naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate, advance,
1728 1);
1729 }
1730#ifdef USEAPI_ALSA
1731 else if (arg == gensym("alsawrite"))
1732 {
1733 int n = atom_getintarg(1, argc, argv);
1734 alsa_putzeros(n);
1735 }
1736 else if (arg == gensym("alsaread"))
1737 {
1738 int n = atom_getintarg(1, argc, argv);
1739 alsa_getzeros(n);
1740 }
1741 else if (arg == gensym("print"))
1742 {
1743 alsa_printstate();
1744 }
1745#endif
1746}