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