Project

General

Profile

Bug #9732 » 14-module-oss.patch

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

View differences:

pulseaudio-11.1/src/modules/oss/module-oss.c Wed Aug 8 17:27:45 2018
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
......
96 98
PA_MODULE_DEPRECATED("Please use module-alsa-card instead of module-oss!");
97 99
#endif
98 100

  
101
#ifdef HAVE_SOLARIS
102
#define DEFAULT_DEVICE "/dev/audio"
103
#else
99 104
#define DEFAULT_DEVICE "/dev/dsp"
105
#endif /* HAVE_SOLARIS */
100 106

  
101 107
struct userdata {
102 108
    pa_core *core;
......
123 129
    int mode;
124 130

  
125 131
    int mixer_fd;
132

  
133
#ifdef HAVE_OSSV4
134
    int mixer_dev;
135
    int mixer_sink_control;
136
    int mixer_source_control;
137
    int mixer_cmax;
138
    int mixer_dsp_fd;
139
    oss_mixext sink_mixext;
140
    oss_mixext source_mixext;
141
#else
126 142
    int mixer_devmask;
143
#endif
127 144

  
128 145
    int nfrags, frag_size, orig_frag_size;
129 146

  
......
809 826
    return ret;
810 827
}
811 828

  
829
#ifdef HAVE_OSSV4
830

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

  
880
    return "Unknown";
