3
* This file is part of Open Sound System.
5
* Copyright (C) 4Front Technologies 1996-2008.
7
* This this source file is released under GPL v2 license (no other versions).
8
* See the COPYING file included in the main directory of this source
9
* distribution for the license terms and conditions.
20
#include <oss_config.h>
21
#include <sys/ioctl.h>
23
static void change_mixer (const char *, char *);
24
static int find_mixerdev (const char *);
25
static char * get_mapname (void);
26
#ifdef APPLIST_SUPPORT
27
static void load_applist (void);
29
static void load_config (const char *);
30
static void open_device (const char *, int);
32
static void reorder_dspdevs (void);
38
static char ossetcdir[ETCDIRLEN] = "/usr/lib/oss/etc";
39
/* This is the usual place */
40
static oss_mixerinfo mixerinfo;
41
static oss_mixext *mixerdefs = NULL;
42
static int fd, load_settings = 0, nummixers, verbose = 0;
46
reorder_dspdevs (void)
48
char line[1024], *p, *s;
49
oss_reroute_t reroute[3] = { {0} };
53
snprintf (line, sizeof (line), "%s/dspdevs.map", ossetcdir);
55
if ((f = fopen (line, "r")) == NULL)
59
while (n < 3 && (fgets (line, sizeof (line), f) != NULL))
61
s = strchr (line, '\n');
62
if (s != NULL) *s = '\0';
72
while (*p && *p != ' ')
77
if (m > MAX_AUDIO_DEVFILES || sscanf (s, "%d", &v) != 1)
79
fprintf (stderr, "Bad info in dspdevs.map\n");
88
reroute[n].devlist.devices[m++] = v;
89
reroute[n].devlist.ndevs = m;
95
for (i = 0; i < n; i++)
97
reroute[i].mode = i + 1;
99
if (ioctl (fd, OSSCTL_SET_REROUTE, &reroute[i]) == -1)
104
"Device configuration changed - use ossdevlinks "
105
"to update device lists\n");
118
fprintf (stdout, "/dev/dsp input assignment: ");
121
fprintf (stdout, "/dev/dsp output assignment: ");
123
case OSS_OPEN_READ | OSS_OPEN_WRITE:
124
fprintf (stdout, "/dev/dsp output assignment: ");
128
for (j = 0; j < reroute[i].devlist.ndevs; j++)
129
fprintf (stdout, "%d ", reroute[i].devlist.devices[j]);
130
fprintf (stdout, "\n");
137
#ifdef APPLIST_SUPPORT
145
snprintf (line, sizeof (line), "%s/applist.conf", ossetcdir);
147
if ((f = fopen (line, "r")) == NULL)
150
if (ioctl (fd, OSSCTL_RESET_APPLIST, NULL) == -1)
152
perror ("OSSCTL_RESET_APPLIST");
157
while (fgets (line, sizeof (line), f) != NULL)
160
char *s, *name, *mode, *dev, *flag;
163
if ((*line == '#') || (*line == '\0'))
166
memset (&rout, 0, sizeof (rout));
169
for (i = 0; i < j; i++)
170
if (line[i] == '\n' || line[i] == '#')
178
/* Find the field separator (LWSP) */
179
while (*s && (*s != ' ' && *s != '\t'))
181
while (*s == ' ' || *s == '\t')
184
strncpy (rout.name, name, 32);
185
rout.name[32] = '\0';
189
/* Find the field separator (LWSP) */
190
while (*s && (*s != ' ' && *s != '\t'))
192
while (*s == ' ' || *s == '\t')
196
for (i = 0; i < j; i++)
200
rout.mode |= OSS_OPEN_READ;
203
rout.mode |= OSS_OPEN_WRITE;
207
fprintf (stderr, "Bad open mode flag '%c' in applist.conf\n",
213
/* Find the field separator (LWSP) */
214
while (*s && (*s != ' ' && *s != '\t'))
216
while (*s == ' ' || *s == '\t')
219
if (sscanf (dev, "%d", &rout.dev) != 1)
221
fprintf (stderr, "bad audio device number '%s' in applist.conf\n",
230
while (*s && *s != '|')
235
if (strcmp (flag, "MMAP") == 0)
237
rout.open_flags |= OF_MMAP;
241
if (strcmp (flag, "BLOCK") == 0)
243
rout.open_flags |= OF_BLOCK;
247
if (strcmp (flag, "NOCONV") == 0)
249
rout.open_flags |= OF_NOCONV;
253
fprintf (stderr, "Bad option '%s' in applist.conf\n", flag);
256
if (ioctl (fd, OSSCTL_ADD_APPLIST, &rout) == -1)
259
perror ("OSSCTL_ADD_APPLIST");
271
char tmp[ETCDIRLEN+11]; /* Adding 'OSSLIBDIR=' */
272
static char name[ETCDIRLEN+15]; /* Adding '/etc/mixer.save' */
275
if (stat ("/etc/oss", &st) != -1) /* Use /etc/oss/mixer.save */
277
strcpy (name, "/etc/oss/mixer.save");
278
strcpy (ossetcdir, "/etc/oss");
282
if ((f = fopen ("/etc/oss.conf", "r")) == NULL)
284
// perror ("/etc/oss.conf");
288
while (fgets (tmp, sizeof (tmp), f) != NULL)
290
size_t l = strlen (tmp);
291
if (l > 0 && tmp[l - 1] == '\n')
294
if (strncmp (tmp, "OSSLIBDIR=", 10) == 0)
296
l = snprintf (name, sizeof (name), "%s/etc/mixer.save", &tmp[10]);
297
if ((l >= sizeof (name)) || (l < 0))
299
fprintf (stderr, "String in /etc/oss.conf is too long!\n");
302
snprintf (ossetcdir, sizeof (ossetcdir), "%s/etc", &tmp[10]);
303
if ((l >= sizeof (ossetcdir)) || (l < 0))
305
fprintf (stderr, "String in /etc/oss.conf is too long!\n");
314
fprintf (stderr, "Error: OSSLIBDIR not set in /etc/oss.conf\n");
317
snprintf (name, sizeof (name), "%s/mixer.save", ossetcdir);
326
find_mixerdev (const char *handle)
329
* Find the mixer device (number) which matches the given handle.
334
if (mixerdefs != NULL)
338
for (i = 0; i < nummixers; i++)
344
if (ioctl (fd, SNDCTL_MIXERINFO, &mixerinfo) == -1)
346
perror ("SNDCTL_MIXERINFO");
350
if (strcmp (mixerinfo.handle, handle) == 0) /* Match */
353
(oss_mixext *)malloc (sizeof (*mixerdefs) * mixerinfo.nrext);
354
if (mixerdefs == NULL)
356
fprintf (stderr, "Out of memory\n");
360
for (j = 0; j < mixerinfo.nrext; j++)
362
oss_mixext *ext = mixerdefs + j;
367
if (ioctl (fd, SNDCTL_MIX_EXTINFO, ext) == -1)
369
perror ("SNDCTL_MIX_EXTINFO");
382
change_mixer (const char *fname, char *line)
384
unsigned int value, i;
387
if (sscanf (line, "%s %x", name, &value) != 2)
389
fprintf (stderr, "Bad line in %s\n", fname);
390
fprintf (stderr, "%s\n", line);
393
for (i = 0; i < mixerinfo.nrext; i++)
395
oss_mixext *ext = mixerdefs + i;
398
if (strcmp (ext->extname, name) == 0)
401
if (!(ext->flags & MIXF_WRITEABLE))
404
if (ext->type == MIXT_GROUP)
406
if (ext->type == MIXT_DEVROOT)
408
if (ext->type == MIXT_MARKER)
412
val.ctrl = ext->ctrl;
413
val.timestamp = ext->timestamp;
416
if (ioctl (fd, SNDCTL_MIX_WRITE, &val) == -1)
418
perror ("SNDCTL_MIX_WRITE");
419
fprintf (stderr, "%s (%d)=%04x\n", name, val.ctrl, value);
428
load_config (const char *name)
431
char line[SLINELEN], *s;
434
if (verbose) fprintf (stdout, "Loading mixer settings from %s\n", name);
435
#ifdef MANAGE_DEV_DSP
438
#ifdef APPLIST_SUPPORT
442
if ((f = fopen (name, "r")) == NULL)
448
/* Remove the EOL character */
449
while (fgets (line, sizeof (line), f) != NULL)
452
if ((s = strchr (line, '\n')) != NULL)
455
if ((*line == '\0') || (*line == '#'))
460
if (strcmp (line, "$endmix") == 0)
461
continue; /* Ignore this */
465
while (*s && *s != ' ')
470
if (strcmp (line, "$startmix") != 0)
473
dev = find_mixerdev (s);
478
if (dev < 0) /* Unknown mixer device? */
481
change_mixer (name, line);
488
open_device (const char * dev_name, int mode)
490
if ((fd = open (dev_name, mode, 0)) == -1)
497
if (ioctl (fd, SNDCTL_MIX_NRMIX, &nummixers) == -1)
499
perror ("SNDCTL_MIX_NRMIX");
500
fprintf (stderr, "Possibly incompatible OSS version\n");
506
fprintf (stderr, "No mixers in the system\n");
513
main (int argc, char *argv[])
516
char * mapname = NULL;
517
extern char * optarg;
521
while ((i = getopt (argc, argv, "LVf:v")) != EOF)
534
fprintf (stdout, "OSS " OSS_VERSION_STRING " savemixer utility\n");
543
fprintf (stdout, "Usage: %s [option(s)]\n", argv[0]);
544
fprintf (stdout, " Options: -L Restore mixer settings\n");
545
fprintf (stdout, " -V Display version\n");
546
fprintf (stdout, " -f<fname> Use fname as settings "
548
fprintf (stdout, " -v Verbose output\n");
553
if (mapname == NULL) mapname = get_mapname ();
557
open_device ("/dev/mixer", O_WRONLY);
558
load_config (mapname);
562
open_device ("/dev/mixer", O_RDONLY);
564
if ((f = fopen (mapname, "w")) == NULL)
569
fprintf (f, "# Automatically generated by OSS savemixer - do not edit\n");
571
if (verbose) fprintf (stdout, "Saving mixer settings to %s\n", mapname);
573
for (dev = 0; dev < nummixers; dev++)
577
if (ioctl (fd, SNDCTL_MIXERINFO, &mixerinfo) == -1)
579
perror ("SNDCTL_MIXERINFO");
583
fprintf (f, "\n# %s\n", mixerinfo.name);
584
fprintf (f, "$startmix %s\n", mixerinfo.handle);
586
for (i = 0; i < mixerinfo.nrext; i++)
594
if (ioctl (fd, SNDCTL_MIX_EXTINFO, &ext) == -1)
596
perror ("SNDCTL_MIX_EXTINFO");
600
if (!(ext.flags & MIXF_WRITEABLE))
603
if (ext.type == MIXT_GROUP)
605
if (ext.type == MIXT_DEVROOT)
607
if (ext.type == MIXT_MARKER)
612
val.timestamp = ext.timestamp;
614
if (ioctl (fd, SNDCTL_MIX_READ, &val) == -1)
616
perror ("SNDCTL_MIX_READ");
620
fprintf (f, "%s %04x\n", ext.extname, val.value);
623
fprintf (f, "$endmix\n");