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 <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-hal-detect instead of module-detect!");
55 static const char* const valid_modargs
[] = {
62 static int detect_alsa(pa_core
*c
, int just_one
) {
64 int n
= 0, n_sink
= 0, n_source
= 0;
66 if (!(f
= fopen("/proc/asound/devices", "r"))) {
69 pa_log_error("open(\"/proc/asound/devices\") failed: %s", pa_cstrerror(errno
));
75 char line
[64], args
[64];
76 unsigned device
, subdevice
;
79 if (!fgets(line
, sizeof(line
), f
))
82 line
[strcspn(line
, "\r\n")] = 0;
84 if (pa_endswith(line
, "digital audio playback"))
86 else if (pa_endswith(line
, "digital audio capture"))
91 if (just_one
&& is_sink
&& n_sink
>= 1)
94 if (just_one
&& !is_sink
&& n_source
>= 1)
97 if (sscanf(line
, " %*i: [%u- %u]: ", &device
, &subdevice
) != 2)
100 /* Only one sink per device */
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
))
122 #ifdef HAVE_OSS_OUTPUT
123 static int detect_oss(pa_core
*c
, int just_one
) {
127 if (!(f
= fopen("/dev/sndstat", "r")) &&
128 !(f
= fopen("/proc/sndstat", "r")) &&
129 !(f
= fopen("/proc/asound/oss/sndstat", "r"))) {
132 pa_log_error("failed to open OSS sndstat device: %s", pa_cstrerror(errno
));
138 char line
[64], args
[64];
141 if (!fgets(line
, sizeof(line
), f
))
144 line
[strcspn(line
, "\r\n")] = 0;
147 b
= strcmp(line
, "Audio devices:") == 0 || strcmp(line
, "Installed devices:") == 0;
154 if (sscanf(line
, "%u: ", &device
) == 1) {
156 pa_snprintf(args
, sizeof(args
), "device=/dev/dsp");
158 pa_snprintf(args
, sizeof(args
), "device=/dev/dsp%u", device
);
160 if (!pa_module_load(c
, "module-oss", args
))
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
))
183 static int detect_solaris(pa_core
*c
, int just_one
) {
188 dev
= getenv("AUDIODEV");
192 if (stat(dev
, &s
) < 0) {
194 pa_log_error("failed to open device %s: %s", dev
, pa_cstrerror(errno
));
198 if (!S_ISCHR(s
.st_mode
))
201 pa_snprintf(args
, sizeof(args
), "device=%s", dev
);
203 if (!pa_module_load(c
, "module-solaris", args
))
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", ""))
223 int pa__init(pa_module
*m
) {
224 pa_bool_t just_one
= FALSE
;
230 if (!(ma
= pa_modargs_new(m
->argument
, valid_modargs
))) {
231 pa_log("Failed to parse module arguments");
235 if (pa_modargs_get_value_boolean(ma
, "just-one", &just_one
) < 0) {
236 pa_log("just_one= expects a boolean argument.");
241 if ((n
= detect_alsa(m
->core
, just_one
)) <= 0)
243 #ifdef HAVE_OSS_OUTPUT
244 if ((n
= detect_oss(m
->core
, just_one
)) <= 0)
247 if ((n
= detect_solaris(m
->core
, just_one
)) <= 0)
250 if ((n
= detect_waveout(m
->core
, just_one
)) <= 0)
253 pa_log_warn("failed to detect any sound hardware.");
257 pa_log_info("loaded %i modules.", n
);
259 /* We were successful and can unload ourselves now. */
260 pa_module_unload_request(m
, TRUE
);