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
34 #include <sys/types.h>
37 #include <pulsecore/core-error.h>
38 #include <pulsecore/module.h>
39 #include <pulsecore/modargs.h>
40 #include <pulsecore/log.h>
41 #include <pulsecore/core-util.h>
42 #include <pulsecore/macro.h>
44 #include "module-detect-symdef.h"
46 PA_MODULE_AUTHOR("Lennart Poettering");
47 PA_MODULE_DESCRIPTION("Detect available audio hardware and load matching drivers");
48 PA_MODULE_VERSION(PACKAGE_VERSION);
49 PA_MODULE_LOAD_ONCE(TRUE);
50 PA_MODULE_USAGE("just-one=<boolean>");
51 PA_MODULE_DEPRECATED("Please use module-udev-detect instead of module-detect!");
53 static const char* const valid_modargs[] = {
60 static int detect_alsa(pa_core *c, int just_one) {
62 int n = 0, n_sink = 0, n_source = 0;
64 if (!(f = pa_fopen_cloexec("/proc/asound/devices", "r"))) {
67 pa_log_error("open(\"/proc/asound/devices\") failed: %s", pa_cstrerror(errno));
73 char line[64], args[64];
74 unsigned device, subdevice;
77 if (!fgets(line, sizeof(line), f))
80 line[strcspn(line, "\r\n")] = 0;
82 if (pa_endswith(line, "digital audio playback"))
84 else if (pa_endswith(line, "digital audio capture"))
89 if (just_one && is_sink && n_sink >= 1)
92 if (just_one && !is_sink && n_source >= 1)
95 if (sscanf(line, " %*i: [%u- %u]: ", &device, &subdevice) != 2)
98 /* Only one sink per device */
102 pa_snprintf(args, sizeof(args), "device_id=%u", device);
103 if (!pa_module_load(c, is_sink ? "module-alsa-sink" : "module-alsa-source", args))
120 #ifdef HAVE_OSS_OUTPUT
121 static int detect_oss(pa_core *c, int just_one) {
125 if (!(f = pa_fopen_cloexec("/dev/sndstat", "r")) &&
126 !(f = pa_fopen_cloexec("/proc/sndstat", "r")) &&
127 !(f = pa_fopen_cloexec("/proc/asound/oss/sndstat", "r"))) {
130 pa_log_error("failed to open OSS sndstat device: %s", pa_cstrerror(errno));
136 char line[64], args[64];
139 if (!fgets(line, sizeof(line), f))
142 line[strcspn(line, "\r\n")] = 0;
145 b = strcmp(line, "Audio devices:") == 0 || strcmp(line, "Installed devices:") == 0;
152 if (sscanf(line, "%u: ", &device) == 1) {
154 pa_snprintf(args, sizeof(args), "device=/dev/dsp");
156 pa_snprintf(args, sizeof(args), "device=/dev/dsp%u", device);
158 if (!pa_module_load(c, "module-oss", args))
161 } else if (sscanf(line, "pcm%u: ", &device) == 1) {
162 /* FreeBSD support, the devices are named /dev/dsp0.0, dsp0.1 and so on */
163 pa_snprintf(args, sizeof(args), "device=/dev/dsp%u.0", device);
165 if (!pa_module_load(c, "module-oss", args))
181 static int detect_solaris(pa_core *c, int just_one) {
186 dev = getenv("AUDIODEV");
190 if (stat(dev, &s) < 0) {
192 pa_log_error("failed to open device %s: %s", dev, pa_cstrerror(errno));
196 if (!S_ISCHR(s.st_mode))
199 pa_snprintf(args, sizeof(args), "device=%s", dev);
201 if (!pa_module_load(c, "module-solaris", args))
209 static int detect_waveout(pa_core *c, int just_one) {
211 * FIXME: No point in enumerating devices until the plugin supports
212 * selecting anything but the first.
214 if (!pa_module_load(c, "module-waveout", ""))
221 int pa__init(pa_module*m) {
222 pa_bool_t just_one = FALSE;
228 if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
229 pa_log("Failed to parse module arguments");
233 if (pa_modargs_get_value_boolean(ma, "just-one", &just_one) < 0) {
234 pa_log("just_one= expects a boolean argument.");
239 if ((n = detect_alsa(m->core, just_one)) <= 0)
241 #ifdef HAVE_OSS_OUTPUT
242 if ((n = detect_oss(m->core, just_one)) <= 0)
245 if ((n = detect_solaris(m->core, just_one)) <= 0)
248 if ((n = detect_waveout(m->core, just_one)) <= 0)
251 pa_log_warn("failed to detect any sound hardware.");
255 pa_log_info("loaded %i modules.", n);
257 /* We were successful and can unload ourselves now. */
258 pa_module_unload_request(m, TRUE);