1 /* 2 * Copyright (c) 2003, 2015, 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 /* 48 * Declare library specific JNI_Onload entry if static build 49 */ 50 DEF_STATIC_JNI_OnLoad 51 52 void initAlsaSupport() { 53 char* enumerate; 54 if (!alsa_inited) { 55 alsa_inited = TRUE; 56 snd_lib_error_set_handler(&alsaDebugOutput); 57 58 enumerate = getenv(ENV_ENUMERATE_PCM_SUBDEVICES); 59 if (enumerate != NULL && strlen(enumerate) > 0 60 && (enumerate[0] != 'f') // false 61 && (enumerate[0] != 'F') // False 62 && (enumerate[0] != 'n') // no 63 && (enumerate[0] != 'N')) { // NO 64 alsa_enumerate_pcm_subdevices = TRUE; 65 } 66 #ifdef ALSA_MIDI_ENUMERATE_SUBDEVICES 67 alsa_enumerate_midi_subdevices = TRUE; 68 #endif 69 } 70 } 71 72 73 /* if true (non-zero), ALSA sub devices should be listed as separate devices 74 */ 75 int needEnumerateSubdevices(int isMidi) { 76 initAlsaSupport(); 77 return isMidi ? alsa_enumerate_midi_subdevices 78 : alsa_enumerate_pcm_subdevices; 79 } 80 81 82 /* 83 * deviceID contains packed card, device and subdevice numbers 84 * each number takes 10 bits 85 * "default" device has id == ALSA_DEFAULT_DEVICE_ID 86 */ 87 UINT32 encodeDeviceID(int card, int device, int subdevice) { 88 return (((card & 0x3FF) << 20) | ((device & 0x3FF) << 10) 89 | (subdevice & 0x3FF)) + 1; 90 } 91 92 93 void decodeDeviceID(UINT32 deviceID, int* card, int* device, int* subdevice, 94 int isMidi) { 95 deviceID--; 96 *card = (deviceID >> 20) & 0x3FF; 97 *device = (deviceID >> 10) & 0x3FF; 98 if (needEnumerateSubdevices(isMidi)) { 99 *subdevice = deviceID & 0x3FF; 100 } else { 101 *subdevice = -1; // ALSA will choose any subdevices 102 } 103 } 104 105 106 void getDeviceString(char* buffer, int card, int device, int subdevice, 107 int usePlugHw, int isMidi) { 108 if (needEnumerateSubdevices(isMidi)) { 109 sprintf(buffer, "%s:%d,%d,%d", 110 usePlugHw ? ALSA_PLUGHARDWARE : ALSA_HARDWARE, 111 card, device, subdevice); 112 } else { 113 sprintf(buffer, "%s:%d,%d", 114 usePlugHw ? ALSA_PLUGHARDWARE : ALSA_HARDWARE, 115 card, device); 116 } 117 } 118 119 120 void getDeviceStringFromDeviceID(char* buffer, UINT32 deviceID, 121 int usePlugHw, int isMidi) { 122 int card, device, subdevice; 123 124 if (deviceID == ALSA_DEFAULT_DEVICE_ID) { 125 strcpy(buffer, ALSA_DEFAULT_DEVICE_NAME); 126 } else { 127 decodeDeviceID(deviceID, &card, &device, &subdevice, isMidi); 128 getDeviceString(buffer, card, device, subdevice, usePlugHw, isMidi); 129 } 130 } 131 132 133 static int hasGottenALSAVersion = FALSE; 134 #define ALSAVersionString_LENGTH 200 135 static char ALSAVersionString[ALSAVersionString_LENGTH]; 136 137 void getALSAVersion(char* buffer, int len) { 138 if (!hasGottenALSAVersion) { 139 // get alsa version from proc interface 140 FILE* file; 141 int curr, len, totalLen, inVersionString; 142 file = fopen(ALSA_VERSION_PROC_FILE, "r"); 143 ALSAVersionString[0] = 0; 144 if (file) { 145 if (NULL != fgets(ALSAVersionString, ALSAVersionString_LENGTH, file)) { 146 // parse for version number 147 totalLen = strlen(ALSAVersionString); 148 inVersionString = FALSE; 149 len = 0; 150 curr = 0; 151 while (curr < totalLen) { 152 if (!inVersionString) { 153 // is this char the beginning of a version string ? 154 if (ALSAVersionString[curr] >= '0' 155 && ALSAVersionString[curr] <= '9') { 156 inVersionString = TRUE; 157 } 158 } 159 if (inVersionString) { 160 // the version string ends with white space 161 if (ALSAVersionString[curr] <= 32) { 162 break; 163 } 164 if (curr != len) { 165 // copy this char to the beginning of the string 166 ALSAVersionString[len] = ALSAVersionString[curr]; 167 } 168 len++; 169 } 170 curr++; 171 } 172 // remove trailing dots 173 while ((len > 0) && (ALSAVersionString[len - 1] == '.')) { 174 len--; 175 } 176 // null terminate 177 ALSAVersionString[len] = 0; 178 } 179 fclose(file); 180 hasGottenALSAVersion = TRUE; 181 } 182 } 183 strncpy(buffer, ALSAVersionString, len); 184 } 185 186 187 /* end */