]> code.delx.au - pulseaudio/blob - src/modules/module-detect.c
Merge branch 'master' of ssh://rootserver/home/lennart/git/public/pulseaudio
[pulseaudio] / src / modules / module-detect.c
1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2006 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
6 Copyright 2006 Diego Pettenò
7
8 PulseAudio is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as published
10 by the Free Software Foundation; either version 2.1 of the License,
11 or (at your option) any later version.
12
13 PulseAudio is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with PulseAudio; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21 USA.
22 ***/
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <stdio.h>
29 #include <unistd.h>
30 #include <string.h>
31 #include <stdlib.h>
32 #include <errno.h>
33 #include <stdlib.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36
37 #include <pulse/xmalloc.h>
38
39 #include <pulsecore/core-error.h>
40 #include <pulsecore/module.h>
41 #include <pulsecore/modargs.h>
42 #include <pulsecore/log.h>
43 #include <pulsecore/core-util.h>
44 #include <pulsecore/macro.h>
45
46 #include "module-detect-symdef.h"
47
48 PA_MODULE_AUTHOR("Lennart Poettering");
49 PA_MODULE_DESCRIPTION("Detect available audio hardware and load matching drivers");
50 PA_MODULE_VERSION(PACKAGE_VERSION);
51 PA_MODULE_LOAD_ONCE(TRUE);
52 PA_MODULE_USAGE("just-one=<boolean>");
53
54 static const char* const valid_modargs[] = {
55 "just-one",
56 NULL
57 };
58
59 #ifdef HAVE_ALSA
60
61 static int detect_alsa(pa_core *c, int just_one) {
62 FILE *f;
63 int n = 0, n_sink = 0, n_source = 0;
64
65 if (!(f = fopen("/proc/asound/devices", "r"))) {
66
67 if (errno != ENOENT)
68 pa_log_error("open(\"/proc/asound/devices\") failed: %s", pa_cstrerror(errno));
69
70 return -1;
71 }
72
73 while (!feof(f)) {
74 char line[64], args[64];
75 unsigned device, subdevice;
76 int is_sink;
77
78 if (!fgets(line, sizeof(line), f))
79 break;
80
81 line[strcspn(line, "\r\n")] = 0;
82
83 if (pa_endswith(line, "digital audio playback"))
84 is_sink = 1;
85 else if (pa_endswith(line, "digital audio capture"))
86 is_sink = 0;
87 else
88 continue;
89
90 if (just_one && is_sink && n_sink >= 1)
91 continue;
92
93 if (just_one && !is_sink && n_source >= 1)
94 continue;
95
96 if (sscanf(line, " %*i: [%u- %u]: ", &device, &subdevice) != 2)
97 continue;
98
99 /* Only one sink per device */
100 if (subdevice != 0)
101 continue;
102
103 pa_snprintf(args, sizeof(args), "device_id=%u", device);
104 if (!pa_module_load(c, is_sink ? "module-alsa-sink" : "module-alsa-source", args))
105 continue;
106
107 n++;
108
109 if (is_sink)
110 n_sink++;
111 else
112 n_source++;
113 }
114
115 fclose(f);
116
117 return n;
118 }
119 #endif
120
121 #ifdef HAVE_OSS
122 static int detect_oss(pa_core *c, int just_one) {
123 FILE *f;
124 int n = 0, b = 0;
125
126 if (!(f = fopen("/dev/sndstat", "r")) &&
127 !(f = fopen("/proc/sndstat", "r")) &&
128 !(f = fopen("/proc/asound/oss/sndstat", "r"))) {
129
130 if (errno != ENOENT)
131 pa_log_error("failed to open OSS sndstat device: %s", pa_cstrerror(errno));
132
133 return -1;
134 }
135
136 while (!feof(f)) {
137 char line[64], args[64];
138 unsigned device;
139
140 if (!fgets(line, sizeof(line), f))
141 break;
142
143 line[strcspn(line, "\r\n")] = 0;
144
145 if (!b) {
146 b = strcmp(line, "Audio devices:") == 0 || strcmp(line, "Installed devices:") == 0;
147 continue;
148 }
149
150 if (line[0] == 0)
151 break;
152
153 if (sscanf(line, "%u: ", &device) == 1) {
154 if (device == 0)
155 pa_snprintf(args, sizeof(args), "device=/dev/dsp");
156 else
157 pa_snprintf(args, sizeof(args), "device=/dev/dsp%u", device);
158
159 if (!pa_module_load(c, "module-oss", args))
160 continue;
161
162 } else if (sscanf(line, "pcm%u: ", &device) == 1) {
163 /* FreeBSD support, the devices are named /dev/dsp0.0, dsp0.1 and so on */
164 pa_snprintf(args, sizeof(args), "device=/dev/dsp%u.0", device);
165
166 if (!pa_module_load(c, "module-oss", args))
167 continue;
168 }
169
170 n++;
171
172 if (just_one)
173 break;
174 }
175
176 fclose(f);
177 return n;
178 }
179 #endif
180
181 #ifdef HAVE_SOLARIS
182 static int detect_solaris(pa_core *c, int just_one) {
183 struct stat s;
184 const char *dev;
185 char args[64];
186
187 dev = getenv("AUDIODEV");
188 if (!dev)
189 dev = "/dev/audio";
190
191 if (stat(dev, &s) < 0) {
192 if (errno != ENOENT)
193 pa_log_error("failed to open device %s: %s", dev, pa_cstrerror(errno));
194 return -1;
195 }
196
197 if (!S_ISCHR(s.st_mode))
198 return 0;
199
200 pa_snprintf(args, sizeof(args), "device=%s", dev);
201
202 if (!pa_module_load(c, "module-solaris", args))
203 return 0;
204
205 return 1;
206 }
207 #endif
208
209 #ifdef OS_IS_WIN32
210 static int detect_waveout(pa_core *c, int just_one) {
211 /*
212 * FIXME: No point in enumerating devices until the plugin supports
213 * selecting anything but the first.
214 */
215 if (!pa_module_load(c, "module-waveout", ""))
216 return 0;
217
218 return 1;
219 }
220 #endif
221
222 int pa__init(pa_module*m) {
223 pa_bool_t just_one = FALSE;
224 int n = 0;
225 pa_modargs *ma;
226
227 pa_assert(m);
228
229 if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
230 pa_log("Failed to parse module arguments");
231 goto fail;
232 }
233
234 if (pa_modargs_get_value_boolean(ma, "just-one", &just_one) < 0) {
235 pa_log("just_one= expects a boolean argument.");
236 goto fail;
237 }
238
239 #ifdef HAVE_ALSA
240 if ((n = detect_alsa(m->core, just_one)) <= 0)
241 #endif
242 #ifdef HAVE_OSS
243 if ((n = detect_oss(m->core, just_one)) <= 0)
244 #endif
245 #ifdef HAVE_SOLARIS
246 if ((n = detect_solaris(m->core, just_one)) <= 0)
247 #endif
248 #ifdef OS_IS_WIN32
249 if ((n = detect_waveout(m->core, just_one)) <= 0)
250 #endif
251 {
252 pa_log_warn("failed to detect any sound hardware.");
253 goto fail;
254 }
255
256 pa_log_info("loaded %i modules.", n);
257
258 /* We were successful and can unload ourselves now. */
259 pa_module_unload_request(m, TRUE);
260
261 pa_modargs_free(ma);
262
263 return 0;
264
265 fail:
266 if (ma)
267 pa_modargs_free(ma);
268
269 return -1;
270 }