Revert "pacat: Don't use any buffer attr if we don't set any latency/process time...
[pulseaudio-mirror.git] / src / modules / module-detect.c
blob1fe8eb8b63a1a46ade9ef53b0ec51d52904b8764
1 /***
2 This file is part of PulseAudio.
4 Copyright 2006 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
6 Copyright 2006 Diego Pettenò
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.
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.
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 ***/
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
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>
37 #include <pulse/xmalloc.h>
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>
46 #include "module-detect-symdef.h"
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 PA_MODULE_DEPRECATED("Please use module-udev-detect instead of module-detect!");
55 static const char* const valid_modargs[] = {
56 "just-one",
57 NULL
60 #ifdef HAVE_ALSA
62 static int detect_alsa(pa_core *c, int just_one) {
63 FILE *f;
64 int n = 0, n_sink = 0, n_source = 0;
66 if (!(f = pa_fopen_cloexec("/proc/asound/devices", "r"))) {
68 if (errno != ENOENT)
69 pa_log_error("open(\"/proc/asound/devices\") failed: %s", pa_cstrerror(errno));
71 return -1;
74 while (!feof(f)) {
75 char line[64], args[64];
76 unsigned device, subdevice;
77 int is_sink;
79 if (!fgets(line, sizeof(line), f))
80 break;
82 line[strcspn(line, "\r\n")] = 0;
84 if (pa_endswith(line, "digital audio playback"))
85 is_sink = 1;
86 else if (pa_endswith(line, "digital audio capture"))
87 is_sink = 0;
88 else
89 continue;
91 if (just_one && is_sink && n_sink >= 1)
92 continue;
94 if (just_one && !is_sink && n_source >= 1)
95 continue;
97 if (sscanf(line, " %*i: [%u- %u]: ", &device, &subdevice) != 2)
98 continue;
100 /* Only one sink per device */
101 if (subdevice != 0)
102 continue;
104 pa_snprintf(args, sizeof(args), "device_id=%u", device);
105 if (!pa_module_load(c, is_sink ? "module-alsa-sink" : "module-alsa-source", args))
106 continue;
108 n++;
110 if (is_sink)
111 n_sink++;
112 else
113 n_source++;
116 fclose(f);
118 return n;
120 #endif
122 #ifdef HAVE_OSS_OUTPUT
123 static int detect_oss(pa_core *c, int just_one) {
124 FILE *f;
125 int n = 0, b = 0;
127 if (!(f = pa_fopen_cloexec("/dev/sndstat", "r")) &&
128 !(f = pa_fopen_cloexec("/proc/sndstat", "r")) &&
129 !(f = pa_fopen_cloexec("/proc/asound/oss/sndstat", "r"))) {
131 if (errno != ENOENT)
132 pa_log_error("failed to open OSS sndstat device: %s", pa_cstrerror(errno));
134 return -1;
137 while (!feof(f)) {
138 char line[64], args[64];
139 unsigned device;
141 if (!fgets(line, sizeof(line), f))
142 break;
144 line[strcspn(line, "\r\n")] = 0;
146 if (!b) {
147 b = strcmp(line, "Audio devices:") == 0 || strcmp(line, "Installed devices:") == 0;
148 continue;
151 if (line[0] == 0)
152 break;
154 if (sscanf(line, "%u: ", &device) == 1) {
155 if (device == 0)
156 pa_snprintf(args, sizeof(args), "device=/dev/dsp");
157 else
158 pa_snprintf(args, sizeof(args), "device=/dev/dsp%u", device);
160 if (!pa_module_load(c, "module-oss", args))
161 continue;
163 } else if (sscanf(line, "pcm%u: ", &device) == 1) {
164 /* FreeBSD support, the devices are named /dev/dsp0.0, dsp0.1 and so on */
165 pa_snprintf(args, sizeof(args), "device=/dev/dsp%u.0", device);
167 if (!pa_module_load(c, "module-oss", args))
168 continue;
171 n++;
173 if (just_one)
174 break;
177 fclose(f);
178 return n;
180 #endif
182 #ifdef HAVE_SOLARIS
183 static int detect_solaris(pa_core *c, int just_one) {
184 struct stat s;
185 const char *dev;
186 char args[64];
188 dev = getenv("AUDIODEV");
189 if (!dev)
190 dev = "/dev/audio";
192 if (stat(dev, &s) < 0) {
193 if (errno != ENOENT)
194 pa_log_error("failed to open device %s: %s", dev, pa_cstrerror(errno));
195 return -1;
198 if (!S_ISCHR(s.st_mode))
199 return 0;
201 pa_snprintf(args, sizeof(args), "device=%s", dev);
203 if (!pa_module_load(c, "module-solaris", args))
204 return 0;
206 return 1;
208 #endif
210 #ifdef OS_IS_WIN32
211 static int detect_waveout(pa_core *c, int just_one) {
213 * FIXME: No point in enumerating devices until the plugin supports
214 * selecting anything but the first.
216 if (!pa_module_load(c, "module-waveout", ""))
217 return 0;
219 return 1;
221 #endif
223 int pa__init(pa_module*m) {
224 pa_bool_t just_one = FALSE;
225 int n = 0;
226 pa_modargs *ma;
228 pa_assert(m);
230 if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
231 pa_log("Failed to parse module arguments");
232 goto fail;
235 if (pa_modargs_get_value_boolean(ma, "just-one", &just_one) < 0) {
236 pa_log("just_one= expects a boolean argument.");
237 goto fail;
240 #ifdef HAVE_ALSA
241 if ((n = detect_alsa(m->core, just_one)) <= 0)
242 #endif
243 #ifdef HAVE_OSS_OUTPUT
244 if ((n = detect_oss(m->core, just_one)) <= 0)
245 #endif
246 #ifdef HAVE_SOLARIS
247 if ((n = detect_solaris(m->core, just_one)) <= 0)
248 #endif
249 #ifdef OS_IS_WIN32
250 if ((n = detect_waveout(m->core, just_one)) <= 0)
251 #endif
253 pa_log_warn("failed to detect any sound hardware.");
254 goto fail;
257 pa_log_info("loaded %i modules.", n);
259 /* We were successful and can unload ourselves now. */
260 pa_module_unload_request(m, TRUE);
262 pa_modargs_free(ma);
264 return 0;
266 fail:
267 if (ma)
268 pa_modargs_free(ma);
270 return -1;