Add "Rear Mic" to alsa mixer paths.
[profile/ivi/pulseaudio.git] / src / modules / module-protocol-stub.c
1 /***
2   This file is part of PulseAudio.
3
4   Copyright 2004-2006 Lennart Poettering
5   Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
6
7   PulseAudio is free software; you can redistribute it and/or modify
8   it under the terms of the GNU Lesser General Public License as published
9   by the Free Software Foundation; either version 2.1 of the License,
10   or (at your option) any later version.
11
12   PulseAudio is distributed in the hope that it will be useful, but
13   WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   General Public License for more details.
16
17   You should have received a copy of the GNU Lesser General Public License
18   along with PulseAudio; if not, write to the Free Software
19   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20   USA.
21 ***/
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <string.h>
28 #include <errno.h>
29 #include <stdio.h>
30 #include <unistd.h>
31 #include <limits.h>
32
33 #ifdef HAVE_SYS_SOCKET_H
34 #include <sys/socket.h>
35 #endif
36 #ifdef HAVE_ARPA_INET_H
37 #include <arpa/inet.h>
38 #endif
39 #ifdef HAVE_NETINET_IN_H
40 #include <netinet/in.h>
41 #endif
42
43 #include <pulse/xmalloc.h>
44
45 #include <pulsecore/winsock.h>
46 #include <pulsecore/core-error.h>
47 #include <pulsecore/module.h>
48 #include <pulsecore/socket-server.h>
49 #include <pulsecore/socket-util.h>
50 #include <pulsecore/core-util.h>
51 #include <pulsecore/modargs.h>
52 #include <pulsecore/log.h>
53 #include <pulsecore/native-common.h>
54 #include <pulsecore/creds.h>
55
56 #ifdef USE_TCP_SOCKETS
57 #define SOCKET_DESCRIPTION "(TCP sockets)"
58 #define SOCKET_USAGE "port=<TCP port number> listen=<address to listen on>"
59 #else
60 #define SOCKET_DESCRIPTION "(UNIX sockets)"
61 #define SOCKET_USAGE "socket=<path to UNIX socket>"
62 #endif
63
64 #if defined(USE_PROTOCOL_SIMPLE)
65 #  include <pulsecore/protocol-simple.h>
66 #  define TCPWRAP_SERVICE "pulseaudio-simple"
67 #  define IPV4_PORT 4711
68 #  define UNIX_SOCKET "simple"
69 #  define MODULE_ARGUMENTS "rate", "format", "channels", "sink", "source", "playback", "record",
70
71 #  if defined(USE_TCP_SOCKETS)
72 #    include "module-simple-protocol-tcp-symdef.h"
73 #  else
74 #    include "module-simple-protocol-unix-symdef.h"
75 #  endif
76
77   PA_MODULE_DESCRIPTION("Simple protocol "SOCKET_DESCRIPTION);
78   PA_MODULE_USAGE("rate=<sample rate> "
79                   "format=<sample format> "
80                   "channels=<number of channels> "
81                   "sink=<sink to connect to> "
82                   "source=<source to connect to> "
83                   "playback=<enable playback?> "
84                   "record=<enable record?> "
85                   SOCKET_USAGE);
86 #elif defined(USE_PROTOCOL_CLI)
87 #  include <pulsecore/protocol-cli.h>
88 #  define TCPWRAP_SERVICE "pulseaudio-cli"
89 #  define IPV4_PORT 4712
90 #  define UNIX_SOCKET "cli"
91 #  define MODULE_ARGUMENTS
92
93 #  ifdef USE_TCP_SOCKETS
94 #    include "module-cli-protocol-tcp-symdef.h"
95 #  else
96 #   include "module-cli-protocol-unix-symdef.h"
97 #  endif
98
99   PA_MODULE_DESCRIPTION("Command line interface protocol "SOCKET_DESCRIPTION);
100   PA_MODULE_USAGE(SOCKET_USAGE);
101 #elif defined(USE_PROTOCOL_HTTP)
102 #  include <pulsecore/protocol-http.h>
103 #  define TCPWRAP_SERVICE "pulseaudio-http"
104 #  define IPV4_PORT 4714
105 #  define UNIX_SOCKET "http"
106 #  define MODULE_ARGUMENTS
107
108 #  ifdef USE_TCP_SOCKETS
109 #    include "module-http-protocol-tcp-symdef.h"
110 #  else
111 #    include "module-http-protocol-unix-symdef.h"
112 #  endif
113
114   PA_MODULE_DESCRIPTION("HTTP "SOCKET_DESCRIPTION);
115   PA_MODULE_USAGE(SOCKET_USAGE);
116 #elif defined(USE_PROTOCOL_NATIVE)
117 #  include <pulsecore/protocol-native.h>
118 #  define TCPWRAP_SERVICE "pulseaudio-native"
119 #  define IPV4_PORT PA_NATIVE_DEFAULT_PORT
120 #  define UNIX_SOCKET PA_NATIVE_DEFAULT_UNIX_SOCKET
121 #  define MODULE_ARGUMENTS_COMMON "cookie", "auth-cookie", "auth-cookie-enabled", "auth-anonymous",
122
123 #  ifdef USE_TCP_SOCKETS
124 #    include "module-native-protocol-tcp-symdef.h"
125 #  else
126 #    include "module-native-protocol-unix-symdef.h"
127 #  endif
128
129 #  if defined(HAVE_CREDS) && !defined(USE_TCP_SOCKETS)
130 #    define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON "auth-group", "auth-group-enable",
131 #    define AUTH_USAGE "auth-group=<system group to allow access> auth-group-enable=<enable auth by UNIX group?> "
132 #  elif defined(USE_TCP_SOCKETS)
133 #    define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON "auth-ip-acl",
134 #    define AUTH_USAGE "auth-ip-acl=<IP address ACL to allow access> "
135 #  else
136 #    define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON
137 #    define AUTH_USAGE
138 #    endif
139
140   PA_MODULE_DESCRIPTION("Native protocol "SOCKET_DESCRIPTION);
141   PA_MODULE_USAGE("auth-anonymous=<don't check for cookies?> "
142                   "auth-cookie=<path to cookie file> "
143                   "auth-cookie-enabled=<enable cookie authentification? "
144                   AUTH_USAGE
145                   SOCKET_USAGE);
146 #elif defined(USE_PROTOCOL_ESOUND)
147 #  include <pulsecore/protocol-esound.h>
148 #  include <pulsecore/esound.h>
149 #  define TCPWRAP_SERVICE "esound"
150 #  define IPV4_PORT ESD_DEFAULT_PORT
151 #  define MODULE_ARGUMENTS_COMMON "sink", "source", "auth-anonymous", "cookie", "auth-cookie", "auth-cookie-enabled",
152
153 #  ifdef USE_TCP_SOCKETS
154 #    include "module-esound-protocol-tcp-symdef.h"
155 #  else
156 #    include "module-esound-protocol-unix-symdef.h"
157 #  endif
158
159 #  if defined(USE_TCP_SOCKETS)
160 #    define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON "auth-ip-acl",
161 #    define AUTH_USAGE "auth-ip-acl=<IP address ACL to allow access> "
162 #  else
163 #    define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON
164 #    define AUTH_USAGE
165 #  endif
166
167   PA_MODULE_DESCRIPTION("ESOUND protocol "SOCKET_DESCRIPTION);
168   PA_MODULE_USAGE("sink=<sink to connect to> "
169                   "source=<source to connect to> "
170                   "auth-anonymous=<don't verify cookies?> "
171                   "auth-cookie=<path to cookie file> "
172                   "auth-cookie-enabled=<enable cookie authentification? "
173                   AUTH_USAGE
174                   SOCKET_USAGE);
175 #else
176 #  error "Broken build system"
177 #endif
178
179 PA_MODULE_LOAD_ONCE(FALSE);
180 PA_MODULE_AUTHOR("Lennart Poettering");
181 PA_MODULE_VERSION(PACKAGE_VERSION);
182
183 static const char* const valid_modargs[] = {
184     MODULE_ARGUMENTS
185 #if defined(USE_TCP_SOCKETS)
186     "port",
187     "listen",
188 #else
189     "socket",
190 #endif
191     NULL
192 };
193
194 struct userdata {
195     pa_module *module;
196
197 #if defined(USE_PROTOCOL_SIMPLE)
198     pa_simple_protocol *simple_protocol;
199     pa_simple_options *simple_options;
200 #elif defined(USE_PROTOCOL_CLI)
201     pa_cli_protocol *cli_protocol;
202 #elif defined(USE_PROTOCOL_HTTP)
203     pa_http_protocol *http_protocol;
204 #elif defined(USE_PROTOCOL_NATIVE)
205     pa_native_protocol *native_protocol;
206     pa_native_options *native_options;
207 #else
208     pa_esound_protocol *esound_protocol;
209     pa_esound_options *esound_options;
210 #endif
211
212 #if defined(USE_TCP_SOCKETS)
213     pa_socket_server *socket_server_ipv4;
214 #  ifdef HAVE_IPV6
215     pa_socket_server *socket_server_ipv6;
216 #  endif
217 #else
218     pa_socket_server *socket_server_unix;
219     char *socket_path;
220 #endif
221 };
222
223 static void socket_server_on_connection_cb(pa_socket_server*s, pa_iochannel *io, void *userdata) {
224     struct userdata *u = userdata;
225
226     pa_assert(s);
227     pa_assert(io);
228     pa_assert(u);
229
230 #if defined(USE_PROTOCOL_SIMPLE)
231     pa_simple_protocol_connect(u->simple_protocol, io, u->simple_options);
232 #elif defined(USE_PROTOCOL_CLI)
233     pa_cli_protocol_connect(u->cli_protocol, io, u->module);
234 #elif defined(USE_PROTOCOL_HTTP)
235     pa_http_protocol_connect(u->http_protocol, io, u->module);
236 #elif defined(USE_PROTOCOL_NATIVE)
237     pa_native_protocol_connect(u->native_protocol, io, u->native_options);
238 #else
239     pa_esound_protocol_connect(u->esound_protocol, io, u->esound_options);
240 #endif
241 }
242
243 int pa__init(pa_module*m) {
244     pa_modargs *ma = NULL;
245     struct userdata *u = NULL;
246
247 #if defined(USE_TCP_SOCKETS)
248     uint32_t port = IPV4_PORT;
249     pa_bool_t port_fallback = TRUE;
250     const char *listen_on;
251 #else
252     int r;
253 #endif
254
255 #if defined(USE_PROTOCOL_NATIVE) || defined(USE_PROTOCOL_HTTP)
256     char t[256];
257 #endif
258
259     pa_assert(m);
260
261     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
262         pa_log("Failed to parse module arguments");
263         goto fail;
264     }
265
266     m->userdata = u = pa_xnew0(struct userdata, 1);
267     u->module = m;
268
269 #if defined(USE_PROTOCOL_SIMPLE)
270     u->simple_protocol = pa_simple_protocol_get(m->core);
271
272     u->simple_options = pa_simple_options_new();
273     if (pa_simple_options_parse(u->simple_options, m->core, ma) < 0)
274         goto fail;
275     u->simple_options->module = m;
276 #elif defined(USE_PROTOCOL_CLI)
277     u->cli_protocol = pa_cli_protocol_get(m->core);
278 #elif defined(USE_PROTOCOL_HTTP)
279     u->http_protocol = pa_http_protocol_get(m->core);
280 #elif defined(USE_PROTOCOL_NATIVE)
281     u->native_protocol = pa_native_protocol_get(m->core);
282
283     u->native_options = pa_native_options_new();
284     if (pa_native_options_parse(u->native_options, m->core, ma) < 0)
285         goto fail;
286     u->native_options->module = m;
287 #else
288     u->esound_protocol = pa_esound_protocol_get(m->core);
289
290     u->esound_options = pa_esound_options_new();
291     if (pa_esound_options_parse(u->esound_options, m->core, ma) < 0)
292         goto fail;
293     u->esound_options->module = m;
294 #endif
295
296 #if defined(USE_TCP_SOCKETS)
297
298     if (pa_in_system_mode() || pa_modargs_get_value(ma, "port", NULL))
299         port_fallback = FALSE;
300
301     if (pa_modargs_get_value_u32(ma, "port", &port) < 0 || port < 1 || port > 0xFFFF) {
302         pa_log("port= expects a numerical argument between 1 and 65535.");
303         goto fail;
304     }
305
306     listen_on = pa_modargs_get_value(ma, "listen", NULL);
307
308     if (listen_on) {
309 #  ifdef HAVE_IPV6
310         u->socket_server_ipv6 = pa_socket_server_new_ipv6_string(m->core->mainloop, listen_on, (uint16_t) port, port_fallback, TCPWRAP_SERVICE);
311 #  endif
312         u->socket_server_ipv4 = pa_socket_server_new_ipv4_string(m->core->mainloop, listen_on, (uint16_t) port, port_fallback, TCPWRAP_SERVICE);
313     } else {
314 #  ifdef HAVE_IPV6
315         u->socket_server_ipv6 = pa_socket_server_new_ipv6_any(m->core->mainloop, (uint16_t) port, port_fallback, TCPWRAP_SERVICE);
316 #  endif
317         u->socket_server_ipv4 = pa_socket_server_new_ipv4_any(m->core->mainloop, (uint16_t) port, port_fallback, TCPWRAP_SERVICE);
318     }
319
320 #  ifdef HAVE_IPV6
321     if (!u->socket_server_ipv4 && !u->socket_server_ipv6)
322 #  else
323     if (!u->socket_server_ipv4)
324 #  endif
325         goto fail;
326
327     if (u->socket_server_ipv4)
328         pa_socket_server_set_callback(u->socket_server_ipv4, socket_server_on_connection_cb, u);
329 #  ifdef HAVE_IPV6
330     if (u->socket_server_ipv6)
331         pa_socket_server_set_callback(u->socket_server_ipv6, socket_server_on_connection_cb, u);
332 #  endif
333
334 #else
335
336 #  if defined(USE_PROTOCOL_ESOUND)
337
338 #    if defined(USE_PER_USER_ESOUND_SOCKET)
339     u->socket_path = pa_sprintf_malloc("/tmp/.esd-%lu/socket", (unsigned long) getuid());
340 #    else
341     u->socket_path = pa_xstrdup("/tmp/.esd/socket");
342 #    endif
343
344     /* This socket doesn't reside in our own runtime dir but in
345      * /tmp/.esd/, hence we have to create the dir first */
346
347     if (pa_make_secure_parent_dir(u->socket_path, pa_in_system_mode() ? 0755U : 0700U, (uid_t)-1, (gid_t)-1) < 0) {
348         pa_log("Failed to create socket directory '%s': %s\n", u->socket_path, pa_cstrerror(errno));
349         goto fail;
350     }
351
352 #  else
353     if (!(u->socket_path = pa_runtime_path(pa_modargs_get_value(ma, "socket", UNIX_SOCKET)))) {
354         pa_log("Failed to generate socket path.");
355         goto fail;
356     }
357 #  endif
358
359     if ((r = pa_unix_socket_remove_stale(u->socket_path)) < 0) {
360         pa_log("Failed to remove stale UNIX socket '%s': %s", u->socket_path, pa_cstrerror(errno));
361         goto fail;
362     } else if (r > 0)
363         pa_log_info("Removed stale UNIX socket '%s'.", u->socket_path);
364
365     if (!(u->socket_server_unix = pa_socket_server_new_unix(m->core->mainloop, u->socket_path)))
366         goto fail;
367
368     pa_socket_server_set_callback(u->socket_server_unix, socket_server_on_connection_cb, u);
369
370 #endif
371
372 #if defined(USE_PROTOCOL_NATIVE)
373 #  if defined(USE_TCP_SOCKETS)
374     if (u->socket_server_ipv4)
375         if (pa_socket_server_get_address(u->socket_server_ipv4, t, sizeof(t)))
376             pa_native_protocol_add_server_string(u->native_protocol, t);
377
378 #    ifdef HAVE_IPV6
379     if (u->socket_server_ipv6)
380         if (pa_socket_server_get_address(u->socket_server_ipv6, t, sizeof(t)))
381             pa_native_protocol_add_server_string(u->native_protocol, t);
382 #    endif
383 #  else
384     if (pa_socket_server_get_address(u->socket_server_unix, t, sizeof(t)))
385         pa_native_protocol_add_server_string(u->native_protocol, t);
386
387 #  endif
388 #endif
389
390 #if defined(USE_PROTOCOL_HTTP)
391 #if defined(USE_TCP_SOCKETS)
392     if (u->socket_server_ipv4)
393         if (pa_socket_server_get_address(u->socket_server_ipv4, t, sizeof(t)))
394             pa_http_protocol_add_server_string(u->http_protocol, t);
395
396 #ifdef HAVE_IPV6
397     if (u->socket_server_ipv6)
398         if (pa_socket_server_get_address(u->socket_server_ipv6, t, sizeof(t)))
399             pa_http_protocol_add_server_string(u->http_protocol, t);
400 #endif /* HAVE_IPV6 */
401 #else /* USE_TCP_SOCKETS */
402     if (pa_socket_server_get_address(u->socket_server_unix, t, sizeof(t)))
403         pa_http_protocol_add_server_string(u->http_protocol, t);
404
405 #endif /* USE_TCP_SOCKETS */
406 #endif /* USE_PROTOCOL_HTTP */
407
408     if (ma)
409         pa_modargs_free(ma);
410
411     return 0;
412
413 fail:
414
415     if (ma)
416         pa_modargs_free(ma);
417
418     pa__done(m);
419
420     return -1;
421 }
422
423 void pa__done(pa_module*m) {
424     struct userdata *u;
425
426     pa_assert(m);
427
428     if (!(u = m->userdata))
429         return;
430
431 #if defined(USE_PROTOCOL_SIMPLE)
432     if (u->simple_protocol) {
433         pa_simple_protocol_disconnect(u->simple_protocol, u->module);
434         pa_simple_protocol_unref(u->simple_protocol);
435     }
436     if (u->simple_options)
437         pa_simple_options_unref(u->simple_options);
438 #elif defined(USE_PROTOCOL_CLI)
439     if (u->cli_protocol) {
440         pa_cli_protocol_disconnect(u->cli_protocol, u->module);
441         pa_cli_protocol_unref(u->cli_protocol);
442     }
443 #elif defined(USE_PROTOCOL_HTTP)
444     if (u->http_protocol) {
445         char t[256];
446
447 #if defined(USE_TCP_SOCKETS)
448         if (u->socket_server_ipv4)
449             if (pa_socket_server_get_address(u->socket_server_ipv4, t, sizeof(t)))
450                 pa_http_protocol_remove_server_string(u->http_protocol, t);
451
452 #ifdef HAVE_IPV6
453         if (u->socket_server_ipv6)
454             if (pa_socket_server_get_address(u->socket_server_ipv6, t, sizeof(t)))
455                 pa_http_protocol_remove_server_string(u->http_protocol, t);
456 #endif /* HAVE_IPV6 */
457 #else /* USE_TCP_SOCKETS */
458         if (u->socket_server_unix)
459             if (pa_socket_server_get_address(u->socket_server_unix, t, sizeof(t)))
460                 pa_http_protocol_remove_server_string(u->http_protocol, t);
461 #endif /* USE_PROTOCOL_HTTP */
462
463         pa_http_protocol_disconnect(u->http_protocol, u->module);
464         pa_http_protocol_unref(u->http_protocol);
465     }
466 #elif defined(USE_PROTOCOL_NATIVE)
467     if (u->native_protocol) {
468
469         char t[256];
470
471 #  if defined(USE_TCP_SOCKETS)
472         if (u->socket_server_ipv4)
473             if (pa_socket_server_get_address(u->socket_server_ipv4, t, sizeof(t)))
474                 pa_native_protocol_remove_server_string(u->native_protocol, t);
475
476 #    ifdef HAVE_IPV6
477         if (u->socket_server_ipv6)
478             if (pa_socket_server_get_address(u->socket_server_ipv6, t, sizeof(t)))
479                 pa_native_protocol_remove_server_string(u->native_protocol, t);
480 #    endif
481 #  else
482         if (u->socket_server_unix)
483             if (pa_socket_server_get_address(u->socket_server_unix, t, sizeof(t)))
484                 pa_native_protocol_remove_server_string(u->native_protocol, t);
485 #  endif
486
487         pa_native_protocol_disconnect(u->native_protocol, u->module);
488         pa_native_protocol_unref(u->native_protocol);
489     }
490     if (u->native_options)
491         pa_native_options_unref(u->native_options);
492 #else
493     if (u->esound_protocol) {
494         pa_esound_protocol_disconnect(u->esound_protocol, u->module);
495         pa_esound_protocol_unref(u->esound_protocol);
496     }
497     if (u->esound_options)
498         pa_esound_options_unref(u->esound_options);
499 #endif
500
501 #if defined(USE_TCP_SOCKETS)
502     if (u->socket_server_ipv4)
503         pa_socket_server_unref(u->socket_server_ipv4);
504 #  ifdef HAVE_IPV6
505     if (u->socket_server_ipv6)
506         pa_socket_server_unref(u->socket_server_ipv6);
507 #  endif
508 #else
509     if (u->socket_server_unix)
510         pa_socket_server_unref(u->socket_server_unix);
511
512 # if defined(USE_PROTOCOL_ESOUND) && !defined(USE_PER_USER_ESOUND_SOCKET)
513     if (u->socket_path) {
514         char *p = pa_parent_dir(u->socket_path);
515         rmdir(p);
516         pa_xfree(p);
517     }
518 # endif
519
520     pa_xfree(u->socket_path);
521 #endif
522
523     pa_xfree(u);
524 }