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