5bd3448b04039e14c12e334f0e763c449a692b90
[profile/ivi/pulseaudio-panda.git] / src / pulse / context.c
1 /***
2   This file is part of PulseAudio.
3
4   Copyright 2004-2008 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 <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <sys/types.h>
31 #include <unistd.h>
32 #include <sys/stat.h>
33 #include <errno.h>
34 #include <signal.h>
35
36 #ifdef HAVE_SYS_WAIT_H
37 #include <sys/wait.h>
38 #endif
39
40 #ifdef HAVE_NETDB_H
41 #include <netdb.h>
42 #endif
43
44 #include <pulse/version.h>
45 #include <pulse/xmalloc.h>
46 #include <pulse/util.h>
47 #include <pulse/mainloop.h>
48 #include <pulse/timeval.h>
49 #include <pulse/fork-detect.h>
50 #include <pulse/client-conf.h>
51 #ifdef HAVE_X11
52 #include <pulse/client-conf-x11.h>
53 #endif
54
55 #include <pulsecore/core-error.h>
56 #include <pulsecore/i18n.h>
57 #include <pulsecore/native-common.h>
58 #include <pulsecore/pdispatch.h>
59 #include <pulsecore/pstream.h>
60 #include <pulsecore/hashmap.h>
61 #include <pulsecore/socket-client.h>
62 #include <pulsecore/pstream-util.h>
63 #include <pulsecore/core-rtclock.h>
64 #include <pulsecore/core-util.h>
65 #include <pulsecore/log.h>
66 #include <pulsecore/socket.h>
67 #include <pulsecore/creds.h>
68 #include <pulsecore/macro.h>
69 #include <pulsecore/proplist-util.h>
70
71 #include "internal.h"
72 #include "context.h"
73
74 void pa_command_extension(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
75
76 static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = {
77     [PA_COMMAND_REQUEST] = pa_command_request,
78     [PA_COMMAND_OVERFLOW] = pa_command_overflow_or_underflow,
79     [PA_COMMAND_UNDERFLOW] = pa_command_overflow_or_underflow,
80     [PA_COMMAND_PLAYBACK_STREAM_KILLED] = pa_command_stream_killed,
81     [PA_COMMAND_RECORD_STREAM_KILLED] = pa_command_stream_killed,
82     [PA_COMMAND_PLAYBACK_STREAM_MOVED] = pa_command_stream_moved,
83     [PA_COMMAND_RECORD_STREAM_MOVED] = pa_command_stream_moved,
84     [PA_COMMAND_PLAYBACK_STREAM_SUSPENDED] = pa_command_stream_suspended,
85     [PA_COMMAND_RECORD_STREAM_SUSPENDED] = pa_command_stream_suspended,
86     [PA_COMMAND_STARTED] = pa_command_stream_started,
87     [PA_COMMAND_SUBSCRIBE_EVENT] = pa_command_subscribe_event,
88     [PA_COMMAND_EXTENSION] = pa_command_extension,
89     [PA_COMMAND_PLAYBACK_STREAM_EVENT] = pa_command_stream_event,
90     [PA_COMMAND_RECORD_STREAM_EVENT] = pa_command_stream_event,
91     [PA_COMMAND_CLIENT_EVENT] = pa_command_client_event,
92     [PA_COMMAND_PLAYBACK_BUFFER_ATTR_CHANGED] = pa_command_stream_buffer_attr,
93     [PA_COMMAND_RECORD_BUFFER_ATTR_CHANGED] = pa_command_stream_buffer_attr
94 };
95 static void context_free(pa_context *c);
96
97 #ifdef HAVE_DBUS
98 static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *message, void *userdata);
99 #endif
100
101 pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) {
102     return pa_context_new_with_proplist(mainloop, name, NULL);
103 }
104
105 static void reset_callbacks(pa_context *c) {
106     pa_assert(c);
107
108     c->state_callback = NULL;
109     c->state_userdata = NULL;
110
111     c->subscribe_callback = NULL;
112     c->subscribe_userdata = NULL;
113
114     c->event_callback = NULL;
115     c->event_userdata = NULL;
116
117     c->ext_device_manager.callback = NULL;
118     c->ext_device_manager.userdata = NULL;
119
120     c->ext_device_restore.callback = NULL;
121     c->ext_device_restore.userdata = NULL;
122
123     c->ext_stream_restore.callback = NULL;
124     c->ext_stream_restore.userdata = NULL;
125 }
126
127 pa_context *pa_context_new_with_proplist(pa_mainloop_api *mainloop, const char *name, pa_proplist *p) {
128     pa_context *c;
129
130     pa_assert(mainloop);
131
132     if (pa_detect_fork())
133         return NULL;
134
135     pa_init_i18n();
136
137     c = pa_xnew0(pa_context, 1);
138     PA_REFCNT_INIT(c);
139
140     c->proplist = p ? pa_proplist_copy(p) : pa_proplist_new();
141
142     if (name)
143         pa_proplist_sets(c->proplist, PA_PROP_APPLICATION_NAME, name);
144
145 #ifdef HAVE_DBUS
146     c->system_bus = c->session_bus = NULL;
147 #endif
148     c->mainloop = mainloop;
149     c->playback_streams = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
150     c->record_streams = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
151     c->client_index = PA_INVALID_INDEX;
152     c->use_rtclock = pa_mainloop_is_our_api(mainloop);
153
154     PA_LLIST_HEAD_INIT(pa_stream, c->streams);
155     PA_LLIST_HEAD_INIT(pa_operation, c->operations);
156
157     c->error = PA_OK;
158     c->state = PA_CONTEXT_UNCONNECTED;
159
160     reset_callbacks(c);
161
162 #ifndef MSG_NOSIGNAL
163 #ifdef SIGPIPE
164     pa_check_signal_is_blocked(SIGPIPE);
165 #endif
166 #endif
167
168     c->conf = pa_client_conf_new();
169     pa_client_conf_load(c->conf, NULL);
170 #ifdef HAVE_X11
171     pa_client_conf_from_x11(c->conf, NULL);
172 #endif
173     pa_client_conf_env(c->conf);
174
175     if (!(c->mempool = pa_mempool_new(!c->conf->disable_shm, c->conf->shm_size))) {
176
177         if (!c->conf->disable_shm)
178             c->mempool = pa_mempool_new(FALSE, c->conf->shm_size);
179
180         if (!c->mempool) {
181             context_free(c);
182             return NULL;
183         }
184     }
185
186     return c;
187 }
188
189 static void context_unlink(pa_context *c) {
190     pa_stream *s;
191
192     pa_assert(c);
193
194     s = c->streams ? pa_stream_ref(c->streams) : NULL;
195     while (s) {
196         pa_stream *n = s->next ? pa_stream_ref(s->next) : NULL;
197         pa_stream_set_state(s, c->state == PA_CONTEXT_FAILED ? PA_STREAM_FAILED : PA_STREAM_TERMINATED);
198         pa_stream_unref(s);
199         s = n;
200     }
201
202     while (c->operations)
203         pa_operation_cancel(c->operations);
204
205     if (c->pdispatch) {
206         pa_pdispatch_unref(c->pdispatch);
207         c->pdispatch = NULL;
208     }
209
210     if (c->pstream) {
211         pa_pstream_unlink(c->pstream);
212         pa_pstream_unref(c->pstream);
213         c->pstream = NULL;
214     }
215
216     if (c->client) {
217         pa_socket_client_unref(c->client);
218         c->client = NULL;
219     }
220
221     reset_callbacks(c);
222 }
223
224 static void context_free(pa_context *c) {
225     pa_assert(c);
226
227     context_unlink(c);
228
229 #ifdef HAVE_DBUS
230     if (c->system_bus) {
231         if (c->filter_added)
232             dbus_connection_remove_filter(pa_dbus_wrap_connection_get(c->system_bus), filter_cb, c);
233         pa_dbus_wrap_connection_free(c->system_bus);
234     }
235
236     if (c->session_bus) {
237         if (c->filter_added)
238             dbus_connection_remove_filter(pa_dbus_wrap_connection_get(c->session_bus), filter_cb, c);
239         pa_dbus_wrap_connection_free(c->session_bus);
240     }
241 #endif
242
243     if (c->record_streams)
244         pa_hashmap_free(c->record_streams, NULL, NULL);
245     if (c->playback_streams)
246         pa_hashmap_free(c->playback_streams, NULL, NULL);
247
248     if (c->mempool)
249         pa_mempool_free(c->mempool);
250
251     if (c->conf)
252         pa_client_conf_free(c->conf);
253
254     pa_strlist_free(c->server_list);
255
256     if (c->proplist)
257         pa_proplist_free(c->proplist);
258
259     pa_xfree(c->server);
260     pa_xfree(c);
261 }
262
263 pa_context* pa_context_ref(pa_context *c) {
264     pa_assert(c);
265     pa_assert(PA_REFCNT_VALUE(c) >= 1);
266
267     PA_REFCNT_INC(c);
268     return c;
269 }
270
271 void pa_context_unref(pa_context *c) {
272     pa_assert(c);
273     pa_assert(PA_REFCNT_VALUE(c) >= 1);
274
275     if (PA_REFCNT_DEC(c) <= 0)
276         context_free(c);
277 }
278
279 void pa_context_set_state(pa_context *c, pa_context_state_t st) {
280     pa_assert(c);
281     pa_assert(PA_REFCNT_VALUE(c) >= 1);
282
283     if (c->state == st)
284         return;
285
286     pa_context_ref(c);
287
288     c->state = st;
289
290     if (c->state_callback)
291         c->state_callback(c, c->state_userdata);
292
293     if (st == PA_CONTEXT_FAILED || st == PA_CONTEXT_TERMINATED)
294         context_unlink(c);
295
296     pa_context_unref(c);
297 }
298
299 int pa_context_set_error(pa_context *c, int error) {
300     pa_assert(error >= 0);
301     pa_assert(error < PA_ERR_MAX);
302
303     if (c)
304         c->error = error;
305
306     return error;
307 }
308
309 void pa_context_fail(pa_context *c, int error) {
310     pa_assert(c);
311     pa_assert(PA_REFCNT_VALUE(c) >= 1);
312
313     pa_context_set_error(c, error);
314     pa_context_set_state(c, PA_CONTEXT_FAILED);
315 }
316
317 static void pstream_die_callback(pa_pstream *p, void *userdata) {
318     pa_context *c = userdata;
319
320     pa_assert(p);
321     pa_assert(c);
322
323     pa_context_fail(c, PA_ERR_CONNECTIONTERMINATED);
324 }
325
326 static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_creds *creds, void *userdata) {
327     pa_context *c = userdata;
328
329     pa_assert(p);
330     pa_assert(packet);
331     pa_assert(c);
332
333     pa_context_ref(c);
334
335     if (pa_pdispatch_run(c->pdispatch, packet, creds, c) < 0)
336         pa_context_fail(c, PA_ERR_PROTOCOL);
337
338     pa_context_unref(c);
339 }
340
341 static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t offset, pa_seek_mode_t seek, const pa_memchunk *chunk, void *userdata) {
342     pa_context *c = userdata;
343     pa_stream *s;
344
345     pa_assert(p);
346     pa_assert(chunk);
347     pa_assert(chunk->length > 0);
348     pa_assert(c);
349     pa_assert(PA_REFCNT_VALUE(c) >= 1);
350
351     pa_context_ref(c);
352
353     if ((s = pa_hashmap_get(c->record_streams, PA_UINT32_TO_PTR(channel)))) {
354
355         if (chunk->memblock) {
356             pa_memblockq_seek(s->record_memblockq, offset, seek, TRUE);
357             pa_memblockq_push_align(s->record_memblockq, chunk);
358         } else
359             pa_memblockq_seek(s->record_memblockq, offset+chunk->length, seek, TRUE);
360
361         if (s->read_callback) {
362             size_t l;
363
364             if ((l = pa_memblockq_get_length(s->record_memblockq)) > 0)
365                 s->read_callback(s, l, s->read_userdata);
366         }
367     }
368
369     pa_context_unref(c);
370 }
371
372 int pa_context_handle_error(pa_context *c, uint32_t command, pa_tagstruct *t, pa_bool_t fail) {
373     uint32_t err;
374     pa_assert(c);
375     pa_assert(PA_REFCNT_VALUE(c) >= 1);
376
377     if (command == PA_COMMAND_ERROR) {
378         pa_assert(t);
379
380         if (pa_tagstruct_getu32(t, &err) < 0 ||
381             !pa_tagstruct_eof(t)) {
382             pa_context_fail(c, PA_ERR_PROTOCOL);
383             return -1;
384         }
385
386     } else if (command == PA_COMMAND_TIMEOUT)
387         err = PA_ERR_TIMEOUT;
388     else {
389         pa_context_fail(c, PA_ERR_PROTOCOL);
390         return -1;
391     }
392
393     if (err == PA_OK) {
394         pa_context_fail(c, PA_ERR_PROTOCOL);
395         return -1;
396     }
397
398     if (err >= PA_ERR_MAX)
399         err = PA_ERR_UNKNOWN;
400
401     if (fail) {
402         pa_context_fail(c, (int) err);
403         return -1;
404     }
405
406     pa_context_set_error(c, (int) err);
407
408     return 0;
409 }
410
411 static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
412     pa_context *c = userdata;
413
414     pa_assert(pd);
415     pa_assert(c);
416     pa_assert(c->state == PA_CONTEXT_AUTHORIZING || c->state == PA_CONTEXT_SETTING_NAME);
417
418     pa_context_ref(c);
419
420     if (command != PA_COMMAND_REPLY) {
421         pa_context_handle_error(c, command, t, TRUE);
422         goto finish;
423     }
424
425     switch(c->state) {
426         case PA_CONTEXT_AUTHORIZING: {
427             pa_tagstruct *reply;
428             pa_bool_t shm_on_remote = FALSE;
429
430             if (pa_tagstruct_getu32(t, &c->version) < 0 ||
431                 !pa_tagstruct_eof(t)) {
432                 pa_context_fail(c, PA_ERR_PROTOCOL);
433                 goto finish;
434             }
435
436             /* Minimum supported version */
437             if (c->version < 8) {
438                 pa_context_fail(c, PA_ERR_VERSION);
439                 goto finish;
440             }
441
442             /* Starting with protocol version 13 the MSB of the version
443                tag reflects if shm is available for this connection or
444                not. */
445             if (c->version >= 13) {
446                 shm_on_remote = !!(c->version & 0x80000000U);
447                 c->version &= 0x7FFFFFFFU;
448             }
449
450             pa_log_debug("Protocol version: remote %u, local %u", c->version, PA_PROTOCOL_VERSION);
451
452             /* Enable shared memory support if possible */
453             if (c->do_shm)
454                 if (c->version < 10 || (c->version >= 13 && !shm_on_remote))
455                     c->do_shm = FALSE;
456
457             if (c->do_shm) {
458
459                 /* Only enable SHM if both sides are owned by the same
460                  * user. This is a security measure because otherwise
461                  * data private to the user might leak. */
462
463 #ifdef HAVE_CREDS
464                 const pa_creds *creds;
465                 if (!(creds = pa_pdispatch_creds(pd)) || getuid() != creds->uid)
466                     c->do_shm = FALSE;
467 #endif
468             }
469
470             pa_log_debug("Negotiated SHM: %s", pa_yes_no(c->do_shm));
471             pa_pstream_enable_shm(c->pstream, c->do_shm);
472
473             reply = pa_tagstruct_command(c, PA_COMMAND_SET_CLIENT_NAME, &tag);
474
475             if (c->version >= 13) {
476                 pa_init_proplist(c->proplist);
477                 pa_tagstruct_put_proplist(reply, c->proplist);
478             } else
479                 pa_tagstruct_puts(reply, pa_proplist_gets(c->proplist, PA_PROP_APPLICATION_NAME));
480
481             pa_pstream_send_tagstruct(c->pstream, reply);
482             pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c, NULL);
483
484             pa_context_set_state(c, PA_CONTEXT_SETTING_NAME);
485             break;
486         }
487
488         case PA_CONTEXT_SETTING_NAME :
489
490             if ((c->version >= 13 && (pa_tagstruct_getu32(t, &c->client_index) < 0 ||
491                                       c->client_index == PA_INVALID_INDEX)) ||
492                 !pa_tagstruct_eof(t)) {
493                 pa_context_fail(c, PA_ERR_PROTOCOL);
494                 goto finish;
495             }
496
497             pa_context_set_state(c, PA_CONTEXT_READY);
498             break;
499
500         default:
501             pa_assert_not_reached();
502     }
503
504 finish:
505     pa_context_unref(c);
506 }
507
508 static void setup_context(pa_context *c, pa_iochannel *io) {
509     pa_tagstruct *t;
510     uint32_t tag;
511
512     pa_assert(c);
513     pa_assert(io);
514
515     pa_context_ref(c);
516
517     pa_assert(!c->pstream);
518     c->pstream = pa_pstream_new(c->mainloop, io, c->mempool);
519
520     pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c);
521     pa_pstream_set_receive_packet_callback(c->pstream, pstream_packet_callback, c);
522     pa_pstream_set_receive_memblock_callback(c->pstream, pstream_memblock_callback, c);
523
524     pa_assert(!c->pdispatch);
525     c->pdispatch = pa_pdispatch_new(c->mainloop, c->use_rtclock, command_table, PA_COMMAND_MAX);
526
527     if (!c->conf->cookie_valid)
528         pa_log_info(_("No cookie loaded. Attempting to connect without."));
529
530     t = pa_tagstruct_command(c, PA_COMMAND_AUTH, &tag);
531
532     c->do_shm =
533         pa_mempool_is_shared(c->mempool) &&
534         c->is_local;
535
536     pa_log_debug("SHM possible: %s", pa_yes_no(c->do_shm));
537
538     /* Starting with protocol version 13 we use the MSB of the version
539      * tag for informing the other side if we could do SHM or not */
540     pa_tagstruct_putu32(t, PA_PROTOCOL_VERSION | (c->do_shm ? 0x80000000U : 0));
541     pa_tagstruct_put_arbitrary(t, c->conf->cookie, sizeof(c->conf->cookie));
542
543 #ifdef HAVE_CREDS
544 {
545     pa_creds ucred;
546
547     if (pa_iochannel_creds_supported(io))
548         pa_iochannel_creds_enable(io);
549
550     ucred.uid = getuid();
551     ucred.gid = getgid();
552
553     pa_pstream_send_tagstruct_with_creds(c->pstream, t, &ucred);
554 }
555 #else
556     pa_pstream_send_tagstruct(c->pstream, t);
557 #endif
558
559     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c, NULL);
560
561     pa_context_set_state(c, PA_CONTEXT_AUTHORIZING);
562
563     pa_context_unref(c);
564 }
565
566 #ifdef ENABLE_LEGACY_RUNTIME_DIR
567 static char *get_old_legacy_runtime_dir(void) {
568     char *p, u[128];
569     struct stat st;
570
571     if (!pa_get_user_name(u, sizeof(u)))
572         return NULL;
573
574     p = pa_sprintf_malloc("/tmp/pulse-%s", u);
575
576     if (stat(p, &st) < 0) {
577         pa_xfree(p);
578         return NULL;
579     }
580
581 #ifdef HAVE_GETUID
582     if (st.st_uid != getuid()) {
583         pa_xfree(p);
584         return NULL;
585     }
586 #endif
587
588     return p;
589 }
590
591 static char *get_very_old_legacy_runtime_dir(void) {
592     char *p, h[128];
593     struct stat st;
594
595     if (!pa_get_home_dir(h, sizeof(h)))
596         return NULL;
597
598     p = pa_sprintf_malloc("%s/.pulse", h);
599
600     if (stat(p, &st) < 0) {
601         pa_xfree(p);
602         return NULL;
603     }
604
605 #ifdef HAVE_GETUID
606     if (st.st_uid != getuid()) {
607         pa_xfree(p);
608         return NULL;
609     }
610 #endif
611
612     return p;
613 }
614 #endif
615
616 static pa_strlist *prepend_per_user(pa_strlist *l) {
617     char *ufn;
618
619 #ifdef ENABLE_LEGACY_RUNTIME_DIR
620     char *legacy_dir;
621
622     /* The very old per-user instance path (< 0.9.11). This is supported only to ease upgrades */
623     if ((legacy_dir = get_very_old_legacy_runtime_dir())) {
624         char *p = pa_sprintf_malloc("%s" PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET, legacy_dir);
625         l = pa_strlist_prepend(l, p);
626         pa_xfree(p);
627         pa_xfree(legacy_dir);
628     }
629
630     /* The old per-user instance path (< 0.9.12). This is supported only to ease upgrades */
631     if ((legacy_dir = get_old_legacy_runtime_dir())) {
632         char *p = pa_sprintf_malloc("%s" PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET, legacy_dir);
633         l = pa_strlist_prepend(l, p);
634         pa_xfree(p);
635         pa_xfree(legacy_dir);
636     }
637 #endif
638
639     /* The per-user instance */
640     if ((ufn = pa_runtime_path(PA_NATIVE_DEFAULT_UNIX_SOCKET))) {
641         l = pa_strlist_prepend(l, ufn);
642         pa_xfree(ufn);
643     }
644
645     return l;
646 }
647
648 #ifndef OS_IS_WIN32
649
650 static int context_autospawn(pa_context *c) {
651     pid_t pid;
652     int status, r;
653     struct sigaction sa;
654
655     pa_context_ref(c);
656
657     if (sigaction(SIGCHLD, NULL, &sa) < 0) {
658         pa_log_debug("sigaction() failed: %s", pa_cstrerror(errno));
659         pa_context_fail(c, PA_ERR_INTERNAL);
660         goto fail;
661     }
662
663 #ifdef SA_NOCLDWAIT
664     if ((sa.sa_flags & SA_NOCLDWAIT) || sa.sa_handler == SIG_IGN) {
665 #else
666     if (sa.sa_handler == SIG_IGN) {
667 #endif
668         pa_log_debug("Process disabled waitpid(), cannot autospawn.");
669         pa_context_fail(c, PA_ERR_CONNECTIONREFUSED);
670         goto fail;
671     }
672
673     pa_log_debug("Trying to autospawn...");
674
675     if (c->spawn_api.prefork)
676         c->spawn_api.prefork();
677
678     if ((pid = fork()) < 0) {
679         pa_log_error(_("fork(): %s"), pa_cstrerror(errno));
680         pa_context_fail(c, PA_ERR_INTERNAL);
681
682         if (c->spawn_api.postfork)
683             c->spawn_api.postfork();
684
685         goto fail;
686     } else if (!pid) {
687         /* Child */
688
689         const char *state = NULL;
690         const char * argv[32];
691         unsigned n = 0;
692
693         if (c->spawn_api.atfork)
694             c->spawn_api.atfork();
695
696         /* We leave most of the cleaning up of the process environment
697          * to the executable. We only clean up the file descriptors to
698          * make sure the executable can actually be loaded
699          * correctly. */
700         pa_close_all(-1);
701
702         /* Setup argv */
703         argv[n++] = c->conf->daemon_binary;
704         argv[n++] = "--start";
705
706         while (n < PA_ELEMENTSOF(argv)-1) {
707             char *a;
708
709             if (!(a = pa_split_spaces(c->conf->extra_arguments, &state)))
710                 break;
711
712             argv[n++] = a;
713         }
714
715         argv[n++] = NULL;
716         pa_assert(n <= PA_ELEMENTSOF(argv));
717
718         execv(argv[0], (char * const *) argv);
719         _exit(1);
720     }
721
722     /* Parent */
723
724     if (c->spawn_api.postfork)
725         c->spawn_api.postfork();
726
727     do {
728         r = waitpid(pid, &status, 0);
729     } while (r < 0 && errno == EINTR);
730
731     if (r < 0) {
732
733         if (errno != ESRCH) {
734             pa_log(_("waitpid(): %s"), pa_cstrerror(errno));
735             pa_context_fail(c, PA_ERR_INTERNAL);
736             goto fail;
737         }
738
739         /* hmm, something already reaped our child, so we assume
740          * startup worked, even if we cannot know */
741
742     } else if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
743         pa_context_fail(c, PA_ERR_CONNECTIONREFUSED);
744         goto fail;
745     }
746
747     pa_context_unref(c);
748
749     return 0;
750
751 fail:
752
753     pa_context_unref(c);
754
755     return -1;
756 }
757
758 #endif /* OS_IS_WIN32 */
759
760 static void on_connection(pa_socket_client *client, pa_iochannel*io, void *userdata);
761
762 #ifdef HAVE_DBUS
763 static void track_pulseaudio_on_dbus(pa_context *c, DBusBusType type, pa_dbus_wrap_connection **conn) {
764     DBusError error;
765
766     pa_assert(c);
767     pa_assert(conn);
768
769     dbus_error_init(&error);
770
771     if (!(*conn = pa_dbus_wrap_connection_new(c->mainloop, c->use_rtclock, type, &error)) || dbus_error_is_set(&error)) {
772         pa_log_warn("Unable to contact DBUS: %s: %s", error.name, error.message);
773         goto fail;
774     }
775
776     if (!dbus_connection_add_filter(pa_dbus_wrap_connection_get(*conn), filter_cb, c, NULL)) {
777         pa_log_warn("Failed to add filter function");
778         goto fail;
779     }
780     c->filter_added = TRUE;
781
782     if (pa_dbus_add_matches(
783                 pa_dbus_wrap_connection_get(*conn), &error,
784                 "type='signal',sender='" DBUS_SERVICE_DBUS "',interface='" DBUS_INTERFACE_DBUS "',member='NameOwnerChanged',arg0='org.pulseaudio.Server',arg1=''", NULL) < 0) {
785
786         pa_log_warn("Unable to track org.pulseaudio.Server: %s: %s", error.name, error.message);
787         goto fail;
788     }
789
790     return;
791
792 fail:
793     if (*conn) {
794         pa_dbus_wrap_connection_free(*conn);
795         *conn = NULL;
796     }
797
798     dbus_error_free(&error);
799 }
800 #endif
801
802 static int try_next_connection(pa_context *c) {
803     char *u = NULL;
804     int r = -1;
805
806     pa_assert(c);
807     pa_assert(!c->client);
808
809     for (;;) {
810         pa_xfree(u);
811         u = NULL;
812
813         c->server_list = pa_strlist_pop(c->server_list, &u);
814
815         if (!u) {
816
817 #ifndef OS_IS_WIN32
818             if (c->do_autospawn) {
819
820                 if ((r = context_autospawn(c)) < 0)
821                     goto finish;
822
823                 /* Autospawn only once */
824                 c->do_autospawn = FALSE;
825
826                 /* Connect only to per-user sockets this time */
827                 c->server_list = prepend_per_user(c->server_list);
828
829                 /* Retry connection */
830                 continue;
831             }
832 #endif
833
834 #ifdef HAVE_DBUS
835             if (c->no_fail && !c->server_specified) {
836                 if (!c->session_bus)
837                     track_pulseaudio_on_dbus(c, DBUS_BUS_SESSION, &c->session_bus);
838                 if (!c->system_bus)
839                     track_pulseaudio_on_dbus(c, DBUS_BUS_SYSTEM, &c->system_bus);
840             } else
841 #endif
842                 pa_context_fail(c, PA_ERR_CONNECTIONREFUSED);
843
844             goto finish;
845         }
846
847         pa_log_debug("Trying to connect to %s...", u);
848
849         pa_xfree(c->server);
850         c->server = pa_xstrdup(u);
851
852         if (!(c->client = pa_socket_client_new_string(c->mainloop, c->use_rtclock, u, PA_NATIVE_DEFAULT_PORT)))
853             continue;
854
855         c->is_local = !!pa_socket_client_is_local(c->client);
856         pa_socket_client_set_callback(c->client, on_connection, c);
857         break;
858     }
859
860     r = 0;
861
862 finish:
863     pa_xfree(u);
864
865     return r;
866 }
867
868 static void on_connection(pa_socket_client *client, pa_iochannel*io, void *userdata) {
869     pa_context *c = userdata;
870     int saved_errno = errno;
871
872     pa_assert(client);
873     pa_assert(c);
874     pa_assert(c->state == PA_CONTEXT_CONNECTING);
875
876     pa_context_ref(c);
877
878     pa_socket_client_unref(client);
879     c->client = NULL;
880
881     if (!io) {
882         /* Try the next item in the list */
883         if (saved_errno == ECONNREFUSED ||
884             saved_errno == ETIMEDOUT ||
885             saved_errno == EHOSTUNREACH) {
886             try_next_connection(c);
887             goto finish;
888         }
889
890         pa_context_fail(c, PA_ERR_CONNECTIONREFUSED);
891         goto finish;
892     }
893
894     setup_context(c, io);
895
896 finish:
897     pa_context_unref(c);
898 }
899
900 #ifdef HAVE_DBUS
901 static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *message, void *userdata) {
902     pa_context *c = userdata;
903     pa_bool_t is_session;
904
905     pa_assert(bus);
906     pa_assert(message);
907     pa_assert(c);
908
909     if (c->state != PA_CONTEXT_CONNECTING)
910         goto finish;
911
912     if (!c->no_fail)
913         goto finish;
914
915     /* FIXME: We probably should check if this is actually the NameOwnerChanged we were looking for */
916
917     is_session = c->session_bus && bus == pa_dbus_wrap_connection_get(c->session_bus);
918     pa_log_debug("Rock!! PulseAudio might be back on %s bus", is_session ? "session" : "system");
919
920     if (is_session)
921         /* The user instance via PF_LOCAL */
922         c->server_list = prepend_per_user(c->server_list);
923     else
924         /* The system wide instance via PF_LOCAL */
925         c->server_list = pa_strlist_prepend(c->server_list, PA_SYSTEM_RUNTIME_PATH PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET);
926
927     if (!c->client)
928         try_next_connection(c);
929
930 finish:
931     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
932 }
933 #endif
934
935 int pa_context_connect(
936         pa_context *c,
937         const char *server,
938         pa_context_flags_t flags,
939         const pa_spawn_api *api) {
940
941     int r = -1;
942
943     pa_assert(c);
944     pa_assert(PA_REFCNT_VALUE(c) >= 1);
945
946     PA_CHECK_VALIDITY(c, !pa_detect_fork(), PA_ERR_FORKED);
947     PA_CHECK_VALIDITY(c, c->state == PA_CONTEXT_UNCONNECTED, PA_ERR_BADSTATE);
948     PA_CHECK_VALIDITY(c, !(flags & ~(PA_CONTEXT_NOAUTOSPAWN|PA_CONTEXT_NOFAIL)), PA_ERR_INVALID);
949     PA_CHECK_VALIDITY(c, !server || *server, PA_ERR_INVALID);
950
951     if (server)
952         c->conf->autospawn = FALSE;
953     else
954         server = c->conf->default_server;
955
956     pa_context_ref(c);
957
958     c->no_fail = !!(flags & PA_CONTEXT_NOFAIL);
959     c->server_specified = !!server;
960     pa_assert(!c->server_list);
961
962     if (server) {
963         if (!(c->server_list = pa_strlist_parse(server))) {
964             pa_context_fail(c, PA_ERR_INVALIDSERVER);
965             goto finish;
966         }
967
968     } else {
969         char *d;
970
971         /* Prepend in reverse order */
972
973         /* Follow the X display */
974         if (c->conf->auto_connect_display) {
975             if ((d = getenv("DISPLAY"))) {
976                 d = pa_xstrndup(d, strcspn(d, ":"));
977
978                 if (*d)
979                     c->server_list = pa_strlist_prepend(c->server_list, d);
980
981                 pa_xfree(d);
982             }
983         }
984
985         /* Add TCP/IP on the localhost */
986         if (c->conf->auto_connect_localhost) {
987             c->server_list = pa_strlist_prepend(c->server_list, "tcp6:[::1]");
988             c->server_list = pa_strlist_prepend(c->server_list, "tcp4:127.0.0.1");
989         }
990
991         /* The system wide instance via PF_LOCAL */
992         c->server_list = pa_strlist_prepend(c->server_list, PA_SYSTEM_RUNTIME_PATH PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET);
993
994         /* The user instance via PF_LOCAL */
995         c->server_list = prepend_per_user(c->server_list);
996     }
997
998     /* Set up autospawning */
999     if (!(flags & PA_CONTEXT_NOAUTOSPAWN) && c->conf->autospawn) {
1000
1001 #ifdef HAVE_GETUID
1002         if (getuid() == 0)
1003             pa_log_debug("Not doing autospawn since we are root.");
1004         else {
1005             c->do_autospawn = TRUE;
1006
1007             if (api)
1008                 c->spawn_api = *api;
1009         }
1010 #endif
1011     }
1012
1013     pa_context_set_state(c, PA_CONTEXT_CONNECTING);
1014     r = try_next_connection(c);
1015
1016 finish:
1017     pa_context_unref(c);
1018
1019     return r;
1020 }
1021
1022 void pa_context_disconnect(pa_context *c) {
1023     pa_assert(c);
1024     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1025
1026     if (pa_detect_fork())
1027         return;
1028
1029     if (PA_CONTEXT_IS_GOOD(c->state))
1030         pa_context_set_state(c, PA_CONTEXT_TERMINATED);
1031 }
1032
1033 pa_context_state_t pa_context_get_state(pa_context *c) {
1034     pa_assert(c);
1035     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1036
1037     return c->state;
1038 }
1039
1040 int pa_context_errno(pa_context *c) {
1041
1042     if (!c)
1043         return PA_ERR_INVALID;
1044
1045     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1046
1047     return c->error;
1048 }
1049
1050 void pa_context_set_state_callback(pa_context *c, pa_context_notify_cb_t cb, void *userdata) {
1051     pa_assert(c);
1052     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1053
1054     if (pa_detect_fork())
1055         return;
1056
1057     if (c->state == PA_CONTEXT_TERMINATED || c->state == PA_CONTEXT_FAILED)
1058         return;
1059
1060     c->state_callback = cb;
1061     c->state_userdata = userdata;
1062 }
1063
1064 void pa_context_set_event_callback(pa_context *c, pa_context_event_cb_t cb, void *userdata) {
1065     pa_assert(c);
1066     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1067
1068     if (pa_detect_fork())
1069         return;
1070
1071     if (c->state == PA_CONTEXT_TERMINATED || c->state == PA_CONTEXT_FAILED)
1072         return;
1073
1074     c->event_callback = cb;
1075     c->event_userdata = userdata;
1076 }
1077
1078 int pa_context_is_pending(pa_context *c) {
1079     pa_assert(c);
1080     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1081
1082     PA_CHECK_VALIDITY(c, !pa_detect_fork(), PA_ERR_FORKED);
1083     PA_CHECK_VALIDITY(c, PA_CONTEXT_IS_GOOD(c->state), PA_ERR_BADSTATE);
1084
1085     return (c->pstream && pa_pstream_is_pending(c->pstream)) ||
1086         (c->pdispatch && pa_pdispatch_is_pending(c->pdispatch)) ||
1087         c->client;
1088 }
1089
1090 static void set_dispatch_callbacks(pa_operation *o);
1091
1092 static void pdispatch_drain_callback(pa_pdispatch*pd, void *userdata) {
1093     set_dispatch_callbacks(userdata);
1094 }
1095
1096 static void pstream_drain_callback(pa_pstream *s, void *userdata) {
1097     set_dispatch_callbacks(userdata);
1098 }
1099
1100 static void set_dispatch_callbacks(pa_operation *o) {
1101     int done = 1;
1102
1103     pa_assert(o);
1104     pa_assert(PA_REFCNT_VALUE(o) >= 1);
1105     pa_assert(o->context);
1106     pa_assert(PA_REFCNT_VALUE(o->context) >= 1);
1107     pa_assert(o->context->state == PA_CONTEXT_READY);
1108
1109     pa_pstream_set_drain_callback(o->context->pstream, NULL, NULL);
1110     pa_pdispatch_set_drain_callback(o->context->pdispatch, NULL, NULL);
1111
1112     if (pa_pdispatch_is_pending(o->context->pdispatch)) {
1113         pa_pdispatch_set_drain_callback(o->context->pdispatch, pdispatch_drain_callback, o);
1114         done = 0;
1115     }
1116
1117     if (pa_pstream_is_pending(o->context->pstream)) {
1118         pa_pstream_set_drain_callback(o->context->pstream, pstream_drain_callback, o);
1119         done = 0;
1120     }
1121
1122     if (done) {
1123         if (o->callback) {
1124             pa_context_notify_cb_t cb = (pa_context_notify_cb_t) o->callback;
1125             cb(o->context, o->userdata);
1126         }
1127
1128         pa_operation_done(o);
1129         pa_operation_unref(o);
1130     }
1131 }
1132
1133 pa_operation* pa_context_drain(pa_context *c, pa_context_notify_cb_t cb, void *userdata) {
1134     pa_operation *o;
1135
1136     pa_assert(c);
1137     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1138
1139     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1140     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1141     PA_CHECK_VALIDITY_RETURN_NULL(c, pa_context_is_pending(c), PA_ERR_BADSTATE);
1142
1143     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1144     set_dispatch_callbacks(pa_operation_ref(o));
1145
1146     return o;
1147 }
1148
1149 void pa_context_simple_ack_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1150     pa_operation *o = userdata;
1151     int success = 1;
1152
1153     pa_assert(pd);
1154     pa_assert(o);
1155     pa_assert(PA_REFCNT_VALUE(o) >= 1);
1156
1157     if (!o->context)
1158         goto finish;
1159
1160     if (command != PA_COMMAND_REPLY) {
1161         if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
1162             goto finish;
1163
1164         success = 0;
1165     } else if (!pa_tagstruct_eof(t)) {
1166         pa_context_fail(o->context, PA_ERR_PROTOCOL);
1167         goto finish;
1168     }
1169
1170     if (o->callback) {
1171         pa_context_success_cb_t cb = (pa_context_success_cb_t) o->callback;
1172         cb(o->context, success, o->userdata);
1173     }
1174
1175 finish:
1176     pa_operation_done(o);
1177     pa_operation_unref(o);
1178 }
1179
1180 pa_operation* pa_context_send_simple_command(pa_context *c, uint32_t command, pa_pdispatch_cb_t internal_cb, pa_operation_cb_t cb, void *userdata) {
1181     pa_tagstruct *t;
1182     pa_operation *o;
1183     uint32_t tag;
1184
1185     pa_assert(c);
1186     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1187
1188     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1189     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1190
1191     o = pa_operation_new(c, NULL, cb, userdata);
1192
1193     t = pa_tagstruct_command(c, command, &tag);
1194     pa_pstream_send_tagstruct(c->pstream, t);
1195     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, internal_cb, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1196
1197     return o;
1198 }
1199
1200 pa_operation* pa_context_exit_daemon(pa_context *c, pa_context_success_cb_t cb, void *userdata) {
1201     pa_assert(c);
1202     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1203
1204     return pa_context_send_simple_command(c, PA_COMMAND_EXIT, pa_context_simple_ack_callback, (pa_operation_cb_t) cb, userdata);
1205 }
1206
1207 pa_operation* pa_context_set_default_sink(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata) {
1208     pa_tagstruct *t;
1209     pa_operation *o;
1210     uint32_t tag;
1211
1212     pa_assert(c);
1213     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1214
1215     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1216     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1217
1218     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1219     t = pa_tagstruct_command(c, PA_COMMAND_SET_DEFAULT_SINK, &tag);
1220     pa_tagstruct_puts(t, name);
1221     pa_pstream_send_tagstruct(c->pstream, t);
1222     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT,  pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1223
1224     return o;
1225 }
1226
1227 pa_operation* pa_context_set_default_source(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata) {
1228     pa_tagstruct *t;
1229     pa_operation *o;
1230     uint32_t tag;
1231
1232     pa_assert(c);
1233     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1234
1235     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1236     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1237
1238     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1239     t = pa_tagstruct_command(c, PA_COMMAND_SET_DEFAULT_SOURCE, &tag);
1240     pa_tagstruct_puts(t, name);
1241     pa_pstream_send_tagstruct(c->pstream, t);
1242     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT,  pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1243
1244     return o;
1245 }
1246
1247 int pa_context_is_local(pa_context *c) {
1248     pa_assert(c);
1249     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1250
1251     PA_CHECK_VALIDITY_RETURN_ANY(c, !pa_detect_fork(), PA_ERR_FORKED, -1);
1252     PA_CHECK_VALIDITY_RETURN_ANY(c, PA_CONTEXT_IS_GOOD(c->state), PA_ERR_BADSTATE, -1);
1253
1254     return !!c->is_local;
1255 }
1256
1257 pa_operation* pa_context_set_name(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata) {
1258     pa_operation *o;
1259
1260     pa_assert(c);
1261     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1262     pa_assert(name);
1263
1264     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1265     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1266
1267     if (c->version >= 13) {
1268         pa_proplist *p = pa_proplist_new();
1269
1270         pa_proplist_sets(p, PA_PROP_APPLICATION_NAME, name);
1271         o = pa_context_proplist_update(c, PA_UPDATE_REPLACE, p, cb, userdata);
1272         pa_proplist_free(p);
1273     } else {
1274         pa_tagstruct *t;
1275         uint32_t tag;
1276
1277         o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1278         t = pa_tagstruct_command(c, PA_COMMAND_SET_CLIENT_NAME, &tag);
1279         pa_tagstruct_puts(t, name);
1280         pa_pstream_send_tagstruct(c->pstream, t);
1281         pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT,  pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1282     }
1283
1284     return o;
1285 }
1286
1287 const char* pa_get_library_version(void) {
1288     return pa_get_headers_version();
1289 }
1290
1291 const char* pa_context_get_server(pa_context *c) {
1292     pa_assert(c);
1293     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1294
1295     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1296     PA_CHECK_VALIDITY_RETURN_NULL(c, c->server, PA_ERR_NOENTITY);
1297
1298     if (*c->server == '{') {
1299         char *e = strchr(c->server+1, '}');
1300         return e ? e+1 : c->server;
1301     }
1302
1303     return c->server;
1304 }
1305
1306 uint32_t pa_context_get_protocol_version(pa_context *c) {
1307     return PA_PROTOCOL_VERSION;
1308 }
1309
1310 uint32_t pa_context_get_server_protocol_version(pa_context *c) {
1311     pa_assert(c);
1312     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1313
1314     PA_CHECK_VALIDITY_RETURN_ANY(c, !pa_detect_fork(), PA_ERR_FORKED, PA_INVALID_INDEX);
1315     PA_CHECK_VALIDITY_RETURN_ANY(c, PA_CONTEXT_IS_GOOD(c->state), PA_ERR_BADSTATE, PA_INVALID_INDEX);
1316
1317     return c->version;
1318 }
1319
1320 pa_tagstruct *pa_tagstruct_command(pa_context *c, uint32_t command, uint32_t *tag) {
1321     pa_tagstruct *t;
1322
1323     pa_assert(c);
1324     pa_assert(tag);
1325
1326     t = pa_tagstruct_new(NULL, 0);
1327     pa_tagstruct_putu32(t, command);
1328     pa_tagstruct_putu32(t, *tag = c->ctag++);
1329
1330     return t;
1331 }
1332
1333 uint32_t pa_context_get_index(pa_context *c) {
1334     pa_assert(c);
1335     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1336
1337     PA_CHECK_VALIDITY_RETURN_ANY(c, !pa_detect_fork(), PA_ERR_FORKED, PA_INVALID_INDEX);
1338     PA_CHECK_VALIDITY_RETURN_ANY(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE, PA_INVALID_INDEX);
1339     PA_CHECK_VALIDITY_RETURN_ANY(c, c->version >= 13, PA_ERR_NOTSUPPORTED, PA_INVALID_INDEX);
1340
1341     return c->client_index;
1342 }
1343
1344 pa_operation *pa_context_proplist_update(pa_context *c, pa_update_mode_t mode, pa_proplist *p, pa_context_success_cb_t cb, void *userdata) {
1345     pa_operation *o;
1346     pa_tagstruct *t;
1347     uint32_t tag;
1348
1349     pa_assert(c);
1350     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1351
1352     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1353     PA_CHECK_VALIDITY_RETURN_NULL(c, mode == PA_UPDATE_SET || mode == PA_UPDATE_MERGE || mode == PA_UPDATE_REPLACE, PA_ERR_INVALID);
1354     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1355     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 13, PA_ERR_NOTSUPPORTED);
1356
1357     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1358
1359     t = pa_tagstruct_command(c, PA_COMMAND_UPDATE_CLIENT_PROPLIST, &tag);
1360     pa_tagstruct_putu32(t, (uint32_t) mode);
1361     pa_tagstruct_put_proplist(t, p);
1362
1363     pa_pstream_send_tagstruct(c->pstream, t);
1364     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1365
1366     /* Please note that we don't update c->proplist here, because we
1367      * don't export that field */
1368
1369     return o;
1370 }
1371
1372 pa_operation *pa_context_proplist_remove(pa_context *c, const char *const keys[], pa_context_success_cb_t cb, void *userdata) {
1373     pa_operation *o;
1374     pa_tagstruct *t;
1375     uint32_t tag;
1376     const char * const *k;
1377
1378     pa_assert(c);
1379     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1380
1381     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1382     PA_CHECK_VALIDITY_RETURN_NULL(c, keys && keys[0], PA_ERR_INVALID);
1383     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1384     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 13, PA_ERR_NOTSUPPORTED);
1385
1386     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1387
1388     t = pa_tagstruct_command(c, PA_COMMAND_REMOVE_CLIENT_PROPLIST, &tag);
1389
1390     for (k = keys; *k; k++)
1391         pa_tagstruct_puts(t, *k);
1392
1393     pa_tagstruct_puts(t, NULL);
1394
1395     pa_pstream_send_tagstruct(c->pstream, t);
1396     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1397
1398     /* Please note that we don't update c->proplist here, because we
1399      * don't export that field */
1400
1401     return o;
1402 }
1403
1404 void pa_command_extension(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1405     pa_context *c = userdata;
1406     uint32_t idx;
1407     const char *name;
1408
1409     pa_assert(pd);
1410     pa_assert(command == PA_COMMAND_EXTENSION);
1411     pa_assert(t);
1412     pa_assert(c);
1413     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1414
1415     pa_context_ref(c);
1416
1417     if (c->version < 15) {
1418         pa_context_fail(c, PA_ERR_PROTOCOL);
1419         goto finish;
1420     }
1421
1422     if (pa_tagstruct_getu32(t, &idx) < 0 ||
1423         pa_tagstruct_gets(t, &name) < 0) {
1424         pa_context_fail(c, PA_ERR_PROTOCOL);
1425         goto finish;
1426     }
1427
1428     if (pa_streq(name, "module-device-manager"))
1429         pa_ext_device_manager_command(c, tag, t);
1430     else if (pa_streq(name, "module-device-restore"))
1431         pa_ext_device_restore_command(c, tag, t);
1432     else if (pa_streq(name, "module-stream-restore"))
1433         pa_ext_stream_restore_command(c, tag, t);
1434     else
1435         pa_log(_("Received message for unknown extension '%s'"), name);
1436
1437 finish:
1438     pa_context_unref(c);
1439 }
1440
1441
1442 void pa_command_client_event(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1443     pa_context *c = userdata;
1444     pa_proplist *pl = NULL;
1445     const char *event;
1446
1447     pa_assert(pd);
1448     pa_assert(command == PA_COMMAND_CLIENT_EVENT);
1449     pa_assert(t);
1450     pa_assert(c);
1451     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1452
1453     pa_context_ref(c);
1454
1455     if (c->version < 15) {
1456         pa_context_fail(c, PA_ERR_PROTOCOL);
1457         goto finish;
1458     }
1459
1460     pl = pa_proplist_new();
1461
1462     if (pa_tagstruct_gets(t, &event) < 0 ||
1463         pa_tagstruct_get_proplist(t, pl) < 0 ||
1464         !pa_tagstruct_eof(t) || !event) {
1465         pa_context_fail(c, PA_ERR_PROTOCOL);
1466         goto finish;
1467     }
1468
1469     if (c->event_callback)
1470         c->event_callback(c, event, pl, c->event_userdata);
1471
1472 finish:
1473     pa_context_unref(c);
1474
1475     if (pl)
1476         pa_proplist_free(pl);
1477 }
1478
1479 pa_time_event* pa_context_rttime_new(pa_context *c, pa_usec_t usec, pa_time_event_cb_t cb, void *userdata) {
1480     struct timeval tv;
1481
1482     pa_assert(c);
1483     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1484     pa_assert(c->mainloop);
1485
1486     if (usec == PA_USEC_INVALID)
1487         return c->mainloop->time_new(c->mainloop, NULL, cb, userdata);
1488
1489     pa_timeval_rtstore(&tv, usec, c->use_rtclock);
1490
1491     return c->mainloop->time_new(c->mainloop, &tv, cb, userdata);
1492 }
1493
1494 void pa_context_rttime_restart(pa_context *c, pa_time_event *e, pa_usec_t usec) {
1495     struct timeval tv;
1496
1497     pa_assert(c);
1498     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1499     pa_assert(c->mainloop);
1500
1501
1502     if (usec == PA_USEC_INVALID)
1503         c->mainloop->time_restart(e, NULL);
1504     else {
1505         pa_timeval_rtstore(&tv, usec, c->use_rtclock);
1506         c->mainloop->time_restart(e, &tv);
1507     }
1508 }
1509
1510 size_t pa_context_get_tile_size(pa_context *c, const pa_sample_spec *ss) {
1511     size_t fs, mbs;
1512
1513     pa_assert(c);
1514     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1515
1516     PA_CHECK_VALIDITY_RETURN_ANY(c, !pa_detect_fork(), PA_ERR_FORKED, (size_t) -1);
1517     PA_CHECK_VALIDITY_RETURN_ANY(c, !ss || pa_sample_spec_valid(ss), PA_ERR_INVALID, (size_t) -1);
1518
1519     fs = ss ? pa_frame_size(ss) : 1;
1520     mbs = PA_ROUND_DOWN(pa_mempool_block_size_max(c->mempool), fs);
1521     return PA_MAX(mbs, fs);
1522 }