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