diff -r 836adbf7a2cd -r 3317bb8137f4 jdk/src/java.desktop/unix/native/libjsound/PLATFORM_API_LinuxOS_ALSA_CommonUtils.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/java.desktop/unix/native/libjsound/PLATFORM_API_LinuxOS_ALSA_CommonUtils.c Sun Aug 17 15:54:13 2014 +0100 @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +//#define USE_ERROR +//#define USE_TRACE + +#include "PLATFORM_API_LinuxOS_ALSA_CommonUtils.h" + +static void alsaDebugOutput(const char *file, int line, const char *function, int err, const char *fmt, ...) { +#ifdef USE_ERROR + va_list args; + va_start(args, fmt); + printf("%s:%d function %s: error %d: %s\n", file, line, function, err, snd_strerror(err)); + if (strlen(fmt) > 0) { + vprintf(fmt, args); + } + va_end(args); +#endif +} + +static int alsa_inited = 0; +static int alsa_enumerate_pcm_subdevices = FALSE; // default: no +static int alsa_enumerate_midi_subdevices = FALSE; // default: no + +void initAlsaSupport() { + char* enumerate; + if (!alsa_inited) { + alsa_inited = TRUE; + snd_lib_error_set_handler(&alsaDebugOutput); + + enumerate = getenv(ENV_ENUMERATE_PCM_SUBDEVICES); + if (enumerate != NULL && strlen(enumerate) > 0 + && (enumerate[0] != 'f') // false + && (enumerate[0] != 'F') // False + && (enumerate[0] != 'n') // no + && (enumerate[0] != 'N')) { // NO + alsa_enumerate_pcm_subdevices = TRUE; + } +#ifdef ALSA_MIDI_ENUMERATE_SUBDEVICES + alsa_enumerate_midi_subdevices = TRUE; +#endif + } +} + + +/* if true (non-zero), ALSA sub devices should be listed as separate devices + */ +int needEnumerateSubdevices(int isMidi) { + initAlsaSupport(); + return isMidi ? alsa_enumerate_midi_subdevices + : alsa_enumerate_pcm_subdevices; +} + + +/* + * deviceID contains packed card, device and subdevice numbers + * each number takes 10 bits + * "default" device has id == ALSA_DEFAULT_DEVICE_ID + */ +UINT32 encodeDeviceID(int card, int device, int subdevice) { + return (((card & 0x3FF) << 20) | ((device & 0x3FF) << 10) + | (subdevice & 0x3FF)) + 1; +} + + +void decodeDeviceID(UINT32 deviceID, int* card, int* device, int* subdevice, + int isMidi) { + deviceID--; + *card = (deviceID >> 20) & 0x3FF; + *device = (deviceID >> 10) & 0x3FF; + if (needEnumerateSubdevices(isMidi)) { + *subdevice = deviceID & 0x3FF; + } else { + *subdevice = -1; // ALSA will choose any subdevices + } +} + + +void getDeviceString(char* buffer, int card, int device, int subdevice, + int usePlugHw, int isMidi) { + if (needEnumerateSubdevices(isMidi)) { + sprintf(buffer, "%s:%d,%d,%d", + usePlugHw ? ALSA_PLUGHARDWARE : ALSA_HARDWARE, + card, device, subdevice); + } else { + sprintf(buffer, "%s:%d,%d", + usePlugHw ? ALSA_PLUGHARDWARE : ALSA_HARDWARE, + card, device); + } +} + + +void getDeviceStringFromDeviceID(char* buffer, UINT32 deviceID, + int usePlugHw, int isMidi) { + int card, device, subdevice; + + if (deviceID == ALSA_DEFAULT_DEVICE_ID) { + strcpy(buffer, ALSA_DEFAULT_DEVICE_NAME); + } else { + decodeDeviceID(deviceID, &card, &device, &subdevice, isMidi); + getDeviceString(buffer, card, device, subdevice, usePlugHw, isMidi); + } +} + + +static int hasGottenALSAVersion = FALSE; +#define ALSAVersionString_LENGTH 200 +static char ALSAVersionString[ALSAVersionString_LENGTH]; + +void getALSAVersion(char* buffer, int len) { + if (!hasGottenALSAVersion) { + // get alsa version from proc interface + FILE* file; + int curr, len, totalLen, inVersionString; + file = fopen(ALSA_VERSION_PROC_FILE, "r"); + ALSAVersionString[0] = 0; + if (file) { + if (NULL != fgets(ALSAVersionString, ALSAVersionString_LENGTH, file)) { + // parse for version number + totalLen = strlen(ALSAVersionString); + inVersionString = FALSE; + len = 0; + curr = 0; + while (curr < totalLen) { + if (!inVersionString) { + // is this char the beginning of a version string ? + if (ALSAVersionString[curr] >= '0' + && ALSAVersionString[curr] <= '9') { + inVersionString = TRUE; + } + } + if (inVersionString) { + // the version string ends with white space + if (ALSAVersionString[curr] <= 32) { + break; + } + if (curr != len) { + // copy this char to the beginning of the string + ALSAVersionString[len] = ALSAVersionString[curr]; + } + len++; + } + curr++; + } + // remove trailing dots + while ((len > 0) && (ALSAVersionString[len - 1] == '.')) { + len--; + } + // null terminate + ALSAVersionString[len] = 0; + } + fclose(file); + hasGottenALSAVersion = TRUE; + } + } + strncpy(buffer, ALSAVersionString, len); +} + + +/* end */