Project

General

Profile

Bug #9732 » 08-oss4.patch

Gary Mills, 2020-09-14 09:32 PM

View differences:

pulseaudio-13.0/src/modules/oss/module-oss.c Fri Sep 11 14:44:33 2020
32 32
 *
33 33
 */
34 34

  
35
#define HAVE_OSSV4
36

  
35 37
#ifdef HAVE_CONFIG_H
36 38
#include <config.h>
37 39
#endif
......
122 124
    int mode;
123 125

  
124 126
    int mixer_fd;
127

  
128
#ifdef HAVE_OSSV4
129
    int mixer_dev;
130
    int mixer_sink_control;
131
    int mixer_source_control;
132
    int mixer_cmax;
133
    int mixer_dsp_fd;
134
    oss_mixext sink_mixext;
135
    oss_mixext source_mixext;
136
#else
125 137
    int mixer_devmask;
138
#endif
126 139

  
127 140
    int nfrags, frag_size, orig_frag_size;
128 141

  
......
197 210
    } else {
198 211

  
199 212
        if (enable_bits)
213
#ifdef HAVE_OSSV4
214
            if (ioctl(u->fd, SNDCTL_DSP_SYNC, NULL) < 0)
215
                pa_log_warn("SNDCTL_DSP_SYNC: %s", pa_cstrerror(errno));
216
#else
200 217
            if (ioctl(u->fd, SNDCTL_DSP_POST, NULL) < 0)
201 218
                pa_log_warn("SNDCTL_DSP_POST: %s", pa_cstrerror(errno));
219
#endif
202 220

  
203 221
        if (!quick) {
204 222
            /*
......
817 835
    return 0;
818 836
}
819 837

  
838
#ifdef HAVE_OSSV4
839

  
840
static const char *
841
mixer_ext_type_get_name (int type)
842
{
843
    switch (type) {
844
        case MIXT_DEVROOT:
845
            return "Device root entry";
846
        case MIXT_GROUP:
847
            return "Controller group";
848
        case MIXT_ONOFF:
849
            return "On/Off switch";
850
        case MIXT_ENUM:
851
            return "Enumeration control";
852
        case MIXT_MONOSLIDER:
853
            return "Mono slider (0-255)";
854
        case MIXT_STEREOSLIDER:
855
            return "Stereo slider (0-255)";
856
        case MIXT_MESSAGE:
857
            return "Textual message";
858
        case MIXT_MONOVU:
859
            return "Mono VU meter value";
860
        case MIXT_STEREOVU:
861
            return "Stereo VU meter value";
862
        case MIXT_MONOPEAK:
863
            return "Mono VU meter peak value";
864
        case MIXT_STEREOPEAK:
865
            return "Stereo VU meter peak value";
866
        case MIXT_RADIOGROUP:
867
            return "Radio button group";
868
        case MIXT_MARKER:
869
            /* Separator between normal and extension entries */
870
            return "Separator";
871
        case MIXT_VALUE:
872
            return "Decimal value entry";
873
        case MIXT_HEXVALUE:
874
            return "Hex value entry";
875
        case MIXT_SLIDER:
876
            return "Mono slider (31-bit value range)";
877
        case MIXT_3D:
878
            return "3D";
879
        case MIXT_MONOSLIDER16:
880
            return "Mono slider (0-32767)";
881
        case MIXT_STEREOSLIDER16:
882
            return "Stereo slider (0-32767)";
883
        case MIXT_MUTE:
884
            return "Mute switch";
885
        default:
886
            break;
887
    }
888

  
889
    return "Unknown";
890
}
891

  
892
void
893
mixer_showflags (int flags)
894
{
895
    struct
896
    {
897
        int flag;
898
        char nick[16];
899
    } all_flags[] = {
900
        /* first the important ones */
901
        {
902
        MIXF_MAINVOL, "MAINVOL"}, {
903
        MIXF_PCMVOL, "PCMVOL"}, {
904
        MIXF_RECVOL, "RECVOL"}, {
905
        MIXF_MONVOL, "MONVOL"}, {
906
        MIXF_DESCR, "DESCR"},
907

  
908
        /* now the rest in the right order */
909
        {
910
        MIXF_READABLE, "READABLE"}, {
911
        MIXF_WRITEABLE, "WRITABLE"}, {
912
        MIXF_POLL, "POLL"}, {
913
        MIXF_HZ, "HZ"}, {
914
        MIXF_STRING, "STRING"}, {
915
        MIXF_DYNAMIC, "DYNAMIC"}, {
916
        MIXF_OKFAIL, "OKFAIL"}, {
917
        MIXF_FLAT, "FLAT"}, {
918
        MIXF_LEGACY, "LEGACY"}, {
919
        MIXF_CENTIBEL, "CENTIBEL"}, {
920
        MIXF_DECIBEL, "DECIBEL"}, {
921
        MIXF_WIDE, "WIDE"}
922
    };
923
    int num_flags = (sizeof (all_flags) / sizeof ((all_flags)[0]));
924
    int i;
925

  
926
    if (flags == 0) {
927
        pa_log_debug ("  flags  : None");
928
        return;
929
    }
930

  
931
    for (i=0; i < num_flags; i++) {
932
        if ((flags & all_flags[i].flag)) {
933
            pa_log_debug ("  flag   : %s", all_flags[i].nick);
934
            flags &= ~all_flags[i].flag;      /* unset */
935
        }
936
    }
937

  
938
    /* Unknown flags? */
939
    if (flags != 0) {
940
        pa_log_debug ("  flag   : ????");
941
    }
942

  
943
    return;
944
}
945

  
820 946
static void sink_get_volume(pa_sink *s) {
821 947
    struct userdata *u;
822 948

  
823 949
    pa_assert_se(u = s->userdata);
824 950

  
951
    if (pa_oss_get_volume(u->mixer_dsp_fd, &(u->sink_mixext), &s->sample_spec, &s->real_volume) >= 0)
952
        return;
953

  
954
    pa_log_info("Device doesn't support reading mixer settings: %s", pa_cstrerror(errno));
955
}
956

  
957
static void sink_set_volume(pa_sink *s) {
958
    struct userdata *u;
959

  
960
    pa_assert_se(u = s->userdata);
961

  
962
    if (pa_oss_set_volume(u->mixer_dsp_fd, &(u->sink_mixext), &s->sample_spec, &s->real_volume) >= 0)
963
        return;
964

  
965
    pa_log_info("Device doesn't support writing mixer settings: %s", pa_cstrerror(errno));
966
}
967

  
968
static void source_get_volume(pa_source *s) {
969
    struct userdata *u;
970

  
971
    pa_assert_se(u = s->userdata);
972

  
973
    if (pa_oss_get_volume(u->mixer_dsp_fd, &(u->source_mixext), &s->sample_spec, &s->real_volume) >= 0)
974
        return;
975

  
976
    pa_log_info("Device doesn't support reading mixer settings: %s", pa_cstrerror(errno));
977
}
978

  
979
static void source_set_volume(pa_source *s) {
980
    struct userdata *u;
981

  
982
    pa_assert_se(u = s->userdata);
983

  
984
    if (pa_oss_set_volume(u->mixer_dsp_fd, &(u->source_mixext), &s->sample_spec, &s->real_volume) >= 0)
985
        return;
986

  
987
    pa_log_info("Device doesn't support writing mixer settings: %s", pa_cstrerror(errno));
988
}
989

  
990
#else
991

  
992
static void sink_get_volume(pa_sink *s) {
993
    struct userdata *u;
994

  
995
    pa_assert_se(u = s->userdata);
996

  
825 997
    pa_assert(u->mixer_devmask & (SOUND_MASK_VOLUME|SOUND_MASK_PCM));
826 998

  
827 999
    if (u->mixer_devmask & SOUND_MASK_VOLUME)
......
888 1060

  
889 1061
    pa_log_info("Device doesn't support writing mixer settings: %s", pa_cstrerror(errno));
890 1062
}
1063
#endif
891 1064

  
892 1065
static void thread_func(void *userdata) {
893 1066
    struct userdata *u = userdata;
......
1170 1343

  
1171 1344
int pa__init(pa_module*m) {
1172 1345

  
1346
#ifdef HAVE_OSSV4
1347
    struct oss_sysinfo si = { {0,}, };
1348
    struct oss_mixerinfo mi = { 0, };
1349
#endif
1350

  
1173 1351
    struct audio_buf_info info;
1174 1352
    struct userdata *u = NULL;
1175 1353
    const char *dev;
......
1267 1445
    m->userdata = u;
1268 1446
    u->fd = fd;
1269 1447
    u->mixer_fd = -1;
1448
#ifndef HAVE_OSSV4
1270 1449
    u->mixer_devmask = 0;
1450
#endif
1271 1451
    u->use_getospace = u->use_getispace = true;
1272 1452
    u->use_getodelay = true;
1273 1453
    u->mode = mode;
......
1441 1621
    if ((u->mixer_fd = pa_oss_open_mixer_for_device(u->device_name)) >= 0) {
1442 1622
        bool do_close = true;
1443 1623

  
1624
#ifdef HAVE_OSSV4
1625
#define IGNORE_DEV 1
1626
        int i;
1627

  
1628
        u->mixer_dsp_fd = -1;
1629

  
1630
        if (ioctl (u->mixer_fd, SNDCTL_SYSINFO, &si) < 0) {
1631
            pa_log_debug ("SNDCTL_SYSINFO failed");
1632
            goto fail;
1633
        }
1634

  
1635
	i = pa_oss_get_device_number(u->device_name);
1636
	if (i >= 0 && i < si.nummixers) {
1637
            mi.dev = i;
1638
            if (ioctl (u->mixer_fd, SNDCTL_MIXERINFO, &mi) < 0) {
1639
                pa_log_debug("SNDCTL_MIXERINFO failed");
1640
                goto fail;
1641
            }
1642
        }
1643

  
1644
        if (i < si.nummixers) {
1645
            struct stat sbuf;
1646

  
1647
            if ((stat(mi.devnode, &sbuf) != 0) ||
1648
                ((sbuf.st_mode & S_IFCHR) == 0)) {
1649
                pa_log("Failed to get mixer dsp device.");
1650
                i = si.nummixers;
1651
            }
1652
        }
1653

  
1654
        if (i < si.nummixers &&
1655
           (u->mixer_dsp_fd = pa_oss_open_mixer(mi.devnode)) >= 0) {
1656

  
1657
            /* Will cause for loop to exit if not filled in by OSS */
1658
            u->mixer_cmax = -1;
1659
            if (ioctl(u->mixer_dsp_fd, SNDCTL_MIX_NREXT, &u->mixer_cmax) < 0) {
1660
                pa_log("Failed to get max control.");
1661
                goto fail;
1662
            }
1663

  
1664
            pa_log_debug ("Opened mixer device %d with %d controls\n",
1665
                          mi.dev, mi.nrext);
1666

  
1667
            u->mixer_sink_control   = -1;
1668
            u->mixer_source_control = -1;
1669

  
1670
            for (i=0; i < u->mixer_cmax; i++) {
1671
                memset (&(u->sink_mixext), 0, sizeof (oss_mixext));
1672

  
1673
#ifdef IGNORE_DEV
1674
                /* This will cause dev to be ignored */
1675
                u->sink_mixext.dev = -1;
1676
#else
1677
                u->sink_mixext.dev = mi.dev;
1678
#endif
1679

  
1680
                /*
1681
                 * The real way to pick a control on a mixer is with this
1682
                 * number.  Note that control numbers are unique across all
1683
                 * mixers. So dev can just be ignored.  When dev is included
1684
                 * it will only be used to check for correct dev from
1685
                 * userland.  But it will not be used to select a mixer.
1686
                 */
1687
                u->sink_mixext.ctrl = i;
1688

  
1689
                pa_log_debug ("Control %d", u->sink_mixext.ctrl);
1690

  
1691
                if (ioctl (u->mixer_dsp_fd, SNDCTL_MIX_EXTINFO,
1692
                         &(u->sink_mixext)) < 0) {
1693
                    pa_log_debug ("SNDCTL_MIX_EXTINFO failed");
1694
                    continue;
1695
                }
1696

  
1697
                pa_log_debug ("  name   : %s", u->sink_mixext.extname);
1698
                pa_log_debug ("  type   : %s (%d)",
1699
                              mixer_ext_type_get_name (u->sink_mixext.type),
1700
                              u->sink_mixext.type);
1701
                pa_log_debug ("  maxval : %d", u->sink_mixext.maxvalue);
1702
                pa_log_debug ("  parent : %d", u->sink_mixext.parent);
1703
                mixer_showflags (u->sink_mixext.flags);
1704

  
1705
                if ((u->sink_mixext.flags & MIXF_PCMVOL)) {
1706
                    pa_log_debug ("First PCM control: %d", i);
1707
                    u->mixer_sink_control = i;
1708
                    break;
1709
                }
1710

  
1711
                /*
1712
                 * Note that MIXF_MAINVOL may not be an exclusive single
1713
                 * control.  For example on AudioHD there will be one for each
1714
                 * output jack (Green, Black, Orange...).  So to really do a
1715
                 * master volume you would need to do all MIXF_MAINVOL at the
1716
                 * same time...
1717
                 */
1718
                if (((u->sink_mixext.flags & MIXF_MAINVOL)) &&
1719
                      u->mixer_sink_control == -1) {
1720
                    pa_log_debug ("First main volume control: %d", i);
1721
                    u->mixer_sink_control = i;
1722
                }
1723
            }
1724

  
1725
            if (u->mixer_sink_control != -1) {
1726
                pa_log_debug ("Setting OSS sink callbacks.");
1727
                pa_sink_set_get_volume_callback(u->sink, sink_get_volume);
1728
                pa_sink_set_set_volume_callback(u->sink, sink_set_volume);
1729
                u->sink->n_volume_steps = 101;
1730
                do_close = false;
1731
            } else {
1732
                pa_log_debug ("Not setting OSS sink callbacks.");
1733
            }
1734

  
1735
            for (i=0; i < mi.nrext; i++) {
1736
                memset (&(u->source_mixext), 0, sizeof (oss_mixext));
1737
#ifdef IGNORE_DEV
1738
                /* This will cause dev to be ignored */
1739
                u->source_mixext.dev = -1;
1740
#else
1741
                u->source_mixext.dev = mi.dev;
1742
#endif
1743
                /*
1744
                 * The real way to pick a control on a mixer is with this
1745
                 * number.  Note that control numbers are unique across all
1746
                 * mixers.  So dev can just be ignored.  When dev is included
1747
                 * it will only be used to check for correct dev from userland.
1748
                 * But it will not be used to select a mixer.
1749
                 */
1750
                u->source_mixext.ctrl = i;
1751

  
1752
                pa_log_debug ("Control %d", u->source_mixext.ctrl);
1753

  
1754
                if (ioctl (u->mixer_dsp_fd, SNDCTL_MIX_EXTINFO,
1755
                         &(u->source_mixext)) == -1) {
1756
                    pa_log_debug ("SNDCTL_MIX_EXTINFO failed");
1757
                    continue;
1758
                }
1759

  
1760
                pa_log_debug ("  name   : %s", u->source_mixext.extname);
1761
                pa_log_debug ("  type   : %s (%d)",
1762
                              mixer_ext_type_get_name (u->source_mixext.type),
1763
                              u->source_mixext.type);
1764
                pa_log_debug ("  maxval : %d", u->source_mixext.maxvalue);
1765
                pa_log_debug ("  parent : %d", u->source_mixext.parent);
1766
                mixer_showflags (u->source_mixext.flags);
1767

  
1768
                /*
1769
                 * There may be more then one MIXF_RECVOL on a mixer.  In fact
1770
                 * for audioHD the can be three (line-in, mix-in, and cd-in).
1771
                 * For a master gain it may be good to adjust all...
1772
                 */
1773
                if ((u->source_mixext.flags & MIXF_RECVOL)) {
1774
                    pa_log_debug ("First REC control: %d", i);
1775
                    u->mixer_source_control = i;
1776
                    break;
1777
                }
1778
            }
1779

  
1780
            if (u->mixer_source_control != -1) {
1781
                pa_log_debug ("Setting OSS source callbacks.");
1782
                pa_source_set_get_volume_callback(u->source, source_get_volume);
1783
                pa_source_set_set_volume_callback(u->source, source_set_volume);
1784
                u->source->n_volume_steps = 101;
1785
                do_close = false;
1786
            } else {
1787
                pa_log_debug ("Not setting OSS source callbacks.");
1788
            }
1789

  
1790
            if (do_close == true) {
1791
                pa_close(u->mixer_dsp_fd);
1792
                u->mixer_dsp_fd = -1;
1793
            }
1794
        }
1795

  
1796
#else
1444 1797
        if (ioctl(u->mixer_fd, SOUND_MIXER_READ_DEVMASK, &u->mixer_devmask) < 0)
1445 1798
            pa_log_warn("SOUND_MIXER_READ_DEVMASK failed: %s", pa_cstrerror(errno));
1446 1799
        else {
......
1460 1813
                do_close = false;
1461 1814
            }
1462 1815
        }
1816
#endif
1463 1817

  
1464 1818
        if (do_close) {
1465 1819
            pa_close(u->mixer_fd);
1466 1820
            u->mixer_fd = -1;
1821
#ifndef HAVE_OSSV4
1467 1822
            u->mixer_devmask = 0;
1823
#endif
1468 1824
        }
1469 1825
    }
1470 1826

  
......
1583 1939
    if (u->fd >= 0)
1584 1940
        pa_close(u->fd);
1585 1941

  
1942
#ifdef HAVE_OSSV4
1943
    if (u->mixer_dsp_fd >= 0)
1944
        pa_close(u->mixer_dsp_fd);
1945
#endif
1586 1946
    if (u->mixer_fd >= 0)
1587 1947
        pa_close(u->mixer_fd);
1588 1948

  
1589
-- pulseaudio-13.0/src/modules/oss/oss-util.c-orig	Fri Jul 13 14:06:14 2018
1949
++ pulseaudio-13.0/src/modules/oss/oss-util.c	Tue Sep  8 10:19:33 2020
......
246 246
    return 0;
247 247
}
248 248

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

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

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

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

  
286
      val = ((rval & 0xffff) << 16) | (lval & 0xffff);