881
}
882

  
883
void
884
mixer_showflags (int flags)
885
{
886
    struct
887
    {
888
        int flag;
889
        char nick[16];
890
    } all_flags[] = {
891
        /* first the important ones */
892
        {
893
        MIXF_MAINVOL, "MAINVOL"}, {
894
        MIXF_PCMVOL, "PCMVOL"}, {
895
        MIXF_RECVOL, "RECVOL"}, {
896
        MIXF_MONVOL, "MONVOL"}, {
897
        MIXF_DESCR, "DESCR"},
898

  
899
        /* now the rest in the right order */
900
        {
901
        MIXF_READABLE, "READABLE"}, {
902
        MIXF_WRITEABLE, "WRITABLE"}, {
903
        MIXF_POLL, "POLL"}, {
904
        MIXF_HZ, "HZ"}, {
905
        MIXF_STRING, "STRING"}, {
906
        MIXF_DYNAMIC, "DYNAMIC"}, {
907
        MIXF_OKFAIL, "OKFAIL"}, {
908
        MIXF_FLAT, "FLAT"}, {
909
        MIXF_LEGACY, "LEGACY"}, {
910
        MIXF_CENTIBEL, "CENTIBEL"}, {
911
        MIXF_DECIBEL, "DECIBEL"}, {
912
        MIXF_WIDE, "WIDE"}
913
    };
914
    int num_flags = (sizeof (all_flags) / sizeof ((all_flags)[0]));
915
    int i;
916

  
917
    if (flags == 0) {
918
        pa_log_debug ("  flags  : None");
919
        return;
920
    }
921

  
922
    for (i=0; i < num_flags; i++) {
923
        if ((flags & all_flags[i].flag)) {
924
            pa_log_debug ("  flag   : %s", all_flags[i].nick);
925
            flags &= ~all_flags[i].flag;      /* unset */
926
        }
927
    }
928

  
929
    /* Unknown flags? */
930
    if (flags != 0) {
931
        pa_log_debug ("  flag   : ????");
932
    }
933

  
934
    return;
935
}
936

  
812 937
static void sink_get_volume(pa_sink *s) {
813 938
    struct userdata *u;
814 939

  
815 940
    pa_assert_se(u = s->userdata);
816 941

  
942
    if (pa_oss_get_volume(u->mixer_dsp_fd, &(u->sink_mixext), &s->sample_spec, &s->real_volume) >= 0)
943
        return;
944

  
945
    pa_log_info("Device doesn't support reading mixer settings: %s", pa_cstrerror(errno));
946
}
947

  
948
static void sink_set_volume(pa_sink *s) {
949
    struct userdata *u;
950

  
951
    pa_assert_se(u = s->userdata);
952

  
953
    if (pa_oss_set_volume(u->mixer_dsp_fd, &(u->sink_mixext), &s->sample_spec, &s->real_volume) >= 0)
954
        return;
955

  
956
    pa_log_info("Device doesn't support writing mixer settings: %s", pa_cstrerror(errno));
957
}
958

  
959
static void source_get_volume(pa_source *s) {
960
    struct userdata *u;
961

  
962
    pa_assert_se(u = s->userdata);
963

  
964
    if (pa_oss_get_volume(u->mixer_dsp_fd, &(u->source_mixext), &s->sample_spec, &s->real_volume) >= 0)
965
        return;
966

  
967
    pa_log_info("Device doesn't support reading mixer settings: %s", pa_cstrerror(errno));
968
}
969

  
970
static void source_set_volume(pa_source *s) {
971
    struct userdata *u;
972

  
973
    pa_assert_se(u = s->userdata);
974

  
975
    if (pa_oss_set_volume(u->mixer_dsp_fd, &(u->source_mixext), &s->sample_spec, &s->real_volume) >= 0)
976
        return;
977

  
978
    pa_log_info("Device doesn't support writing mixer settings: %s", pa_cstrerror(errno));
979
}
980

  
981
#else
982

  
983
static void sink_get_volume(pa_sink *s) {
984
    struct userdata *u;
985

  
986
    pa_assert_se(u = s->userdata);
987

  
817 988
    pa_assert(u->mixer_devmask & (SOUND_MASK_VOLUME|SOUND_MASK_PCM));
818 989

  
819 990
    if (u->mixer_devmask & SOUND_MASK_VOLUME)
......
880 1051

  
881 1052
    pa_log_info("Device doesn't support writing mixer settings: %s", pa_cstrerror(errno));
882 1053
}
1054
#endif
883 1055

  
884 1056
static void thread_func(void *userdata) {
885 1057
    struct userdata *u = userdata;
......
1162 1334

  
1163 1335
int pa__init(pa_module*m) {
1164 1336

  
1337
#ifdef HAVE_OSSV4
1338
    struct oss_sysinfo si = { {0,}, };
1339
    struct oss_mixerinfo mi = { 0, };
1340
#endif
1341

  
1165 1342
    struct audio_buf_info info;
1166 1343
    struct userdata *u = NULL;
1167 1344
    const char *dev;
1345
    const char *default_dev;
1168 1346
    int fd = -1;
1169 1347
    int nfrags, orig_frag_size, frag_size;
1170 1348
    int mode, caps;
1349
    int dev_num;
1171 1350
    bool record = true, playback = true, use_mmap = true;
1172 1351
    pa_sample_spec ss;
1173 1352
    pa_channel_map map;
......
1219 1398
        goto fail;
1220 1399
    }
1221 1400

  
1222
    if ((fd = pa_oss_open(dev = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), &mode, &caps)) < 0)
1401
#ifdef HAVE_SOLARIS
1402
    default_dev = getenv("AUDIODEV");
1403
    if (!default_dev)
1404
        default_dev = DEFAULT_DEVICE;
1405
#else /* HAVE_SOLARIS */
1406
    default_dev = DEFAULT_DEVICE;
1407
#endif /* HAVE_SOLARIS */
1408

  
1409
    if ((fd = pa_oss_open(dev = pa_modargs_get_value(ma, "device", default_dev), &mode, &caps)) < 0)
1223 1410
        goto fail;
1224 1411

  
1225 1412
    if (use_mmap && (!(caps & DSP_CAP_MMAP) || !(caps & DSP_CAP_TRIGGER))) {
......
1259 1446
    m->userdata = u;
1260 1447
    u->fd = fd;
1261 1448
    u->mixer_fd = -1;
1449
#ifndef HAVE_OSSV4
1262 1450
    u->mixer_devmask = 0;
1451
#endif
1263 1452
    u->use_getospace = u->use_getispace = true;
1264 1453
    u->use_getodelay = true;
1265 1454
    u->mode = mode;
......
1428 1617
            u->out_mmap_memblocks = pa_xnew0(pa_memblock*, u->out_nfrags);
1429 1618
    }
