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
);
109 static DBusHandlerResult
filter_cb(DBusConnection
*bus
, DBusMessage
*message
, void *userdata
);
112 pa_context
*pa_context_new(pa_mainloop_api
*mainloop
, const char *name
) {
113 return pa_context_new_with_proplist(mainloop
, name
, NULL
);
116 static void reset_callbacks(pa_context
*c
) {
119 c
->state_callback
= NULL
;
120 c
->state_userdata
= NULL
;
122 c
->subscribe_callback
= NULL
;
123 c
->subscribe_userdata
= NULL
;
125 c
->event_callback
= NULL
;
126 c
->event_userdata
= NULL
;
128 c
->ext_stream_restore
.callback
= NULL
;
129 c
->ext_stream_restore
.userdata
= NULL
;
132 pa_context
*pa_context_new_with_proplist(pa_mainloop_api
*mainloop
, const char *name
, pa_proplist
*p
) {
137 if (pa_detect_fork())
142 c
= pa_xnew(pa_context
, 1);
145 c
->proplist
= p
? pa_proplist_copy(p
) : pa_proplist_new();
148 pa_proplist_sets(c
->proplist
, PA_PROP_APPLICATION_NAME
, name
);
151 c
->system_bus
= c
->session_bus
= NULL
;
153 c
->mainloop
= mainloop
;
157 c
->playback_streams
= pa_dynarray_new();
158 c
->record_streams
= pa_dynarray_new();
159 c
->client_index
= PA_INVALID_INDEX
;
161 PA_LLIST_HEAD_INIT(pa_stream
, c
->streams
);
162 PA_LLIST_HEAD_INIT(pa_operation
, c
->operations
);
165 c
->state
= PA_CONTEXT_UNCONNECTED
;
172 c
->server_list
= NULL
;
177 c
->server_specified
= FALSE
;
179 c
->do_autospawn
= FALSE
;
180 memset(&c
->spawn_api
, 0, sizeof(c
->spawn_api
));
184 pa_check_signal_is_blocked(SIGPIPE
);
188 c
->conf
= pa_client_conf_new();
190 pa_client_conf_from_x11(c
->conf
, NULL
);
192 pa_client_conf_load(c
->conf
, NULL
);
193 pa_client_conf_env(c
->conf
);
195 if (!(c
->mempool
= pa_mempool_new(!c
->conf
->disable_shm
, c
->conf
->shm_size
))) {
197 if (!c
->conf
->disable_shm
)
198 c
->mempool
= pa_mempool_new(FALSE
, c
->conf
->shm_size
);
209 static void context_unlink(pa_context
*c
) {
214 s
= c
->streams
? pa_stream_ref(c
->streams
) : NULL
;
216 pa_stream
*n
= s
->next
? pa_stream_ref(s
->next
) : NULL
;
217 pa_stream_set_state(s
, c
->state
== PA_CONTEXT_FAILED
? PA_STREAM_FAILED
: PA_STREAM_TERMINATED
);
222 while (c
->operations
)
223 pa_operation_cancel(c
->operations
);
226 pa_pdispatch_unref(c
->pdispatch
);
231 pa_pstream_unlink(c
->pstream
);
232 pa_pstream_unref(c
->pstream
);
237 pa_socket_client_unref(c
->client
);
244 static void context_free(pa_context
*c
) {
251 dbus_connection_remove_filter(pa_dbus_wrap_connection_get(c
->system_bus
), filter_cb
, c
);
252 pa_dbus_wrap_connection_free(c
->system_bus
);
255 if (c
->session_bus
) {
256 dbus_connection_remove_filter(pa_dbus_wrap_connection_get(c
->session_bus
), filter_cb
, c
);
257 pa_dbus_wrap_connection_free(c
->session_bus
);
261 if (c
->record_streams
)
262 pa_dynarray_free(c
->record_streams
, NULL
, NULL
);
263 if (c
->playback_streams
)
264 pa_dynarray_free(c
->playback_streams
, NULL
, NULL
);
267 pa_mempool_free(c
->mempool
);
270 pa_client_conf_free(c
->conf
);
272 pa_strlist_free(c
->server_list
);
275 pa_proplist_free(c
->proplist
);
281 pa_context
* pa_context_ref(pa_context
*c
) {
283 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
289 void pa_context_unref(pa_context
*c
) {
291 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
293 if (PA_REFCNT_DEC(c
) <= 0)
297 void pa_context_set_state(pa_context
*c
, pa_context_state_t st
) {
299 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
308 if (c
->state_callback
)
309 c
->state_callback(c
, c
->state_userdata
);
311 if (st
== PA_CONTEXT_FAILED
|| st
== PA_CONTEXT_TERMINATED
)
317 int pa_context_set_error(pa_context
*c
, int error
) {
318 pa_assert(error
>= 0);
319 pa_assert(error
< PA_ERR_MAX
);
327 void pa_context_fail(pa_context
*c
, int error
) {
329 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
331 pa_context_set_error(c
, error
);
332 pa_context_set_state(c
, PA_CONTEXT_FAILED
);
335 static void pstream_die_callback(pa_pstream
*p
, void *userdata
) {
336 pa_context
*c
= userdata
;
341 pa_context_fail(c
, PA_ERR_CONNECTIONTERMINATED
);
344 static void pstream_packet_callback(pa_pstream
*p
, pa_packet
*packet
, const pa_creds
*creds
, void *userdata
) {
345 pa_context
*c
= userdata
;
353 if (pa_pdispatch_run(c
->pdispatch
, packet
, creds
, c
) < 0)
354 pa_context_fail(c
, PA_ERR_PROTOCOL
);
359 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
) {
360 pa_context
*c
= userdata
;
365 pa_assert(chunk
->length
> 0);
367 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
371 if ((s
= pa_dynarray_get(c
->record_streams
, channel
))) {
373 if (chunk
->memblock
) {
374 pa_memblockq_seek(s
->record_memblockq
, offset
, seek
, TRUE
);
375 pa_memblockq_push_align(s
->record_memblockq
, chunk
);
377 pa_memblockq_seek(s
->record_memblockq
, offset
+chunk
->length
, seek
, TRUE
);
379 if (s
->read_callback
) {
382 if ((l
= pa_memblockq_get_length(s
->record_memblockq
)) > 0)
383 s
->read_callback(s
, l
, s
->read_userdata
);
390 int pa_context_handle_error(pa_context
*c
, uint32_t command
, pa_tagstruct
*t
, pa_bool_t fail
) {
393 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
395 if (command
== PA_COMMAND_ERROR
) {
398 if (pa_tagstruct_getu32(t
, &err
) < 0 ||
399 !pa_tagstruct_eof(t
)) {
400 pa_context_fail(c
, PA_ERR_PROTOCOL
);
404 } else if (command
== PA_COMMAND_TIMEOUT
)
405 err
= PA_ERR_TIMEOUT
;
407 pa_context_fail(c
, PA_ERR_PROTOCOL
);
412 pa_context_fail(c
, PA_ERR_PROTOCOL
);
416 if (err
>= PA_ERR_MAX
)
417 err
= PA_ERR_UNKNOWN
;
420 pa_context_fail(c
, (int) err
);
424 pa_context_set_error(c
, (int) err
);
429 static void setup_complete_callback(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
430 pa_context
*c
= userdata
;
434 pa_assert(c
->state
== PA_CONTEXT_AUTHORIZING
|| c
->state
== PA_CONTEXT_SETTING_NAME
);
438 if (command
!= PA_COMMAND_REPLY
) {
439 pa_context_handle_error(c
, command
, t
, TRUE
);
444 case PA_CONTEXT_AUTHORIZING
: {
446 pa_bool_t shm_on_remote
= FALSE
;
448 if (pa_tagstruct_getu32(t
, &c
->version
) < 0 ||
449 !pa_tagstruct_eof(t
)) {
450 pa_context_fail(c
, PA_ERR_PROTOCOL
);
454 /* Minimum supported version */
455 if (c
->version
< 8) {
456 pa_context_fail(c
, PA_ERR_VERSION
);
460 /* Starting with protocol version 13 the MSB of the version
461 tag reflects if shm is available for this connection or
463 if (c
->version
>= 13) {
464 shm_on_remote
= !!(c
->version
& 0x80000000U
);
465 c
->version
&= 0x7FFFFFFFU
;
468 pa_log_debug("Protocol version: remote %u, local %u", c
->version
, PA_PROTOCOL_VERSION
);
470 /* Enable shared memory support if possible */
472 if (c
->version
< 10 || (c
->version
>= 13 && !shm_on_remote
))
477 /* Only enable SHM if both sides are owned by the same
478 * user. This is a security measure because otherwise
479 * data private to the user might leak. */
482 const pa_creds
*creds
;
483 if (!(creds
= pa_pdispatch_creds(pd
)) || getuid() != creds
->uid
)
488 pa_log_debug("Negotiated SHM: %s", pa_yes_no(c
->do_shm
));
489 pa_pstream_enable_shm(c
->pstream
, c
->do_shm
);
491 reply
= pa_tagstruct_command(c
, PA_COMMAND_SET_CLIENT_NAME
, &tag
);
493 if (c
->version
>= 13) {
494 pa_init_proplist(c
->proplist
);
495 pa_tagstruct_put_proplist(reply
, c
->proplist
);
497 pa_tagstruct_puts(reply
, pa_proplist_gets(c
->proplist
, PA_PROP_APPLICATION_NAME
));
499 pa_pstream_send_tagstruct(c
->pstream
, reply
);
500 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, setup_complete_callback
, c
, NULL
);
502 pa_context_set_state(c
, PA_CONTEXT_SETTING_NAME
);
506 case PA_CONTEXT_SETTING_NAME
:
508 if ((c
->version
>= 13 && (pa_tagstruct_getu32(t
, &c
->client_index
) < 0 ||
509 c
->client_index
== PA_INVALID_INDEX
)) ||
510 !pa_tagstruct_eof(t
)) {
511 pa_context_fail(c
, PA_ERR_PROTOCOL
);
515 pa_context_set_state(c
, PA_CONTEXT_READY
);
519 pa_assert_not_reached();
526 static void setup_context(pa_context
*c
, pa_iochannel
*io
) {
535 pa_assert(!c
->pstream
);
536 c
->pstream
= pa_pstream_new(c
->mainloop
, io
, c
->mempool
);
538 pa_pstream_set_die_callback(c
->pstream
, pstream_die_callback
, c
);
539 pa_pstream_set_recieve_packet_callback(c
->pstream
, pstream_packet_callback
, c
);
540 pa_pstream_set_recieve_memblock_callback(c
->pstream
, pstream_memblock_callback
, c
);
542 pa_assert(!c
->pdispatch
);
543 c
->pdispatch
= pa_pdispatch_new(c
->mainloop
, command_table
, PA_COMMAND_MAX
);
545 if (!c
->conf
->cookie_valid
)
546 pa_log_info(_("No cookie loaded. Attempting to connect without."));
548 t
= pa_tagstruct_command(c
, PA_COMMAND_AUTH
, &tag
);
551 pa_mempool_is_shared(c
->mempool
) &&
554 pa_log_debug("SHM possible: %s", pa_yes_no(c
->do_shm
));
556 /* Starting with protocol version 13 we use the MSB of the version
557 * tag for informing the other side if we could do SHM or not */
558 pa_tagstruct_putu32(t
, PA_PROTOCOL_VERSION
| (c
->do_shm
? 0x80000000U
: 0));
559 pa_tagstruct_put_arbitrary(t
, c
->conf
->cookie
, sizeof(c
->conf
->cookie
));
565 if (pa_iochannel_creds_supported(io
))
566 pa_iochannel_creds_enable(io
);
568 ucred
.uid
= getuid();
569 ucred
.gid
= getgid();
571 pa_pstream_send_tagstruct_with_creds(c
->pstream
, t
, &ucred
);
574 pa_pstream_send_tagstruct(c
->pstream
, t
);
577 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, setup_complete_callback
, c
, NULL
);
579 pa_context_set_state(c
, PA_CONTEXT_AUTHORIZING
);
584 #ifdef ENABLE_LEGACY_RUNTIME_DIR
585 static char *get_old_legacy_runtime_dir(void) {
589 if (!pa_get_user_name(u
, sizeof(u
)))
592 p
= pa_sprintf_malloc("/tmp/pulse-%s", u
);
594 if (stat(p
, &st
) < 0) {
599 if (st
.st_uid
!= getuid()) {
607 static char *get_very_old_legacy_runtime_dir(void) {
611 if (!pa_get_home_dir(h
, sizeof(h
)))
614 p
= pa_sprintf_malloc("%s/.pulse", h
);
616 if (stat(p
, &st
) < 0) {
621 if (st
.st_uid
!= getuid()) {
630 static pa_strlist
*prepend_per_user(pa_strlist
*l
) {
633 #ifdef ENABLE_LEGACY_RUNTIME_DIR
634 static char *legacy_dir
;
636 /* The very old per-user instance path (< 0.9.11). This is supported only to ease upgrades */
637 if ((legacy_dir
= get_very_old_legacy_runtime_dir())) {
638 char *p
= pa_sprintf_malloc("%s" PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET
, legacy_dir
);
639 l
= pa_strlist_prepend(l
, p
);
641 pa_xfree(legacy_dir
);
644 /* The old per-user instance path (< 0.9.12). This is supported only to ease upgrades */
645 if ((legacy_dir
= get_old_legacy_runtime_dir())) {
646 char *p
= pa_sprintf_malloc("%s" PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET
, legacy_dir
);
647 l
= pa_strlist_prepend(l
, p
);
649 pa_xfree(legacy_dir
);
653 /* The per-user instance */
654 if ((ufn
= pa_runtime_path(PA_NATIVE_DEFAULT_UNIX_SOCKET
))) {
655 l
= pa_strlist_prepend(l
, ufn
);
664 static int context_autospawn(pa_context
*c
) {
668 pa_log_debug("Trying to autospawn...");
672 if (c
->spawn_api
.prefork
)
673 c
->spawn_api
.prefork();
675 if ((pid
= fork()) < 0) {
676 pa_log_error(_("fork(): %s"), pa_cstrerror(errno
));
677 pa_context_fail(c
, PA_ERR_INTERNAL
);
679 if (c
->spawn_api
.postfork
)
680 c
->spawn_api
.postfork();
686 const char *state
= NULL
;
688 const char * argv
[MAX_ARGS
+1];
691 if (c
->spawn_api
.atfork
)
692 c
->spawn_api
.atfork();
700 argv
[n
++] = c
->conf
->daemon_binary
;
701 argv
[n
++] = "--start";
703 while (n
< MAX_ARGS
) {
706 if (!(a
= pa_split_spaces(c
->conf
->extra_arguments
, &state
)))
714 execv(argv
[0], (char * const *) argv
);
721 if (c
->spawn_api
.postfork
)
722 c
->spawn_api
.postfork();
725 r
= waitpid(pid
, &status
, 0);
726 } while (r
< 0 && errno
== EINTR
);
729 pa_log(_("waitpid(): %s"), pa_cstrerror(errno
));
730 pa_context_fail(c
, PA_ERR_INTERNAL
);
732 } else if (!WIFEXITED(status
) || WEXITSTATUS(status
) != 0) {
733 pa_context_fail(c
, PA_ERR_CONNECTIONREFUSED
);
748 #endif /* OS_IS_WIN32 */
750 static void on_connection(pa_socket_client
*client
, pa_iochannel
*io
, void *userdata
);
753 static void track_pulseaudio_on_dbus(pa_context
*c
, DBusBusType type
, pa_dbus_wrap_connection
**conn
) {
759 dbus_error_init(&error
);
760 if (!(*conn
= pa_dbus_wrap_connection_new(c
->mainloop
, type
, &error
)) || dbus_error_is_set(&error
)) {
761 pa_log_warn("Unable to contact DBUS: %s: %s", error
.name
, error
.message
);
765 if (!dbus_connection_add_filter(pa_dbus_wrap_connection_get(*conn
), filter_cb
, c
, NULL
)) {
766 pa_log_warn("Failed to add filter function");
770 if (pa_dbus_add_matches(
771 pa_dbus_wrap_connection_get(*conn
), &error
,
772 "type='signal',sender='" DBUS_SERVICE_DBUS
"',interface='" DBUS_INTERFACE_DBUS
"',member='NameOwnerChanged',arg0='org.pulseaudio.Server',arg1=''", NULL
) < 0)
773 pa_log_warn("Unable to track org.pulseaudio.Server: %s: %s", error
.name
, error
.message
);
776 dbus_error_free(&error
);
780 static int try_next_connection(pa_context
*c
) {
785 pa_assert(!c
->client
);
791 c
->server_list
= pa_strlist_pop(c
->server_list
, &u
);
796 if (c
->do_autospawn
) {
798 if ((r
= context_autospawn(c
)) < 0)
801 /* Autospawn only once */
802 c
->do_autospawn
= FALSE
;
804 /* Connect only to per-user sockets this time */
805 c
->server_list
= prepend_per_user(c
->server_list
);
807 /* Retry connection */
813 if (c
->no_fail
&& !c
->server_specified
) {
815 track_pulseaudio_on_dbus(c
, DBUS_BUS_SYSTEM
, &c
->system_bus
);
817 track_pulseaudio_on_dbus(c
, DBUS_BUS_SESSION
, &c
->session_bus
);
820 pa_context_fail(c
, PA_ERR_CONNECTIONREFUSED
);
825 pa_log_debug("Trying to connect to %s...", u
);
828 c
->server
= pa_xstrdup(u
);
830 if (!(c
->client
= pa_socket_client_new_string(c
->mainloop
, u
, PA_NATIVE_DEFAULT_PORT
)))
833 c
->is_local
= !!pa_socket_client_is_local(c
->client
);
834 pa_socket_client_set_callback(c
->client
, on_connection
, c
);
846 static void on_connection(pa_socket_client
*client
, pa_iochannel
*io
, void *userdata
) {
847 pa_context
*c
= userdata
;
848 int saved_errno
= errno
;
852 pa_assert(c
->state
== PA_CONTEXT_CONNECTING
);
856 pa_socket_client_unref(client
);
860 /* Try the item in the list */
861 if (saved_errno
== ECONNREFUSED
||
862 saved_errno
== ETIMEDOUT
||
863 saved_errno
== EHOSTUNREACH
) {
864 try_next_connection(c
);
868 pa_context_fail(c
, PA_ERR_CONNECTIONREFUSED
);
872 setup_context(c
, io
);
879 static DBusHandlerResult
filter_cb(DBusConnection
*bus
, DBusMessage
*message
, void *userdata
) {
880 pa_context
*c
= userdata
;
881 pa_bool_t is_session
;
887 if (c
->state
!= PA_CONTEXT_CONNECTING
)
893 /* FIXME: We probably should check if this is actually the NameOwnerChanged we were looking for */
895 is_session
= bus
== pa_dbus_wrap_connection_get(c
->session_bus
);
896 pa_log_debug("Rock!! PulseAudio is back on %s bus", is_session
? "session" : "system");
899 /* The user instance via PF_LOCAL */
900 c
->server_list
= prepend_per_user(c
->server_list
);
902 /* The system wide instance via PF_LOCAL */
903 c
->server_list
= pa_strlist_prepend(c
->server_list
, PA_SYSTEM_RUNTIME_PATH PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET
);
905 try_next_connection(c
);
908 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED
;
912 int pa_context_connect(
915 pa_context_flags_t flags
,
916 const pa_spawn_api
*api
) {
921 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
923 PA_CHECK_VALIDITY(c
, !pa_detect_fork(), PA_ERR_FORKED
);
924 PA_CHECK_VALIDITY(c
, c
->state
== PA_CONTEXT_UNCONNECTED
, PA_ERR_BADSTATE
);
925 PA_CHECK_VALIDITY(c
, !(flags
& ~(PA_CONTEXT_NOAUTOSPAWN
|PA_CONTEXT_NOFAIL
)), PA_ERR_INVALID
);
926 PA_CHECK_VALIDITY(c
, !server
|| *server
, PA_ERR_INVALID
);
929 server
= c
->conf
->default_server
;
933 c
->no_fail
= flags
& PA_CONTEXT_NOFAIL
;
934 c
->server_specified
= !!server
;
935 pa_assert(!c
->server_list
);
938 if (!(c
->server_list
= pa_strlist_parse(server
))) {
939 pa_context_fail(c
, PA_ERR_INVALIDSERVER
);
946 /* Prepend in reverse order */
948 /* Follow the X display */
949 if ((d
= getenv("DISPLAY"))) {
952 if ((e
= strchr(d
, ':')))
956 c
->server_list
= pa_strlist_prepend(c
->server_list
, d
);
961 /* Add TCP/IP on the localhost */
962 c
->server_list
= pa_strlist_prepend(c
->server_list
, "tcp6:[::1]");
963 c
->server_list
= pa_strlist_prepend(c
->server_list
, "tcp4:127.0.0.1");
965 /* The system wide instance via PF_LOCAL */
966 c
->server_list
= pa_strlist_prepend(c
->server_list
, PA_SYSTEM_RUNTIME_PATH PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET
);
968 /* The user instance via PF_LOCAL */
969 c
->server_list
= prepend_per_user(c
->server_list
);
971 /* Set up autospawning */
972 if (!(flags
& PA_CONTEXT_NOAUTOSPAWN
) && c
->conf
->autospawn
) {
975 pa_log_debug("Not doing autospawn since we are root.");
977 c
->do_autospawn
= TRUE
;
985 pa_context_set_state(c
, PA_CONTEXT_CONNECTING
);
986 r
= try_next_connection(c
);
994 void pa_context_disconnect(pa_context
*c
) {
996 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
998 if (pa_detect_fork())
1001 if (PA_CONTEXT_IS_GOOD(c
->state
))
1002 pa_context_set_state(c
, PA_CONTEXT_TERMINATED
);
1005 pa_context_state_t
pa_context_get_state(pa_context
*c
) {
1007 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1012 int pa_context_errno(pa_context
*c
) {
1014 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1019 void pa_context_set_state_callback(pa_context
*c
, pa_context_notify_cb_t cb
, void *userdata
) {
1021 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1023 if (pa_detect_fork())
1026 if (c
->state
== PA_CONTEXT_TERMINATED
|| c
->state
== PA_CONTEXT_FAILED
)
1029 c
->state_callback
= cb
;
1030 c
->state_userdata
= userdata
;
1033 void pa_context_set_event_callback(pa_context
*c
, pa_context_event_cb_t cb
, void *userdata
) {
1035 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1037 if (pa_detect_fork())
1040 if (c
->state
== PA_CONTEXT_TERMINATED
|| c
->state
== PA_CONTEXT_FAILED
)
1043 c
->event_callback
= cb
;
1044 c
->event_userdata
= userdata
;
1047 int pa_context_is_pending(pa_context
*c
) {
1049 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1051 PA_CHECK_VALIDITY(c
, !pa_detect_fork(), PA_ERR_FORKED
);
1052 PA_CHECK_VALIDITY(c
, PA_CONTEXT_IS_GOOD(c
->state
), PA_ERR_BADSTATE
);
1054 return (c
->pstream
&& pa_pstream_is_pending(c
->pstream
)) ||
1055 (c
->pdispatch
&& pa_pdispatch_is_pending(c
->pdispatch
)) ||
1059 static void set_dispatch_callbacks(pa_operation
*o
);
1061 static void pdispatch_drain_callback(pa_pdispatch
*pd
, void *userdata
) {
1062 set_dispatch_callbacks(userdata
);
1065 static void pstream_drain_callback(pa_pstream
*s
, void *userdata
) {
1066 set_dispatch_callbacks(userdata
);
1069 static void set_dispatch_callbacks(pa_operation
*o
) {
1073 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
1074 pa_assert(o
->context
);
1075 pa_assert(PA_REFCNT_VALUE(o
->context
) >= 1);
1076 pa_assert(o
->context
->state
== PA_CONTEXT_READY
);
1078 pa_pstream_set_drain_callback(o
->context
->pstream
, NULL
, NULL
);
1079 pa_pdispatch_set_drain_callback(o
->context
->pdispatch
, NULL
, NULL
);
1081 if (pa_pdispatch_is_pending(o
->context
->pdispatch
)) {
1082 pa_pdispatch_set_drain_callback(o
->context
->pdispatch
, pdispatch_drain_callback
, o
);
1086 if (pa_pstream_is_pending(o
->context
->pstream
)) {
1087 pa_pstream_set_drain_callback(o
->context
->pstream
, pstream_drain_callback
, o
);
1093 pa_context_notify_cb_t cb
= (pa_context_notify_cb_t
) o
->callback
;
1094 cb(o
->context
, o
->userdata
);
1097 pa_operation_done(o
);
1098 pa_operation_unref(o
);
1102 pa_operation
* pa_context_drain(pa_context
*c
, pa_context_notify_cb_t cb
, void *userdata
) {
1106 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1108 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
1109 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
1110 PA_CHECK_VALIDITY_RETURN_NULL(c
, pa_context_is_pending(c
), PA_ERR_BADSTATE
);
1112 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
1113 set_dispatch_callbacks(pa_operation_ref(o
));
1118 void pa_context_simple_ack_callback(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
1119 pa_operation
*o
= userdata
;
1124 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
1129 if (command
!= PA_COMMAND_REPLY
) {
1130 if (pa_context_handle_error(o
->context
, command
, t
, FALSE
) < 0)
1134 } else if (!pa_tagstruct_eof(t
)) {
1135 pa_context_fail(o
->context
, PA_ERR_PROTOCOL
);
1140 pa_context_success_cb_t cb
= (pa_context_success_cb_t
) o
->callback
;
1141 cb(o
->context
, success
, o
->userdata
);
1145 pa_operation_done(o
);
1146 pa_operation_unref(o
);
1149 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
) {
1155 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1157 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
1158 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
1160 o
= pa_operation_new(c
, NULL
, cb
, userdata
);
1162 t
= pa_tagstruct_command(c
, command
, &tag
);
1163 pa_pstream_send_tagstruct(c
->pstream
, t
);
1164 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, internal_cb
, pa_operation_ref(o
), (pa_free_cb_t
) pa_operation_unref
);
1169 pa_operation
* pa_context_exit_daemon(pa_context
*c
, pa_context_success_cb_t cb
, void *userdata
) {
1171 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1173 return pa_context_send_simple_command(c
, PA_COMMAND_EXIT
, pa_context_simple_ack_callback
, (pa_operation_cb_t
) cb
, userdata
);
1176 pa_operation
* pa_context_set_default_sink(pa_context
*c
, const char *name
, pa_context_success_cb_t cb
, void *userdata
) {
1182 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1184 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
1185 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
1187 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
1188 t
= pa_tagstruct_command(c
, PA_COMMAND_SET_DEFAULT_SINK
, &tag
);
1189 pa_tagstruct_puts(t
, name
);
1190 pa_pstream_send_tagstruct(c
->pstream
, t
);
1191 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
);
1196 pa_operation
* pa_context_set_default_source(pa_context
*c
, const char *name
, pa_context_success_cb_t cb
, void *userdata
) {
1202 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1204 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
1205 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
1207 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
1208 t
= pa_tagstruct_command(c
, PA_COMMAND_SET_DEFAULT_SOURCE
, &tag
);
1209 pa_tagstruct_puts(t
, name
);
1210 pa_pstream_send_tagstruct(c
->pstream
, t
);
1211 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
);
1216 int pa_context_is_local(pa_context
*c
) {
1218 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1220 PA_CHECK_VALIDITY_RETURN_ANY(c
, !pa_detect_fork(), PA_ERR_FORKED
, -1);
1221 PA_CHECK_VALIDITY_RETURN_ANY(c
, PA_CONTEXT_IS_GOOD(c
->state
), PA_ERR_BADSTATE
, -1);
1223 return !!c
->is_local
;
1226 pa_operation
* pa_context_set_name(pa_context
*c
, const char *name
, pa_context_success_cb_t cb
, void *userdata
) {
1230 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1233 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
1234 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
1236 if (c
->version
>= 13) {
1237 pa_proplist
*p
= pa_proplist_new();
1239 pa_proplist_sets(p
, PA_PROP_APPLICATION_NAME
, name
);
1240 o
= pa_context_proplist_update(c
, PA_UPDATE_REPLACE
, p
, cb
, userdata
);
1241 pa_proplist_free(p
);
1246 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
1247 t
= pa_tagstruct_command(c
, PA_COMMAND_SET_CLIENT_NAME
, &tag
);
1248 pa_tagstruct_puts(t
, name
);
1249 pa_pstream_send_tagstruct(c
->pstream
, t
);
1250 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
);
1256 const char* pa_get_library_version(void) {
1257 return PACKAGE_VERSION
;
1260 const char* pa_context_get_server(pa_context
*c
) {
1262 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1264 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
1265 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->server
, PA_ERR_NOENTITY
);
1267 if (*c
->server
== '{') {
1268 char *e
= strchr(c
->server
+1, '}');
1269 return e
? e
+1 : c
->server
;
1275 uint32_t pa_context_get_protocol_version(pa_context
*c
) {
1276 return PA_PROTOCOL_VERSION
;
1279 uint32_t pa_context_get_server_protocol_version(pa_context
*c
) {
1281 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1283 PA_CHECK_VALIDITY_RETURN_ANY(c
, !pa_detect_fork(), PA_ERR_FORKED
, PA_INVALID_INDEX
);
1284 PA_CHECK_VALIDITY_RETURN_ANY(c
, PA_CONTEXT_IS_GOOD(c
->state
), PA_ERR_BADSTATE
, PA_INVALID_INDEX
);
1289 pa_tagstruct
*pa_tagstruct_command(pa_context
*c
, uint32_t command
, uint32_t *tag
) {
1295 t
= pa_tagstruct_new(NULL
, 0);
1296 pa_tagstruct_putu32(t
, command
);
1297 pa_tagstruct_putu32(t
, *tag
= c
->ctag
++);
1302 uint32_t pa_context_get_index(pa_context
*c
) {
1304 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1306 PA_CHECK_VALIDITY_RETURN_ANY(c
, !pa_detect_fork(), PA_ERR_FORKED
, PA_INVALID_INDEX
);
1307 PA_CHECK_VALIDITY_RETURN_ANY(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
, PA_INVALID_INDEX
);
1308 PA_CHECK_VALIDITY_RETURN_ANY(c
, c
->version
>= 13, PA_ERR_NOTSUPPORTED
, PA_INVALID_INDEX
);
1310 return c
->client_index
;
1313 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
) {
1319 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1321 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
1322 PA_CHECK_VALIDITY_RETURN_NULL(c
, mode
== PA_UPDATE_SET
|| mode
== PA_UPDATE_MERGE
|| mode
== PA_UPDATE_REPLACE
, PA_ERR_INVALID
);
1323 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
1324 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 13, PA_ERR_NOTSUPPORTED
);
1326 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
1328 t
= pa_tagstruct_command(c
, PA_COMMAND_UPDATE_CLIENT_PROPLIST
, &tag
);
1329 pa_tagstruct_putu32(t
, (uint32_t) mode
);
1330 pa_tagstruct_put_proplist(t
, p
);
1332 pa_pstream_send_tagstruct(c
->pstream
, t
);
1333 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
);
1335 /* Please note that we don't update c->proplist here, because we
1336 * don't export that field */
1341 pa_operation
*pa_context_proplist_remove(pa_context
*c
, const char *const keys
[], pa_context_success_cb_t cb
, void *userdata
) {
1345 const char * const *k
;
1348 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1350 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
1351 PA_CHECK_VALIDITY_RETURN_NULL(c
, keys
&& keys
[0], PA_ERR_INVALID
);
1352 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
1353 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 13, PA_ERR_NOTSUPPORTED
);
1355 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
1357 t
= pa_tagstruct_command(c
, PA_COMMAND_REMOVE_CLIENT_PROPLIST
, &tag
);
1359 for (k
= keys
; *k
; k
++)
1360 pa_tagstruct_puts(t
, *k
);
1362 pa_tagstruct_puts(t
, NULL
);
1364 pa_pstream_send_tagstruct(c
->pstream
, t
);
1365 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
);
1367 /* Please note that we don't update c->proplist here, because we
1368 * don't export that field */
1373 void pa_command_extension(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
1374 pa_context
*c
= userdata
;
1379 pa_assert(command
== PA_COMMAND_EXTENSION
);
1382 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1386 if (c
->version
< 15) {
1387 pa_context_fail(c
, PA_ERR_PROTOCOL
);
1391 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
1392 pa_tagstruct_gets(t
, &name
) < 0) {
1393 pa_context_fail(c
, PA_ERR_PROTOCOL
);
1397 if (!strcmp(name
, "module-stream-restore"))
1398 pa_ext_stream_restore_command(c
, tag
, t
);
1400 pa_log(_("Received message for unknown extension '%s'"), name
);
1403 pa_context_unref(c
);
1407 void pa_command_client_event(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
1408 pa_context
*c
= userdata
;
1409 pa_proplist
*pl
= NULL
;
1413 pa_assert(command
== PA_COMMAND_CLIENT_EVENT
);
1416 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1420 if (c
->version
< 15) {
1421 pa_context_fail(c
, PA_ERR_PROTOCOL
);
1425 pl
= pa_proplist_new();
1427 if (pa_tagstruct_gets(t
, &event
) < 0 ||
1428 pa_tagstruct_get_proplist(t
, pl
) < 0 ||
1429 !pa_tagstruct_eof(t
) || !event
) {
1430 pa_context_fail(c
, PA_ERR_PROTOCOL
);
1434 if (c
->event_callback
)
1435 c
->event_callback(c
, event
, pl
, c
->event_userdata
);
1438 pa_context_unref(c
);
1441 pa_proplist_free(pl
);