287

  
288
      break;
289

  
290
    default:
291
      return 0;
292
  }
293

  
294
  return val;
295
}
296

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

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

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

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

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

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

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

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

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

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

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

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

  
411
  pa_cvolume_reset(volume, ss->channels);
412

  
413
  oss4_mixer_slider_unpack_volume (mixext, v, volume);
414

  
415
  return 0;
416
}
417

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

  
421
  val = oss4_mixer_slider_pack_volume (mixext, ss->channels, volume);
422

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

  
428
  return 0;
429
}
430

  
431
#else
432

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

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

  
297
    if (!(p = rp = pa_readlink(dev))) {
482
    p = strchr(dev, '\0') - 1;
483

  
484
    if (*p >= '0' && *p <= '9') {
485
        p = dev;
486
    }
487
    else {
488
        /* We need to resolve the symlink */
489
        if (!(p = rp = pa_readlink(dev))) {
298 490
#ifdef ENOLINK
299
        if (errno != EINVAL && errno != ENOLINK) {
491
            if (errno != EINVAL && errno != ENOLINK) {
300 492
#else
301
        if (errno != EINVAL) {
493
            if (errno != EINVAL) {
302 494
#endif
303
            r = -1;
304
            goto finish;
305
        }
495
                r = -1;
496
                goto finish;
497
            }
306 498

  
307
        p = dev;
499
        }
308 500
    }
309 501

  
310
    if ((e = strrchr(p, '/')))
311
        p = e+1;
502
    p = strchr(p, '\0') - 1;
312 503

  
313
    if (p == 0) {
314
        r = 0;
315
        goto finish;
316
    }
317

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

  
320 504
    if (*p >= '0' && *p <= '9') {
321 505
        r = *p - '0';
322 506
        goto finish;
......
329 513
    return r;
330 514
}
331 515

  
516
int pa_oss_get_device_number(const char *dev) {
517
    return (get_device_number(dev));
518
}
519

  
332 520
int pa_oss_get_hw_description(const char *dev, char *name, size_t l) {
333 521
    FILE *f;
334 522
    int n, r = -1;
......
357 545
        line[strcspn(line, "\r\n")] = 0;
358 546

  
359 547
        if (!b) {
360
            b = pa_streq(line, "Audio devices:");
548
            b = pa_streq(line, "Audio Devices:");
361 549
            continue;
362 550
        }
363 551

  
......
386 574
    return r;
387 575
}
388 576

  
389
static int open_mixer(const char *mixer) {
577
int pa_oss_open_mixer(const char *mixer) {
390 578
    int fd;
391 579

  
580
    pa_log_debug ("Opening device %s", mixer);
581

  
392 582
    if ((fd = pa_open_cloexec(mixer, O_RDWR|O_NDELAY, 0)) >= 0)
393 583
        return fd;
394 584

  
......
400 590
    char *fn;
401 591
    int fd;
402 592

  
403
    if ((n = get_device_number(device)) < 0)
593
    if ((n = get_device_number(device)) < 0) {
594
        pa_log_warn ("Cannot find number for device '%s'", device);
404 595
        return -1;
596
    }
405 597

  
406
    if (n == 0)
407
        if ((fd = open_mixer("/dev/mixer")) >= 0)
408
            return fd;
409

  
410 598
    fn = pa_sprintf_malloc("/dev/mixer%i", n);
411
    fd = open_mixer(fn);
599
    fd = pa_oss_open_mixer(fn);
412 600
    pa_xfree(fn);
413 601

  
414 602
    if (fd < 0)
415
-- pulseaudio-13.0/src/modules/oss/oss-util.h-orig	Fri Jul 13 14:06:14 2018
603
++ pulseaudio-13.0/src/modules/oss/oss-util.h	Tue Sep  8 11:08:51 2020
......
29 29

  
30 30
int pa_oss_set_fragments(int fd, int frags, int frag_size);
31 31

  
32
#define HAVE_OSSV4
33

  
34
#ifdef HAVE_OSSV4
35
int pa_oss_set_volume(int fd, oss_mixext *mixext, const pa_sample_spec *ss, const pa_cvolume *volume);
36
int pa_oss_get_volume(int fd, oss_mixext *mixext, const pa_sample_spec *ss, pa_cvolume *volume);
37

  
38
#else
39

  
32 40
int pa_oss_set_volume(int fd, unsigned long mixer, const pa_sample_spec *ss, const pa_cvolume *volume);
33 41
int pa_oss_get_volume(int fd, unsigned long mixer, const pa_sample_spec *ss, pa_cvolume *volume);
42
#endif
34 43

  
35 44
int pa_oss_get_hw_description(const char *dev, char *name, size_t l);
36 45

  
46
int pa_oss_get_device_number(const char *dev);
37 47
int pa_oss_open_mixer_for_device(const char *device);
48
int pa_oss_open_mixer(const char *device);
38 49

  
39 50
#endif
(8-8/11)