1 /* 2 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 //#define USE_ERROR 27 //#define USE_TRACE 28 29 #include "PLATFORM_API_LinuxOS_ALSA_CommonUtils.h" 30 31 static void alsaDebugOutput(const char *file, int line, const char *function, int err, const char *fmt, ...) { 32 #ifdef USE_ERROR 33 va_list args; 34 va_start(args, fmt); 35 printf("%s:%d function %s: error %d: %s\n", file, line, function, err, snd_strerror(err)); 36 if (strlen(fmt) > 0) { 37 vprintf(fmt, args); 38 } 39 va_end(args); 40 #endif 41 } 42 43 static int alsa_inited = 0; 44 static int alsa_enumerate_pcm_subdevices = FALSE; // default: no 45 static int alsa_enumerate_midi_subdevices = FALSE; // default: no 46 47 void initAlsaSupport() { 48 char* enumerate; 49 if (!alsa_inited) { 50 alsa_inited = TRUE; 51 snd_lib_error_set_handler(&alsaDebugOutput); 52 53 enumerate = getenv(ENV_ENUMERATE_PCM_SUBDEVICES); 54 if (enumerate != NULL && strlen(enumerate) > 0 55 && (enumerate[0] != 'f') // false 56 && (enumerate[0] != 'F') // False 57 && (enumerate[0] != 'n') // no 58 && (enumerate[0] != 'N')) { // NO 59 alsa_enumerate_pcm_subdevices = TRUE; 60 } 61 #ifdef ALSA_MIDI_ENUMERATE_SUBDEVICES 62 alsa_enumerate_midi_subdevices = TRUE; 63 #endif 64 } 65 } 66 67 68 /* if true (non-zero), ALSA sub devices should be listed as separate devices 69 */ 70 int needEnumerateSubdevices(int isMidi) { 71 initAlsaSupport(); 72 return isMidi ? alsa_enumerate_midi_subdevices 73 : alsa_enumerate_pcm_subdevices; 74 } 75 76 77 /* 78 * deviceID contains packed card, device and subdevice numbers 79 * each number takes 10 bits 80 * "default" device has id == ALSA_DEFAULT_DEVICE_ID 81 */ 82 UINT32 encodeDeviceID(int card, int device, int subdevice) { 83 return (((card & 0x3FF) << 20) | ((device & 0x3FF) << 10) 84 | (subdevice & 0x3FF)) + 1; 85 } 86 87 88 void decodeDeviceID(UINT32 deviceID, int* card, int* device, int* subdevice, 89 int isMidi) { 90 deviceID--; 91 *card = (deviceID >> 20) & 0x3FF; 92 *device = (deviceID >> 10) & 0x3FF; 93 if (needEnumerateSubdevices(isMidi)) { 94 *subdevice = deviceID & 0x3FF; 95 } else { 96 *subdevice = -1; // ALSA will choose any subdevices 97 } 98 } 99 100 101 void getDeviceString(char* buffer, int card, int device, int subdevice, 102 int usePlugHw, int isMidi) { 103 if (needEnumerateSubdevices(isMidi)) { 104 sprintf(buffer, "%s:%d,%d,%d", 105 usePlugHw ? ALSA_PLUGHARDWARE : ALSA_HARDWARE, 106 card, device, subdevice); 107 } else { 108 sprintf(buffer, "%s:%d,%d", 109 usePlugHw ? ALSA_PLUGHARDWARE : ALSA_HARDWARE, 110 card, device); 111 } 112 } 113 114 115 void getDeviceStringFromDeviceID(char* buffer, UINT32 deviceID, 116 int usePlugHw, int isMidi) { 117 int card, device, subdevice; 118 119 if (deviceID == ALSA_DEFAULT_DEVICE_ID) { 120 strcpy(buffer, ALSA_DEFAULT_DEVICE_NAME); 121 } else { 122 decodeDeviceID(deviceID, &card, &device, &subdevice, isMidi); 123 getDeviceString(buffer, card, device, subdevice, usePlugHw, isMidi); 124 } 125 } 126 127 128 static int hasGottenALSAVersion = FALSE; 129 #define ALSAVersionString_LENGTH 200 130 static char ALSAVersionString[ALSAVersionString_LENGTH]; 131 132 void getALSAVersion(char* buffer, int len) { 133 if (!hasGottenALSAVersion) { 134 // get alsa version from proc interface 135 FILE* file; 136 int curr, len, totalLen, inVersionString; 137 file = fopen(ALSA_VERSION_PROC_FILE, "r"); 138 ALSAVersionString[0] = 0; 139 if (file) { 140 if (NULL != fgets(ALSAVersionString, ALSAVersionString_LENGTH, file)) { 141 // parse for version number 142 totalLen = strlen(ALSAVersionString); 143 inVersionString = FALSE; 144 len = 0; 145 curr = 0; 146 while (curr < totalLen) { 147 if (!inVersionString) { 148 // is this char the beginning of a version string ? 149 if (ALSAVersionString[curr] >= '0' 150 && ALSAVersionString[curr] <= '9') { 151 inVersionString = TRUE; 152 } 153 } 154 if (inVersionString) { 155 // the version string ends with white space 156 if (ALSAVersionString[curr] <= 32) { 157 break; 158 } 159 if (curr != len) { 160 // copy this char to the beginning of the string 161 ALSAVersionString[len] = ALSAVersionString[curr]; 162 } 163 len++; 164 } 165 curr++; 166 } 167 // remove trailing dots 168 while ((len > 0) && (ALSAVersionString[len - 1] == '.')) { 169 len--; 170 } 171 // null terminate 172 ALSAVersionString[len] = 0; 173 } 174 fclose(file); 175 hasGottenALSAVersion = TRUE; 176 } 177 } 178 strncpy(buffer, ALSAVersionString, len); 179 } 180 181 182 /* end */