Project

General

Profile

Bug #9732 » 11-oss-util.patch

Gary Mills, 2018-08-13 09:09 PM

View differences:

pulseaudio-11.1/src/modules/oss/oss-util.c Wed Aug 8 17:21:50 2018
39 39

  
40 40
#include "oss-util.h"
41 41

  
42
static int pa_oss_open_dsp_for_device(const char *fn, int flags, mode_t cmode);
43

  
42 44
int pa_oss_open(const char *device, int *mode, int* pcaps) {
43 45
    int fd = -1;
44 46
    int caps;
......
52 54
        pcaps = ∩︀
53 55

  
54 56
    if (*mode == O_RDWR) {
55
        if ((fd = pa_open_cloexec(device, O_RDWR|O_NDELAY, 0)) >= 0) {
57
        if ((fd = pa_oss_open_dsp_for_device(device, O_RDWR|O_NDELAY, 0)) >= 0) {
56 58
            ioctl(fd, SNDCTL_DSP_SETDUPLEX, 0);
57 59

  
58 60
            if (ioctl(fd, SNDCTL_DSP_GETCAPS, pcaps) < 0) {
......
68 70
            pa_close(fd);
69 71
        }
70 72

  
71
        if ((fd = pa_open_cloexec(device, (*mode = O_WRONLY)|O_NDELAY, 0)) < 0) {
72
            if ((fd = pa_open_cloexec(device, (*mode = O_RDONLY)|O_NDELAY, 0)) < 0) {
73
        if ((fd = pa_oss_open_dsp_for_device(device, (*mode = O_WRONLY)|O_NDELAY, 0)) < 0) {
74
            if ((fd = pa_oss_open_dsp_for_device(device, (*mode = O_RDONLY)|O_NDELAY, 0)) < 0) {
73 75
                pa_log("open('%s'): %s", device, pa_cstrerror(errno));
74 76
                goto fail;
75 77
            }
76 78
        }
77 79
    } else {
78
        if ((fd = pa_open_cloexec(device, *mode|O_NDELAY, 0)) < 0) {
80
        if ((fd = pa_oss_open_dsp_for_device(device, *mode|O_NDELAY, 0)) < 0) {
79 81
            pa_log("open('%s'): %s", device, pa_cstrerror(errno));
80 82
            goto fail;
81 83
        }
......
246 248
    return 0;
247 249
}
248 250

  
251
#ifdef HAVE_OSSV4
252
static int
253
oss4_mixer_slider_pack_volume (oss_mixext *mixext, int channels, const pa_cvolume *volume)
254
{
255
  int val  = 0;
256
  int lvol = 0;
257
  int rvol = 0;
258
  int lval = 0;
259
  int rval = 0;
260

  
261
  switch (mixext->type) {
262
    case MIXT_MONOSLIDER:
263
    case MIXT_MONOSLIDER16:
264
    case MIXT_SLIDER:
265
      lvol = volume->values[0] > PA_VOLUME_NORM ? PA_VOLUME_NORM : volume->values[0];
266
      val = (lvol*mixext->maxvalue)/PA_VOLUME_NORM;
267
      break;
268

  
269
    case MIXT_STEREOSLIDER:
270
      lvol = volume->values[0] > PA_VOLUME_NORM ? PA_VOLUME_NORM : volume->values[0];
271
      lval = (lvol*mixext->maxvalue)/PA_VOLUME_NORM;
272
      if (channels >= 2) {
273
          rvol = volume->values[1] > PA_VOLUME_NORM ? PA_VOLUME_NORM : volume->values[1];
274
          rval = (rvol*mixext->maxvalue)/PA_VOLUME_NORM;
275
      }
276
     
277
      val = ((rval & 0xff) << 8) | (lval & 0xff);
278
      break;
279

  
280
    case MIXT_STEREOSLIDER16:
281
      lvol = volume->values[0] > PA_VOLUME_NORM ? PA_VOLUME_NORM : volume->values[0];
282
      lval = (lvol*mixext->maxvalue)/PA_VOLUME_NORM;
283
      if (channels >= 2) {
284
          rvol = volume->values[1] > PA_VOLUME_NORM ? PA_VOLUME_NORM : volume->values[1];
285
          rval = (rvol*mixext->maxvalue)/PA_VOLUME_NORM;
286
      }
287

  
288
      val = ((rval & 0xffff) << 16) | (lval & 0xffff);
289

  
290
      break;
291

  
292
    default:
293
      return 0;
294
  }
295

  
296
  return val;
297
}
298

  
299
static void
300
oss4_mixer_slider_unpack_volume (oss_mixext *mixext, int v, pa_cvolume * volume)
301
{
302
  uint32_t val, vol;
303

  
304
  val = (uint32_t) v;
305
  switch (mixext->type) {
306
    case MIXT_SLIDER:
307
      vol = val;
308
      volume->values[0] = PA_CLAMP_VOLUME((vol * PA_VOLUME_NORM) / mixext->maxvalue);
309
      if (volume->channels >= 2) {
310
          volume->values[1] = volume->values[0];
311
      }
312
      break;
313
    case MIXT_MONOSLIDER:
314
      /* oss repeats the value in the upper bits, as if it was stereo */
315
      vol = val & 0x00ff;
316
      volume->values[0] = PA_CLAMP_VOLUME((vol * PA_VOLUME_NORM) / mixext->maxvalue);
317
      if (volume->channels >= 2) {
318
          volume->values[1] = volume->values[0];
319
      }
320
      break;
321
    case MIXT_MONOSLIDER16:
322
      /* oss repeats the value in the upper bits, as if it was stereo */
323
      vol = val & 0x0000ffff;
324
      volume->values[0] = PA_CLAMP_VOLUME((vol * PA_VOLUME_NORM) / mixext->maxvalue);
325
      if (volume->channels >= 2) {
326
          volume->values[1] = volume->values[0];
327
      }
328
      break;
329
    case MIXT_STEREOSLIDER:
330
      vol = (val & 0x00ff);
331
      volume->values[0] = PA_CLAMP_VOLUME((vol * PA_VOLUME_NORM) / mixext->maxvalue);
332
      if (volume->channels >= 2) {
333
          vol = (val & 0xff00) >> 8;
334
          volume->values[1] = PA_CLAMP_VOLUME((vol * PA_VOLUME_NORM) / mixext->maxvalue);
335
      }
336
      break;
337
    case MIXT_STEREOSLIDER16:
338
      vol = (val & 0x0000ffff);
339
      volume->values[0] = PA_CLAMP_VOLUME((vol * PA_VOLUME_NORM) / mixext->maxvalue);
340
      if (volume->channels >= 2) {
341
          vol = (val & 0xffff0000) >> 16;
342
          volume->values[1] = PA_CLAMP_VOLUME((vol * PA_VOLUME_NORM) / mixext->maxvalue);
343
      }
344
      break;
345
    default:
346
      return;
347
  }
348
}
349

  
350
static int
351
oss4_mixer_get_control_val (int fd, oss_mixext *mixext, int *val)
352
{
353
  oss_mixer_value ossval = { 0, };
354

  
355
  /* ossval.dev = mixext->dev; */
356
  ossval.dev = -1;		/* if -1 on entry then is ignored */
357
  /*
358
   * The real way to pick a control on a mixer is with this number.
359
   * Note that control numbers are uniq across all mixers. So dev
360
   * can just be ignored. When dev is included it will only be used
361
   * to check for correct dev from userland. But it will not be used
362
   * to select a mixer.
363
   */
364
  ossval.ctrl = mixext->ctrl;
365
  ossval.timestamp = mixext->timestamp;
366

  
367
  if (ioctl (fd, SNDCTL_MIX_READ, &ossval) == -1) {
368
    pa_log_debug ("SNDCTL_MIX_READ failed");
369
    *val = 0;
370
    return -1;
371
  }
372

  
373
  *val = ossval.value;
374
  pa_log_debug ("got value 0x%08x from %s", *val, mixext->extname);
375
  return 0;
376
}
377

  
378
static int
379
oss4_mixer_set_control_val (int fd, oss_mixext *mixext, int val)
380
{
381
  oss_mixer_value ossval = { 0, };
382

  
383
  /* ossval.dev = mixext->dev; */
384
  ossval.dev = -1;		/* if -1 on entry then is ignored */
385
  /*
386
   * The real way to pick a control on a mixer is with this number.
387
   * Note that control numbers are uniq across all mixers. So dev
388
   * can just be ignored. When dev is included it will only be used
389
   * to check for correct dev from userland. But it will not be used
390
   * to select a mixer.
391
   */
392
  ossval.ctrl = mixext->ctrl;
393
  ossval.timestamp = mixext->timestamp;
394
  ossval.value = val;
395

  
396
  if (ioctl (fd, SNDCTL_MIX_WRITE, &ossval) == -1) {
397
    pa_log_debug ("SNDCTL_MIX_WRITE failed");
398
    return -1;
399
  }
400

  
401
  pa_log_debug ("set value 0x%08x on %s", val, mixext->extname);
402
  return 0;
403
}
404

  
405
int pa_oss_get_volume(int fd, oss_mixext *mixext, const pa_sample_spec *ss, pa_cvolume *volume) {
406
  int v = 0;
407

  
408
  if (oss4_mixer_get_control_val (fd, mixext, &v) != 0) {
409
    pa_log_debug ("Getting volume failed");
410
    return -1;
411
  }
412

  
413
  pa_cvolume_reset(volume, ss->channels);
414

  
415
  oss4_mixer_slider_unpack_volume (mixext, v, volume);
416

  
417
  return 0;
418
}
419

  
420
int pa_oss_set_volume(int fd, oss_mixext *mixext, const pa_sample_spec *ss, const pa_cvolume *volume) {
421
  int val = 0;
422

  
423
  val = oss4_mixer_slider_pack_volume (mixext, ss->channels, volume);
424

  
425
  if (oss4_mixer_set_control_val (fd, mixext, val) != 0) {
426
    pa_log_debug ("Setting volume failed");
427
    return -1;
428
  }
429

  
430
  return 0;
431
}
432

  
433
#else
434

  
249 435
int pa_oss_get_volume(int fd, unsigned long mixer, const pa_sample_spec *ss, pa_cvolume *volume) {
250 436
    char cv[PA_CVOLUME_SNPRINT_VERBOSE_MAX];
251 437
    unsigned vol;
......
288 474
    pa_log_debug("Wrote mixer settings: %s", pa_cvolume_snprint(cv, sizeof(cv), volume));
289 475
    return 0;
290 476
}
477
#endif
291 478

  
292 479
static int get_device_number(const char *dev) {
293
    const char *p, *e;
480
    const char *p;
294 481
    char *rp = NULL;
295
    int r;
482
    int r, n;
296 483

  
484
    pa_log_debug ("Finding number for device %s", dev);
485

  
486
#ifdef HAVE_SOLARIS
487
    /* Ensure there is a trailing digit */
488
    if ((n = (strlen(dev) - 1)) < 0) {
489
        r = -1;
490
        goto finish;
491
    }
492
    p = dev + n;
493
    if (*p >= '0' && *p <= '9') {
494
        p = dev;
495
    }
496
    else {
497
        if (!(p = rp = pa_readlink(dev))) {
498
            r = -1;
499
            goto finish;
500
        }
501
    }
502
#else /* HAVE_SOLARIS */
297 503
    if (!(p = rp = pa_readlink(dev))) {
298 504
#ifdef ENOLINK
299 505
        if (errno != EINVAL && errno != ENOLINK) {
......
306 512

  
307 513
        p = dev;
308 514
    }
515
#endif /* HAVE_SOLARIS */
309 516

  
310
    if ((e = strrchr(p, '/')))
311
        p = e+1;
517
    if ((n = (strlen(p) - 1)) < 0) {
518
        r = -1;
519
        goto finish;
520
    }
521
    p += n;
312 522

  
313
    if (p == 0) {
523
    if (*p == '/') {
314 524
        r = 0;
315 525
        goto finish;
316 526
    }
317 527

  
318
    p = strchr(p, 0) -1;
319

  
320 528
    if (*p >= '0' && *p <= '9') {
321 529
        r = *p - '0';
322 530
        goto finish;
......
357 565
        line[strcspn(line, "\r\n")] = 0;
358 566

  
359 567
        if (!b) {
360
            b = pa_streq(line, "Audio devices:");
568
            b = pa_streq(line, "Audio Devices:");
361 569
            continue;
362 570
        }
363 571

  
......
386 594
    return r;
387 595
}
388 596

  
389
static int open_mixer(const char *mixer) {
597
static int pa_oss_open_dsp(const char *dsp, int flags, mode_t cmode) {
390 598
    int fd;
391 599

  
600
    pa_log_debug ("Opening dsp device %s", dsp);
601

  
602
    if ((fd = pa_open_cloexec(dsp, flags, cmode)) >= 0)
603
        return fd;
604

  
605
    return -1;
606
}
607

  
608
static int pa_oss_open_dsp_for_device(const char *device, int flags, mode_t cmode) {
609
    int n;
610
    char *fn;
611
    int fd;
612

  
613
    if ((n = get_device_number(device)) < 0) {
614
        pa_log_debug ("Cannot find number for device %s", device);
615
        return -1;
616
    }
617

  
618
#ifndef HAVE_SOLARIS
619
    if (n == 0)
620
        if ((fd = pa_oss_open_dsp("/dev/dsp", flags, cmode)) >= 0)
621
            return fd;
622
#endif /* HAVE_SOLARIS */
623

  
624
    fn = pa_sprintf_malloc("/dev/dsp%i", n);
625
    fd = pa_oss_open_dsp(fn, flags, cmode);
626
    pa_xfree(fn);
627

  
628
    if (fd < 0)
629
        pa_log_warn("Failed to open dsp for '%s': %s", device, pa_cstrerror(errno));
630

  
631
    return fd;
632
}
633

  
634
int pa_oss_open_mixer(const char *mixer) {
635
    int fd;
636

  
637
    pa_log_debug ("Opening mixer device %s", mixer);
638

  
392 639
    if ((fd = pa_open_cloexec(mixer, O_RDWR|O_NDELAY, 0)) >= 0)
393 640
        return fd;
394 641

  
395 642
    return -1;
396 643
}
397 644

  
398
int pa_oss_open_mixer_for_device(const char *device) {
645
int pa_oss_open_mixer_for_device(const char *device, int *number) {
399 646
    int n;
400 647
    char *fn;
401 648
    int fd;
402 649

  
403
    if ((n = get_device_number(device)) < 0)
650
    if ((n = get_device_number(device)) < 0) {
651
        pa_log_debug ("Cannot find number for device %s", device);
404 652
        return -1;
653
    }
405 654

  
655
    if (number != NULL) *number = n;
656

  
657
#ifndef HAVE_SOLARIS
406 658
    if (n == 0)
407
        if ((fd = open_mixer("/dev/mixer")) >= 0)
659
        if ((fd = pa_oss_open_mixer("/dev/mixer")) >= 0)
408 660
            return fd;
661
#endif /* HAVE_SOLARIS */
409 662

  
410 663
    fn = pa_sprintf_malloc("/dev/mixer%i", n);
411
    fd = open_mixer(fn);
664
    fd = pa_oss_open_mixer(fn);
412 665
    pa_xfree(fn);
413 666

  
414 667
    if (fd < 0)
415
        pa_log_warn("Failed to open mixer '%s': %s", device, pa_cstrerror(errno));
668
        pa_log_warn("Failed to open mixer for '%s': %s", device, pa_cstrerror(errno));
416 669

  
417 670
    return fd;
418 671
}
(3-3/11)