2 This file is part of PulseAudio.
4 Copyright 2004-2008 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
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.
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.
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
30 #include <sys/types.h>
38 #ifdef HAVE_SYS_WAIT_H
42 #ifdef HAVE_SYS_SOCKET_H
43 #include <sys/socket.h>
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>
58 #include <pulsecore/winsock.h>
59 #include <pulsecore/core-error.h>
61 #include <pulsecore/native-common.h>
62 #include <pulsecore/pdispatch.h>
63 #include <pulsecore/pstream.h>
64 #include <pulsecore/dynarray.h>
65 #include <pulsecore/socket-client.h>
66 #include <pulsecore/pstream-util.h>
67 #include <pulsecore/core-util.h>
68 #include <pulsecore/log.h>
69 #include <pulsecore/socket-util.h>
70 #include <pulsecore/creds.h>
71 #include <pulsecore/macro.h>
72 #include <pulsecore/proplist-util.h>
76 #include "client-conf.h"
77 #include "fork-detect.h"
80 #include "client-conf-x11.h"
85 void pa_command_extension(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
87 static const pa_pdispatch_cb_t command_table
[PA_COMMAND_MAX
] = {
88 [PA_COMMAND_REQUEST
] = pa_command_request
,
89 [PA_COMMAND_OVERFLOW
] = pa_command_overflow_or_underflow
,
90 [PA_COMMAND_UNDERFLOW
] = pa_command_overflow_or_underflow
,
91 [PA_COMMAND_PLAYBACK_STREAM_KILLED
] = pa_command_stream_killed
,
92 [PA_COMMAND_RECORD_STREAM_KILLED
] = pa_command_stream_killed
,
93 [PA_COMMAND_PLAYBACK_STREAM_MOVED
] = pa_command_stream_moved
,
94 [PA_COMMAND_RECORD_STREAM_MOVED
] = pa_command_stream_moved
,
95 [PA_COMMAND_PLAYBACK_STREAM_SUSPENDED
] = pa_command_stream_suspended
,
96 [PA_COMMAND_RECORD_STREAM_SUSPENDED
] = pa_command_stream_suspended
,
97 [PA_COMMAND_STARTED
] = pa_command_stream_started
,
98 [PA_COMMAND_SUBSCRIBE_EVENT
] = pa_command_subscribe_event
,
99 [PA_COMMAND_EXTENSION
] = pa_command_extension
,
100 [PA_COMMAND_PLAYBACK_STREAM_EVENT
] = pa_command_stream_event
,
101 [PA_COMMAND_RECORD_STREAM_EVENT
] = pa_command_stream_event
,
102 [PA_COMMAND_CLIENT_EVENT
] = pa_command_client_event
,
103 [PA_COMMAND_PLAYBACK_BUFFER_ATTR_CHANGED
] = pa_command_stream_buffer_attr
,
104 [PA_COMMAND_RECORD_BUFFER_ATTR_CHANGED
] = pa_command_stream_buffer_attr
106 static void context_free(pa_context
*c
);
108 pa_context
*pa_context_new(pa_mainloop_api
*mainloop
, const char *name
) {
109 return pa_context_new_with_proplist(mainloop
, name
, NULL
);
112 static void reset_callbacks(pa_context
*c
) {
115 c
->state_callback
= NULL
;
116 c
->state_userdata
= NULL
;
118 c
->subscribe_callback
= NULL
;
119 c
->subscribe_userdata
= NULL
;
121 c
->event_callback
= NULL
;
122 c
->event_userdata
= NULL
;
124 c
->ext_stream_restore
.callback
= NULL
;
125 c
->ext_stream_restore
.userdata
= NULL
;
128 pa_context
*pa_context_new_with_proplist(pa_mainloop_api
*mainloop
, const char *name
, pa_proplist
*p
) {
133 if (pa_detect_fork())
138 c
= pa_xnew(pa_context
, 1);
141 c
->proplist
= p
? pa_proplist_copy(p
) : pa_proplist_new();
144 pa_proplist_sets(c
->proplist
, PA_PROP_APPLICATION_NAME
, name
);
146 c
->mainloop
= mainloop
;
150 c
->playback_streams
= pa_dynarray_new();
151 c
->record_streams
= pa_dynarray_new();
152 c
->client_index
= PA_INVALID_INDEX
;
154 PA_LLIST_HEAD_INIT(pa_stream
, c
->streams
);
155 PA_LLIST_HEAD_INIT(pa_operation
, c
->operations
);
158 c
->state
= PA_CONTEXT_UNCONNECTED
;
165 c
->server_list
= NULL
;
170 c
->do_autospawn
= FALSE
;
171 memset(&c
->spawn_api
, 0, sizeof(c
->spawn_api
));
175 pa_check_signal_is_blocked(SIGPIPE
);
179 c
->conf
= pa_client_conf_new();
181 pa_client_conf_from_x11(c
->conf
, NULL
);
183 pa_client_conf_load(c
->conf
, NULL
);
184 pa_client_conf_env(c
->conf
);
186 if (!(c
->mempool
= pa_mempool_new(!c
->conf
->disable_shm
, c
->conf
->shm_size
))) {
188 if (!c
->conf
->disable_shm
)
189 c
->mempool
= pa_mempool_new(FALSE
, c
->conf
->shm_size
);
200 static void context_unlink(pa_context
*c
) {
205 s
= c
->streams
? pa_stream_ref(c
->streams
) : NULL
;
207 pa_stream
*n
= s
->next
? pa_stream_ref(s
->next
) : NULL
;
208 pa_stream_set_state(s
, c
->state
== PA_CONTEXT_FAILED
? PA_STREAM_FAILED
: PA_STREAM_TERMINATED
);
213 while (c
->operations
)
214 pa_operation_cancel(c
->operations
);
217 pa_pdispatch_unref(c
->pdispatch
);
222 pa_pstream_unlink(c
->pstream
);
223 pa_pstream_unref(c
->pstream
);
228 pa_socket_client_unref(c
->client
);
235 static void context_free(pa_context
*c
) {
240 if (c
->record_streams
)
241 pa_dynarray_free(c
->record_streams
, NULL
, NULL
);
242 if (c
->playback_streams
)
243 pa_dynarray_free(c
->playback_streams
, NULL
, NULL
);
246 pa_mempool_free(c
->mempool
);
249 pa_client_conf_free(c
->conf
);
251 pa_strlist_free(c
->server_list
);
254 pa_proplist_free(c
->proplist
);
260 pa_context
* pa_context_ref(pa_context
*c
) {
262 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
268 void pa_context_unref(pa_context
*c
) {
270 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
272 if (PA_REFCNT_DEC(c
) <= 0)
276 void pa_context_set_state(pa_context
*c
, pa_context_state_t st
) {
278 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
287 if (c
->state_callback
)
288 c
->state_callback(c
, c
->state_userdata
);
290 if (st
== PA_CONTEXT_FAILED
|| st
== PA_CONTEXT_TERMINATED
)
296 int pa_context_set_error(pa_context
*c
, int error
) {
297 pa_assert(error
>= 0);
298 pa_assert(error
< PA_ERR_MAX
);
306 void pa_context_fail(pa_context
*c
, int error
) {
308 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
310 pa_context_set_error(c
, error
);
311 pa_context_set_state(c
, PA_CONTEXT_FAILED
);
314 static void pstream_die_callback(pa_pstream
*p
, void *userdata
) {
315 pa_context
*c
= userdata
;
320 pa_context_fail(c
, PA_ERR_CONNECTIONTERMINATED
);
323 static void pstream_packet_callback(pa_pstream
*p
, pa_packet
*packet
, const pa_creds
*creds
, void *userdata
) {
324 pa_context
*c
= userdata
;
332 if (pa_pdispatch_run(c
->pdispatch
, packet
, creds
, c
) < 0)
333 pa_context_fail(c
, PA_ERR_PROTOCOL
);
338 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
) {
339 pa_context
*c
= userdata
;
344 pa_assert(chunk
->length
> 0);
346 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
350 if ((s
= pa_dynarray_get(c
->record_streams
, channel
))) {
352 if (chunk
->memblock
) {
353 pa_memblockq_seek(s
->record_memblockq
, offset
, seek
);
354 pa_memblockq_push_align(s
->record_memblockq
, chunk
);
356 pa_memblockq_seek(s
->record_memblockq
, offset
+chunk
->length
, seek
);
358 if (s
->read_callback
) {
361 if ((l
= pa_memblockq_get_length(s
->record_memblockq
)) > 0)
362 s
->read_callback(s
, l
, s
->read_userdata
);
369 int pa_context_handle_error(pa_context
*c
, uint32_t command
, pa_tagstruct
*t
, pa_bool_t fail
) {
372 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
374 if (command
== PA_COMMAND_ERROR
) {
377 if (pa_tagstruct_getu32(t
, &err
) < 0 ||
378 !pa_tagstruct_eof(t
)) {
379 pa_context_fail(c
, PA_ERR_PROTOCOL
);
383 } else if (command
== PA_COMMAND_TIMEOUT
)
384 err
= PA_ERR_TIMEOUT
;
386 pa_context_fail(c
, PA_ERR_PROTOCOL
);
391 pa_context_fail(c
, PA_ERR_PROTOCOL
);
395 if (err
>= PA_ERR_MAX
)
396 err
= PA_ERR_UNKNOWN
;
399 pa_context_fail(c
, (int) err
);
403 pa_context_set_error(c
, (int) err
);
408 static void setup_complete_callback(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
409 pa_context
*c
= userdata
;
413 pa_assert(c
->state
== PA_CONTEXT_AUTHORIZING
|| c
->state
== PA_CONTEXT_SETTING_NAME
);
417 if (command
!= PA_COMMAND_REPLY
) {
418 pa_context_handle_error(c
, command
, t
, TRUE
);
423 case PA_CONTEXT_AUTHORIZING
: {
425 pa_bool_t shm_on_remote
= FALSE
;
427 if (pa_tagstruct_getu32(t
, &c
->version
) < 0 ||
428 !pa_tagstruct_eof(t
)) {
429 pa_context_fail(c
, PA_ERR_PROTOCOL
);
433 /* Minimum supported version */
434 if (c
->version
< 8) {
435 pa_context_fail(c
, PA_ERR_VERSION
);
439 /* Starting with protocol version 13 the MSB of the version
440 tag reflects if shm is available for this connection or
442 if (c
->version
>= 13) {
443 shm_on_remote
= !!(c
->version
& 0x80000000U
);
444 c
->version
&= 0x7FFFFFFFU
;
447 pa_log_debug("Protocol version: remote %u, local %u", c
->version
, PA_PROTOCOL_VERSION
);
449 /* Enable shared memory support if possible */
451 if (c
->version
< 10 || (c
->version
>= 13 && !shm_on_remote
))
456 /* Only enable SHM if both sides are owned by the same
457 * user. This is a security measure because otherwise
458 * data private to the user might leak. */
461 const pa_creds
*creds
;
462 if (!(creds
= pa_pdispatch_creds(pd
)) || getuid() != creds
->uid
)
467 pa_log_debug("Negotiated SHM: %s", pa_yes_no(c
->do_shm
));
468 pa_pstream_enable_shm(c
->pstream
, c
->do_shm
);
470 reply
= pa_tagstruct_command(c
, PA_COMMAND_SET_CLIENT_NAME
, &tag
);
472 if (c
->version
>= 13) {
473 pa_init_proplist(c
->proplist
);
474 pa_tagstruct_put_proplist(reply
, c
->proplist
);
476 pa_tagstruct_puts(reply
, pa_proplist_gets(c
->proplist
, PA_PROP_APPLICATION_NAME
));
478 pa_pstream_send_tagstruct(c
->pstream
, reply
);
479 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, setup_complete_callback
, c
, NULL
);
481 pa_context_set_state(c
, PA_CONTEXT_SETTING_NAME
);
485 case PA_CONTEXT_SETTING_NAME
:
487 if ((c
->version
>= 13 && (pa_tagstruct_getu32(t
, &c
->client_index
) < 0 ||
488 c
->client_index
== PA_INVALID_INDEX
)) ||
489 !pa_tagstruct_eof(t
)) {
490 pa_context_fail(c
, PA_ERR_PROTOCOL
);
494 pa_context_set_state(c
, PA_CONTEXT_READY
);
498 pa_assert_not_reached();
505 static void setup_context(pa_context
*c
, pa_iochannel
*io
) {
514 pa_assert(!c
->pstream
);
515 c
->pstream
= pa_pstream_new(c
->mainloop
, io
, c
->mempool
);
517 pa_pstream_set_die_callback(c
->pstream
, pstream_die_callback
, c
);
518 pa_pstream_set_recieve_packet_callback(c
->pstream
, pstream_packet_callback
, c
);
519 pa_pstream_set_recieve_memblock_callback(c
->pstream
, pstream_memblock_callback
, c
);
521 pa_assert(!c
->pdispatch
);
522 c
->pdispatch
= pa_pdispatch_new(c
->mainloop
, command_table
, PA_COMMAND_MAX
);
524 if (!c
->conf
->cookie_valid
)
525 pa_log_info(_("No cookie loaded. Attempting to connect without."));
527 t
= pa_tagstruct_command(c
, PA_COMMAND_AUTH
, &tag
);
530 pa_mempool_is_shared(c
->mempool
) &&
533 pa_log_debug("SHM possible: %s", pa_yes_no(c
->do_shm
));
535 /* Starting with protocol version 13 we use the MSB of the version
536 * tag for informing the other side if we could do SHM or not */
537 pa_tagstruct_putu32(t
, PA_PROTOCOL_VERSION
| (c
->do_shm
? 0x80000000U
: 0));
538 pa_tagstruct_put_arbitrary(t
, c
->conf
->cookie
, sizeof(c
->conf
->cookie
));
544 if (pa_iochannel_creds_supported(io
))
545 pa_iochannel_creds_enable(io
);
547 ucred
.uid
= getuid();
548 ucred
.gid
= getgid();
550 pa_pstream_send_tagstruct_with_creds(c
->pstream
, t
, &ucred
);
553 pa_pstream_send_tagstruct(c
->pstream
, t
);
556 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, setup_complete_callback
, c
, NULL
);
558 pa_context_set_state(c
, PA_CONTEXT_AUTHORIZING
);
563 #ifdef ENABLE_LEGACY_RUNTIME_DIR
564 static char *get_old_legacy_runtime_dir(void) {
568 if (!pa_get_user_name(u
, sizeof(u
)))
571 p
= pa_sprintf_malloc("/tmp/pulse-%s", u
);
573 if (stat(p
, &st
) < 0) {
578 if (st
.st_uid
!= getuid()) {
586 static char *get_very_old_legacy_runtime_dir(void) {
590 if (!pa_get_home_dir(h
, sizeof(h
)))
593 p
= pa_sprintf_malloc("%s/.pulse", h
);
595 if (stat(p
, &st
) < 0) {
600 if (st
.st_uid
!= getuid()) {
609 static pa_strlist
*prepend_per_user(pa_strlist
*l
) {
612 #ifdef ENABLE_LEGACY_RUNTIME_DIR
613 static char *legacy_dir
;
615 /* The very old per-user instance path (< 0.9.11). This is supported only to ease upgrades */
616 if ((legacy_dir
= get_very_old_legacy_runtime_dir())) {
617 char *p
= pa_sprintf_malloc("%s" PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET
, legacy_dir
);
618 l
= pa_strlist_prepend(l
, p
);
620 pa_xfree(legacy_dir
);
623 /* The old per-user instance path (< 0.9.12). This is supported only to ease upgrades */
624 if ((legacy_dir
= get_old_legacy_runtime_dir())) {
625 char *p
= pa_sprintf_malloc("%s" PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET
, legacy_dir
);
626 l
= pa_strlist_prepend(l
, p
);
628 pa_xfree(legacy_dir
);
632 /* The per-user instance */
633 if ((ufn
= pa_runtime_path(PA_NATIVE_DEFAULT_UNIX_SOCKET
))) {
634 l
= pa_strlist_prepend(l
, ufn
);
643 static int context_autospawn(pa_context
*c
) {
647 pa_log_debug("Trying to autospawn...");
651 if (c
->spawn_api
.prefork
)
652 c
->spawn_api
.prefork();
654 if ((pid
= fork()) < 0) {
655 pa_log_error(_("fork(): %s"), pa_cstrerror(errno
));
656 pa_context_fail(c
, PA_ERR_INTERNAL
);
658 if (c
->spawn_api
.postfork
)
659 c
->spawn_api
.postfork();
665 const char *state
= NULL
;
667 const char * argv
[MAX_ARGS
+1];
670 if (c
->spawn_api
.atfork
)
671 c
->spawn_api
.atfork();
679 argv
[n
++] = c
->conf
->daemon_binary
;
680 argv
[n
++] = "--start";
682 while (n
< MAX_ARGS
) {
685 if (!(a
= pa_split_spaces(c
->conf
->extra_arguments
, &state
)))
693 execv(argv
[0], (char * const *) argv
);
700 if (c
->spawn_api
.postfork
)
701 c
->spawn_api
.postfork();
704 r
= waitpid(pid
, &status
, 0);
705 } while (r
< 0 && errno
== EINTR
);
708 pa_log(_("waitpid(): %s"), pa_cstrerror(errno
));
709 pa_context_fail(c
, PA_ERR_INTERNAL
);
711 } else if (!WIFEXITED(status
) || WEXITSTATUS(status
) != 0) {
712 pa_context_fail(c
, PA_ERR_CONNECTIONREFUSED
);
727 #endif /* OS_IS_WIN32 */
729 static void on_connection(pa_socket_client
*client
, pa_iochannel
*io
, void *userdata
);
731 static int try_next_connection(pa_context
*c
) {
736 pa_assert(!c
->client
);
742 c
->server_list
= pa_strlist_pop(c
->server_list
, &u
);
747 if (c
->do_autospawn
) {
749 if ((r
= context_autospawn(c
)) < 0)
752 /* Autospawn only once */
753 c
->do_autospawn
= FALSE
;
755 /* Connect only to per-user sockets this time */
756 c
->server_list
= prepend_per_user(c
->server_list
);
758 /* Retry connection */
763 pa_context_fail(c
, PA_ERR_CONNECTIONREFUSED
);
767 pa_log_debug("Trying to connect to %s...", u
);
770 c
->server
= pa_xstrdup(u
);
772 if (!(c
->client
= pa_socket_client_new_string(c
->mainloop
, u
, PA_NATIVE_DEFAULT_PORT
)))
775 c
->is_local
= !!pa_socket_client_is_local(c
->client
);
776 pa_socket_client_set_callback(c
->client
, on_connection
, c
);
788 static void on_connection(pa_socket_client
*client
, pa_iochannel
*io
, void *userdata
) {
789 pa_context
*c
= userdata
;
790 int saved_errno
= errno
;
794 pa_assert(c
->state
== PA_CONTEXT_CONNECTING
);
798 pa_socket_client_unref(client
);
802 /* Try the item in the list */
803 if (saved_errno
== ECONNREFUSED
||
804 saved_errno
== ETIMEDOUT
||
805 saved_errno
== EHOSTUNREACH
) {
806 try_next_connection(c
);
810 pa_context_fail(c
, PA_ERR_CONNECTIONREFUSED
);
814 setup_context(c
, io
);
820 int pa_context_connect(
823 pa_context_flags_t flags
,
824 const pa_spawn_api
*api
) {
829 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
831 PA_CHECK_VALIDITY(c
, !pa_detect_fork(), PA_ERR_FORKED
);
832 PA_CHECK_VALIDITY(c
, c
->state
== PA_CONTEXT_UNCONNECTED
, PA_ERR_BADSTATE
);
833 PA_CHECK_VALIDITY(c
, !(flags
& ~PA_CONTEXT_NOAUTOSPAWN
), PA_ERR_INVALID
);
834 PA_CHECK_VALIDITY(c
, !server
|| *server
, PA_ERR_INVALID
);
837 server
= c
->conf
->default_server
;
841 pa_assert(!c
->server_list
);
844 if (!(c
->server_list
= pa_strlist_parse(server
))) {
845 pa_context_fail(c
, PA_ERR_INVALIDSERVER
);
852 /* Prepend in reverse order */
854 /* Follow the X display */
855 if ((d
= getenv("DISPLAY"))) {
858 if ((e
= strchr(d
, ':')))
862 c
->server_list
= pa_strlist_prepend(c
->server_list
, d
);
867 /* Add TCP/IP on the localhost */
868 c
->server_list
= pa_strlist_prepend(c
->server_list
, "tcp6:[::1]");
869 c
->server_list
= pa_strlist_prepend(c
->server_list
, "tcp4:127.0.0.1");
871 /* The system wide instance via PF_LOCAL */
872 c
->server_list
= pa_strlist_prepend(c
->server_list
, PA_SYSTEM_RUNTIME_PATH PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET
);
874 /* The user instance via PF_LOCAL */
875 c
->server_list
= prepend_per_user(c
->server_list
);
877 /* Set up autospawning */
878 if (!(flags
& PA_CONTEXT_NOAUTOSPAWN
) && c
->conf
->autospawn
) {
881 pa_log_debug("Not doing autospawn since we are root.");
883 c
->do_autospawn
= TRUE
;
891 pa_context_set_state(c
, PA_CONTEXT_CONNECTING
);
892 r
= try_next_connection(c
);
900 void pa_context_disconnect(pa_context
*c
) {
902 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
904 if (pa_detect_fork())
907 if (PA_CONTEXT_IS_GOOD(c
->state
))
908 pa_context_set_state(c
, PA_CONTEXT_TERMINATED
);
911 pa_context_state_t
pa_context_get_state(pa_context
*c
) {
913 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
918 int pa_context_errno(pa_context
*c
) {
920 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
925 void pa_context_set_state_callback(pa_context
*c
, pa_context_notify_cb_t cb
, void *userdata
) {
927 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
929 if (pa_detect_fork())
932 if (c
->state
== PA_CONTEXT_TERMINATED
|| c
->state
== PA_CONTEXT_FAILED
)
935 c
->state_callback
= cb
;
936 c
->state_userdata
= userdata
;
939 void pa_context_set_event_callback(pa_context
*c
, pa_context_event_cb_t cb
, void *userdata
) {
941 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
943 if (pa_detect_fork())
946 if (c
->state
== PA_CONTEXT_TERMINATED
|| c
->state
== PA_CONTEXT_FAILED
)
949 c
->event_callback
= cb
;
950 c
->event_userdata
= userdata
;
953 int pa_context_is_pending(pa_context
*c
) {
955 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
957 PA_CHECK_VALIDITY(c
, !pa_detect_fork(), PA_ERR_FORKED
);
958 PA_CHECK_VALIDITY(c
, PA_CONTEXT_IS_GOOD(c
->state
), PA_ERR_BADSTATE
);
960 return (c
->pstream
&& pa_pstream_is_pending(c
->pstream
)) ||
961 (c
->pdispatch
&& pa_pdispatch_is_pending(c
->pdispatch
)) ||
965 static void set_dispatch_callbacks(pa_operation
*o
);
967 static void pdispatch_drain_callback(pa_pdispatch
*pd
, void *userdata
) {
968 set_dispatch_callbacks(userdata
);
971 static void pstream_drain_callback(pa_pstream
*s
, void *userdata
) {
972 set_dispatch_callbacks(userdata
);
975 static void set_dispatch_callbacks(pa_operation
*o
) {
979 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
980 pa_assert(o
->context
);
981 pa_assert(PA_REFCNT_VALUE(o
->context
) >= 1);
982 pa_assert(o
->context
->state
== PA_CONTEXT_READY
);
984 pa_pstream_set_drain_callback(o
->context
->pstream
, NULL
, NULL
);
985 pa_pdispatch_set_drain_callback(o
->context
->pdispatch
, NULL
, NULL
);
987 if (pa_pdispatch_is_pending(o
->context
->pdispatch
)) {
988 pa_pdispatch_set_drain_callback(o
->context
->pdispatch
, pdispatch_drain_callback
, o
);
992 if (pa_pstream_is_pending(o
->context
->pstream
)) {
993 pa_pstream_set_drain_callback(o
->context
->pstream
, pstream_drain_callback
, o
);
999 pa_context_notify_cb_t cb
= (pa_context_notify_cb_t
) o
->callback
;
1000 cb(o
->context
, o
->userdata
);
1003 pa_operation_done(o
);
1004 pa_operation_unref(o
);
1008 pa_operation
* pa_context_drain(pa_context
*c
, pa_context_notify_cb_t cb
, void *userdata
) {
1012 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1014 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
1015 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
1016 PA_CHECK_VALIDITY_RETURN_NULL(c
, pa_context_is_pending(c
), PA_ERR_BADSTATE
);
1018 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
1019 set_dispatch_callbacks(pa_operation_ref(o
));
1024 void pa_context_simple_ack_callback(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
1025 pa_operation
*o
= userdata
;
1030 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
1035 if (command
!= PA_COMMAND_REPLY
) {
1036 if (pa_context_handle_error(o
->context
, command
, t
, FALSE
) < 0)
1040 } else if (!pa_tagstruct_eof(t
)) {
1041 pa_context_fail(o
->context
, PA_ERR_PROTOCOL
);
1046 pa_context_success_cb_t cb
= (pa_context_success_cb_t
) o
->callback
;
1047 cb(o
->context
, success
, o
->userdata
);
1051 pa_operation_done(o
);
1052 pa_operation_unref(o
);
1055 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
) {
1061 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1063 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
1064 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
1066 o
= pa_operation_new(c
, NULL
, cb
, userdata
);
1068 t
= pa_tagstruct_command(c
, command
, &tag
);
1069 pa_pstream_send_tagstruct(c
->pstream
, t
);
1070 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, internal_cb
, pa_operation_ref(o
), (pa_free_cb_t
) pa_operation_unref
);
1075 pa_operation
* pa_context_exit_daemon(pa_context
*c
, pa_context_success_cb_t cb
, void *userdata
) {
1077 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1079 return pa_context_send_simple_command(c
, PA_COMMAND_EXIT
, pa_context_simple_ack_callback
, (pa_operation_cb_t
) cb
, userdata
);
1082 pa_operation
* pa_context_set_default_sink(pa_context
*c
, const char *name
, pa_context_success_cb_t cb
, void *userdata
) {
1088 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1090 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
1091 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
1093 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
1094 t
= pa_tagstruct_command(c
, PA_COMMAND_SET_DEFAULT_SINK
, &tag
);
1095 pa_tagstruct_puts(t
, name
);
1096 pa_pstream_send_tagstruct(c
->pstream
, t
);
1097 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
);
1102 pa_operation
* pa_context_set_default_source(pa_context
*c
, const char *name
, pa_context_success_cb_t cb
, void *userdata
) {
1108 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1110 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
1111 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
1113 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
1114 t
= pa_tagstruct_command(c
, PA_COMMAND_SET_DEFAULT_SOURCE
, &tag
);
1115 pa_tagstruct_puts(t
, name
);
1116 pa_pstream_send_tagstruct(c
->pstream
, t
);
1117 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
);
1122 int pa_context_is_local(pa_context
*c
) {
1124 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1126 PA_CHECK_VALIDITY_RETURN_ANY(c
, !pa_detect_fork(), PA_ERR_FORKED
, -1);
1127 PA_CHECK_VALIDITY_RETURN_ANY(c
, PA_CONTEXT_IS_GOOD(c
->state
), PA_ERR_BADSTATE
, -1);
1129 return !!c
->is_local
;
1132 pa_operation
* pa_context_set_name(pa_context
*c
, const char *name
, pa_context_success_cb_t cb
, void *userdata
) {
1136 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1139 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
1140 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
1142 if (c
->version
>= 13) {
1143 pa_proplist
*p
= pa_proplist_new();
1145 pa_proplist_sets(p
, PA_PROP_APPLICATION_NAME
, name
);
1146 o
= pa_context_proplist_update(c
, PA_UPDATE_REPLACE
, p
, cb
, userdata
);
1147 pa_proplist_free(p
);
1152 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
1153 t
= pa_tagstruct_command(c
, PA_COMMAND_SET_CLIENT_NAME
, &tag
);
1154 pa_tagstruct_puts(t
, name
);
1155 pa_pstream_send_tagstruct(c
->pstream
, t
);
1156 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
);
1162 const char* pa_get_library_version(void) {
1163 return PACKAGE_VERSION
;
1166 const char* pa_context_get_server(pa_context
*c
) {
1168 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1170 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
1171 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->server
, PA_ERR_NOENTITY
);
1173 if (*c
->server
== '{') {
1174 char *e
= strchr(c
->server
+1, '}');
1175 return e
? e
+1 : c
->server
;
1181 uint32_t pa_context_get_protocol_version(pa_context
*c
) {
1182 return PA_PROTOCOL_VERSION
;
1185 uint32_t pa_context_get_server_protocol_version(pa_context
*c
) {
1187 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1189 PA_CHECK_VALIDITY_RETURN_ANY(c
, !pa_detect_fork(), PA_ERR_FORKED
, PA_INVALID_INDEX
);
1190 PA_CHECK_VALIDITY_RETURN_ANY(c
, PA_CONTEXT_IS_GOOD(c
->state
), PA_ERR_BADSTATE
, PA_INVALID_INDEX
);
1195 pa_tagstruct
*pa_tagstruct_command(pa_context
*c
, uint32_t command
, uint32_t *tag
) {
1201 t
= pa_tagstruct_new(NULL
, 0);
1202 pa_tagstruct_putu32(t
, command
);
1203 pa_tagstruct_putu32(t
, *tag
= c
->ctag
++);
1208 uint32_t pa_context_get_index(pa_context
*c
) {
1210 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1212 PA_CHECK_VALIDITY_RETURN_ANY(c
, !pa_detect_fork(), PA_ERR_FORKED
, PA_INVALID_INDEX
);
1213 PA_CHECK_VALIDITY_RETURN_ANY(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
, PA_INVALID_INDEX
);
1214 PA_CHECK_VALIDITY_RETURN_ANY(c
, c
->version
>= 13, PA_ERR_NOTSUPPORTED
, PA_INVALID_INDEX
);
1216 return c
->client_index
;
1219 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
) {
1225 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1227 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
1228 PA_CHECK_VALIDITY_RETURN_NULL(c
, mode
== PA_UPDATE_SET
|| mode
== PA_UPDATE_MERGE
|| mode
== PA_UPDATE_REPLACE
, PA_ERR_INVALID
);
1229 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
1230 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 13, PA_ERR_NOTSUPPORTED
);
1232 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
1234 t
= pa_tagstruct_command(c
, PA_COMMAND_UPDATE_CLIENT_PROPLIST
, &tag
);
1235 pa_tagstruct_putu32(t
, (uint32_t) mode
);
1236 pa_tagstruct_put_proplist(t
, p
);
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
);
1241 /* Please note that we don't update c->proplist here, because we
1242 * don't export that field */
1247 pa_operation
*pa_context_proplist_remove(pa_context
*c
, const char *const keys
[], pa_context_success_cb_t cb
, void *userdata
) {
1251 const char * const *k
;
1254 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1256 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
1257 PA_CHECK_VALIDITY_RETURN_NULL(c
, keys
&& keys
[0], PA_ERR_INVALID
);
1258 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
1259 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 13, PA_ERR_NOTSUPPORTED
);
1261 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
1263 t
= pa_tagstruct_command(c
, PA_COMMAND_REMOVE_CLIENT_PROPLIST
, &tag
);
1265 for (k
= keys
; *k
; k
++)
1266 pa_tagstruct_puts(t
, *k
);
1268 pa_tagstruct_puts(t
, NULL
);
1270 pa_pstream_send_tagstruct(c
->pstream
, t
);
1271 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
);
1273 /* Please note that we don't update c->proplist here, because we
1274 * don't export that field */
1279 void pa_command_extension(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
1280 pa_context
*c
= userdata
;
1285 pa_assert(command
== PA_COMMAND_EXTENSION
);
1288 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1292 if (c
->version
< 15) {
1293 pa_context_fail(c
, PA_ERR_PROTOCOL
);
1297 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
1298 pa_tagstruct_gets(t
, &name
) < 0) {
1299 pa_context_fail(c
, PA_ERR_PROTOCOL
);
1303 if (!strcmp(name
, "module-stream-restore"))
1304 pa_ext_stream_restore_command(c
, tag
, t
);
1306 pa_log(_("Received message for unknown extension '%s'"), name
);
1309 pa_context_unref(c
);
1313 void pa_command_client_event(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
1314 pa_context
*c
= userdata
;
1315 pa_proplist
*pl
= NULL
;
1319 pa_assert(command
== PA_COMMAND_CLIENT_EVENT
);
1322 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1326 if (c
->version
< 15) {
1327 pa_context_fail(c
, PA_ERR_PROTOCOL
);
1331 pl
= pa_proplist_new();
1333 if (pa_tagstruct_gets(t
, &event
) < 0 ||
1334 pa_tagstruct_get_proplist(t
, pl
) < 0 ||
1335 !pa_tagstruct_eof(t
) || !event
) {
1336 pa_context_fail(c
, PA_ERR_PROTOCOL
);
1340 if (c
->event_callback
)
1341 c
->event_callback(c
, event
, pl
, c
->event_userdata
);
1344 pa_context_unref(c
);
1347 pa_proplist_free(pl
);