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