Newer
Older
/* Copyright (c) 2003, Miller Puckette and others.
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
/* machine-independent (well, mostly!) audio layer. Stores and recalls
audio settings from argparse routine and from dialog window.
*/
Ivica Bukvic
committed
#include "config.h"
#include "m_pd.h"
#include "s_stuff.h"
#include <stdio.h>
Ivica Bukvic
committed
#ifdef HAVE_UNISTD_H
Ivica Bukvic
committed
/* XXX Hack!!! These should be checked for independently of unistd.h ... */
#include <sys/time.h>
#include <sys/resource.h>
Ivica Bukvic
committed
#endif
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#define SYS_DEFAULTCH 2
Ivica Bukvic
committed
#define SYS_MAXCH 100
typedef long t_pa_sample;
#define SYS_SAMPLEWIDTH sizeof(t_pa_sample)
#define SYS_BYTESPERCHAN (DEFDACBLKSIZE * SYS_SAMPLEWIDTH)
#define SYS_XFERSAMPS (SYS_DEFAULTCH*DEFDACBLKSIZE)
#define SYS_XFERSIZE (SYS_SAMPLEWIDTH * SYS_XFERSAMPS)
#define MAXNDEV 20
#define DEVDESCSIZE 80
static void audio_getdevs(char *indevlist, int *nindevs,
char *outdevlist, int *noutdevs, int *canmulti, int *cancallback,
int maxndev, int devdescsize);
/* these are set in this file when opening audio, but then may be reduced,
even to zero, in the system dependent open_audio routines. */
int sys_inchannels;
int sys_outchannels;
int sys_advance_samples; /* scheduler advance in samples */
Ivica Bukvic
committed
int sys_blocksize = 0; /* audio I/O block size in sample frames */
int sys_audioapiopened = -1; /* save last API opened for later closing */
static int sys_meters; /* true if we're metering */
static t_sample sys_inmax; /* max input amplitude */
static t_sample sys_outmax; /* max output amplitude */
/* exported variables */
int sys_schedadvance; /* scheduler advance in microseconds */
t_sample *sys_soundout;
t_sample *sys_soundin;
/* the "state" is normally one if we're open and zero otherwise;
but if the state is one, we still haven't necessarily opened the
audio hardware; see audio_isopen() below. */
static int audio_state;
/* last requested parameters */
static int audio_naudioindev = -1;
static int audio_audioindev[MAXAUDIOINDEV];
static int audio_audiochindev[MAXAUDIOINDEV];
static char audio_indevnames[MAXMIDIINDEV * DEVDESCSIZE];
static int audio_naudiooutdev = -1;
static int audio_audiooutdev[MAXAUDIOOUTDEV];
static int audio_audiochoutdev[MAXAUDIOOUTDEV];
static char audio_outdevnames[MAXMIDIINDEV * DEVDESCSIZE];
static int audio_callback_is_open; /* reflects true actual state */
static int audio_nextinchans, audio_nextoutchans;
Ivica Bukvic
committed
#ifdef USEAPI_JACK
/* needed to fix srate when using jack, inclded in s_audio_jack.c */
Ivica Bukvic
committed
extern int jack_get_srate(void);
#endif /* JACK */
{
return (audio_state &&
((audio_naudioindev > 0 && audio_audiochindev[0] > 0)
|| (audio_naudiooutdev > 0 && audio_audiochoutdev[0] > 0)));
}
Ivica Bukvic
committed
int sys_audio_get_blocksize(void)
{
return (audio_blocksize);
}
void sys_get_audio_params(
int *pnaudioindev, int *paudioindev, int *chindev,
int *pnaudiooutdev, int *paudiooutdev, int *choutdev,
int *prate, int *padvance, int *pcallback, int *pblocksize)
for (i = 0; i < audio_naudioindev; i++)
{
if ((devn = sys_audiodevnametonumber(0,
&audio_indevnames[i * DEVDESCSIZE])) >= 0)
paudioindev[i] = devn;
else paudioindev[i] = audio_audioindev[i];
chindev[i] = audio_audiochindev[i];
}
for (i = 0; i < audio_naudiooutdev; i++)
if ((devn = sys_audiodevnametonumber(1,
&audio_outdevnames[i * DEVDESCSIZE])) >= 0)
paudiooutdev[i] = devn;
else paudiooutdev[i] = audio_audiooutdev[i];
choutdev[i] = audio_audiochoutdev[i];
*prate = audio_rate;
*padvance = audio_advance;
}
void sys_save_audio_params(
int naudioindev, int *audioindev, int *chindev,
int naudiooutdev, int *audiooutdev, int *choutdev,
int rate, int advance, int callback, int blocksize)
{
int i;
audio_naudioindev = naudioindev;
for (i = 0; i < naudioindev; i++)
{
audio_audiochindev[i] = chindev[i];
sys_audiodevnumbertoname(0, audioindev[i],
&audio_indevnames[i * DEVDESCSIZE], DEVDESCSIZE);
}
for (i = 0; i < naudiooutdev; i++)
{
audio_audiochoutdev[i] = choutdev[i];
sys_audiodevnumbertoname(1, audiooutdev[i],
&audio_outdevnames[i * DEVDESCSIZE], DEVDESCSIZE);
}
}
/* init routines for any API which needs to set stuff up before
any other API gets used. This is only true of OSS so far. */
#ifdef USEAPI_OSS
void oss_init(void);
#endif
static void audio_init( void)
{
static int initted = 0;
if (initted)
return;
initted = 1;
#ifdef USEAPI_OSS
oss_init();
#endif
}
/* set channels and sample rate. */
void sys_setchsr(int chin, int chout, int sr)
{
int inbytes = (chin ? chin : 2) *
(DEFDACBLKSIZE*sizeof(t_sample));
(DEFDACBLKSIZE*sizeof(t_sample));
if (sys_soundin)
freebytes(sys_soundin,
(sys_inchannels? sys_inchannels : 2) *
(DEFDACBLKSIZE*sizeof(t_sample)));
if (sys_soundout)
freebytes(sys_soundout,
(sys_outchannels? sys_outchannels : 2) *
(DEFDACBLKSIZE*sizeof(t_sample)));
sys_inchannels = chin;
sys_outchannels = chout;
sys_dacsr = sr;
sys_advance_samples = (sys_schedadvance * sys_dacsr) / (1000000.);
Ivica Bukvic
committed
if (sys_advance_samples < 3 * DEFDACBLKSIZE)
sys_advance_samples = 3 * DEFDACBLKSIZE;
sys_soundin = (t_sample *)getbytes(inbytes);
sys_soundout = (t_sample *)getbytes(outbytes);
memset(sys_soundout, 0, outbytes);
if (sys_verbose)
post("input channels = %d, output channels = %d",
sys_inchannels, sys_outchannels);
canvas_resume_dsp(canvas_suspend_dsp());
}
/* ----------------------- public routines ----------------------- */
/* set audio device settings (after cleaning up the specified device and
channel vectors). The audio devices are "zero based" (i.e. "0" means the
first one.) We can later re-open audio and/or show the settings on a
void sys_set_audio_settings(int naudioindev, int *audioindev, int nchindev,
int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev,
int *choutdev, int rate, int advance, int callback, int blocksize)
int defaultchannels = SYS_DEFAULTCH;
int inchans, outchans, nrealindev, nrealoutdev;
int realindev[MAXAUDIOINDEV], realoutdev[MAXAUDIOOUTDEV];
int realinchans[MAXAUDIOINDEV], realoutchans[MAXAUDIOOUTDEV];
char indevlist[MAXNDEV*DEVDESCSIZE], outdevlist[MAXNDEV*DEVDESCSIZE];
int indevs = 0, outdevs = 0, canmulti = 0, cancallback = 0;
audio_getdevs(indevlist, &indevs, outdevlist, &outdevs, &canmulti,
if (blocksize != (1 << ilog2(blocksize)) || blocksize < DEFDACBLKSIZE)
blocksize = DEFDACBLKSIZE;
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
audio_init();
/* Since the channel vector might be longer than the
audio device vector, or vice versa, we fill the shorter one
in to match the longer one. Also, if both are empty, we fill in
one device (the default) and two channels. */
if (naudioindev == -1)
{ /* no input audio devices specified */
if (nchindev == -1)
{
if (indevs >= 1)
{
nchindev=1;
chindev[0] = defaultchannels;
naudioindev = 1;
audioindev[0] = DEFAULTAUDIODEV;
}
else naudioindev = nchindev = 0;
}
else
{
for (i = 0; i < MAXAUDIOINDEV; i++)
audioindev[i] = i;
naudioindev = nchindev;
}
}
else
{
if (nchindev == -1)
{
nchindev = naudioindev;
for (i = 0; i < naudioindev; i++)
chindev[i] = defaultchannels;
}
else if (nchindev > naudioindev)
{
for (i = naudioindev; i < nchindev; i++)
{
if (i == 0)
audioindev[0] = DEFAULTAUDIODEV;
else audioindev[i] = audioindev[i-1] + 1;
}
naudioindev = nchindev;
}
else if (nchindev < naudioindev)
{
for (i = nchindev; i < naudioindev; i++)
{
if (i == 0)
chindev[0] = defaultchannels;
else chindev[i] = chindev[i-1];
}
naudioindev = nchindev;
}
}
if (naudiooutdev == -1)
{ /* not set */
if (nchoutdev == -1)
{
if (outdevs >= 1)
{
nchoutdev=1;
choutdev[0]=defaultchannels;
naudiooutdev=1;
audiooutdev[0] = DEFAULTAUDIODEV;
}
else nchoutdev = naudiooutdev = 0;
}
else
{
for (i = 0; i < MAXAUDIOOUTDEV; i++)
audiooutdev[i] = i;
naudiooutdev = nchoutdev;
}
}
else
{
if (nchoutdev == -1)
{
nchoutdev = naudiooutdev;
for (i = 0; i < naudiooutdev; i++)
choutdev[i] = defaultchannels;
}
else if (nchoutdev > naudiooutdev)
{
for (i = naudiooutdev; i < nchoutdev; i++)
{
if (i == 0)
audiooutdev[0] = DEFAULTAUDIODEV;
else audiooutdev[i] = audiooutdev[i-1] + 1;
}
naudiooutdev = nchoutdev;
}
else if (nchoutdev < naudiooutdev)
{
for (i = nchoutdev; i < naudiooutdev; i++)
{
if (i == 0)
choutdev[0] = defaultchannels;
else choutdev[i] = choutdev[i-1];
}
naudiooutdev = nchoutdev;
}
}
/* count total number of input and output channels */
for (i = nrealindev = inchans = 0; i < naudioindev; i++)
if (chindev[i] > 0)
{
realinchans[nrealindev] = chindev[i];
realindev[nrealindev] = audioindev[i];
inchans += chindev[i];
nrealindev++;
}
for (i = nrealoutdev = outchans = 0; i < naudiooutdev; i++)
if (choutdev[i] > 0)
{
realoutchans[nrealoutdev] = choutdev[i];
realoutdev[nrealoutdev] = audiooutdev[i];
outchans += choutdev[i];
nrealoutdev++;
}
sys_schedadvance = advance * 1000;
sys_log_error(ERR_NOTHING);
audio_nextinchans = inchans;
audio_nextoutchans = outchans;
sys_setchsr(audio_nextinchans, audio_nextoutchans, rate);
sys_save_audio_params(nrealindev, realindev, realinchans,
nrealoutdev, realoutdev, realoutchans, rate, advance, callback,
blocksize);
}
void sys_close_audio(void)
{
if (sys_externalschedlib)
{
return;
}
if (!audio_isopen())
return;
#ifdef USEAPI_PORTAUDIO
pa_close_audio();
else
#endif
#ifdef USEAPI_JACK
jack_close_audio();
else
#endif
#ifdef USEAPI_OSS
oss_close_audio();
else
#endif
#ifdef USEAPI_ALSA
alsa_close_audio();
else
#endif
#ifdef USEAPI_MMIO
post("sys_close_audio: unknown API %d", sys_audioapiopened);
sched_set_using_audio(SCHED_AUDIO_NONE);
}
/* open audio using whatever parameters were last used */
void sys_reopen_audio( void)
{
int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV];
int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV];
int rate, advance, callback, blocksize, outcome = 0;
sys_get_audio_params(&naudioindev, audioindev, chindev,
&naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback,
&blocksize);
sys_setchsr(audio_nextinchans, audio_nextoutchans, rate);
if (!naudioindev && !naudiooutdev)
{
sched_set_using_audio(SCHED_AUDIO_NONE);
return;
}
#ifdef USEAPI_PORTAUDIO
if (sys_audioapi == API_PORTAUDIO)
{
Ivica Bukvic
committed
int blksize = (audio_blocksize ? audio_blocksize : 64);
outcome = pa_open_audio((naudioindev > 0 ? chindev[0] : 0),
(naudiooutdev > 0 ? choutdev[0] : 0), rate, sys_soundin,
sys_soundout, blksize, sys_advance_samples/blksize,
(naudioindev > 0 ? audioindev[0] : 0),
(naudiooutdev > 0 ? audiooutdev[0] : 0),
(callback ? sched_audio_callbackfn : 0));
}
else
#endif
#ifdef USEAPI_JACK
if (sys_audioapi == API_JACK)
outcome = jack_open_audio((naudioindev > 0 ? chindev[0] : 0),
Ivica Bukvic
committed
(naudioindev > 0 ? choutdev[0] : 0), rate);
else
#endif
#ifdef USEAPI_OSS
if (sys_audioapi == API_OSS)
outcome = oss_open_audio(naudioindev, audioindev, naudioindev,
Ivica Bukvic
committed
chindev, naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate,
audio_blocksize);
else
#endif
#ifdef USEAPI_ALSA
/* for alsa, only one device is supported; it may
be open for both input and output. */
if (sys_audioapi == API_ALSA)
outcome = alsa_open_audio(naudioindev, audioindev, naudioindev,
chindev, naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate,
audio_blocksize);
else
#endif
#ifdef USEAPI_MMIO
if (sys_audioapi == API_MMIO)
outcome = mmio_open_audio(naudioindev, audioindev, naudioindev,
Ivica Bukvic
committed
chindev, naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate,
audio_blocksize);
else
#endif
#ifdef USEAPI_AUDIOUNIT
if (sys_audioapi == API_AUDIOUNIT)
outcome = audiounit_open_audio((naudioindev > 0 ? chindev[0] : 0),
(naudioindev > 0 ? choutdev[0] : 0), rate);
else
#endif
#ifdef USEAPI_ESD
if (sys_audioapi == API_ALSA)
outcome = esd_open_audio(naudioindev, audioindev, naudioindev,
chindev, naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate);
Ivica Bukvic
committed
else
#endif
#ifdef USEAPI_DUMMY
if (sys_audioapi == API_DUMMY)
outcome = dummy_open_audio(naudioindev, naudiooutdev, rate);
if (sys_audioapi == API_NONE)
;
else post("unknown audio API specified");
if (outcome) /* failed */
{
audio_state = 0;
sched_set_using_audio(SCHED_AUDIO_NONE);
/* fprintf(stderr, "started w/callback %d\n", callback); */
audio_state = 1;
sched_set_using_audio(
(callback ? SCHED_AUDIO_CALLBACK : SCHED_AUDIO_POLL));
gui_vmess("set_audioapi", "i", (outcome == 0 ? sys_audioapi : 0));
}
int sys_send_dacs(void)
{
if (sys_meters)
{
int i, n;
for (i = 0, n = sys_inchannels * DEFDACBLKSIZE, maxsamp = sys_inmax;
i < n; i++)
{
t_sample f = sys_soundin[i];
if (f > maxsamp) maxsamp = f;
else if (-f > maxsamp) maxsamp = -f;
}
sys_inmax = maxsamp;
for (i = 0, n = sys_outchannels * DEFDACBLKSIZE, maxsamp = sys_outmax;
i < n; i++)
{
t_sample f = sys_soundout[i];
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
if (f > maxsamp) maxsamp = f;
else if (-f > maxsamp) maxsamp = -f;
}
sys_outmax = maxsamp;
}
#ifdef USEAPI_PORTAUDIO
if (sys_audioapi == API_PORTAUDIO)
return (pa_send_dacs());
else
#endif
#ifdef USEAPI_JACK
if (sys_audioapi == API_JACK)
return (jack_send_dacs());
else
#endif
#ifdef USEAPI_OSS
if (sys_audioapi == API_OSS)
return (oss_send_dacs());
else
#endif
#ifdef USEAPI_ALSA
if (sys_audioapi == API_ALSA)
return (alsa_send_dacs());
else
#endif
#ifdef USEAPI_MMIO
if (sys_audioapi == API_MMIO)
return (mmio_send_dacs());
else
#endif
post("unknown API");
return (0);
}
t_float sys_getsr(void)
Ivica Bukvic
committed
// when starting with -nogui option, it is conceivable that sys_dacsr
// is not initialized even though the audio_rate by this time has
// proper sample rate entered. Hence we check for this here and avoid
// the -nogui nonsense where we have to do various workarounds to make
// sure that audio objects that depend on this call get the proper sr
if (sys_dacsr == 0 && audio_rate > 0)
Ivica Bukvic
committed
{
sys_dacsr = (t_float)audio_rate;
}
return (sys_dacsr);
}
int sys_get_outchannels(void)
{
return (sys_outchannels);
}
int sys_get_inchannels(void)
{
return (sys_inchannels);
}
void sys_getmeters(t_sample *inmax, t_sample *outmax)
{
if (inmax)
{
sys_meters = 1;
*inmax = sys_inmax;
*outmax = sys_outmax;
}
else
sys_meters = 0;
sys_inmax = sys_outmax = 0;
}
void sys_reportidle(void)
{
}
static void audio_getdevs(char *indevlist, int *nindevs,
char *outdevlist, int *noutdevs, int *canmulti, int *cancallback,
int maxndev, int devdescsize)
{
audio_init();
*cancallback = 0; /* may be overridden by specific API implementation */
#ifdef USEAPI_PORTAUDIO
if (sys_audioapi == API_PORTAUDIO)
{
pa_getdevs(indevlist, nindevs, outdevlist, noutdevs, canmulti,
maxndev, devdescsize);
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
}
else
#endif
#ifdef USEAPI_JACK
if (sys_audioapi == API_JACK)
{
jack_getdevs(indevlist, nindevs, outdevlist, noutdevs, canmulti,
maxndev, devdescsize);
}
else
#endif
#ifdef USEAPI_OSS
if (sys_audioapi == API_OSS)
{
oss_getdevs(indevlist, nindevs, outdevlist, noutdevs, canmulti,
maxndev, devdescsize);
}
else
#endif
#ifdef USEAPI_ALSA
if (sys_audioapi == API_ALSA)
{
alsa_getdevs(indevlist, nindevs, outdevlist, noutdevs, canmulti,
maxndev, devdescsize);
}
else
#endif
#ifdef USEAPI_MMIO
if (sys_audioapi == API_MMIO)
{
mmio_getdevs(indevlist, nindevs, outdevlist, noutdevs, canmulti,
maxndev, devdescsize);
}
else
#endif
{
/* this shouldn't happen once all the above get filled in. */
int i;
*nindevs = *noutdevs = 3;
for (i = 0; i < 3; i++)
{
sprintf(indevlist + i * devdescsize, "input device #%d", i+1);
sprintf(outdevlist + i * devdescsize, "output device #%d", i+1);
}
*canmulti = 0;
}
}
static void sys_listaudiodevs(void )
{
char indevlist[MAXNDEV*DEVDESCSIZE], outdevlist[MAXNDEV*DEVDESCSIZE];
int nindevs = 0, noutdevs = 0, i, canmulti = 0, cancallback = 0;
audio_getdevs(indevlist, &nindevs, outdevlist, &noutdevs, &canmulti,
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
if (!nindevs)
post("no audio input devices found");
else
{
/* To agree with command line flags, normally start at 1 */
/* But microsoft "MMIO" device list starts at 0 (the "mapper"). */
/* (see also sys_mmio variable in s_main.c) */
post("audio input devices:");
for (i = 0; i < nindevs; i++)
post("%d. %s", i + (sys_audioapi != API_MMIO),
indevlist + i * DEVDESCSIZE);
}
if (!noutdevs)
post("no audio output devices found");
else
{
post("audio output devices:");
for (i = 0; i < noutdevs; i++)
post("%d. %s", i + (sys_audioapi != API_MMIO),
outdevlist + i * DEVDESCSIZE);
}
post("API number %d\n", sys_audioapi);
}
/* start an audio settings dialog window */
void glob_audio_properties(t_pd *dummy, t_floatarg flongform)
{
char buf[1024 + 2 * MAXNDEV*(DEVDESCSIZE+4)];
/* these are the devices you're using: */
int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV];
int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV];
int audioindev1, audioindev2, audioindev3, audioindev4,
audioinchan1, audioinchan2, audioinchan3, audioinchan4,
audiooutdev1, audiooutdev2, audiooutdev3, audiooutdev4,
audiooutchan1, audiooutchan2, audiooutchan3, audiooutchan4;
int rate, advance, callback, blocksize;
/* these are all the devices on your system: */
char indevlist[MAXNDEV*DEVDESCSIZE], outdevlist[MAXNDEV*DEVDESCSIZE];
int nindevs = 0, noutdevs = 0, canmulti = 0, cancallback = 0, i;
audio_getdevs(indevlist, &nindevs, outdevlist, &noutdevs, &canmulti,
gui_start_vmess("gui_audio_properties", "s",
gfxstub_new2(&glob_pdobject, (void *)glob_audio_properties));
//sys_gui("global audio_indevlist; set audio_indevlist {}\n");
gui_start_array(); // input devices
{
//sys_vgui("lappend audio_indevlist {%s}\n",
// indevlist + i * DEVDESCSIZE);
gui_s(indevlist + i * DEVDESCSIZE);
}
gui_end_array();
// sys_gui("global audio_outdevlist; set audio_outdevlist {}\n");
gui_start_array(); // output devices
{
//sys_vgui("lappend audio_outdevlist {%s}\n",
// outdevlist + i * DEVDESCSIZE);
gui_s(outdevlist + i * DEVDESCSIZE);
}
gui_end_array();
sys_get_audio_params(&naudioindev, audioindev, chindev,
&naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback,
&blocksize);
Ivica Bukvic
committed
#ifdef USEAPI_JACK
if (sys_audioapiopened == API_JACK)
{
sys_setchsr(audio_nextinchans, audio_nextoutchans, rate);
}
Ivica Bukvic
committed
#endif /* JACK */
/* post("naudioindev %d naudiooutdev %d longform %f",
naudioindev, naudiooutdev, flongform); */
if (naudioindev > 1 || naudiooutdev > 1)
flongform = 1;
audioindev1 = (naudioindev > 0 && audioindev[0]>= 0 ? audioindev[0] : 0);
audioindev2 = (naudioindev > 1 && audioindev[1]>= 0 ? audioindev[1] : 0);
audioindev3 = (naudioindev > 2 && audioindev[2]>= 0 ? audioindev[2] : 0);
audioindev4 = (naudioindev > 3 && audioindev[3]>= 0 ? audioindev[3] : 0);
audioinchan1 = (naudioindev > 0 ? chindev[0] : 0);
audioinchan2 = (naudioindev > 1 ? chindev[1] : 0);
audioinchan3 = (naudioindev > 2 ? chindev[2] : 0);
audioinchan4 = (naudioindev > 3 ? chindev[3] : 0);
audiooutdev1 = (naudiooutdev > 0 && audiooutdev[0]>=0 ? audiooutdev[0] : 0);
audiooutdev2 = (naudiooutdev > 1 && audiooutdev[1]>=0 ? audiooutdev[1] : 0);
audiooutdev3 = (naudiooutdev > 2 && audiooutdev[2]>=0 ? audiooutdev[2] : 0);
audiooutdev4 = (naudiooutdev > 3 && audiooutdev[3]>=0 ? audiooutdev[3] : 0);
audiooutchan1 = (naudiooutdev > 0 ? choutdev[0] : 0);
audiooutchan2 = (naudiooutdev > 1 ? choutdev[1] : 0);
audiooutchan3 = (naudiooutdev > 2 ? choutdev[2] : 0);
audiooutchan4 = (naudiooutdev > 3 ? choutdev[3] : 0);
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
// sprintf(buf,
//"pdtk_audio_dialog %%s \
//%d %d %d %d %d %d %d %d \
//%d %d %d %d %d %d %d %d \
//%d %d %d %d %d %d\n",
// audioindev1, audioindev2, audioindev3, audioindev4,
// audioinchan1, audioinchan2, audioinchan3, audioinchan4,
// audiooutdev1, audiooutdev2, audiooutdev3, audiooutdev4,
// audiooutchan1, audiooutchan2, audiooutchan3, audiooutchan4,
// rate, advance, canmulti, (cancallback ? callback : -1),
// (flongform != 0), blocksize);
gui_start_array(); // audio input devices
gui_i(audioindev1); gui_i(audioindev2);
gui_i(audioindev3); gui_i(audioindev4);
gui_end_array();
gui_start_array(); // audio input channels
gui_i(audioinchan1); gui_i(audioinchan2);
gui_i(audioinchan3); gui_i(audioinchan4);
gui_end_array();
gui_start_array(); // audio output devices
gui_i(audiooutdev1); gui_i(audiooutdev2);
gui_i(audiooutdev3); gui_i(audiooutdev4);
gui_end_array();
gui_start_array(); // audio output channels
gui_i(audiooutchan1); gui_i(audiooutchan2);
gui_i(audiooutchan3); gui_i(audiooutchan4);
gui_end_array();
gui_start_array();
gui_s("rate"); gui_i(rate);
gui_s("advance"); gui_i(advance);
gui_s("canmulti"); gui_i(canmulti);
gui_s("cancallback"); gui_i(cancallback ? callback : -1);
gui_s("flongform"); gui_i(flongform != 0);
gui_s("blocksize"); gui_i(blocksize);
gui_s("current-api"); gui_i(sys_audioapi); // cannot figure out how this
// originally got set
gui_end_array();
gui_end_vmess();
// not sure why we were deleting the key 0 here...
// gfxstub_deleteforkey(0);
// gfxstub_new(&glob_pdobject, (void *)glob_audio_properties, buf);
/* new values from dialog window */
void glob_audio_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv)
{
int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV];
int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV];
int rate, advance, audioon, i, nindev, noutdev;
int audioindev1, audioinchan1, audiooutdev1, audiooutchan1;
int newaudioindev[4], newaudioinchan[4],
newaudiooutdev[4], newaudiooutchan[4];
/* the new values the dialog came back with: */
int newrate = atom_getintarg(16, argc, argv);
int newadvance = atom_getintarg(17, argc, argv);
int newcallback = atom_getintarg(18, argc, argv);
int newblocksize = atom_getintarg(19, argc, argv);
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
for (i = 0; i < 4; i++)
{
newaudioindev[i] = atom_getintarg(i, argc, argv);
newaudioinchan[i] = atom_getintarg(i+4, argc, argv);
newaudiooutdev[i] = atom_getintarg(i+8, argc, argv);
newaudiooutchan[i] = atom_getintarg(i+12, argc, argv);
}
for (i = 0, nindev = 0; i < 4; i++)
{
if (newaudioinchan[i])
{
newaudioindev[nindev] = newaudioindev[i];
newaudioinchan[nindev] = newaudioinchan[i];
/* post("in %d %d %d", nindev,
newaudioindev[nindev] , newaudioinchan[nindev]); */
nindev++;
}
}
for (i = 0, noutdev = 0; i < 4; i++)
{
if (newaudiooutchan[i])
{
newaudiooutdev[noutdev] = newaudiooutdev[i];
newaudiooutchan[noutdev] = newaudiooutchan[i];
/* post("out %d %d %d", noutdev,
newaudiooutdev[noutdev] , newaudioinchan[noutdev]); */
noutdev++;
}
}
sys_set_audio_settings_reopen(nindev, newaudioindev, nindev, newaudioinchan,
Ivica Bukvic
committed
noutdev, newaudiooutdev, noutdev, newaudiooutchan,
newrate, newadvance, newcallback, newblocksize);
}
void sys_set_audio_settings_reopen(int naudioindev, int *audioindev, int nchindev,
int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev,
int *choutdev, int rate, int advance, int callback, int newblocksize)
{
if (callback < 0)
callback = 0;
if (newblocksize != (1<<ilog2(newblocksize)) ||
newblocksize < DEFDACBLKSIZE || newblocksize > 2048)
newblocksize = DEFDACBLKSIZE;
if (!audio_callback_is_open && !callback)
sys_close_audio();
sys_set_audio_settings(naudioindev, audioindev, nchindev, chindev,
naudiooutdev, audiooutdev, nchoutdev, choutdev,
rate, advance, (callback >= 0 ? callback : 0), newblocksize);
if (!audio_callback_is_open && !callback)
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
}
void sys_listdevs(void )
{
#ifdef USEAPI_PORTAUDIO
if (sys_audioapi == API_PORTAUDIO)
sys_listaudiodevs();
else
#endif
#ifdef USEAPI_JACK
if (sys_audioapi == API_JACK)
jack_listdevs();
else
#endif
#ifdef USEAPI_OSS
if (sys_audioapi == API_OSS)
sys_listaudiodevs();
else
#endif
#ifdef USEAPI_ALSA
if (sys_audioapi == API_ALSA)
sys_listaudiodevs();
else
#endif
#ifdef USEAPI_MMIO
if (sys_audioapi == API_MMIO)
sys_listaudiodevs();
else
#endif
post("unknown API");
sys_listmididevs();
}
Ivica Bukvic
committed
void sys_setblocksize(int n)
Ivica Bukvic
committed
if (n < 1)
n = 1;
if (n != (1 << ilog2(n)))
post("warning: adjusting blocksize to power of 2: %d",
(n = (1 << ilog2(n))));
sys_blocksize = n;
void sys_get_audio_devs(char *indevlist, int *nindevs,
char *outdevlist, int *noutdevs, int *canmulti, int *cancallback,
int maxndev, int devdescsize)
{
audio_getdevs(indevlist, nindevs,
outdevlist, noutdevs,
canmulti, cancallback,
maxndev, devdescsize);
}
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
void sys_set_audio_api(int which)
{
sys_audioapi = which;
if (sys_verbose)
post("sys_audioapi %d", sys_audioapi);
}
void glob_audio_setapi(void *dummy, t_floatarg f)
{
int newapi = f;
if (newapi)
{
if (newapi == sys_audioapi)
{
if (!audio_isopen())
sys_reopen_audio();
}
else
{
sys_close_audio();
sys_audioapi = newapi;
/* bash device params back to default */
audio_naudioindev = audio_naudiooutdev = 1;
audio_audioindev[0] = audio_audiooutdev[0] = DEFAULTAUDIODEV;
audio_audiochindev[0] = audio_audiochoutdev[0] = SYS_DEFAULTCH;
sys_reopen_audio();
}
glob_audio_properties(0, 0);
}
else if (audio_isopen())
{
sys_close_audio();
}
}
/* start or stop the audio hardware */
void sys_set_audio_state(int onoff)
{
if (onoff) /* start */
{
if (!audio_isopen())
sys_reopen_audio();
}
else
{
if (audio_isopen())
sys_close_audio();
}
}
void sys_get_audio_apis(char *buf)
{
int n = 0;