hashmap: Add the ability to free keys
[platform/upstream/pulseaudio.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);
245     if (c->playback_streams)
246         pa_hashmap_free(c->playback_streams);
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, bool 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             bool 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 static pa_strlist *prepend_per_user(pa_strlist *l) {
567     char *ufn;
568
569     /* The per-user instance */
570     if ((ufn = pa_runtime_path(PA_NATIVE_DEFAULT_UNIX_SOCKET))) {
571         l = pa_strlist_prepend(l, ufn);
572         pa_xfree(ufn);
573     }
574
575     return l;
576 }
577
578 #ifndef OS_IS_WIN32
579
580 static int context_autospawn(pa_context *c) {
581     pid_t pid;
582     int status, r;
583     struct sigaction sa;
584
585     pa_context_ref(c);
586
587     if (sigaction(SIGCHLD, NULL, &sa) < 0) {
588         pa_log_debug("sigaction() failed: %s", pa_cstrerror(errno));
589         pa_context_fail(c, PA_ERR_INTERNAL);
590         goto fail;
591     }
592
593 #ifdef SA_NOCLDWAIT
594     if ((sa.sa_flags & SA_NOCLDWAIT) || sa.sa_handler == SIG_IGN) {
595 #else
596     if (sa.sa_handler == SIG_IGN) {
597 #endif
598         pa_log_debug("Process disabled waitpid(), cannot autospawn.");
599         pa_context_fail(c, PA_ERR_CONNECTIONREFUSED);
600         goto fail;
601     }
602
603     pa_log_debug("Trying to autospawn...");
604
605     if (c->spawn_api.prefork)
606         c->spawn_api.prefork();
607
608     if ((pid = fork()) < 0) {
609         pa_log_error(_("fork(): %s"), pa_cstrerror(errno));
610         pa_context_fail(c, PA_ERR_INTERNAL);
611
612         if (c->spawn_api.postfork)
613             c->spawn_api.postfork();
614
615         goto fail;
616     } else if (!pid) {
617         /* Child */
618
619         const char *state = NULL;
620         const char * argv[32];
621         unsigned n = 0;
622
623         if (c->spawn_api.atfork)
624             c->spawn_api.atfork();
625
626         /* We leave most of the cleaning up of the process environment
627          * to the executable. We only clean up the file descriptors to
628          * make sure the executable can actually be loaded
629          * correctly. */
630         pa_close_all(-1);
631
632         /* Setup argv */
633         argv[n++] = c->conf->daemon_binary;
634         argv[n++] = "--start";
635
636         while (n < PA_ELEMENTSOF(argv)-1) {
637             char *a;
638
639             if (!(a = pa_split_spaces(c->conf->extra_arguments, &state)))
640                 break;
641
642             argv[n++] = a;
643         }
644
645         argv[n++] = NULL;
646         pa_assert(n <= PA_ELEMENTSOF(argv));
647
648         execv(argv[0], (char * const *) argv);
649         _exit(1);
650     }
651
652     /* Parent */
653
654     if (c->spawn_api.postfork)
655         c->spawn_api.postfork();
656
657     do {
658         r = waitpid(pid, &status, 0);
659     } while (r < 0 && errno == EINTR);
660
661     if (r < 0) {
662
663         if (errno != ESRCH) {
664             pa_log(_("waitpid(): %s"), pa_cstrerror(errno));
665             pa_context_fail(c, PA_ERR_INTERNAL);
666             goto fail;
667         }
668
669         /* hmm, something already reaped our child, so we assume
670          * startup worked, even if we cannot know */
671
672     } else if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
673         pa_context_fail(c, PA_ERR_CONNECTIONREFUSED);
674         goto fail;
675     }
676
677     pa_context_unref(c);
678
679     return 0;
680
681 fail:
682
683     pa_context_unref(c);
684
685     return -1;
686 }
687
688 #endif /* OS_IS_WIN32 */
689
690 static void on_connection(pa_socket_client *client, pa_iochannel*io, void *userdata);
691
692 #ifdef HAVE_DBUS
693 static void track_pulseaudio_on_dbus(pa_context *c, DBusBusType type, pa_dbus_wrap_connection **conn) {
694     DBusError error;
695
696     pa_assert(c);
697     pa_assert(conn);
698
699     dbus_error_init(&error);
700
701     if (!(*conn = pa_dbus_wrap_connection_new(c->mainloop, c->use_rtclock, type, &error)) || dbus_error_is_set(&error)) {
702         pa_log_warn("Unable to contact DBUS: %s: %s", error.name, error.message);
703         goto fail;
704     }
705
706     if (!dbus_connection_add_filter(pa_dbus_wrap_connection_get(*conn), filter_cb, c, NULL)) {
707         pa_log_warn("Failed to add filter function");
708         goto fail;
709     }
710     c->filter_added = true;
711
712     if (pa_dbus_add_matches(
713                 pa_dbus_wrap_connection_get(*conn), &error,
714                 "type='signal',sender='" DBUS_SERVICE_DBUS "',interface='" DBUS_INTERFACE_DBUS "',member='NameOwnerChanged',arg0='org.pulseaudio.Server',arg1=''", NULL) < 0) {
715
716         pa_log_warn("Unable to track org.pulseaudio.Server: %s: %s", error.name, error.message);
717         goto fail;
718     }
719
720     return;
721
722 fail:
723     if (*conn) {
724         pa_dbus_wrap_connection_free(*conn);
725         *conn = NULL;
726     }
727
728     dbus_error_free(&error);
729 }
730 #endif
731
732 static int try_next_connection(pa_context *c) {
733     char *u = NULL;
734     int r = -1;
735
736     pa_assert(c);
737     pa_assert(!c->client);
738
739     for (;;) {
740         pa_xfree(u);
741         u = NULL;
742
743         c->server_list = pa_strlist_pop(c->server_list, &u);
744
745         if (!u) {
746
747 #ifndef OS_IS_WIN32
748             if (c->do_autospawn) {
749
750                 if ((r = context_autospawn(c)) < 0)
751                     goto finish;
752
753                 /* Autospawn only once */
754                 c->do_autospawn = false;
755
756                 /* Connect only to per-user sockets this time */
757                 c->server_list = prepend_per_user(c->server_list);
758
759                 /* Retry connection */
760                 continue;
761             }
762 #endif
763
764 #ifdef HAVE_DBUS
765             if (c->no_fail && !c->server_specified) {
766                 if (!c->session_bus)
767                     track_pulseaudio_on_dbus(c, DBUS_BUS_SESSION, &c->session_bus);
768                 if (!c->system_bus)
769                     track_pulseaudio_on_dbus(c, DBUS_BUS_SYSTEM, &c->system_bus);
770             } else
771 #endif
772                 pa_context_fail(c, PA_ERR_CONNECTIONREFUSED);
773
774             goto finish;
775         }
776
777         pa_log_debug("Trying to connect to %s...", u);
778
779         pa_xfree(c->server);
780         c->server = pa_xstrdup(u);
781
782         if (!(c->client = pa_socket_client_new_string(c->mainloop, c->use_rtclock, u, PA_NATIVE_DEFAULT_PORT)))
783             continue;
784
785         c->is_local = !!pa_socket_client_is_local(c->client);
786         pa_socket_client_set_callback(c->client, on_connection, c);
787         break;
788     }
789
790     r = 0;
791
792 finish:
793     pa_xfree(u);
794
795     return r;
796 }
797
798 static void on_connection(pa_socket_client *client, pa_iochannel*io, void *userdata) {
799     pa_context *c = userdata;
800     int saved_errno = errno;
801
802     pa_assert(client);
803     pa_assert(c);
804     pa_assert(c->state == PA_CONTEXT_CONNECTING);
805
806     pa_context_ref(c);
807
808     pa_socket_client_unref(client);
809     c->client = NULL;
810
811     if (!io) {
812         /* Try the next item in the list */
813         if (saved_errno == ECONNREFUSED ||
814             saved_errno == ETIMEDOUT ||
815             saved_errno == EHOSTUNREACH) {
816             try_next_connection(c);
817             goto finish;
818         }
819
820         pa_context_fail(c, PA_ERR_CONNECTIONREFUSED);
821         goto finish;
822     }
823
824     setup_context(c, io);
825
826 finish:
827     pa_context_unref(c);
828 }
829
830 #ifdef HAVE_DBUS
831 static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *message, void *userdata) {
832     pa_context *c = userdata;
833     bool is_session;
834
835     pa_assert(bus);
836     pa_assert(message);
837     pa_assert(c);
838
839     if (c->state != PA_CONTEXT_CONNECTING)
840         goto finish;
841
842     if (!c->no_fail)
843         goto finish;
844
845     /* FIXME: We probably should check if this is actually the NameOwnerChanged we were looking for */
846
847     is_session = c->session_bus && bus == pa_dbus_wrap_connection_get(c->session_bus);
848     pa_log_debug("Rock!! PulseAudio might be back on %s bus", is_session ? "session" : "system");
849
850     if (is_session)
851         /* The user instance via PF_LOCAL */
852         c->server_list = prepend_per_user(c->server_list);
853     else
854         /* The system wide instance via PF_LOCAL */
855         c->server_list = pa_strlist_prepend(c->server_list, PA_SYSTEM_RUNTIME_PATH PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET);
856
857     if (!c->client)
858         try_next_connection(c);
859
860 finish:
861     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
862 }
863 #endif
864
865 int pa_context_connect(
866         pa_context *c,
867         const char *server,
868         pa_context_flags_t flags,
869         const pa_spawn_api *api) {
870
871     int r = -1;
872
873     pa_assert(c);
874     pa_assert(PA_REFCNT_VALUE(c) >= 1);
875
876     PA_CHECK_VALIDITY(c, !pa_detect_fork(), PA_ERR_FORKED);
877     PA_CHECK_VALIDITY(c, c->state == PA_CONTEXT_UNCONNECTED, PA_ERR_BADSTATE);
878     PA_CHECK_VALIDITY(c, !(flags & ~(PA_CONTEXT_NOAUTOSPAWN|PA_CONTEXT_NOFAIL)), PA_ERR_INVALID);
879     PA_CHECK_VALIDITY(c, !server || *server, PA_ERR_INVALID);
880
881     if (server)
882         c->conf->autospawn = false;
883     else
884         server = c->conf->default_server;
885
886     pa_context_ref(c);
887
888     c->no_fail = !!(flags & PA_CONTEXT_NOFAIL);
889     c->server_specified = !!server;
890     pa_assert(!c->server_list);
891
892     if (server) {
893         if (!(c->server_list = pa_strlist_parse(server))) {
894             pa_context_fail(c, PA_ERR_INVALIDSERVER);
895             goto finish;
896         }
897
898     } else {
899         char *d;
900
901         /* Prepend in reverse order */
902
903         /* Follow the X display */
904         if (c->conf->auto_connect_display) {
905             if ((d = getenv("DISPLAY"))) {
906                 d = pa_xstrndup(d, strcspn(d, ":"));
907
908                 if (*d)
909                     c->server_list = pa_strlist_prepend(c->server_list, d);
910
911                 pa_xfree(d);
912             }
913         }
914
915         /* Add TCP/IP on the localhost */
916         if (c->conf->auto_connect_localhost) {
917             c->server_list = pa_strlist_prepend(c->server_list, "tcp6:[::1]");
918             c->server_list = pa_strlist_prepend(c->server_list, "tcp4:127.0.0.1");
919         }
920
921         /* The system wide instance via PF_LOCAL */
922         c->server_list = pa_strlist_prepend(c->server_list, PA_SYSTEM_RUNTIME_PATH PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET);
923
924         /* The user instance via PF_LOCAL */
925         c->server_list = prepend_per_user(c->server_list);
926     }
927
928     /* Set up autospawning */
929     if (!(flags & PA_CONTEXT_NOAUTOSPAWN) && c->conf->autospawn) {
930
931 #ifdef HAVE_GETUID
932         if (getuid() == 0)
933             pa_log_debug("Not doing autospawn since we are root.");
934         else {
935             c->do_autospawn = true;
936
937             if (api)
938                 c->spawn_api = *api;
939         }
940 #endif
941     }
942
943     pa_context_set_state(c, PA_CONTEXT_CONNECTING);
944     r = try_next_connection(c);
945
946 finish:
947     pa_context_unref(c);
948
949     return r;
950 }
951
952 void pa_context_disconnect(pa_context *c) {
953     pa_assert(c);
954     pa_assert(PA_REFCNT_VALUE(c) >= 1);
955
956     if (pa_detect_fork())
957         return;
958
959     if (PA_CONTEXT_IS_GOOD(c->state))
960         pa_context_set_state(c, PA_CONTEXT_TERMINATED);
961 }
962
963 pa_context_state_t pa_context_get_state(pa_context *c) {
964     pa_assert(c);
965     pa_assert(PA_REFCNT_VALUE(c) >= 1);
966
967     return c->state;
968 }
969
970 int pa_context_errno(pa_context *c) {
971
972     if (!c)
973         return PA_ERR_INVALID;
974
975     pa_assert(PA_REFCNT_VALUE(c) >= 1);
976
977     return c->error;
978 }
979
980 void pa_context_set_state_callback(pa_context *c, pa_context_notify_cb_t cb, void *userdata) {
981     pa_assert(c);
982     pa_assert(PA_REFCNT_VALUE(c) >= 1);
983
984     if (pa_detect_fork())
985         return;
986
987     if (c->state == PA_CONTEXT_TERMINATED || c->state == PA_CONTEXT_FAILED)
988         return;
989
990     c->state_callback = cb;
991     c->state_userdata = userdata;
992 }
993
994 void pa_context_set_event_callback(pa_context *c, pa_context_event_cb_t cb, void *userdata) {
995     pa_assert(c);
996     pa_assert(PA_REFCNT_VALUE(c) >= 1);
997
998     if (pa_detect_fork())
999         return;
1000
1001     if (c->state == PA_CONTEXT_TERMINATED || c->state == PA_CONTEXT_FAILED)
1002         return;
1003
1004     c->event_callback = cb;
1005     c->event_userdata = userdata;
1006 }
1007
1008 int pa_context_is_pending(pa_context *c) {
1009     pa_assert(c);
1010     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1011
1012     PA_CHECK_VALIDITY(c, !pa_detect_fork(), PA_ERR_FORKED);
1013     PA_CHECK_VALIDITY(c, PA_CONTEXT_IS_GOOD(c->state), PA_ERR_BADSTATE);
1014
1015     return (c->pstream && pa_pstream_is_pending(c->pstream)) ||
1016         (c->pdispatch && pa_pdispatch_is_pending(c->pdispatch)) ||
1017         c->client;
1018 }
1019
1020 static void set_dispatch_callbacks(pa_operation *o);
1021
1022 static void pdispatch_drain_callback(pa_pdispatch*pd, void *userdata) {
1023     set_dispatch_callbacks(userdata);
1024 }
1025
1026 static void pstream_drain_callback(pa_pstream *s, void *userdata) {
1027     set_dispatch_callbacks(userdata);
1028 }
1029
1030 static void set_dispatch_callbacks(pa_operation *o) {
1031     int done = 1;
1032
1033     pa_assert(o);
1034     pa_assert(PA_REFCNT_VALUE(o) >= 1);
1035     pa_assert(o->context);
1036     pa_assert(PA_REFCNT_VALUE(o->context) >= 1);
1037     pa_assert(o->context->state == PA_CONTEXT_READY);
1038
1039     pa_pstream_set_drain_callback(o->context->pstream, NULL, NULL);
1040     pa_pdispatch_set_drain_callback(o->context->pdispatch, NULL, NULL);
1041
1042     if (pa_pdispatch_is_pending(o->context->pdispatch)) {
1043         pa_pdispatch_set_drain_callback(o->context->pdispatch, pdispatch_drain_callback, o);
1044         done = 0;
1045     }
1046
1047     if (pa_pstream_is_pending(o->context->pstream)) {
1048         pa_pstream_set_drain_callback(o->context->pstream, pstream_drain_callback, o);
1049         done = 0;
1050     }
1051
1052     if (done) {
1053         if (o->callback) {
1054             pa_context_notify_cb_t cb = (pa_context_notify_cb_t) o->callback;
1055             cb(o->context, o->userdata);
1056         }
1057
1058         pa_operation_done(o);
1059         pa_operation_unref(o);
1060     }
1061 }
1062
1063 pa_operation* pa_context_drain(pa_context *c, pa_context_notify_cb_t cb, void *userdata) {
1064     pa_operation *o;
1065
1066     pa_assert(c);
1067     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1068
1069     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1070     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1071     PA_CHECK_VALIDITY_RETURN_NULL(c, pa_context_is_pending(c), PA_ERR_BADSTATE);
1072
1073     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1074     set_dispatch_callbacks(pa_operation_ref(o));
1075
1076     return o;
1077 }
1078
1079 void pa_context_simple_ack_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1080     pa_operation *o = userdata;
1081     int success = 1;
1082
1083     pa_assert(pd);
1084     pa_assert(o);
1085     pa_assert(PA_REFCNT_VALUE(o) >= 1);
1086
1087     if (!o->context)
1088         goto finish;
1089
1090     if (command != PA_COMMAND_REPLY) {
1091         if (pa_context_handle_error(o->context, command, t, false) < 0)
1092             goto finish;
1093
1094         success = 0;
1095     } else if (!pa_tagstruct_eof(t)) {
1096         pa_context_fail(o->context, PA_ERR_PROTOCOL);
1097         goto finish;
1098     }
1099
1100     if (o->callback) {
1101         pa_context_success_cb_t cb = (pa_context_success_cb_t) o->callback;
1102         cb(o->context, success, o->userdata);
1103     }
1104
1105 finish:
1106     pa_operation_done(o);
1107     pa_operation_unref(o);
1108 }
1109
1110 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) {
1111     pa_tagstruct *t;
1112     pa_operation *o;
1113     uint32_t tag;
1114
1115     pa_assert(c);
1116     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1117
1118     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1119     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1120
1121     o = pa_operation_new(c, NULL, cb, userdata);
1122
1123     t = pa_tagstruct_command(c, command, &tag);
1124     pa_pstream_send_tagstruct(c->pstream, t);
1125     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, internal_cb, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1126
1127     return o;
1128 }
1129
1130 pa_operation* pa_context_exit_daemon(pa_context *c, pa_context_success_cb_t cb, void *userdata) {
1131     pa_assert(c);
1132     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1133
1134     return pa_context_send_simple_command(c, PA_COMMAND_EXIT, pa_context_simple_ack_callback, (pa_operation_cb_t) cb, userdata);
1135 }
1136
1137 pa_operation* pa_context_set_default_sink(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata) {
1138     pa_tagstruct *t;
1139     pa_operation *o;
1140     uint32_t tag;
1141
1142     pa_assert(c);
1143     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1144
1145     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1146     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1147
1148     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1149     t = pa_tagstruct_command(c, PA_COMMAND_SET_DEFAULT_SINK, &tag);
1150     pa_tagstruct_puts(t, name);
1151     pa_pstream_send_tagstruct(c->pstream, t);
1152     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);
1153
1154     return o;
1155 }
1156
1157 pa_operation* pa_context_set_default_source(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata) {
1158     pa_tagstruct *t;
1159     pa_operation *o;
1160     uint32_t tag;
1161
1162     pa_assert(c);
1163     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1164
1165     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1166     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1167
1168     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1169     t = pa_tagstruct_command(c, PA_COMMAND_SET_DEFAULT_SOURCE, &tag);
1170     pa_tagstruct_puts(t, name);
1171     pa_pstream_send_tagstruct(c->pstream, t);
1172     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);
1173
1174     return o;
1175 }
1176
1177 int pa_context_is_local(pa_context *c) {
1178     pa_assert(c);
1179     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1180
1181     PA_CHECK_VALIDITY_RETURN_ANY(c, !pa_detect_fork(), PA_ERR_FORKED, -1);
1182     PA_CHECK_VALIDITY_RETURN_ANY(c, PA_CONTEXT_IS_GOOD(c->state), PA_ERR_BADSTATE, -1);
1183
1184     return !!c->is_local;
1185 }
1186
1187 pa_operation* pa_context_set_name(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata) {
1188     pa_operation *o;
1189
1190     pa_assert(c);
1191     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1192     pa_assert(name);
1193
1194     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1195     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1196
1197     if (c->version >= 13) {
1198         pa_proplist *p = pa_proplist_new();
1199
1200         pa_proplist_sets(p, PA_PROP_APPLICATION_NAME, name);
1201         o = pa_context_proplist_update(c, PA_UPDATE_REPLACE, p, cb, userdata);
1202         pa_proplist_free(p);
1203     } else {
1204         pa_tagstruct *t;
1205         uint32_t tag;
1206
1207         o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1208         t = pa_tagstruct_command(c, PA_COMMAND_SET_CLIENT_NAME, &tag);
1209         pa_tagstruct_puts(t, name);
1210         pa_pstream_send_tagstruct(c->pstream, t);
1211         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);
1212     }
1213
1214     return o;
1215 }
1216
1217 const char* pa_get_library_version(void) {
1218     return pa_get_headers_version();
1219 }
1220
1221 const char* pa_context_get_server(pa_context *c) {
1222     pa_assert(c);
1223     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1224
1225     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1226     PA_CHECK_VALIDITY_RETURN_NULL(c, c->server, PA_ERR_NOENTITY);
1227
1228     if (*c->server == '{') {
1229         char *e = strchr(c->server+1, '}');
1230         return e ? e+1 : c->server;
1231     }
1232
1233     return c->server;
1234 }
1235
1236 uint32_t pa_context_get_protocol_version(pa_context *c) {
1237     return PA_PROTOCOL_VERSION;
1238 }
1239
1240 uint32_t pa_context_get_server_protocol_version(pa_context *c) {
1241     pa_assert(c);
1242     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1243
1244     PA_CHECK_VALIDITY_RETURN_ANY(c, !pa_detect_fork(), PA_ERR_FORKED, PA_INVALID_INDEX);
1245     PA_CHECK_VALIDITY_RETURN_ANY(c, PA_CONTEXT_IS_GOOD(c->state), PA_ERR_BADSTATE, PA_INVALID_INDEX);
1246
1247     return c->version;
1248 }
1249
1250 pa_tagstruct *pa_tagstruct_command(pa_context *c, uint32_t command, uint32_t *tag) {
1251     pa_tagstruct *t;
1252
1253     pa_assert(c);
1254     pa_assert(tag);
1255
1256     t = pa_tagstruct_new(NULL, 0);
1257     pa_tagstruct_putu32(t, command);
1258     pa_tagstruct_putu32(t, *tag = c->ctag++);
1259
1260     return t;
1261 }
1262
1263 uint32_t pa_context_get_index(pa_context *c) {
1264     pa_assert(c);
1265     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1266
1267     PA_CHECK_VALIDITY_RETURN_ANY(c, !pa_detect_fork(), PA_ERR_FORKED, PA_INVALID_INDEX);
1268     PA_CHECK_VALIDITY_RETURN_ANY(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE, PA_INVALID_INDEX);
1269     PA_CHECK_VALIDITY_RETURN_ANY(c, c->version >= 13, PA_ERR_NOTSUPPORTED, PA_INVALID_INDEX);
1270
1271     return c->client_index;
1272 }
1273
1274 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) {
1275     pa_operation *o;
1276     pa_tagstruct *t;
1277     uint32_t tag;
1278
1279     pa_assert(c);
1280     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1281
1282     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1283     PA_CHECK_VALIDITY_RETURN_NULL(c, mode == PA_UPDATE_SET || mode == PA_UPDATE_MERGE || mode == PA_UPDATE_REPLACE, PA_ERR_INVALID);
1284     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1285     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 13, PA_ERR_NOTSUPPORTED);
1286
1287     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1288
1289     t = pa_tagstruct_command(c, PA_COMMAND_UPDATE_CLIENT_PROPLIST, &tag);
1290     pa_tagstruct_putu32(t, (uint32_t) mode);
1291     pa_tagstruct_put_proplist(t, p);
1292
1293     pa_pstream_send_tagstruct(c->pstream, t);
1294     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);
1295
1296     /* Please note that we don't update c->proplist here, because we
1297      * don't export that field */
1298
1299     return o;
1300 }
1301
1302 pa_operation *pa_context_proplist_remove(pa_context *c, const char *const keys[], pa_context_success_cb_t cb, void *userdata) {
1303     pa_operation *o;
1304     pa_tagstruct *t;
1305     uint32_t tag;
1306     const char * const *k;
1307
1308     pa_assert(c);
1309     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1310
1311     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1312     PA_CHECK_VALIDITY_RETURN_NULL(c, keys && keys[0], PA_ERR_INVALID);
1313     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1314     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 13, PA_ERR_NOTSUPPORTED);
1315
1316     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1317
1318     t = pa_tagstruct_command(c, PA_COMMAND_REMOVE_CLIENT_PROPLIST, &tag);
1319
1320     for (k = keys; *k; k++)
1321         pa_tagstruct_puts(t, *k);
1322
1323     pa_tagstruct_puts(t, NULL);
1324
1325     pa_pstream_send_tagstruct(c->pstream, t);
1326     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);
1327
1328     /* Please note that we don't update c->proplist here, because we
1329      * don't export that field */
1330
1331     return o;
1332 }
1333
1334 void pa_command_extension(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1335     pa_context *c = userdata;
1336     uint32_t idx;
1337     const char *name;
1338
1339     pa_assert(pd);
1340     pa_assert(command == PA_COMMAND_EXTENSION);
1341     pa_assert(t);
1342     pa_assert(c);
1343     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1344
1345     pa_context_ref(c);
1346
1347     if (c->version < 15) {
1348         pa_context_fail(c, PA_ERR_PROTOCOL);
1349         goto finish;
1350     }
1351
1352     if (pa_tagstruct_getu32(t, &idx) < 0 ||
1353         pa_tagstruct_gets(t, &name) < 0) {
1354         pa_context_fail(c, PA_ERR_PROTOCOL);
1355         goto finish;
1356     }
1357
1358     if (pa_streq(name, "module-device-manager"))
1359         pa_ext_device_manager_command(c, tag, t);
1360     else if (pa_streq(name, "module-device-restore"))
1361         pa_ext_device_restore_command(c, tag, t);
1362     else if (pa_streq(name, "module-stream-restore"))
1363         pa_ext_stream_restore_command(c, tag, t);
1364     else
1365         pa_log(_("Received message for unknown extension '%s'"), name);
1366
1367 finish:
1368     pa_context_unref(c);
1369 }
1370
1371 void pa_command_client_event(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1372     pa_context *c = userdata;
1373     pa_proplist *pl = NULL;
1374     const char *event;
1375
1376     pa_assert(pd);
1377     pa_assert(command == PA_COMMAND_CLIENT_EVENT);
1378     pa_assert(t);
1379     pa_assert(c);
1380     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1381
1382     pa_context_ref(c);
1383
1384     if (c->version < 15) {
1385         pa_context_fail(c, PA_ERR_PROTOCOL);
1386         goto finish;
1387     }
1388
1389     pl = pa_proplist_new();
1390
1391     if (pa_tagstruct_gets(t, &event) < 0 ||
1392         pa_tagstruct_get_proplist(t, pl) < 0 ||
1393         !pa_tagstruct_eof(t) || !event) {
1394         pa_context_fail(c, PA_ERR_PROTOCOL);
1395         goto finish;
1396     }
1397
1398     if (c->event_callback)
1399         c->event_callback(c, event, pl, c->event_userdata);
1400
1401 finish:
1402     pa_context_unref(c);
1403
1404     if (pl)
1405         pa_proplist_free(pl);
1406 }
1407
1408 pa_time_event* pa_context_rttime_new(pa_context *c, pa_usec_t usec, pa_time_event_cb_t cb, void *userdata) {
1409     struct timeval tv;
1410
1411     pa_assert(c);
1412     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1413     pa_assert(c->mainloop);
1414
1415     if (usec == PA_USEC_INVALID)
1416         return c->mainloop->time_new(c->mainloop, NULL, cb, userdata);
1417
1418     pa_timeval_rtstore(&tv, usec, c->use_rtclock);
1419
1420     return c->mainloop->time_new(c->mainloop, &tv, cb, userdata);
1421 }
1422
1423 void pa_context_rttime_restart(pa_context *c, pa_time_event *e, pa_usec_t usec) {
1424     struct timeval tv;
1425
1426     pa_assert(c);
1427     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1428     pa_assert(c->mainloop);
1429
1430     if (usec == PA_USEC_INVALID)
1431         c->mainloop->time_restart(e, NULL);
1432     else {
1433         pa_timeval_rtstore(&tv, usec, c->use_rtclock);
1434         c->mainloop->time_restart(e, &tv);
1435     }
1436 }
1437
1438 size_t pa_context_get_tile_size(pa_context *c, const pa_sample_spec *ss) {
1439     size_t fs, mbs;
1440
1441     pa_assert(c);
1442     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1443
1444     PA_CHECK_VALIDITY_RETURN_ANY(c, !pa_detect_fork(), PA_ERR_FORKED, (size_t) -1);
1445     PA_CHECK_VALIDITY_RETURN_ANY(c, !ss || pa_sample_spec_valid(ss), PA_ERR_INVALID, (size_t) -1);
1446
1447     fs = ss ? pa_frame_size(ss) : 1;
1448     mbs = PA_ROUND_DOWN(pa_mempool_block_size_max(c->mempool), fs);
1449     return PA_MAX(mbs, fs);
1450 }
1451
1452 int pa_context_load_cookie_from_file(pa_context *c, const char *cookie_file_path) {
1453     pa_assert(c);
1454     pa_assert(cookie_file_path);
1455     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1456
1457     PA_CHECK_VALIDITY(c, !pa_detect_fork(), PA_ERR_FORKED);
1458     PA_CHECK_VALIDITY(c, c->state == PA_CONTEXT_UNCONNECTED, PA_ERR_BADSTATE);
1459
1460     return pa_client_conf_load_cookie_from_file(c->conf, cookie_file_path);
1461 }