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