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