1 /* 2 * Copyright (c) 2002, 2007, 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_SolarisOS_Utils.h" 30 31 #define MAX_AUDIO_DEVICES 20 32 33 // not thread safe... 34 static AudioDevicePath globalADPaths[MAX_AUDIO_DEVICES]; 35 static int globalADCount = -1; 36 static int globalADCacheTime = -1; 37 /* how many seconds do we cache devices */ 38 #define AD_CACHE_TIME 30 39 40 // return seconds 41 long getTimeInSeconds() { 42 struct timeval tv; 43 gettimeofday(&tv, NULL); 44 return tv.tv_sec; 45 } 46 47 48 int getAudioDeviceCount() { 49 int count = MAX_AUDIO_DEVICES; 50 51 getAudioDevices(globalADPaths, &count); 52 return count; 53 } 54 55 /* returns TRUE if the path exists at all */ 56 int addAudioDevice(char* path, AudioDevicePath* adPath, int* count) { 57 int i; 58 int found = 0; 59 int fileExists = 0; 60 // not thread safe... 61 static struct stat statBuf; 62 63 // get stats on the file 64 if (stat(path, &statBuf) == 0) { 65 // file exists. 66 fileExists = 1; 67 // If it is not yet in the adPath array, add it to the array 68 for (i = 0; i < *count; i++) { 69 if (adPath[i].st_ino == statBuf.st_ino 70 && adPath[i].st_dev == statBuf.st_dev) { 71 found = 1; 72 break; 73 } 74 } 75 if (!found) { 76 adPath[*count].st_ino = statBuf.st_ino; 77 adPath[*count].st_dev = statBuf.st_dev; 78 strncpy(adPath[*count].path, path, MAX_NAME_LENGTH); 79 adPath[*count].path[MAX_NAME_LENGTH - 1] = 0; 80 (*count)++; 81 TRACE1("Added audio device %s\n", path); 82 } 83 } 84 return fileExists; 85 } 86 87 88 void getAudioDevices(AudioDevicePath* adPath, int* count) { 89 int maxCount = *count; 90 char* audiodev; 91 char devsound[15]; 92 int i; 93 long timeInSeconds = getTimeInSeconds(); 94 95 if (globalADCount < 0 96 || (getTimeInSeconds() - globalADCacheTime) > AD_CACHE_TIME 97 || (adPath != globalADPaths)) { 98 *count = 0; 99 // first device, if set, is AUDIODEV variable 100 audiodev = getenv("AUDIODEV"); 101 if (audiodev != NULL && audiodev[0] != 0) { 102 addAudioDevice(audiodev, adPath, count); 103 } 104 // then try /dev/audio 105 addAudioDevice("/dev/audio", adPath, count); 106 // then go through all of the /dev/sound/? devices 107 for (i = 0; i < 100; i++) { 108 sprintf(devsound, "/dev/sound/%d", i); 109 if (!addAudioDevice(devsound, adPath, count)) { 110 break; 111 } 112 } 113 if (adPath == globalADPaths) { 114 /* commit cache */ 115 globalADCount = *count; 116 /* set cache time */ 117 globalADCacheTime = timeInSeconds; 118 } 119 } else { 120 /* return cache */ 121 *count = globalADCount; 122 } 123 // that's it 124 } 125 126 int getAudioDeviceDescriptionByIndex(int index, AudioDeviceDescription* adDesc, int getNames) { 127 int count = MAX_AUDIO_DEVICES; 128 int ret = 0; 129 130 getAudioDevices(globalADPaths, &count); 131 if (index>=0 && index < count) { 132 ret = getAudioDeviceDescription(globalADPaths[index].path, adDesc, getNames); 133 } 134 return ret; 135 } 136 137 int getAudioDeviceDescription(char* path, AudioDeviceDescription* adDesc, int getNames) { 138 int fd; 139 int mixerMode; 140 int len; 141 audio_info_t info; 142 audio_device_t deviceInfo; 143 144 strncpy(adDesc->path, path, MAX_NAME_LENGTH); 145 adDesc->path[MAX_NAME_LENGTH] = 0; 146 strcpy(adDesc->pathctl, adDesc->path); 147 strcat(adDesc->pathctl, "ctl"); 148 strcpy(adDesc->name, adDesc->path); 149 adDesc->vendor[0] = 0; 150 adDesc->version[0] = 0; 151 adDesc->description[0] = 0; 152 adDesc->maxSimulLines = 1; 153 154 // try to open the pseudo device and get more information 155 fd = open(adDesc->pathctl, O_WRONLY | O_NONBLOCK); 156 if (fd >= 0) { 157 close(fd); 158 if (getNames) { 159 fd = open(adDesc->pathctl, O_RDONLY); 160 if (fd >= 0) { 161 if (ioctl(fd, AUDIO_GETDEV, &deviceInfo) >= 0) { 162 strncpy(adDesc->vendor, deviceInfo.name, MAX_AUDIO_DEV_LEN); 163 adDesc->vendor[MAX_AUDIO_DEV_LEN] = 0; 164 strncpy(adDesc->version, deviceInfo.version, MAX_AUDIO_DEV_LEN); 165 adDesc->version[MAX_AUDIO_DEV_LEN] = 0; 166 /* add config string to the dev name 167 * creates a string like "/dev/audio (onboard1)" 168 */ 169 len = strlen(adDesc->name) + 1; 170 if (MAX_NAME_LENGTH - len > 3) { 171 strcat(adDesc->name, " ("); 172 strncat(adDesc->name, deviceInfo.config, MAX_NAME_LENGTH - len); 173 strcat(adDesc->name, ")"); 174 } 175 adDesc->name[MAX_NAME_LENGTH-1] = 0; 176 } 177 if (ioctl(fd, AUDIO_MIXERCTL_GET_MODE, &mixerMode) >= 0) { 178 if (mixerMode == AM_MIXER_MODE) { 179 TRACE1(" getAudioDeviceDescription: %s is in mixer mode\n", adDesc->path); 180 adDesc->maxSimulLines = -1; 181 } 182 } else { 183 ERROR1("ioctl AUDIO_MIXERCTL_GET_MODE failed on %s!\n", adDesc->path); 184 } 185 close(fd); 186 } else { 187 ERROR1("could not open %s!\n", adDesc->pathctl); 188 } 189 } 190 return 1; 191 } 192 return 0; 193 }