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
);
107 static DBusHandlerResult
filter_cb(DBusConnection
*bus
, DBusMessage
*message
, void *userdata
);
109 pa_context
*pa_context_new(pa_mainloop_api
*mainloop
, const char *name
) {
110 return pa_context_new_with_proplist(mainloop
, name
, NULL
);
113 static void reset_callbacks(pa_context
*c
) {
116 c
->state_callback
= NULL
;
117 c
->state_userdata
= NULL
;
119 c
->subscribe_callback
= NULL
;
120 c
->subscribe_userdata
= NULL
;
122 c
->event_callback
= NULL
;
123 c
->event_userdata
= NULL
;
125 c
->ext_stream_restore
.callback
= NULL
;
126 c
->ext_stream_restore
.userdata
= NULL
;
129 pa_context
*pa_context_new_with_proplist(pa_mainloop_api
*mainloop
, const char *name
, pa_proplist
*p
) {
134 if (pa_detect_fork())
139 c
= pa_xnew(pa_context
, 1);
142 c
->proplist
= p
? pa_proplist_copy(p
) : pa_proplist_new();
145 pa_proplist_sets(c
->proplist
, PA_PROP_APPLICATION_NAME
, name
);
147 c
->system_bus
= c
->session_bus
= NULL
;
148 c
->mainloop
= mainloop
;
152 c
->playback_streams
= pa_dynarray_new();
153 c
->record_streams
= pa_dynarray_new();
154 c
->client_index
= PA_INVALID_INDEX
;
156 PA_LLIST_HEAD_INIT(pa_stream
, c
->streams
);
157 PA_LLIST_HEAD_INIT(pa_operation
, c
->operations
);
160 c
->state
= PA_CONTEXT_UNCONNECTED
;
167 c
->server_list
= NULL
;
172 c
->server_specified
= FALSE
;
174 c
->do_autospawn
= FALSE
;
175 memset(&c
->spawn_api
, 0, sizeof(c
->spawn_api
));
179 pa_check_signal_is_blocked(SIGPIPE
);
183 c
->conf
= pa_client_conf_new();
185 pa_client_conf_from_x11(c
->conf
, NULL
);
187 pa_client_conf_load(c
->conf
, NULL
);
188 pa_client_conf_env(c
->conf
);
190 if (!(c
->mempool
= pa_mempool_new(!c
->conf
->disable_shm
, c
->conf
->shm_size
))) {
192 if (!c
->conf
->disable_shm
)
193 c
->mempool
= pa_mempool_new(FALSE
, c
->conf
->shm_size
);
204 static void context_unlink(pa_context
*c
) {
209 s
= c
->streams
? pa_stream_ref(c
->streams
) : NULL
;
211 pa_stream
*n
= s
->next
? pa_stream_ref(s
->next
) : NULL
;
212 pa_stream_set_state(s
, c
->state
== PA_CONTEXT_FAILED
? PA_STREAM_FAILED
: PA_STREAM_TERMINATED
);
217 while (c
->operations
)
218 pa_operation_cancel(c
->operations
);
221 pa_pdispatch_unref(c
->pdispatch
);
226 pa_pstream_unlink(c
->pstream
);
227 pa_pstream_unref(c
->pstream
);
232 pa_socket_client_unref(c
->client
);
239 static void context_free(pa_context
*c
) {
245 dbus_connection_remove_filter(pa_dbus_wrap_connection_get(c
->system_bus
), filter_cb
, c
);
246 pa_dbus_wrap_connection_free(c
->system_bus
);
249 if (c
->session_bus
) {
250 dbus_connection_remove_filter(pa_dbus_wrap_connection_get(c
->session_bus
), filter_cb
, c
);
251 pa_dbus_wrap_connection_free(c
->session_bus
);
254 if (c
->record_streams
)
255 pa_dynarray_free(c
->record_streams
, NULL
, NULL
);
256 if (c
->playback_streams
)
257 pa_dynarray_free(c
->playback_streams
, NULL
, NULL
);
260 pa_mempool_free(c
->mempool
);
263 pa_client_conf_free(c
->conf
);
265 pa_strlist_free(c
->server_list
);
268 pa_proplist_free(c
->proplist
);
274 pa_context
* pa_context_ref(pa_context
*c
) {
276 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
282 void pa_context_unref(pa_context
*c
) {
284 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
286 if (PA_REFCNT_DEC(c
) <= 0)
290 void pa_context_set_state(pa_context
*c
, pa_context_state_t st
) {
292 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
301 if (c
->state_callback
)
302 c
->state_callback(c
, c
->state_userdata
);
304 if (st
== PA_CONTEXT_FAILED
|| st
== PA_CONTEXT_TERMINATED
)
310 int pa_context_set_error(pa_context
*c
, int error
) {
311 pa_assert(error
>= 0);
312 pa_assert(error
< PA_ERR_MAX
);
320 void pa_context_fail(pa_context
*c
, int error
) {
322 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
324 pa_context_set_error(c
, error
);
325 pa_context_set_state(c
, PA_CONTEXT_FAILED
);
328 static void pstream_die_callback(pa_pstream
*p
, void *userdata
) {
329 pa_context
*c
= userdata
;
334 pa_context_fail(c
, PA_ERR_CONNECTIONTERMINATED
);
337 static void pstream_packet_callback(pa_pstream
*p
, pa_packet
*packet
, const pa_creds
*creds
, void *userdata
) {
338 pa_context
*c
= userdata
;
346 if (pa_pdispatch_run(c
->pdispatch
, packet
, creds
, c
) < 0)
347 pa_context_fail(c
, PA_ERR_PROTOCOL
);
352 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
) {
353 pa_context
*c
= userdata
;
358 pa_assert(chunk
->length
> 0);
360 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
364 if ((s
= pa_dynarray_get(c
->record_streams
, channel
))) {
366 if (chunk
->memblock
) {
367 pa_memblockq_seek(s
->record_memblockq
, offset
, seek
, TRUE
);
368 pa_memblockq_push_align(s
->record_memblockq
, chunk
);
370 pa_memblockq_seek(s
->record_memblockq
, offset
+chunk
->length
, seek
, TRUE
);
372 if (s
->read_callback
) {
375 if ((l
= pa_memblockq_get_length(s
->record_memblockq
)) > 0)
376 s
->read_callback(s
, l
, s
->read_userdata
);
383 int pa_context_handle_error(pa_context
*c
, uint32_t command
, pa_tagstruct
*t
, pa_bool_t fail
) {
386 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
388 if (command
== PA_COMMAND_ERROR
) {
391 if (pa_tagstruct_getu32(t
, &err
) < 0 ||
392 !pa_tagstruct_eof(t
)) {
393 pa_context_fail(c
, PA_ERR_PROTOCOL
);
397 } else if (command
== PA_COMMAND_TIMEOUT
)
398 err
= PA_ERR_TIMEOUT
;
400 pa_context_fail(c
, PA_ERR_PROTOCOL
);
405 pa_context_fail(c
, PA_ERR_PROTOCOL
);
409 if (err
>= PA_ERR_MAX
)
410 err
= PA_ERR_UNKNOWN
;
413 pa_context_fail(c
, (int) err
);
417 pa_context_set_error(c
, (int) err
);
422 static void setup_complete_callback(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
423 pa_context
*c
= userdata
;
427 pa_assert(c
->state
== PA_CONTEXT_AUTHORIZING
|| c
->state
== PA_CONTEXT_SETTING_NAME
);
431 if (command
!= PA_COMMAND_REPLY
) {
432 pa_context_handle_error(c
, command
, t
, TRUE
);
437 case PA_CONTEXT_AUTHORIZING
: {
439 pa_bool_t shm_on_remote
= FALSE
;
441 if (pa_tagstruct_getu32(t
, &c
->version
) < 0 ||
442 !pa_tagstruct_eof(t
)) {
443 pa_context_fail(c
, PA_ERR_PROTOCOL
);
447 /* Minimum supported version */
448 if (c
->version
< 8) {
449 pa_context_fail(c
, PA_ERR_VERSION
);
453 /* Starting with protocol version 13 the MSB of the version
454 tag reflects if shm is available for this connection or
456 if (c
->version
>= 13) {
457 shm_on_remote
= !!(c
->version
& 0x80000000U
);
458 c
->version
&= 0x7FFFFFFFU
;
461 pa_log_debug("Protocol version: remote %u, local %u", c
->version
, PA_PROTOCOL_VERSION
);
463 /* Enable shared memory support if possible */
465 if (c
->version
< 10 || (c
->version
>= 13 && !shm_on_remote
))
470 /* Only enable SHM if both sides are owned by the same
471 * user. This is a security measure because otherwise
472 * data private to the user might leak. */
475 const pa_creds
*creds
;
476 if (!(creds
= pa_pdispatch_creds(pd
)) || getuid() != creds
->uid
)
481 pa_log_debug("Negotiated SHM: %s", pa_yes_no(c
->do_shm
));
482 pa_pstream_enable_shm(c
->pstream
, c
->do_shm
);
484 reply
= pa_tagstruct_command(c
, PA_COMMAND_SET_CLIENT_NAME
, &tag
);
486 if (c
->version
>= 13) {
487 pa_init_proplist(c
->proplist
);
488 pa_tagstruct_put_proplist(reply
, c
->proplist
);
490 pa_tagstruct_puts(reply
, pa_proplist_gets(c
->proplist
, PA_PROP_APPLICATION_NAME
));
492 pa_pstream_send_tagstruct(c
->pstream
, reply
);
493 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, setup_complete_callback
, c
, NULL
);
495 pa_context_set_state(c
, PA_CONTEXT_SETTING_NAME
);
499 case PA_CONTEXT_SETTING_NAME
:
501 if ((c
->version
>= 13 && (pa_tagstruct_getu32(t
, &c
->client_index
) < 0 ||
502 c
->client_index
== PA_INVALID_INDEX
)) ||
503 !pa_tagstruct_eof(t
)) {
504 pa_context_fail(c
, PA_ERR_PROTOCOL
);
508 pa_context_set_state(c
, PA_CONTEXT_READY
);
512 pa_assert_not_reached();
519 static void setup_context(pa_context
*c
, pa_iochannel
*io
) {
528 pa_assert(!c
->pstream
);
529 c
->pstream
= pa_pstream_new(c
->mainloop
, io
, c
->mempool
);
531 pa_pstream_set_die_callback(c
->pstream
, pstream_die_callback
, c
);
532 pa_pstream_set_recieve_packet_callback(c
->pstream
, pstream_packet_callback
, c
);
533 pa_pstream_set_recieve_memblock_callback(c
->pstream
, pstream_memblock_callback
, c
);
535 pa_assert(!c
->pdispatch
);
536 c
->pdispatch
= pa_pdispatch_new(c
->mainloop
, command_table
, PA_COMMAND_MAX
);
538 if (!c
->conf
->cookie_valid
)
539 pa_log_info(_("No cookie loaded. Attempting to connect without."));
541 t
= pa_tagstruct_command(c
, PA_COMMAND_AUTH
, &tag
);
544 pa_mempool_is_shared(c
->mempool
) &&
547 pa_log_debug("SHM possible: %s", pa_yes_no(c
->do_shm
));
549 /* Starting with protocol version 13 we use the MSB of the version
550 * tag for informing the other side if we could do SHM or not */
551 pa_tagstruct_putu32(t
, PA_PROTOCOL_VERSION
| (c
->do_shm
? 0x80000000U
: 0));
552 pa_tagstruct_put_arbitrary(t
, c
->conf
->cookie
, sizeof(c
->conf
->cookie
));
558 if (pa_iochannel_creds_supported(io
))
559 pa_iochannel_creds_enable(io
);
561 ucred
.uid
= getuid();
562 ucred
.gid
= getgid();
564 pa_pstream_send_tagstruct_with_creds(c
->pstream
, t
, &ucred
);
567 pa_pstream_send_tagstruct(c
->pstream
, t
);
570 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, setup_complete_callback
, c
, NULL
);
572 pa_context_set_state(c
, PA_CONTEXT_AUTHORIZING
);
577 #ifdef ENABLE_LEGACY_RUNTIME_DIR
578 static char *get_old_legacy_runtime_dir(void) {
582 if (!pa_get_user_name(u
, sizeof(u
)))
585 p
= pa_sprintf_malloc("/tmp/pulse-%s", u
);
587 if (stat(p
, &st
) < 0) {
592 if (st
.st_uid
!= getuid()) {
600 static char *get_very_old_legacy_runtime_dir(void) {
604 if (!pa_get_home_dir(h
, sizeof(h
)))
607 p
= pa_sprintf_malloc("%s/.pulse", h
);
609 if (stat(p
, &st
) < 0) {
614 if (st
.st_uid
!= getuid()) {
623 static pa_strlist
*prepend_per_user(pa_strlist
*l
) {
626 #ifdef ENABLE_LEGACY_RUNTIME_DIR
627 static char *legacy_dir
;
629 /* The very old per-user instance path (< 0.9.11). This is supported only to ease upgrades */
630 if ((legacy_dir
= get_very_old_legacy_runtime_dir())) {
631 char *p
= pa_sprintf_malloc("%s" PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET
, legacy_dir
);
632 l
= pa_strlist_prepend(l
, p
);
634 pa_xfree(legacy_dir
);
637 /* The old per-user instance path (< 0.9.12). This is supported only to ease upgrades */
638 if ((legacy_dir
= get_old_legacy_runtime_dir())) {
639 char *p
= pa_sprintf_malloc("%s" PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET
, legacy_dir
);
640 l
= pa_strlist_prepend(l
, p
);
642 pa_xfree(legacy_dir
);
646 /* The per-user instance */
647 if ((ufn
= pa_runtime_path(PA_NATIVE_DEFAULT_UNIX_SOCKET
))) {
648 l
= pa_strlist_prepend(l
, ufn
);
657 static int context_autospawn(pa_context
*c
) {
661 pa_log_debug("Trying to autospawn...");
665 if (c
->spawn_api
.prefork
)
666 c
->spawn_api
.prefork();
668 if ((pid
= fork()) < 0) {
669 pa_log_error(_("fork(): %s"), pa_cstrerror(errno
));
670 pa_context_fail(c
, PA_ERR_INTERNAL
);
672 if (c
->spawn_api
.postfork
)
673 c
->spawn_api
.postfork();
679 const char *state
= NULL
;
681 const char * argv
[MAX_ARGS
+1];
684 if (c
->spawn_api
.atfork
)
685 c
->spawn_api
.atfork();
693 argv
[n
++] = c
->conf
->daemon_binary
;
694 argv
[n
++] = "--start";
696 while (n
< MAX_ARGS
) {
699 if (!(a
= pa_split_spaces(c
->conf
->extra_arguments
, &state
)))
707 execv(argv
[0], (char * const *) argv
);
714 if (c
->spawn_api
.postfork
)
715 c
->spawn_api
.postfork();
718 r
= waitpid(pid
, &status
, 0);
719 } while (r
< 0 && errno
== EINTR
);
722 pa_log(_("waitpid(): %s"), pa_cstrerror(errno
));
723 pa_context_fail(c
, PA_ERR_INTERNAL
);
725 } else if (!WIFEXITED(status
) || WEXITSTATUS(status
) != 0) {
726 pa_context_fail(c
, PA_ERR_CONNECTIONREFUSED
);
741 #endif /* OS_IS_WIN32 */
743 static void on_connection(pa_socket_client
*client
, pa_iochannel
*io
, void *userdata
);
745 static void track_pulseaudio_on_dbus(pa_context
*c
, DBusBusType type
, pa_dbus_wrap_connection
**conn
) {
751 dbus_error_init(&error
);
752 if (!(*conn
= pa_dbus_wrap_connection_new(c
->mainloop
, type
, &error
)) || dbus_error_is_set(&error
)) {
753 pa_log_warn("Unable to contact DBUS: %s: %s", error
.name
, error
.message
);
757 if (!dbus_connection_add_filter(pa_dbus_wrap_connection_get(*conn
), filter_cb
, c
, NULL
)) {
758 pa_log_warn("Failed to add filter function");
762 if (pa_dbus_add_matches(
763 pa_dbus_wrap_connection_get(*conn
), &error
,
764 "type='signal',sender='" DBUS_SERVICE_DBUS
"',interface='" DBUS_INTERFACE_DBUS
"',member='NameOwnerChanged',arg0='org.pulseaudio.Server',arg1=''", NULL
) < 0)
765 pa_log_warn("Unable to track org.pulseaudio.Server: %s: %s", error
.name
, error
.message
);
768 dbus_error_free(&error
);
771 static int try_next_connection(pa_context
*c
) {
776 pa_assert(!c
->client
);
782 c
->server_list
= pa_strlist_pop(c
->server_list
, &u
);
787 if (c
->do_autospawn
) {
789 if ((r
= context_autospawn(c
)) < 0)
792 /* Autospawn only once */
793 c
->do_autospawn
= FALSE
;
795 /* Connect only to per-user sockets this time */
796 c
->server_list
= prepend_per_user(c
->server_list
);
798 /* Retry connection */
803 if (c
->no_fail
&& !c
->server_specified
) {
805 track_pulseaudio_on_dbus(c
, DBUS_BUS_SYSTEM
, &c
->system_bus
);
807 track_pulseaudio_on_dbus(c
, DBUS_BUS_SESSION
, &c
->session_bus
);
809 pa_context_fail(c
, PA_ERR_CONNECTIONREFUSED
);
814 pa_log_debug("Trying to connect to %s...", u
);
817 c
->server
= pa_xstrdup(u
);
819 if (!(c
->client
= pa_socket_client_new_string(c
->mainloop
, u
, PA_NATIVE_DEFAULT_PORT
)))
822 c
->is_local
= !!pa_socket_client_is_local(c
->client
);
823 pa_socket_client_set_callback(c
->client
, on_connection
, c
);
835 static void on_connection(pa_socket_client
*client
, pa_iochannel
*io
, void *userdata
) {
836 pa_context
*c
= userdata
;
837 int saved_errno
= errno
;
841 pa_assert(c
->state
== PA_CONTEXT_CONNECTING
);
845 pa_socket_client_unref(client
);
849 /* Try the item in the list */
850 if (saved_errno
== ECONNREFUSED
||
851 saved_errno
== ETIMEDOUT
||
852 saved_errno
== EHOSTUNREACH
) {
853 try_next_connection(c
);
857 pa_context_fail(c
, PA_ERR_CONNECTIONREFUSED
);
861 setup_context(c
, io
);
867 static DBusHandlerResult
filter_cb(DBusConnection
*bus
, DBusMessage
*message
, void *userdata
) {
868 pa_context
*c
= userdata
;
869 pa_bool_t is_session
;
875 if (c
->state
!= PA_CONTEXT_CONNECTING
)
881 /* FIXME: We probably should check if this is actually the NameOwnerChanged we were looking for */
883 is_session
= bus
== pa_dbus_wrap_connection_get(c
->session_bus
);
884 pa_log_debug("Rock!! PulseAudio is back on %s bus", is_session
? "session" : "system");
887 /* The user instance via PF_LOCAL */
888 c
->server_list
= prepend_per_user(c
->server_list
);
890 /* The system wide instance via PF_LOCAL */
891 c
->server_list
= pa_strlist_prepend(c
->server_list
, PA_SYSTEM_RUNTIME_PATH PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET
);
893 try_next_connection(c
);
896 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED
;
899 int pa_context_connect(
902 pa_context_flags_t flags
,
903 const pa_spawn_api
*api
) {
908 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
910 PA_CHECK_VALIDITY(c
, !pa_detect_fork(), PA_ERR_FORKED
);
911 PA_CHECK_VALIDITY(c
, c
->state
== PA_CONTEXT_UNCONNECTED
, PA_ERR_BADSTATE
);
912 PA_CHECK_VALIDITY(c
, !(flags
& ~(PA_CONTEXT_NOAUTOSPAWN
|PA_CONTEXT_NOFAIL
)), PA_ERR_INVALID
);
913 PA_CHECK_VALIDITY(c
, !server
|| *server
, PA_ERR_INVALID
);
916 server
= c
->conf
->default_server
;
920 c
->no_fail
= flags
& PA_CONTEXT_NOFAIL
;
921 c
->server_specified
= !!server
;
922 pa_assert(!c
->server_list
);
925 if (!(c
->server_list
= pa_strlist_parse(server
))) {
926 pa_context_fail(c
, PA_ERR_INVALIDSERVER
);
933 /* Prepend in reverse order */
935 /* Follow the X display */
936 if ((d
= getenv("DISPLAY"))) {
939 if ((e
= strchr(d
, ':')))
943 c
->server_list
= pa_strlist_prepend(c
->server_list
, d
);
948 /* Add TCP/IP on the localhost */
949 c
->server_list
= pa_strlist_prepend(c
->server_list
, "tcp6:[::1]");
950 c
->server_list
= pa_strlist_prepend(c
->server_list
, "tcp4:127.0.0.1");
952 /* The system wide instance via PF_LOCAL */
953 c
->server_list
= pa_strlist_prepend(c
->server_list
, PA_SYSTEM_RUNTIME_PATH PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET
);
955 /* The user instance via PF_LOCAL */
956 c
->server_list
= prepend_per_user(c
->server_list
);
958 /* Set up autospawning */
959 if (!(flags
& PA_CONTEXT_NOAUTOSPAWN
) && c
->conf
->autospawn
) {
962 pa_log_debug("Not doing autospawn since we are root.");
964 c
->do_autospawn
= TRUE
;
972 pa_context_set_state(c
, PA_CONTEXT_CONNECTING
);
973 r
= try_next_connection(c
);
981 void pa_context_disconnect(pa_context
*c
) {
983 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
985 if (pa_detect_fork())
988 if (PA_CONTEXT_IS_GOOD(c
->state
))
989 pa_context_set_state(c
, PA_CONTEXT_TERMINATED
);
992 pa_context_state_t
pa_context_get_state(pa_context
*c
) {
994 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
999 int pa_context_errno(pa_context
*c
) {
1001 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1006 void pa_context_set_state_callback(pa_context
*c
, pa_context_notify_cb_t cb
, void *userdata
) {
1008 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1010 if (pa_detect_fork())
1013 if (c
->state
== PA_CONTEXT_TERMINATED
|| c
->state
== PA_CONTEXT_FAILED
)
1016 c
->state_callback
= cb
;
1017 c
->state_userdata
= userdata
;
1020 void pa_context_set_event_callback(pa_context
*c
, pa_context_event_cb_t cb
, void *userdata
) {
1022 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1024 if (pa_detect_fork())
1027 if (c
->state
== PA_CONTEXT_TERMINATED
|| c
->state
== PA_CONTEXT_FAILED
)
1030 c
->event_callback
= cb
;
1031 c
->event_userdata
= userdata
;
1034 int pa_context_is_pending(pa_context
*c
) {
1036 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1038 PA_CHECK_VALIDITY(c
, !pa_detect_fork(), PA_ERR_FORKED
);
1039 PA_CHECK_VALIDITY(c
, PA_CONTEXT_IS_GOOD(c
->state
), PA_ERR_BADSTATE
);
1041 return (c
->pstream
&& pa_pstream_is_pending(c
->pstream
)) ||
1042 (c
->pdispatch
&& pa_pdispatch_is_pending(c
->pdispatch
)) ||
1046 static void set_dispatch_callbacks(pa_operation
*o
);
1048 static void pdispatch_drain_callback(pa_pdispatch
*pd
, void *userdata
) {
1049 set_dispatch_callbacks(userdata
);
1052 static void pstream_drain_callback(pa_pstream
*s
, void *userdata
) {
1053 set_dispatch_callbacks(userdata
);
1056 static void set_dispatch_callbacks(pa_operation
*o
) {
1060 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
1061 pa_assert(o
->context
);
1062 pa_assert(PA_REFCNT_VALUE(o
->context
) >= 1);
1063 pa_assert(o
->context
->state
== PA_CONTEXT_READY
);
1065 pa_pstream_set_drain_callback(o
->context
->pstream
, NULL
, NULL
);
1066 pa_pdispatch_set_drain_callback(o
->context
->pdispatch
, NULL
, NULL
);
1068 if (pa_pdispatch_is_pending(o
->context
->pdispatch
)) {
1069 pa_pdispatch_set_drain_callback(o
->context
->pdispatch
, pdispatch_drain_callback
, o
);
1073 if (pa_pstream_is_pending(o
->context
->pstream
)) {
1074 pa_pstream_set_drain_callback(o
->context
->pstream
, pstream_drain_callback
, o
);
1080 pa_context_notify_cb_t cb
= (pa_context_notify_cb_t
) o
->callback
;
1081 cb(o
->context
, o
->userdata
);
1084 pa_operation_done(o
);
1085 pa_operation_unref(o
);
1089 pa_operation
* pa_context_drain(pa_context
*c
, pa_context_notify_cb_t cb
, void *userdata
) {
1093 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1095 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
1096 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
1097 PA_CHECK_VALIDITY_RETURN_NULL(c
, pa_context_is_pending(c
), PA_ERR_BADSTATE
);
1099 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
1100 set_dispatch_callbacks(pa_operation_ref(o
));
1105 void pa_context_simple_ack_callback(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
1106 pa_operation
*o
= userdata
;
1111 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
1116 if (command
!= PA_COMMAND_REPLY
) {
1117 if (pa_context_handle_error(o
->context
, command
, t
, FALSE
) < 0)
1121 } else if (!pa_tagstruct_eof(t
)) {
1122 pa_context_fail(o
->context
, PA_ERR_PROTOCOL
);
1127 pa_context_success_cb_t cb
= (pa_context_success_cb_t
) o
->callback
;
1128 cb(o
->context
, success
, o
->userdata
);
1132 pa_operation_done(o
);
1133 pa_operation_unref(o
);
1136 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
) {
1142 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1144 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
1145 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
1147 o
= pa_operation_new(c
, NULL
, cb
, userdata
);
1149 t
= pa_tagstruct_command(c
, command
, &tag
);
1150 pa_pstream_send_tagstruct(c
->pstream
, t
);
1151 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, internal_cb
, pa_operation_ref(o
), (pa_free_cb_t
) pa_operation_unref
);
1156 pa_operation
* pa_context_exit_daemon(pa_context
*c
, pa_context_success_cb_t cb
, void *userdata
) {
1158 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1160 return pa_context_send_simple_command(c
, PA_COMMAND_EXIT
, pa_context_simple_ack_callback
, (pa_operation_cb_t
) cb
, userdata
);
1163 pa_operation
* pa_context_set_default_sink(pa_context
*c
, const char *name
, pa_context_success_cb_t cb
, void *userdata
) {
1169 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1171 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
1172 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
1174 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
1175 t
= pa_tagstruct_command(c
, PA_COMMAND_SET_DEFAULT_SINK
, &tag
);
1176 pa_tagstruct_puts(t
, name
);
1177 pa_pstream_send_tagstruct(c
->pstream
, t
);
1178 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
);
1183 pa_operation
* pa_context_set_default_source(pa_context
*c
, const char *name
, pa_context_success_cb_t cb
, void *userdata
) {
1189 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1191 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
1192 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
1194 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
1195 t
= pa_tagstruct_command(c
, PA_COMMAND_SET_DEFAULT_SOURCE
, &tag
);
1196 pa_tagstruct_puts(t
, name
);
1197 pa_pstream_send_tagstruct(c
->pstream
, t
);
1198 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
);
1203 int pa_context_is_local(pa_context
*c
) {
1205 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1207 PA_CHECK_VALIDITY_RETURN_ANY(c
, !pa_detect_fork(), PA_ERR_FORKED
, -1);
1208 PA_CHECK_VALIDITY_RETURN_ANY(c
, PA_CONTEXT_IS_GOOD(c
->state
), PA_ERR_BADSTATE
, -1);
1210 return !!c
->is_local
;
1213 pa_operation
* pa_context_set_name(pa_context
*c
, const char *name
, pa_context_success_cb_t cb
, void *userdata
) {
1217 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1220 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
1221 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
1223 if (c
->version
>= 13) {
1224 pa_proplist
*p
= pa_proplist_new();
1226 pa_proplist_sets(p
, PA_PROP_APPLICATION_NAME
, name
);
1227 o
= pa_context_proplist_update(c
, PA_UPDATE_REPLACE
, p
, cb
, userdata
);
1228 pa_proplist_free(p
);
1233 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
1234 t
= pa_tagstruct_command(c
, PA_COMMAND_SET_CLIENT_NAME
, &tag
);
1235 pa_tagstruct_puts(t
, name
);
1236 pa_pstream_send_tagstruct(c
->pstream
, t
);
1237 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
);
1243 const char* pa_get_library_version(void) {
1244 return PACKAGE_VERSION
;
1247 const char* pa_context_get_server(pa_context
*c
) {
1249 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1251 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
1252 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->server
, PA_ERR_NOENTITY
);
1254 if (*c
->server
== '{') {
1255 char *e
= strchr(c
->server
+1, '}');
1256 return e
? e
+1 : c
->server
;
1262 uint32_t pa_context_get_protocol_version(pa_context
*c
) {
1263 return PA_PROTOCOL_VERSION
;
1266 uint32_t pa_context_get_server_protocol_version(pa_context
*c
) {
1268 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1270 PA_CHECK_VALIDITY_RETURN_ANY(c
, !pa_detect_fork(), PA_ERR_FORKED
, PA_INVALID_INDEX
);
1271 PA_CHECK_VALIDITY_RETURN_ANY(c
, PA_CONTEXT_IS_GOOD(c
->state
), PA_ERR_BADSTATE
, PA_INVALID_INDEX
);
1276 pa_tagstruct
*pa_tagstruct_command(pa_context
*c
, uint32_t command
, uint32_t *tag
) {
1282 t
= pa_tagstruct_new(NULL
, 0);
1283 pa_tagstruct_putu32(t
, command
);
1284 pa_tagstruct_putu32(t
, *tag
= c
->ctag
++);
1289 uint32_t pa_context_get_index(pa_context
*c
) {
1291 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1293 PA_CHECK_VALIDITY_RETURN_ANY(c
, !pa_detect_fork(), PA_ERR_FORKED
, PA_INVALID_INDEX
);
1294 PA_CHECK_VALIDITY_RETURN_ANY(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
, PA_INVALID_INDEX
);
1295 PA_CHECK_VALIDITY_RETURN_ANY(c
, c
->version
>= 13, PA_ERR_NOTSUPPORTED
, PA_INVALID_INDEX
);
1297 return c
->client_index
;
1300 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
) {
1306 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1308 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
1309 PA_CHECK_VALIDITY_RETURN_NULL(c
, mode
== PA_UPDATE_SET
|| mode
== PA_UPDATE_MERGE
|| mode
== PA_UPDATE_REPLACE
, PA_ERR_INVALID
);
1310 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
1311 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 13, PA_ERR_NOTSUPPORTED
);
1313 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
1315 t
= pa_tagstruct_command(c
, PA_COMMAND_UPDATE_CLIENT_PROPLIST
, &tag
);
1316 pa_tagstruct_putu32(t
, (uint32_t) mode
);
1317 pa_tagstruct_put_proplist(t
, p
);
1319 pa_pstream_send_tagstruct(c
->pstream
, t
);
1320 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
);
1322 /* Please note that we don't update c->proplist here, because we
1323 * don't export that field */
1328 pa_operation
*pa_context_proplist_remove(pa_context
*c
, const char *const keys
[], pa_context_success_cb_t cb
, void *userdata
) {
1332 const char * const *k
;
1335 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1337 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
1338 PA_CHECK_VALIDITY_RETURN_NULL(c
, keys
&& keys
[0], PA_ERR_INVALID
);
1339 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
1340 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 13, PA_ERR_NOTSUPPORTED
);
1342 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
1344 t
= pa_tagstruct_command(c
, PA_COMMAND_REMOVE_CLIENT_PROPLIST
, &tag
);
1346 for (k
= keys
; *k
; k
++)
1347 pa_tagstruct_puts(t
, *k
);
1349 pa_tagstruct_puts(t
, NULL
);
1351 pa_pstream_send_tagstruct(c
->pstream
, t
);
1352 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
);
1354 /* Please note that we don't update c->proplist here, because we
1355 * don't export that field */
1360 void pa_command_extension(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
1361 pa_context
*c
= userdata
;
1366 pa_assert(command
== PA_COMMAND_EXTENSION
);
1369 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1373 if (c
->version
< 15) {
1374 pa_context_fail(c
, PA_ERR_PROTOCOL
);
1378 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
1379 pa_tagstruct_gets(t
, &name
) < 0) {
1380 pa_context_fail(c
, PA_ERR_PROTOCOL
);
1384 if (!strcmp(name
, "module-stream-restore"))
1385 pa_ext_stream_restore_command(c
, tag
, t
);
1387 pa_log(_("Received message for unknown extension '%s'"), name
);
1390 pa_context_unref(c
);
1394 void pa_command_client_event(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
1395 pa_context
*c
= userdata
;
1396 pa_proplist
*pl
= NULL
;
1400 pa_assert(command
== PA_COMMAND_CLIENT_EVENT
);
1403 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1407 if (c
->version
< 15) {
1408 pa_context_fail(c
, PA_ERR_PROTOCOL
);
1412 pl
= pa_proplist_new();
1414 if (pa_tagstruct_gets(t
, &event
) < 0 ||
1415 pa_tagstruct_get_proplist(t
, pl
) < 0 ||
1416 !pa_tagstruct_eof(t
) || !event
) {
1417 pa_context_fail(c
, PA_ERR_PROTOCOL
);
1421 if (c
->event_callback
)
1422 c
->event_callback(c
, event
, pl
, c
->event_userdata
);
1425 pa_context_unref(c
);
1428 pa_proplist_free(pl
);