lirc: fix logic behind mute buttons
[profile/ivi/pulseaudio-panda.git] / 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 }