~ubuntu-branches/ubuntu/vivid/oss4/vivid-proposed

« back to all changes in this revision

Viewing changes to .pc/cmd.patch/cmd/savemixer/savemixer.c

  • Committer: Package Import Robot
  • Author(s): Sebastien NOEL
  • Date: 2012-11-19 11:47:24 UTC
  • mfrom: (1.1.6)
  • Revision ID: package-import@ubuntu.com-20121119114724-svu8mq7x3pk64nez
Tags: 4.2-build2007-1
* New upstream release.
* Acknowledge NMU, thanks Michael Gilbert.
* Add debian/patches/110_ld-as-needed.patch: Rearrange order of linker
  arguments to fix building with "ld --as-needed" (closes: #630737).
* Add missing dependency on dpkg-dev to oss4-dkms and oss4-source
  (closes: #687086).
* Fix typo in the changelog (closes: #628876, #675933)
* Add debian/patches/002_fix-linux-oss_native_word.patch (closes: #693657).
  Thanks to Ben Hutchings.
* Add debian/patches/003_linux-error-logging-fixes.patch (closes: #693657).
  Thanks to Ben Hutchings.
* check for /lib/modules/${kernelver}/build in addition of
  /lib/modules/${kernelver}/source (closes: #587191).
* oss4-dkms.dkms.in: fix 'CLEAN' rules (closes: #653374).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *
3
 
 * This file is part of Open Sound System.
4
 
 *
5
 
 * Copyright (C) 4Front Technologies 1996-2008.
6
 
 *
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.
10
 
 *
11
 
 */
12
 
 
13
 
#include <stdio.h>
14
 
#include <unistd.h>
15
 
#include <stdlib.h>
16
 
#include <string.h>
17
 
#include <sys/stat.h>
18
 
#include <fcntl.h>
19
 
#include <errno.h>
20
 
#include <oss_config.h>
21
 
#include <sys/ioctl.h>
22
 
 
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);
28
 
#endif
29
 
static void load_config (const char *);
30
 
static void open_device (const char *, int);
31
 
#ifdef MANAGE_DEV_DSP
32
 
static void reorder_dspdevs (void);
33
 
#endif
34
 
 
35
 
#define ETCDIRLEN 512
36
 
#define SLINELEN 256
37
 
 
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;
43
 
 
44
 
#ifdef MANAGE_DEV_DSP
45
 
static void
46
 
reorder_dspdevs (void)
47
 
{
48
 
  char line[1024], *p, *s;
49
 
  oss_reroute_t reroute[3] = { {0} };
50
 
  int i, j, n, m;
51
 
  FILE *f;
52
 
 
53
 
  snprintf (line, sizeof (line), "%s/dspdevs.map", ossetcdir);
54
 
 
55
 
  if ((f = fopen (line, "r")) == NULL)
56
 
    return;
57
 
 
58
 
  n = 0;
59
 
  while (n < 3 && (fgets (line, sizeof (line), f) != NULL))
60
 
    {
61
 
      s = strchr (line, '\n');
62
 
      if (s != NULL) *s = '\0';
63
 
 
64
 
      m = 0;
65
 
      s = line;
66
 
      while (*s)
67
 
        {
68
 
          int v;
69
 
 
70
 
          p = s;
71
 
 
72
 
          while (*p && *p != ' ')
73
 
            p++;
74
 
          if (*p)
75
 
            *p++ = '\0';
76
 
 
77
 
          if (m > MAX_AUDIO_DEVFILES || sscanf (s, "%d", &v) != 1)
78
 
            {
79
 
              fprintf (stderr, "Bad info in dspdevs.map\n");
80
 
              fclose (f);
81
 
              return;
82
 
            }
83
 
          while (*p == ' ')
84
 
            p++;
85
 
 
86
 
          s = p;
87
 
 
88
 
          reroute[n].devlist.devices[m++] = v;
89
 
          reroute[n].devlist.ndevs = m;
90
 
        }
91
 
      n++;
92
 
    }
93
 
  fclose (f);
94
 
 
95
 
  for (i = 0; i < n; i++)
96
 
    {
97
 
      reroute[i].mode = i + 1;
98
 
 
99
 
      if (ioctl (fd, OSSCTL_SET_REROUTE, &reroute[i]) == -1)
100
 
        {
101
 
          if (errno == EINVAL)
102
 
            {
103
 
              fprintf (stderr,
104
 
                       "Device configuration changed - use ossdevlinks "
105
 
                       "to update device lists\n");
106
 
              return;
107
 
            }
108
 
 
109
 
          perror ("reroute");
110
 
          return;
111
 
        }
112
 
 
113
 
      if (verbose)
114
 
        {
115
 
          switch (i + 1)
116
 
            {
117
 
            case OSS_OPEN_READ:
118
 
              fprintf (stdout, "/dev/dsp input assignment: ");
119
 
              break;
120
 
            case OSS_OPEN_WRITE:
121
 
              fprintf (stdout, "/dev/dsp output assignment: ");
122
 
              break;
123
 
            case OSS_OPEN_READ | OSS_OPEN_WRITE:
124
 
              fprintf (stdout, "/dev/dsp output assignment: ");
125
 
              break;
126
 
            }
127
 
 
128
 
          for (j = 0; j < reroute[i].devlist.ndevs; j++)
129
 
            fprintf (stdout, "%d ", reroute[i].devlist.devices[j]);
130
 
          fprintf (stdout, "\n");
131
 
        }
132
 
    }
133
 
 
134
 
}
135
 
#endif
136
 
 
137
 
#ifdef APPLIST_SUPPORT
138
 
static void
139
 
load_applist (void)
140
 
{
141
 
  char line[1024];
142
 
 
143
 
  FILE *f;
144
 
 
145
 
  snprintf (line, sizeof (line), "%s/applist.conf", ossetcdir);
146
 
 
147
 
  if ((f = fopen (line, "r")) == NULL)
148
 
    return;
149
 
 
150
 
  if (ioctl (fd, OSSCTL_RESET_APPLIST, NULL) == -1)
151
 
    {
152
 
      perror ("OSSCTL_RESET_APPLIST");
153
 
      fclose (f);
154
 
      return;
155
 
    }
156
 
 
157
 
  while (fgets (line, sizeof (line), f) != NULL)
158
 
    {
159
 
      int i, j;
160
 
      char *s, *name, *mode, *dev, *flag;
161
 
      app_routing_t rout;
162
 
 
163
 
      if ((*line == '#') || (*line == '\0'))
164
 
        continue;
165
 
 
166
 
      memset (&rout, 0, sizeof (rout));
167
 
 
168
 
      j = strlen (line);
169
 
      for (i = 0; i < j; i++)
170
 
        if (line[i] == '\n' || line[i] == '#')
171
 
          {
172
 
            line[i] = '\0';
173
 
            break;
174
 
          }
175
 
 
176
 
      s = name = line;
177
 
 
178
 
      /* Find the field separator (LWSP) */
179
 
      while (*s && (*s != ' ' && *s != '\t'))
180
 
        s++;
181
 
      while (*s == ' ' || *s == '\t')
182
 
        *s++ = '\0';
183
 
 
184
 
      strncpy (rout.name, name, 32);
185
 
      rout.name[32] = '\0';
186
 
 
187
 
      mode = s;
188
 
 
189
 
      /* Find the field separator (LWSP) */
190
 
      while (*s && (*s != ' ' && *s != '\t'))
191
 
        s++;
192
 
      while (*s == ' ' || *s == '\t')
193
 
        *s++ = '\0';
194
 
 
195
 
      j = strlen (mode);
196
 
      for (i = 0; i < j; i++)
197
 
        switch (mode[i])
198
 
          {
199
 
          case 'r':
200
 
            rout.mode |= OSS_OPEN_READ;
201
 
            break;
202
 
          case 'w':
203
 
            rout.mode |= OSS_OPEN_WRITE;
204
 
            break;
205
 
 
206
 
          default:
207
 
            fprintf (stderr, "Bad open mode flag '%c' in applist.conf\n",
208
 
                     mode[i]);
209
 
          }
210
 
 
211
 
      dev = s;
212
 
 
213
 
      /* Find the field separator (LWSP) */
214
 
      while (*s && (*s != ' ' && *s != '\t'))
215
 
        s++;
216
 
      while (*s == ' ' || *s == '\t')
217
 
        *s++ = '\0';
218
 
 
219
 
      if (sscanf (dev, "%d", &rout.dev) != 1)
220
 
        {
221
 
          fprintf (stderr, "bad audio device number '%s' in applist.conf\n",
222
 
                   dev);
223
 
          continue;
224
 
        }
225
 
 
226
 
      while (*s)
227
 
        {
228
 
          flag = s;
229
 
 
230
 
          while (*s && *s != '|')
231
 
            s++;
232
 
          while (*s == '|')
233
 
            *s++ = '\0';
234
 
 
235
 
          if (strcmp (flag, "MMAP") == 0)
236
 
            {
237
 
              rout.open_flags |= OF_MMAP;
238
 
              continue;
239
 
            }
240
 
 
241
 
          if (strcmp (flag, "BLOCK") == 0)
242
 
            {
243
 
              rout.open_flags |= OF_BLOCK;
244
 
              continue;
245
 
            }
246
 
 
247
 
          if (strcmp (flag, "NOCONV") == 0)
248
 
            {
249
 
              rout.open_flags |= OF_NOCONV;
250
 
              continue;
251
 
            }
252
 
 
253
 
          fprintf (stderr, "Bad option '%s' in applist.conf\n", flag);
254
 
        }
255
 
 
256
 
      if (ioctl (fd, OSSCTL_ADD_APPLIST, &rout) == -1)
257
 
        {
258
 
          if (errno != ENXIO)
259
 
            perror ("OSSCTL_ADD_APPLIST");
260
 
        }
261
 
    }
262
 
 
263
 
  fclose (f);
264
 
}
265
 
#endif
266
 
 
267
 
static char *
268
 
get_mapname (void)
269
 
{
270
 
  FILE *f;
271
 
  char tmp[ETCDIRLEN+11]; /* Adding 'OSSLIBDIR=' */
272
 
  static char name[ETCDIRLEN+15]; /* Adding '/etc/mixer.save' */
273
 
  struct stat st;
274
 
 
275
 
  if (stat ("/etc/oss", &st) != -1)     /* Use /etc/oss/mixer.save */
276
 
    {
277
 
      strcpy (name, "/etc/oss/mixer.save");
278
 
      strcpy (ossetcdir, "/etc/oss");
279
 
      return name;
280
 
    }
281
 
 
282
 
  if ((f = fopen ("/etc/oss.conf", "r")) == NULL)
283
 
    {
284
 
      // perror ("/etc/oss.conf");
285
 
      goto dexit;
286
 
    }
287
 
 
288
 
  while (fgets (tmp, sizeof (tmp), f) != NULL)
289
 
    {
290
 
      size_t l = strlen (tmp);
291
 
      if (l > 0 && tmp[l - 1] == '\n')
292
 
        tmp[l - 1] = '\0';
293
 
 
294
 
      if (strncmp (tmp, "OSSLIBDIR=", 10) == 0)
295
 
        {
296
 
          l = snprintf (name, sizeof (name), "%s/etc/mixer.save", &tmp[10]);
297
 
          if ((l >= sizeof (name)) || (l < 0))
298
 
            {
299
 
              fprintf (stderr, "String in /etc/oss.conf is too long!\n");
300
 
              goto oexit;
301
 
            }
302
 
          snprintf (ossetcdir, sizeof (ossetcdir), "%s/etc", &tmp[10]);
303
 
          if ((l >= sizeof (ossetcdir)) || (l < 0))
304
 
            {
305
 
              fprintf (stderr, "String in /etc/oss.conf is too long!\n");
306
 
              goto oexit;
307
 
            }
308
 
          fclose (f);
309
 
          return name;
310
 
        }
311
 
    }
312
 
 
313
 
  fclose (f);
314
 
  fprintf (stderr, "Error: OSSLIBDIR not set in /etc/oss.conf\n");
315
 
 
316
 
dexit:
317
 
  snprintf (name, sizeof (name), "%s/mixer.save", ossetcdir);
318
 
  return name;
319
 
 
320
 
oexit:
321
 
  fclose (f);
322
 
  exit (-1);
323
 
}
324
 
 
325
 
static int
326
 
find_mixerdev (const char *handle)
327
 
{
328
 
/*
329
 
 * Find the mixer device (number) which matches the given handle.
330
 
 */
331
 
 
332
 
  int i;
333
 
 
334
 
  if (mixerdefs != NULL)
335
 
    free (mixerdefs);
336
 
  mixerdefs = NULL;
337
 
 
338
 
  for (i = 0; i < nummixers; i++)
339
 
    {
340
 
      int j;
341
 
 
342
 
      mixerinfo.dev = i;
343
 
 
344
 
      if (ioctl (fd, SNDCTL_MIXERINFO, &mixerinfo) == -1)
345
 
        {
346
 
          perror ("SNDCTL_MIXERINFO");
347
 
          exit (-1);
348
 
        }
349
 
 
350
 
      if (strcmp (mixerinfo.handle, handle) == 0)       /* Match */
351
 
        {
352
 
          mixerdefs =
353
 
            (oss_mixext *)malloc (sizeof (*mixerdefs) * mixerinfo.nrext);
354
 
          if (mixerdefs == NULL)
355
 
            {
356
 
              fprintf (stderr, "Out of memory\n");
357
 
              exit (-1);
358
 
            }
359
 
 
360
 
          for (j = 0; j < mixerinfo.nrext; j++)
361
 
            {
362
 
              oss_mixext *ext = mixerdefs + j;
363
 
 
364
 
              ext->dev = i;
365
 
              ext->ctrl = j;
366
 
 
367
 
              if (ioctl (fd, SNDCTL_MIX_EXTINFO, ext) == -1)
368
 
                {
369
 
                  perror ("SNDCTL_MIX_EXTINFO");
370
 
                  exit (-1);
371
 
                }
372
 
            }
373
 
 
374
 
          return i;
375
 
        }
376
 
    }
377
 
 
378
 
  return -1;
379
 
}
380
 
 
381
 
static void
382
 
change_mixer (const char *fname, char *line)
383
 
{
384
 
  unsigned int value, i;
385
 
  char name[SLINELEN];
386
 
 
387
 
  if (sscanf (line, "%s %x", name, &value) != 2)
388
 
    {
389
 
      fprintf (stderr, "Bad line in %s\n", fname);
390
 
      fprintf (stderr, "%s\n", line);
391
 
    }
392
 
 
393
 
  for (i = 0; i < mixerinfo.nrext; i++)
394
 
    {
395
 
      oss_mixext *ext = mixerdefs + i;
396
 
      oss_mixer_value val;
397
 
 
398
 
      if (strcmp (ext->extname, name) == 0)
399
 
        {
400
 
 
401
 
          if (!(ext->flags & MIXF_WRITEABLE))
402
 
            continue;
403
 
 
404
 
          if (ext->type == MIXT_GROUP)
405
 
            continue;
406
 
          if (ext->type == MIXT_DEVROOT)
407
 
            continue;
408
 
          if (ext->type == MIXT_MARKER)
409
 
            continue;
410
 
 
411
 
          val.dev = ext->dev;
412
 
          val.ctrl = ext->ctrl;
413
 
          val.timestamp = ext->timestamp;
414
 
          val.value = value;
415
 
 
416
 
          if (ioctl (fd, SNDCTL_MIX_WRITE, &val) == -1)
417
 
            {
418
 
              perror ("SNDCTL_MIX_WRITE");
419
 
              fprintf (stderr, "%s (%d)=%04x\n", name, val.ctrl, value);
420
 
              continue;
421
 
            }
422
 
          return;
423
 
        }
424
 
    }
425
 
}
426
 
 
427
 
static void
428
 
load_config (const char *name)
429
 
{
430
 
  FILE *f;
431
 
  char line[SLINELEN], *s;
432
 
  int dev = -1;
433
 
 
434
 
  if (verbose) fprintf (stdout, "Loading mixer settings from %s\n", name);
435
 
#ifdef MANAGE_DEV_DSP
436
 
  reorder_dspdevs ();
437
 
#endif
438
 
#ifdef APPLIST_SUPPORT
439
 
  load_applist ();
440
 
#endif
441
 
 
442
 
  if ((f = fopen (name, "r")) == NULL)
443
 
    {
444
 
      /* Nothing to do */
445
 
      exit (0);
446
 
    }
447
 
 
448
 
  /* Remove the EOL character */
449
 
  while (fgets (line, sizeof (line), f) != NULL)
450
 
    {
451
 
 
452
 
      if ((s = strchr (line, '\n')) != NULL)
453
 
        *s = '\0';
454
 
 
455
 
      if ((*line == '\0') || (*line == '#'))
456
 
        continue;
457
 
 
458
 
      if (*line == '$')
459
 
        {
460
 
          if (strcmp (line, "$endmix") == 0)
461
 
            continue;           /* Ignore this */
462
 
 
463
 
          s = line;
464
 
 
465
 
          while (*s && *s != ' ')
466
 
            s++;
467
 
          if (*s == ' ')
468
 
            *s++ = 0;
469
 
 
470
 
          if (strcmp (line, "$startmix") != 0)
471
 
            continue;
472
 
 
473
 
          dev = find_mixerdev (s);
474
 
 
475
 
          continue;
476
 
        }
477
 
 
478
 
      if (dev < 0)              /* Unknown mixer device? */
479
 
        continue;
480
 
 
481
 
      change_mixer (name, line);
482
 
    }
483
 
 
484
 
  fclose (f);
485
 
}
486
 
 
487
 
static void
488
 
open_device (const char * dev_name, int mode)
489
 
{
490
 
  if ((fd = open (dev_name, mode, 0)) == -1)
491
 
    {
492
 
      if (errno != ENODEV)
493
 
        perror (dev_name);
494
 
      exit (-1);
495
 
    }
496
 
 
497
 
  if (ioctl (fd, SNDCTL_MIX_NRMIX, &nummixers) == -1)
498
 
    {
499
 
      perror ("SNDCTL_MIX_NRMIX");
500
 
      fprintf (stderr, "Possibly incompatible OSS version\n");
501
 
      exit (-1);
502
 
    }
503
 
 
504
 
  if (nummixers < 1)
505
 
    {
506
 
      fprintf (stderr, "No mixers in the system\n");
507
 
      exit (-1);
508
 
    }
509
 
 
510
 
}
511
 
 
512
 
int
513
 
main (int argc, char *argv[])
514
 
{
515
 
  int dev, i;
516
 
  char * mapname = NULL;
517
 
  extern char * optarg;
518
 
 
519
 
  FILE *f;
520
 
 
521
 
  while ((i = getopt (argc, argv, "LVf:v")) != EOF)
522
 
    {
523
 
      switch (i)
524
 
        {
525
 
        case 'v':
526
 
          verbose++;
527
 
          break;
528
 
 
529
 
        case 'L':
530
 
          load_settings = 1;
531
 
          break;
532
 
 
533
 
        case 'V':
534
 
          fprintf (stdout, "OSS " OSS_VERSION_STRING " savemixer utility\n");
535
 
          exit (0);
536
 
          break;
537
 
 
538
 
        case 'f':
539
 
          mapname = optarg;
540
 
          break;
541
 
 
542
 
        default:
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 "
547
 
                   "file\n");
548
 
          fprintf (stdout, "            -v           Verbose output\n");
549
 
          exit (-1);
550
 
        }
551
 
    }
552
 
 
553
 
  if (mapname == NULL) mapname = get_mapname ();
554
 
 
555
 
  if (load_settings)
556
 
    {
557
 
      open_device ("/dev/mixer", O_WRONLY);
558
 
      load_config (mapname);
559
 
      exit (0);
560
 
    }
561
 
 
562
 
  open_device ("/dev/mixer", O_RDONLY);
563
 
 
564
 
  if ((f = fopen (mapname, "w")) == NULL)
565
 
    {
566
 
      perror (mapname);
567
 
      exit (-1);
568
 
    }
569
 
  fprintf (f, "# Automatically generated by OSS savemixer - do not edit\n");
570
 
 
571
 
  if (verbose) fprintf (stdout, "Saving mixer settings to %s\n", mapname);
572
 
 
573
 
  for (dev = 0; dev < nummixers; dev++)
574
 
    {
575
 
      mixerinfo.dev = dev;
576
 
 
577
 
      if (ioctl (fd, SNDCTL_MIXERINFO, &mixerinfo) == -1)
578
 
        {
579
 
          perror ("SNDCTL_MIXERINFO");
580
 
          exit (-1);
581
 
        }
582
 
 
583
 
      fprintf (f, "\n# %s\n", mixerinfo.name);
584
 
      fprintf (f, "$startmix %s\n", mixerinfo.handle);
585
 
 
586
 
      for (i = 0; i < mixerinfo.nrext; i++)
587
 
        {
588
 
          oss_mixext ext;
589
 
          oss_mixer_value val;
590
 
 
591
 
          ext.dev = dev;
592
 
          ext.ctrl = i;
593
 
 
594
 
          if (ioctl (fd, SNDCTL_MIX_EXTINFO, &ext) == -1)
595
 
            {
596
 
              perror ("SNDCTL_MIX_EXTINFO");
597
 
              exit (-1);
598
 
            }
599
 
 
600
 
          if (!(ext.flags & MIXF_WRITEABLE))
601
 
            continue;
602
 
 
603
 
          if (ext.type == MIXT_GROUP)
604
 
            continue;
605
 
          if (ext.type == MIXT_DEVROOT)
606
 
            continue;
607
 
          if (ext.type == MIXT_MARKER)
608
 
            continue;
609
 
 
610
 
          val.dev = dev;
611
 
          val.ctrl = i;
612
 
          val.timestamp = ext.timestamp;
613
 
 
614
 
          if (ioctl (fd, SNDCTL_MIX_READ, &val) == -1)
615
 
            {
616
 
              perror ("SNDCTL_MIX_READ");
617
 
              continue;
618
 
            }
619
 
 
620
 
          fprintf (f, "%s %04x\n", ext.extname, val.value);
621
 
        }
622
 
 
623
 
      fprintf (f, "$endmix\n");
624
 
    }
625
 
  fclose (f);
626
 
 
627
 
  return 0;
628
 
}