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 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>
57 #include <pulse/lock-autospawn.h>
59 #include <pulsecore/winsock.h>
60 #include <pulsecore/core-error.h>
62 #include <pulsecore/native-common.h>
63 #include <pulsecore/pdispatch.h>
64 #include <pulsecore/pstream.h>
65 #include <pulsecore/dynarray.h>
66 #include <pulsecore/socket-client.h>
67 #include <pulsecore/pstream-util.h>
68 #include <pulsecore/core-util.h>
69 #include <pulsecore/log.h>
70 #include <pulsecore/socket-util.h>
71 #include <pulsecore/creds.h>
72 #include <pulsecore/macro.h>
73 #include <pulsecore/proplist-util.h>
77 #include "client-conf.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
102 static void unlock_autospawn(pa_context
*c
) {
105 if (c
->autospawn_fd
>= 0) {
107 if (c
->autospawn_locked
)
108 pa_autospawn_lock_release();
110 if (c
->autospawn_event
)
111 c
->mainloop
->io_free(c
->autospawn_event
);
113 pa_autospawn_lock_done(FALSE
);
116 c
->autospawn_locked
= FALSE
;
117 c
->autospawn_fd
= -1;
118 c
->autospawn_event
= NULL
;
121 static void context_free(pa_context
*c
);
123 pa_context
*pa_context_new(pa_mainloop_api
*mainloop
, const char *name
) {
124 return pa_context_new_with_proplist(mainloop
, name
, NULL
);
127 static void reset_callbacks(pa_context
*c
) {
130 c
->state_callback
= NULL
;
131 c
->state_userdata
= NULL
;
133 c
->subscribe_callback
= NULL
;
134 c
->subscribe_userdata
= NULL
;
136 c
->ext_stream_restore
.callback
= NULL
;
137 c
->ext_stream_restore
.userdata
= NULL
;
140 pa_context
*pa_context_new_with_proplist(pa_mainloop_api
*mainloop
, const char *name
, pa_proplist
*p
) {
147 if (!name
&& !pa_proplist_contains(p
, PA_PROP_APPLICATION_NAME
))
150 c
= pa_xnew(pa_context
, 1);
153 c
->proplist
= p
? pa_proplist_copy(p
) : pa_proplist_new();
156 pa_proplist_sets(c
->proplist
, PA_PROP_APPLICATION_NAME
, name
);
158 c
->mainloop
= mainloop
;
162 c
->playback_streams
= pa_dynarray_new();
163 c
->record_streams
= pa_dynarray_new();
164 c
->client_index
= PA_INVALID_INDEX
;
166 PA_LLIST_HEAD_INIT(pa_stream
, c
->streams
);
167 PA_LLIST_HEAD_INIT(pa_operation
, c
->operations
);
170 c
->state
= PA_CONTEXT_UNCONNECTED
;
177 c
->server_list
= NULL
;
182 c
->do_autospawn
= FALSE
;
183 c
->autospawn_fd
= -1;
184 c
->autospawn_locked
= FALSE
;
185 c
->autospawn_event
= NULL
;
186 memset(&c
->spawn_api
, 0, sizeof(c
->spawn_api
));
190 pa_check_signal_is_blocked(SIGPIPE
);
194 c
->conf
= pa_client_conf_new();
196 pa_client_conf_from_x11(c
->conf
, NULL
);
198 pa_client_conf_load(c
->conf
, NULL
);
199 pa_client_conf_env(c
->conf
);
201 if (!(c
->mempool
= pa_mempool_new(!c
->conf
->disable_shm
))) {
203 if (!c
->conf
->disable_shm
)
204 c
->mempool
= pa_mempool_new(FALSE
);
215 static void context_unlink(pa_context
*c
) {
220 s
= c
->streams
? pa_stream_ref(c
->streams
) : NULL
;
222 pa_stream
*n
= s
->next
? pa_stream_ref(s
->next
) : NULL
;
223 pa_stream_set_state(s
, c
->state
== PA_CONTEXT_FAILED
? PA_STREAM_FAILED
: PA_STREAM_TERMINATED
);
228 while (c
->operations
)
229 pa_operation_cancel(c
->operations
);
232 pa_pdispatch_unref(c
->pdispatch
);
237 pa_pstream_unlink(c
->pstream
);
238 pa_pstream_unref(c
->pstream
);
243 pa_socket_client_unref(c
->client
);
250 static void context_free(pa_context
*c
) {
257 if (c
->record_streams
)
258 pa_dynarray_free(c
->record_streams
, NULL
, NULL
);
259 if (c
->playback_streams
)
260 pa_dynarray_free(c
->playback_streams
, NULL
, NULL
);
263 pa_mempool_free(c
->mempool
);
266 pa_client_conf_free(c
->conf
);
268 pa_strlist_free(c
->server_list
);
271 pa_proplist_free(c
->proplist
);
277 pa_context
* pa_context_ref(pa_context
*c
) {
279 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
285 void pa_context_unref(pa_context
*c
) {
287 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
289 if (PA_REFCNT_DEC(c
) <= 0)
293 void pa_context_set_state(pa_context
*c
, pa_context_state_t st
) {
295 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
304 if (c
->state_callback
)
305 c
->state_callback(c
, c
->state_userdata
);
307 if (st
== PA_CONTEXT_FAILED
|| st
== PA_CONTEXT_TERMINATED
)
313 int pa_context_set_error(pa_context
*c
, int error
) {
314 pa_assert(error
>= 0);
315 pa_assert(error
< PA_ERR_MAX
);
323 void pa_context_fail(pa_context
*c
, int error
) {
325 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
327 pa_context_set_error(c
, error
);
328 pa_context_set_state(c
, PA_CONTEXT_FAILED
);
331 static void pstream_die_callback(pa_pstream
*p
, void *userdata
) {
332 pa_context
*c
= userdata
;
337 pa_context_fail(c
, PA_ERR_CONNECTIONTERMINATED
);
340 static void pstream_packet_callback(pa_pstream
*p
, pa_packet
*packet
, const pa_creds
*creds
, void *userdata
) {
341 pa_context
*c
= userdata
;
349 if (pa_pdispatch_run(c
->pdispatch
, packet
, creds
, c
) < 0)
350 pa_context_fail(c
, PA_ERR_PROTOCOL
);
355 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
) {
356 pa_context
*c
= userdata
;
361 pa_assert(chunk
->memblock
);
362 pa_assert(chunk
->length
);
364 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
368 if ((s
= pa_dynarray_get(c
->record_streams
, channel
))) {
370 pa_assert(seek
== PA_SEEK_RELATIVE
);
371 pa_assert(offset
== 0);
373 pa_memblockq_seek(s
->record_memblockq
, offset
, seek
);
374 pa_memblockq_push_align(s
->record_memblockq
, chunk
);
376 if (s
->read_callback
) {
379 if ((l
= pa_memblockq_get_length(s
->record_memblockq
)) > 0)
380 s
->read_callback(s
, l
, s
->read_userdata
);
387 int pa_context_handle_error(pa_context
*c
, uint32_t command
, pa_tagstruct
*t
, pa_bool_t fail
) {
390 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
392 if (command
== PA_COMMAND_ERROR
) {
395 if (pa_tagstruct_getu32(t
, &err
) < 0) {
396 pa_context_fail(c
, PA_ERR_PROTOCOL
);
400 } else if (command
== PA_COMMAND_TIMEOUT
)
401 err
= PA_ERR_TIMEOUT
;
403 pa_context_fail(c
, PA_ERR_PROTOCOL
);
408 pa_context_fail(c
, PA_ERR_PROTOCOL
);
412 if (err
>= PA_ERR_MAX
)
413 err
= PA_ERR_UNKNOWN
;
416 pa_context_fail(c
, (int) err
);
420 pa_context_set_error(c
, (int) err
);
425 static void setup_complete_callback(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
426 pa_context
*c
= userdata
;
430 pa_assert(c
->state
== PA_CONTEXT_AUTHORIZING
|| c
->state
== PA_CONTEXT_SETTING_NAME
);
434 if (command
!= PA_COMMAND_REPLY
) {
435 pa_context_handle_error(c
, command
, t
, TRUE
);
440 case PA_CONTEXT_AUTHORIZING
: {
442 pa_bool_t shm_on_remote
= FALSE
;
444 if (pa_tagstruct_getu32(t
, &c
->version
) < 0 ||
445 !pa_tagstruct_eof(t
)) {
446 pa_context_fail(c
, PA_ERR_PROTOCOL
);
450 /* Minimum supported version */
451 if (c
->version
< 8) {
452 pa_context_fail(c
, PA_ERR_VERSION
);
456 /* Starting with protocol version 13 the MSB of the version
457 tag reflects if shm is available for this connection or
459 if (c
->version
>= 13) {
460 shm_on_remote
= !!(c
->version
& 0x80000000U
);
461 c
->version
&= 0x7FFFFFFFU
;
464 pa_log_debug("Protocol version: remote %u, local %u", c
->version
, PA_PROTOCOL_VERSION
);
466 /* Enable shared memory support if possible */
468 if (c
->version
< 10 || (c
->version
>= 13 && !shm_on_remote
))
473 /* Only enable SHM if both sides are owned by the same
474 * user. This is a security measure because otherwise
475 * data private to the user might leak. */
478 const pa_creds
*creds
;
479 if (!(creds
= pa_pdispatch_creds(pd
)) || getuid() != creds
->uid
)
484 pa_log_debug("Negotiated SHM: %s", pa_yes_no(c
->do_shm
));
485 pa_pstream_enable_shm(c
->pstream
, c
->do_shm
);
487 reply
= pa_tagstruct_command(c
, PA_COMMAND_SET_CLIENT_NAME
, &tag
);
489 if (c
->version
>= 13) {
490 pa_init_proplist(c
->proplist
);
491 pa_tagstruct_put_proplist(reply
, c
->proplist
);
493 pa_tagstruct_puts(reply
, pa_proplist_gets(c
->proplist
, PA_PROP_APPLICATION_NAME
));
495 pa_pstream_send_tagstruct(c
->pstream
, reply
);
496 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, setup_complete_callback
, c
, NULL
);
498 pa_context_set_state(c
, PA_CONTEXT_SETTING_NAME
);
502 case PA_CONTEXT_SETTING_NAME
:
504 if ((c
->version
>= 13 && (pa_tagstruct_getu32(t
, &c
->client_index
) < 0 ||
505 c
->client_index
== PA_INVALID_INDEX
)) ||
506 !pa_tagstruct_eof(t
)) {
507 pa_context_fail(c
, PA_ERR_PROTOCOL
);
511 pa_context_set_state(c
, PA_CONTEXT_READY
);
515 pa_assert_not_reached();
522 static void setup_context(pa_context
*c
, pa_iochannel
*io
) {
531 pa_assert(!c
->pstream
);
532 c
->pstream
= pa_pstream_new(c
->mainloop
, io
, c
->mempool
);
534 pa_pstream_set_die_callback(c
->pstream
, pstream_die_callback
, c
);
535 pa_pstream_set_recieve_packet_callback(c
->pstream
, pstream_packet_callback
, c
);
536 pa_pstream_set_recieve_memblock_callback(c
->pstream
, pstream_memblock_callback
, c
);
538 pa_assert(!c
->pdispatch
);
539 c
->pdispatch
= pa_pdispatch_new(c
->mainloop
, command_table
, PA_COMMAND_MAX
);
541 if (!c
->conf
->cookie_valid
)
542 pa_log_info(_("No cookie loaded. Attempting to connect without."));
544 t
= pa_tagstruct_command(c
, PA_COMMAND_AUTH
, &tag
);
547 pa_mempool_is_shared(c
->mempool
) &&
550 pa_log_debug("SHM possible: %s", pa_yes_no(c
->do_shm
));
552 /* Starting with protocol version 13 we use the MSB of the version
553 * tag for informing the other side if we could do SHM or not */
554 pa_tagstruct_putu32(t
, PA_PROTOCOL_VERSION
| (c
->do_shm
? 0x80000000U
: 0));
555 pa_tagstruct_put_arbitrary(t
, c
->conf
->cookie
, sizeof(c
->conf
->cookie
));
561 if (pa_iochannel_creds_supported(io
))
562 pa_iochannel_creds_enable(io
);
564 ucred
.uid
= getuid();
565 ucred
.gid
= getgid();
567 pa_pstream_send_tagstruct_with_creds(c
->pstream
, t
, &ucred
);
570 pa_pstream_send_tagstruct(c
->pstream
, t
);
573 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, setup_complete_callback
, c
, NULL
);
575 pa_context_set_state(c
, PA_CONTEXT_AUTHORIZING
);
580 static void on_connection(pa_socket_client
*client
, pa_iochannel
*io
, void *userdata
);
584 static int context_connect_spawn(pa_context
*c
) {
587 int fds
[2] = { -1, -1} ;
595 if (socketpair(AF_UNIX
, SOCK_STREAM
, 0, fds
) < 0) {
596 pa_log_error(_("socketpair(): %s"), pa_cstrerror(errno
));
597 pa_context_fail(c
, PA_ERR_INTERNAL
);
601 pa_make_fd_cloexec(fds
[0]);
603 pa_make_socket_low_delay(fds
[0]);
604 pa_make_socket_low_delay(fds
[1]);
606 if (c
->spawn_api
.prefork
)
607 c
->spawn_api
.prefork();
609 if ((pid
= fork()) < 0) {
610 pa_log_error(_("fork(): %s"), pa_cstrerror(errno
));
611 pa_context_fail(c
, PA_ERR_INTERNAL
);
613 if (c
->spawn_api
.postfork
)
614 c
->spawn_api
.postfork();
621 const char *state
= NULL
;
623 const char * argv
[MAX_ARGS
+1];
627 pa_close_all(fds
[1], -1);
629 f
= pa_sprintf_malloc("%i", fds
[1]);
630 pa_set_env("PULSE_PASSED_FD", f
);
633 if (c
->spawn_api
.atfork
)
634 c
->spawn_api
.atfork();
640 argv
[n
++] = c
->conf
->daemon_binary
;
641 argv
[n
++] = "--daemonize=yes";
643 pa_snprintf(t
, sizeof(t
), "-Lmodule-native-protocol-fd fd=%i", fds
[1]);
644 argv
[n
++] = strdup(t
);
646 while (n
< MAX_ARGS
) {
649 if (!(a
= pa_split_spaces(c
->conf
->extra_arguments
, &state
)))
657 execv(argv
[0], (char * const *) argv
);
664 pa_assert_se(pa_close(fds
[1]) == 0);
667 r
= waitpid(pid
, &status
, 0);
669 if (c
->spawn_api
.postfork
)
670 c
->spawn_api
.postfork();
673 pa_log(_("waitpid(): %s"), pa_cstrerror(errno
));
674 pa_context_fail(c
, PA_ERR_INTERNAL
);
676 } else if (!WIFEXITED(status
) || WEXITSTATUS(status
) != 0) {
677 pa_context_fail(c
, PA_ERR_CONNECTIONREFUSED
);
685 io
= pa_iochannel_new(c
->mainloop
, fds
[0], fds
[0]);
686 setup_context(c
, io
);
702 #endif /* OS_IS_WIN32 */
704 static int try_next_connection(pa_context
*c
) {
709 pa_assert(!c
->client
);
715 c
->server_list
= pa_strlist_pop(c
->server_list
, &u
);
720 if (c
->do_autospawn
) {
721 r
= context_connect_spawn(c
);
726 pa_context_fail(c
, PA_ERR_CONNECTIONREFUSED
);
730 pa_log_debug("Trying to connect to %s...", u
);
733 c
->server
= pa_xstrdup(u
);
735 if (!(c
->client
= pa_socket_client_new_string(c
->mainloop
, u
, PA_NATIVE_DEFAULT_PORT
)))
738 c
->is_local
= !!pa_socket_client_is_local(c
->client
);
739 pa_socket_client_set_callback(c
->client
, on_connection
, c
);
751 static void on_connection(pa_socket_client
*client
, pa_iochannel
*io
, void *userdata
) {
752 pa_context
*c
= userdata
;
753 int saved_errno
= errno
;
757 pa_assert(c
->state
== PA_CONTEXT_CONNECTING
);
761 pa_socket_client_unref(client
);
765 /* Try the item in the list */
766 if (saved_errno
== ECONNREFUSED
||
767 saved_errno
== ETIMEDOUT
||
768 saved_errno
== EHOSTUNREACH
) {
769 try_next_connection(c
);
773 pa_context_fail(c
, PA_ERR_CONNECTIONREFUSED
);
778 setup_context(c
, io
);
784 static void autospawn_cb(pa_mainloop_api
*a
, pa_io_event
*e
, int fd
, pa_io_event_flags_t events
, void *userdata
) {
785 pa_context
*c
= userdata
;
791 pa_assert(events
== PA_IO_EVENT_INPUT
);
793 pa_assert(e
== c
->autospawn_event
);
794 pa_assert(fd
== c
->autospawn_fd
);
798 /* Check whether we can get the lock right now*/
799 if ((k
= pa_autospawn_lock_acquire(FALSE
)) < 0) {
800 pa_context_fail(c
, PA_ERR_ACCESS
);
805 /* So we got it, rock on! */
806 c
->autospawn_locked
= TRUE
;
807 try_next_connection(c
);
809 c
->mainloop
->io_free(c
->autospawn_event
);
810 c
->autospawn_event
= NULL
;
818 static char *get_old_legacy_runtime_dir(void) {
822 if (!pa_get_user_name(u
, sizeof(u
)))
825 p
= pa_sprintf_malloc("/tmp/pulse-%s", u
);
827 if (stat(p
, &st
) < 0) {
832 if (st
.st_uid
!= getuid()) {
840 static char *get_very_old_legacy_runtime_dir(void) {
844 if (!pa_get_home_dir(h
, sizeof(h
)))
847 p
= pa_sprintf_malloc("%s/.pulse", h
);
849 if (stat(p
, &st
) < 0) {
854 if (st
.st_uid
!= getuid()) {
862 int pa_context_connect(
865 pa_context_flags_t flags
,
866 const pa_spawn_api
*api
) {
871 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
873 PA_CHECK_VALIDITY(c
, c
->state
== PA_CONTEXT_UNCONNECTED
, PA_ERR_BADSTATE
);
874 PA_CHECK_VALIDITY(c
, !(flags
& ~PA_CONTEXT_NOAUTOSPAWN
), PA_ERR_INVALID
);
875 PA_CHECK_VALIDITY(c
, !server
|| *server
, PA_ERR_INVALID
);
878 server
= c
->conf
->default_server
;
882 pa_assert(!c
->server_list
);
885 if (!(c
->server_list
= pa_strlist_parse(server
))) {
886 pa_context_fail(c
, PA_ERR_INVALIDSERVER
);
892 static char *legacy_dir
;
894 /* Prepend in reverse order */
896 if ((d
= getenv("DISPLAY"))) {
899 if ((e
= strchr(d
, ':')))
903 c
->server_list
= pa_strlist_prepend(c
->server_list
, d
);
908 c
->server_list
= pa_strlist_prepend(c
->server_list
, "tcp6:localhost");
909 c
->server_list
= pa_strlist_prepend(c
->server_list
, "tcp4:localhost");
911 /* The system wide instance */
912 c
->server_list
= pa_strlist_prepend(c
->server_list
, PA_SYSTEM_RUNTIME_PATH PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET
);
914 /* The very old per-user instance path (< 0.9.11). This is supported only to ease upgrades */
915 if ((legacy_dir
= get_very_old_legacy_runtime_dir())) {
916 char *p
= pa_sprintf_malloc("%s" PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET
, legacy_dir
);
917 c
->server_list
= pa_strlist_prepend(c
->server_list
, p
);
919 pa_xfree(legacy_dir
);
922 /* The old per-user instance path (< 0.9.12). This is supported only to ease upgrades */
923 if ((legacy_dir
= get_old_legacy_runtime_dir())) {
924 char *p
= pa_sprintf_malloc("%s" PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET
, legacy_dir
);
925 c
->server_list
= pa_strlist_prepend(c
->server_list
, p
);
927 pa_xfree(legacy_dir
);
930 /* The per-user instance */
931 if ((ufn
= pa_runtime_path(PA_NATIVE_DEFAULT_UNIX_SOCKET
))) {
932 c
->server_list
= pa_strlist_prepend(c
->server_list
, ufn
);
936 /* Wrap the connection attempts in a single transaction for sane autospawn locking */
937 if (!(flags
& PA_CONTEXT_NOAUTOSPAWN
) && c
->conf
->autospawn
) {
940 pa_assert(c
->autospawn_fd
< 0);
941 pa_assert(!c
->autospawn_locked
);
943 /* Start the locking procedure */
944 if ((c
->autospawn_fd
= pa_autospawn_lock_init()) < 0) {
945 pa_context_fail(c
, PA_ERR_ACCESS
);
952 c
->do_autospawn
= TRUE
;
954 /* Check whether we can get the lock right now*/
955 if ((k
= pa_autospawn_lock_acquire(FALSE
)) < 0) {
956 pa_context_fail(c
, PA_ERR_ACCESS
);
961 /* So we got it, rock on! */
962 c
->autospawn_locked
= TRUE
;
964 /* Hmm, we didn't get it, so let's wait for it */
965 c
->autospawn_event
= c
->mainloop
->io_new(c
->mainloop
, c
->autospawn_fd
, PA_IO_EVENT_INPUT
, autospawn_cb
, c
);
967 pa_context_set_state(c
, PA_CONTEXT_CONNECTING
);
975 pa_context_set_state(c
, PA_CONTEXT_CONNECTING
);
976 r
= try_next_connection(c
);
984 void pa_context_disconnect(pa_context
*c
) {
986 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
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 (c
->state
== PA_CONTEXT_TERMINATED
|| c
->state
== PA_CONTEXT_FAILED
)
1013 c
->state_callback
= cb
;
1014 c
->state_userdata
= userdata
;
1017 int pa_context_is_pending(pa_context
*c
) {
1019 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1021 PA_CHECK_VALIDITY(c
, PA_CONTEXT_IS_GOOD(c
->state
), PA_ERR_BADSTATE
);
1023 return (c
->pstream
&& pa_pstream_is_pending(c
->pstream
)) ||
1024 (c
->pdispatch
&& pa_pdispatch_is_pending(c
->pdispatch
)) ||
1028 static void set_dispatch_callbacks(pa_operation
*o
);
1030 static void pdispatch_drain_callback(pa_pdispatch
*pd
, void *userdata
) {
1031 set_dispatch_callbacks(userdata
);
1034 static void pstream_drain_callback(pa_pstream
*s
, void *userdata
) {
1035 set_dispatch_callbacks(userdata
);
1038 static void set_dispatch_callbacks(pa_operation
*o
) {
1042 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
1043 pa_assert(o
->context
);
1044 pa_assert(PA_REFCNT_VALUE(o
->context
) >= 1);
1045 pa_assert(o
->context
->state
== PA_CONTEXT_READY
);
1047 pa_pstream_set_drain_callback(o
->context
->pstream
, NULL
, NULL
);
1048 pa_pdispatch_set_drain_callback(o
->context
->pdispatch
, NULL
, NULL
);
1050 if (pa_pdispatch_is_pending(o
->context
->pdispatch
)) {
1051 pa_pdispatch_set_drain_callback(o
->context
->pdispatch
, pdispatch_drain_callback
, o
);
1055 if (pa_pstream_is_pending(o
->context
->pstream
)) {
1056 pa_pstream_set_drain_callback(o
->context
->pstream
, pstream_drain_callback
, o
);
1062 pa_context_notify_cb_t cb
= (pa_context_notify_cb_t
) o
->callback
;
1063 cb(o
->context
, o
->userdata
);
1066 pa_operation_done(o
);
1067 pa_operation_unref(o
);
1071 pa_operation
* pa_context_drain(pa_context
*c
, pa_context_notify_cb_t cb
, void *userdata
) {
1075 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1077 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
1078 PA_CHECK_VALIDITY_RETURN_NULL(c
, pa_context_is_pending(c
), PA_ERR_BADSTATE
);
1080 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
1081 set_dispatch_callbacks(pa_operation_ref(o
));
1086 void pa_context_simple_ack_callback(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
1087 pa_operation
*o
= userdata
;
1092 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
1097 if (command
!= PA_COMMAND_REPLY
) {
1098 if (pa_context_handle_error(o
->context
, command
, t
, FALSE
) < 0)
1102 } else if (!pa_tagstruct_eof(t
)) {
1103 pa_context_fail(o
->context
, PA_ERR_PROTOCOL
);
1108 pa_context_success_cb_t cb
= (pa_context_success_cb_t
) o
->callback
;
1109 cb(o
->context
, success
, o
->userdata
);
1113 pa_operation_done(o
);
1114 pa_operation_unref(o
);
1117 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
) {
1123 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1125 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
1127 o
= pa_operation_new(c
, NULL
, cb
, userdata
);
1129 t
= pa_tagstruct_command(c
, command
, &tag
);
1130 pa_pstream_send_tagstruct(c
->pstream
, t
);
1131 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, internal_cb
, pa_operation_ref(o
), (pa_free_cb_t
) pa_operation_unref
);
1136 pa_operation
* pa_context_exit_daemon(pa_context
*c
, pa_context_success_cb_t cb
, void *userdata
) {
1138 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1140 return pa_context_send_simple_command(c
, PA_COMMAND_EXIT
, pa_context_simple_ack_callback
, (pa_operation_cb_t
) cb
, userdata
);
1143 pa_operation
* pa_context_set_default_sink(pa_context
*c
, const char *name
, pa_context_success_cb_t cb
, void *userdata
) {
1149 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1151 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
1153 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
1154 t
= pa_tagstruct_command(c
, PA_COMMAND_SET_DEFAULT_SINK
, &tag
);
1155 pa_tagstruct_puts(t
, name
);
1156 pa_pstream_send_tagstruct(c
->pstream
, t
);
1157 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 pa_operation
* pa_context_set_default_source(pa_context
*c
, const char *name
, pa_context_success_cb_t cb
, void *userdata
) {
1168 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1170 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
1172 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
1173 t
= pa_tagstruct_command(c
, PA_COMMAND_SET_DEFAULT_SOURCE
, &tag
);
1174 pa_tagstruct_puts(t
, name
);
1175 pa_pstream_send_tagstruct(c
->pstream
, t
);
1176 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
);
1181 int pa_context_is_local(pa_context
*c
) {
1183 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1185 PA_CHECK_VALIDITY_RETURN_ANY(c
, PA_CONTEXT_IS_GOOD(c
->state
), PA_ERR_BADSTATE
, -1);
1187 return !!c
->is_local
;
1190 pa_operation
* pa_context_set_name(pa_context
*c
, const char *name
, pa_context_success_cb_t cb
, void *userdata
) {
1194 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1197 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
1199 if (c
->version
>= 13) {
1200 pa_proplist
*p
= pa_proplist_new();
1202 pa_proplist_sets(p
, PA_PROP_APPLICATION_NAME
, name
);
1203 o
= pa_context_proplist_update(c
, PA_UPDATE_REPLACE
, p
, cb
, userdata
);
1204 pa_proplist_free(p
);
1209 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
1210 t
= pa_tagstruct_command(c
, PA_COMMAND_SET_CLIENT_NAME
, &tag
);
1211 pa_tagstruct_puts(t
, name
);
1212 pa_pstream_send_tagstruct(c
->pstream
, t
);
1213 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
);
1219 const char* pa_get_library_version(void) {
1220 return PACKAGE_VERSION
;
1223 const char* pa_context_get_server(pa_context
*c
) {
1225 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1230 if (*c
->server
== '{') {
1231 char *e
= strchr(c
->server
+1, '}');
1232 return e
? e
+1 : c
->server
;
1238 uint32_t pa_context_get_protocol_version(pa_context
*c
) {
1239 return PA_PROTOCOL_VERSION
;
1242 uint32_t pa_context_get_server_protocol_version(pa_context
*c
) {
1244 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1246 PA_CHECK_VALIDITY_RETURN_ANY(c
, PA_CONTEXT_IS_GOOD(c
->state
), PA_ERR_BADSTATE
, PA_INVALID_INDEX
);
1251 pa_tagstruct
*pa_tagstruct_command(pa_context
*c
, uint32_t command
, uint32_t *tag
) {
1257 t
= pa_tagstruct_new(NULL
, 0);
1258 pa_tagstruct_putu32(t
, command
);
1259 pa_tagstruct_putu32(t
, *tag
= c
->ctag
++);
1264 uint32_t pa_context_get_index(pa_context
*c
) {
1266 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1268 PA_CHECK_VALIDITY_RETURN_ANY(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
, PA_INVALID_INDEX
);
1269 PA_CHECK_VALIDITY_RETURN_ANY(c
, c
->version
>= 13, PA_ERR_NOTSUPPORTED
, PA_INVALID_INDEX
);
1271 return c
->client_index
;
1274 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
) {
1280 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1282 PA_CHECK_VALIDITY_RETURN_NULL(c
, mode
== PA_UPDATE_SET
|| mode
== PA_UPDATE_MERGE
|| mode
== PA_UPDATE_REPLACE
, PA_ERR_INVALID
);
1283 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
1284 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 13, PA_ERR_NOTSUPPORTED
);
1286 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
1288 t
= pa_tagstruct_command(c
, PA_COMMAND_UPDATE_CLIENT_PROPLIST
, &tag
);
1289 pa_tagstruct_putu32(t
, (uint32_t) mode
);
1290 pa_tagstruct_put_proplist(t
, p
);
1292 pa_pstream_send_tagstruct(c
->pstream
, t
);
1293 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
);
1295 /* Please note that we don't update c->proplist here, because we
1296 * don't export that field */
1301 pa_operation
*pa_context_proplist_remove(pa_context
*c
, const char *const keys
[], pa_context_success_cb_t cb
, void *userdata
) {
1305 const char * const *k
;
1308 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1310 PA_CHECK_VALIDITY_RETURN_NULL(c
, keys
&& keys
[0], PA_ERR_INVALID
);
1311 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
1312 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 13, PA_ERR_NOTSUPPORTED
);
1314 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
1316 t
= pa_tagstruct_command(c
, PA_COMMAND_REMOVE_CLIENT_PROPLIST
, &tag
);
1318 for (k
= keys
; *k
; k
++)
1319 pa_tagstruct_puts(t
, *k
);
1321 pa_tagstruct_puts(t
, NULL
);
1323 pa_pstream_send_tagstruct(c
->pstream
, t
);
1324 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
);
1326 /* Please note that we don't update c->proplist here, because we
1327 * don't export that field */
1332 void pa_command_extension(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
1333 pa_context
*c
= userdata
;
1338 pa_assert(command
== PA_COMMAND_EXTENSION
);
1341 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1345 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
1346 pa_tagstruct_gets(t
, &name
) < 0) {
1347 pa_context_fail(c
, PA_ERR_PROTOCOL
);
1351 if (!strcmp(name
, "module-stream-restore"))
1352 pa_ext_stream_restore_command(c
, tag
, t
);
1354 pa_log(_("Received message for unknown extension '%s'"), name
);
1357 pa_context_unref(c
);