blob: 02ca9d4a95448fade227e1369a6df96e38bb1989 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2002-2007 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any 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...
34static AudioDevicePath globalADPaths[MAX_AUDIO_DEVICES];
35static int globalADCount = -1;
36static int globalADCacheTime = -1;
37/* how many seconds do we cache devices */
38#define AD_CACHE_TIME 30
39
40// return seconds
41long getTimeInSeconds() {
42 struct timeval tv;
43 gettimeofday(&tv, NULL);
44 return tv.tv_sec;
45}
46
47
48int 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 */
56int 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] = 0;
80 (*count)++;
81 TRACE1("Added audio device %s\n", path);
82 }
83 }
84 return fileExists;
85}
86
87
88void 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
126int 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
137int 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}