1430 1619

  
1431
    if ((u->mixer_fd = pa_oss_open_mixer_for_device(u->device_name)) >= 0) {
1620
    if ((u->mixer_fd = pa_oss_open_mixer_for_device(u->device_name, &dev_num)) >= 0) {
1432 1621
        bool do_close = true;
1433 1622

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

  
1627
        u->mixer_dsp_fd = -1;
1628

  
1629
        if (ioctl (u->mixer_fd, SNDCTL_SYSINFO, &si) < 0) {
1630
            pa_log_debug ("SNDCTL_SYSINFO failed");
1631
            goto fail;
1632
        }
1633
        for (i = 0; i < si.nummixers; i++) {
1634
            mi.dev = i;
1635
            if (ioctl (u->mixer_fd, SNDCTL_MIXERINFO, &mi) < 0) {
1636
                pa_log_debug("SNDCTL_MIXERINFO failed");
1637
                goto fail;
1638
            }
1639
            if (mi.enabled != 0) {
1640
                /*
1641
                 * There could be multiple mixers. First we only care about
1642
                 * ones which are enabled.  In any case we should not touch
1643
                 * disabled mixers!
1644
                 * This code now will always pick the first enabled mixer
1645
                 * found that has the matching device number.
1646
                 */
1647
                if (i == dev_num) break;
1648
            }
1649
        }
1650

  
1651
        if (i < si.nummixers) {
1652
            struct stat sbuf;
1653

  
1654
            if ((stat(mi.devnode, &sbuf) != 0) ||
1655
                ((sbuf.st_mode & S_IFCHR) == 0)) {
1656
                pa_log("Failed to get mixer dsp device.");
1657
                i = si.nummixers;
1658
            }
1659
        }
1660

  
1661
        if (i < si.nummixers &&
1662
           (u->mixer_dsp_fd = pa_oss_open_mixer(mi.devnode)) >= 0) {
1663

  
1664
            /* Will cause for loop to exit if not filled in by OSS */
1665
            u->mixer_cmax = -1;
1666
            if (ioctl(u->mixer_dsp_fd, SNDCTL_MIX_NREXT, &u->mixer_cmax) < 0) {
1667
                pa_log("Failed to get max control.");
1668
                goto fail;
1669
            }
1670

  
1671
            pa_log_debug ("Opened mixer device %d with %d controls\n",
1672
                          mi.dev, mi.nrext);
1673

  
1674
            u->mixer_sink_control   = -1;
1675
            u->mixer_source_control = -1;
1676

  
1677
            for (i=0; i < u->mixer_cmax; i++) {
1678
                memset (&(u->sink_mixext), 0, sizeof (oss_mixext));
1679

  
1680
#ifdef IGNORE_DEV
1681
                /* This will cause dev to be ignored */
1682
                u->sink_mixext.dev = -1;
1683
#else
1684
                u->sink_mixext.dev = mi.dev;
1685
#endif
1686

  
1687
                /*
1688
                 * The real way to pick a control on a mixer is with this
1689
                 * number.  Note that control numbers are unique across all
1690
                 * mixers. So dev can just be ignored.  When dev is included
1691
                 * it will only be used to check for correct dev from
1692
                 * userland.  But it will not be used to select a mixer.
1693
                 */
1694
                u->sink_mixext.ctrl = i;
1695

  
1696
                pa_log_debug ("Control %d", u->sink_mixext.ctrl);
1697

  
1698
                if (ioctl (u->mixer_dsp_fd, SNDCTL_MIX_EXTINFO,
1699
                         &(u->sink_mixext)) < 0) {
1700
                    pa_log_debug ("SNDCTL_MIX_EXTINFO failed");
1701
                    continue;
1702
                }
1703

  
1704
                pa_log_debug ("  name   : %s", u->sink_mixext.extname);
1705
                pa_log_debug ("  type   : %s (%d)",
1706
                              mixer_ext_type_get_name (u->sink_mixext.type),
1707
                              u->sink_mixext.type);
1708
                pa_log_debug ("  maxval : %d", u->sink_mixext.maxvalue);
1709
                pa_log_debug ("  parent : %d", u->sink_mixext.parent);
1710
                mixer_showflags (u->sink_mixext.flags);
1711

  
1712
                if ((u->sink_mixext.flags & MIXF_PCMVOL)) {
1713
                    pa_log_debug ("First PCM control: %d", i);
1714
                    u->mixer_sink_control = i;
1715
                    break;
1716
                }
1717

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

  
1732
            if (u->mixer_sink_control != -1) {
1733
                pa_log_debug ("Setting OSS sink callbacks.");
1734
                pa_sink_set_get_volume_callback(u->sink, sink_get_volume);
1735
                pa_sink_set_set_volume_callback(u->sink, sink_set_volume);
1736
                u->sink->n_volume_steps = 101;
1737
                do_close = false;
1738
            } else {
1739
                pa_log_debug ("Not setting OSS sink callbacks.");
1740
            }
1741

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

  
1759
                pa_log_debug ("Control %d", u->source_mixext.ctrl);
1760

  
1761
                if (ioctl (u->mixer_dsp_fd, SNDCTL_MIX_EXTINFO,
1762
                         &(u->source_mixext)) == -1) {
1763
                    pa_log_debug ("SNDCTL_MIX_EXTINFO failed");
1764
                    continue;
1765
                }
1766

  
1767
                pa_log_debug ("  name   : %s", u->source_mixext.extname);
1768
                pa_log_debug ("  type   : %s (%d)",
1769
                              mixer_ext_type_get_name (u->source_mixext.type),
1770
                              u->source_mixext.type);
1771
                pa_log_debug ("  maxval : %d", u->source_mixext.maxvalue);
1772
                pa_log_debug ("  parent : %d", u->source_mixext.parent);
1773
                mixer_showflags (u->source_mixext.flags);
1774

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

  
1787
            if (u->mixer_source_control != -1) {
1788
                pa_log_debug ("Setting OSS source callbacks.");
1789
                pa_source_set_get_volume_callback(u->source, source_get_volume);
1790
                pa_source_set_set_volume_callback(u->source, source_set_volume);
1791
                u->source->n_volume_steps = 101;
1792
                do_close = false;
1793
            } else {
1794
                pa_log_debug ("Not setting OSS source callbacks.");
1795
            }
1796

  
1797
            if (do_close == true) {
1798
                pa_close(u->mixer_dsp_fd);
1799
                u->mixer_dsp_fd = -1;
1800
            }
1801
        }
1802

  
1803
#else
1434 1804
        if (ioctl(u->mixer_fd, SOUND_MIXER_READ_DEVMASK, &u->mixer_devmask) < 0)
1435 1805
            pa_log_warn("SOUND_MIXER_READ_DEVMASK failed: %s", pa_cstrerror(errno));
1436 1806
        else {
......
1450 1820
                do_close = false;
1451 1821
            }
1452 1822
        }
1823
#endif
1453 1824

  
1454 1825
        if (do_close) {
1455 1826
            pa_close(u->mixer_fd);
1456 1827
            u->mixer_fd = -1;
1828
#ifndef HAVE_OSSV4
1457 1829
            u->mixer_devmask = 0;
1830
#endif
1458 1831
        }
1459 1832
    }
1460 1833

  
......
1573 1946
    if (u->fd >= 0)
1574 1947
        pa_close(u->fd);
1575 1948

  
1949
#ifdef HAVE_OSSV4
1950
    if (u->mixer_dsp_fd >= 0)
1951
        pa_close(u->mixer_dsp_fd);
1952
#endif
1576 1953
    if (u->mixer_fd >= 0)
1577 1954
        pa_close(u->mixer_fd);
1578 1955

  
(2-2/11)