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