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