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