src/java.desktop/linux/native/libjsound/PLATFORM_API_LinuxOS_ALSA_PCMUtils.c
author hannesw
Tue, 10 Sep 2019 15:30:23 +0200
changeset 58071 8a066d872553
parent 49289 148e29df1644
permissions -rw-r--r--
8230766: Changed message in IllegalMonitorStateException Reviewed-by: attila, jlaskey
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
23668
98a5be057aad 8008114: [parfait] False positive buffer overrun in jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_LinuxOS_ALSA_MidiUtils.c
serb
parents: 5506
diff changeset
     2
 * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 *
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    23
 * questions.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
//#define USE_ERROR
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
//#define USE_TRACE
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
#include "PLATFORM_API_LinuxOS_ALSA_PCMUtils.h"
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
#include "PLATFORM_API_LinuxOS_ALSA_CommonUtils.h"
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
// callback for iteration through devices
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
// returns TRUE if iteration should continue
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
// NOTE: cardinfo may be NULL (for "default" device)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
typedef int (*DeviceIteratorPtr)(UINT32 deviceID, snd_pcm_info_t* pcminfo,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
                             snd_ctl_card_info_t* cardinfo, void *userData);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
// for each ALSA device, call iterator. userData is passed to the iterator
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
// returns total number of iterations
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
int iteratePCMDevices(DeviceIteratorPtr iterator, void* userData) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
    int count = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
    int subdeviceCount;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
    int card, dev, subDev;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
    char devname[16];
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
    int err;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
    snd_ctl_t *handle;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
    snd_pcm_t *pcm;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
    snd_pcm_info_t* pcminfo;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
    snd_ctl_card_info_t *cardinfo, *defcardinfo = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
    UINT32 deviceID;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
    int doContinue = TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
    snd_pcm_info_malloc(&pcminfo);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
    snd_ctl_card_info_malloc(&cardinfo);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
    // 1st try "default" device
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
    err = snd_pcm_open(&pcm, ALSA_DEFAULT_DEVICE_NAME,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
                       SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
    if (err < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
        // try with the other direction
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
        err = snd_pcm_open(&pcm, ALSA_DEFAULT_DEVICE_NAME,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
                           SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
    if (err < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
        ERROR1("ERROR: snd_pcm_open (\"default\"): %s\n", snd_strerror(err));
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
        err = snd_pcm_info(pcm, pcminfo);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
        snd_pcm_close(pcm);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
        if (err < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
            ERROR1("ERROR: snd_pcm_info (\"default\"): %s\n",
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
                    snd_strerror(err));
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
            // try to get card info
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
            card = snd_pcm_info_get_card(pcminfo);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
            if (card >= 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
                sprintf(devname, ALSA_HARDWARE_CARD, card);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
                if (snd_ctl_open(&handle, devname, SND_CTL_NONBLOCK) >= 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
                    if (snd_ctl_card_info(handle, cardinfo) >= 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
                        defcardinfo = cardinfo;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
                    snd_ctl_close(handle);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
            // call callback function for the device
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
            if (iterator != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
                doContinue = (*iterator)(ALSA_DEFAULT_DEVICE_ID, pcminfo,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
                                         defcardinfo, userData);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
            count++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
    // iterate cards
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
    card = -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
    while (doContinue) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
        if (snd_card_next(&card) < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
        if (card < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
        sprintf(devname, ALSA_HARDWARE_CARD, card);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
        TRACE1("Opening alsa device \"%s\"...\n", devname);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
        err = snd_ctl_open(&handle, devname, SND_CTL_NONBLOCK);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
        if (err < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
            ERROR2("ERROR: snd_ctl_open, card=%d: %s\n",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
                    card, snd_strerror(err));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
            err = snd_ctl_card_info(handle, cardinfo);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
            if (err < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
                ERROR2("ERROR: snd_ctl_card_info, card=%d: %s\n",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
                        card, snd_strerror(err));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
                dev = -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
                while (doContinue) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
                    if (snd_ctl_pcm_next_device(handle, &dev) < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
                        ERROR0("snd_ctl_pcm_next_device\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
                    if (dev < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
                        break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
                    snd_pcm_info_set_device(pcminfo, dev);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
                    snd_pcm_info_set_subdevice(pcminfo, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
                    snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_PLAYBACK);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
                    err = snd_ctl_pcm_info(handle, pcminfo);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
                    if (err == -ENOENT) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
                        // try with the other direction
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
                        snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_CAPTURE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
                        err = snd_ctl_pcm_info(handle, pcminfo);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
                    if (err < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
                        if (err != -ENOENT) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
                            ERROR2("ERROR: snd_ctl_pcm_info, card=%d: %s",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
                                    card, snd_strerror(err));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
                    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
                        subdeviceCount = needEnumerateSubdevices(ALSA_PCM) ?
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
                            snd_pcm_info_get_subdevices_count(pcminfo) : 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
                        if (iterator!=NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
                            for (subDev = 0; subDev < subdeviceCount; subDev++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
                                deviceID = encodeDeviceID(card, dev, subDev);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
                                doContinue = (*iterator)(deviceID, pcminfo,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
                                                         cardinfo, userData);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
                                count++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
                                if (!doContinue) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
                                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
                                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
                            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
                        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
                            count += subdeviceCount;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
                } // of while(doContinue)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
            snd_ctl_close(handle);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
    snd_ctl_card_info_free(cardinfo);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
    snd_pcm_info_free(pcminfo);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
    return count;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
int getAudioDeviceCount() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
    initAlsaSupport();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
    return iteratePCMDevices(NULL, NULL);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
int deviceInfoIterator(UINT32 deviceID, snd_pcm_info_t* pcminfo,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
                       snd_ctl_card_info_t* cardinfo, void* userData) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
    char buffer[300];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
    ALSA_AudioDeviceDescription* desc = (ALSA_AudioDeviceDescription*)userData;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
#ifdef ALSA_PCM_USE_PLUGHW
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
    int usePlugHw = 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
#else
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
    int usePlugHw = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
#endif
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
    initAlsaSupport();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
    if (desc->index == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
        // we found the device with correct index
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
        *(desc->maxSimultaneousLines) = needEnumerateSubdevices(ALSA_PCM) ?
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
                1 : snd_pcm_info_get_subdevices_count(pcminfo);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
        *desc->deviceID = deviceID;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
        buffer[0]=' '; buffer[1]='[';
23668
98a5be057aad 8008114: [parfait] False positive buffer overrun in jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_LinuxOS_ALSA_MidiUtils.c
serb
parents: 5506
diff changeset
   187
        // buffer[300] is enough to store the actual device string w/o overrun
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
        getDeviceStringFromDeviceID(&buffer[2], deviceID, usePlugHw, ALSA_PCM);
23668
98a5be057aad 8008114: [parfait] False positive buffer overrun in jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_LinuxOS_ALSA_MidiUtils.c
serb
parents: 5506
diff changeset
   189
        strncat(buffer, "]", sizeof(buffer) - strlen(buffer) - 1);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
        strncpy(desc->name,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
                (cardinfo != NULL)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
                    ? snd_ctl_card_info_get_id(cardinfo)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
                    : snd_pcm_info_get_id(pcminfo),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
                desc->strLen - strlen(buffer));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
        strncat(desc->name, buffer, desc->strLen - strlen(desc->name));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
        strncpy(desc->vendor, "ALSA (http://www.alsa-project.org)", desc->strLen);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
        strncpy(desc->description,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
                (cardinfo != NULL)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
                    ? snd_ctl_card_info_get_name(cardinfo)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
                    : snd_pcm_info_get_name(pcminfo),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
                desc->strLen);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
        strncat(desc->description, ", ", desc->strLen - strlen(desc->description));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
        strncat(desc->description, snd_pcm_info_get_id(pcminfo), desc->strLen - strlen(desc->description));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
        strncat(desc->description, ", ", desc->strLen - strlen(desc->description));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
        strncat(desc->description, snd_pcm_info_get_name(pcminfo), desc->strLen - strlen(desc->description));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
        getALSAVersion(desc->version, desc->strLen);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
        TRACE4("Returning %s, %s, %s, %s\n", desc->name, desc->vendor, desc->description, desc->version);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
        return FALSE; // do not continue iteration
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
    desc->index--;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
    return TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
// returns 0 if successful
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
int openPCMfromDeviceID(int deviceID, snd_pcm_t** handle, int isSource, int hardware) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
    char buffer[200];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
    int ret;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
    initAlsaSupport();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
    getDeviceStringFromDeviceID(buffer, deviceID, !hardware, ALSA_PCM);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
    TRACE1("Opening ALSA device %s\n", buffer);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
    ret = snd_pcm_open(handle, buffer,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
                       isSource?SND_PCM_STREAM_PLAYBACK:SND_PCM_STREAM_CAPTURE,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
                       SND_PCM_NONBLOCK);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
    if (ret != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
        ERROR1("snd_pcm_open returned error code %d \n", ret);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
        *handle = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
    return ret;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
int getAudioDeviceDescriptionByIndex(ALSA_AudioDeviceDescription* desc) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
    initAlsaSupport();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
    TRACE1(" getAudioDeviceDescriptionByIndex(mixerIndex = %d\n", desc->index);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
    iteratePCMDevices(&deviceInfoIterator, desc);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
    return (desc->index == 0)?TRUE:FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
// returns 1 if successful
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
// enc: 0 for PCM, 1 for ULAW, 2 for ALAW (see DirectAudio.h)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
int getFormatFromAlsaFormat(snd_pcm_format_t alsaFormat,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
                            int* sampleSizeInBytes, int* significantBits,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
                            int* isSigned, int* isBigEndian, int* enc) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
    *sampleSizeInBytes = (snd_pcm_format_physical_width(alsaFormat) + 7) / 8;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
    *significantBits = snd_pcm_format_width(alsaFormat);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
    // defaults
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
    *enc = 0; // PCM
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
    *isSigned = (snd_pcm_format_signed(alsaFormat) > 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
    *isBigEndian = (snd_pcm_format_big_endian(alsaFormat) > 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
    // non-PCM formats
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
    if (alsaFormat == SND_PCM_FORMAT_MU_LAW) { // Mu-Law
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
        *sampleSizeInBytes = 8; *enc = 1; *significantBits = *sampleSizeInBytes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
    else if (alsaFormat == SND_PCM_FORMAT_A_LAW) {     // A-Law
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
        *sampleSizeInBytes = 8; *enc = 2; *significantBits = *sampleSizeInBytes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
    else if (snd_pcm_format_linear(alsaFormat) < 1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
        return 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
    return (*sampleSizeInBytes > 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
// returns 1 if successful
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
int getAlsaFormatFromFormat(snd_pcm_format_t* alsaFormat,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
                            int sampleSizeInBytes, int significantBits,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
                            int isSigned, int isBigEndian, int enc) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
    *alsaFormat = SND_PCM_FORMAT_UNKNOWN;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
    if (enc == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
        *alsaFormat = snd_pcm_build_linear_format(significantBits,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
                                                  sampleSizeInBytes * 8,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
                                                  isSigned?0:1,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
                                                  isBigEndian?1:0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
    else if ((sampleSizeInBytes == 1) && (significantBits == 8)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
        if (enc == 1) { // ULAW
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
            *alsaFormat = SND_PCM_FORMAT_MU_LAW;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
        else if (enc == 2) { // ALAW
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
            *alsaFormat = SND_PCM_FORMAT_A_LAW;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
    return (*alsaFormat == SND_PCM_FORMAT_UNKNOWN)?0:1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
/* end */