4 This file is part of PulseAudio.
6 Copyright 2004-2006 Lennart Poettering
7 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
9 PulseAudio is free software; you can redistribute it and/or modify
10 it under the terms of the GNU Lesser General Public License as published
11 by the Free Software Foundation; either version 2 of the License,
12 or (at your option) any later version.
14 PulseAudio is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public License
20 along with PulseAudio; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
32 #include <sys/types.h>
40 #ifdef HAVE_SYS_WAIT_H
44 #ifdef HAVE_SYS_SOCKET_H
45 #include <sys/socket.h>
54 #include <pulse/version.h>
55 #include <pulse/xmalloc.h>
56 #include <pulse/utf8.h>
57 #include <pulse/util.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>
76 #include "client-conf.h"
79 #include "client-conf-x11.h"
84 #define AUTOSPAWN_LOCK "autospawn.lock"
86 static const pa_pdispatch_cb_t command_table
[PA_COMMAND_MAX
] = {
87 [PA_COMMAND_REQUEST
] = pa_command_request
,
88 [PA_COMMAND_OVERFLOW
] = pa_command_overflow_or_underflow
,
89 [PA_COMMAND_UNDERFLOW
] = pa_command_overflow_or_underflow
,
90 [PA_COMMAND_PLAYBACK_STREAM_KILLED
] = pa_command_stream_killed
,
91 [PA_COMMAND_RECORD_STREAM_KILLED
] = pa_command_stream_killed
,
92 [PA_COMMAND_PLAYBACK_STREAM_MOVED
] = pa_command_stream_moved
,
93 [PA_COMMAND_RECORD_STREAM_MOVED
] = pa_command_stream_moved
,
94 [PA_COMMAND_PLAYBACK_STREAM_SUSPENDED
] = pa_command_stream_suspended
,
95 [PA_COMMAND_RECORD_STREAM_SUSPENDED
] = pa_command_stream_suspended
,
96 [PA_COMMAND_SUBSCRIBE_EVENT
] = pa_command_subscribe_event
99 static void unlock_autospawn_lock_file(pa_context
*c
) {
102 if (c
->autospawn_lock_fd
>= 0) {
104 pa_runtime_path(AUTOSPAWN_LOCK
, lf
, sizeof(lf
));
106 pa_unlock_lockfile(lf
, c
->autospawn_lock_fd
);
107 c
->autospawn_lock_fd
= -1;
111 static void context_free(pa_context
*c
);
113 pa_context
*pa_context_new(pa_mainloop_api
*mainloop
, const char *name
) {
114 return pa_context_new_with_proplist(mainloop
, name
, NULL
);
117 pa_context
*pa_context_new_with_proplist(pa_mainloop_api
*mainloop
, const char *name
, pa_proplist
*p
) {
122 if (!name
&& !pa_proplist_contains(p
, PA_PROP_APPLICATION_NAME
))
125 c
= pa_xnew(pa_context
, 1);
128 c
->proplist
= p
? pa_proplist_copy(p
) : pa_proplist_new();
131 pa_proplist_sets(c
->proplist
, PA_PROP_APPLICATION_NAME
, name
);
133 c
->mainloop
= mainloop
;
137 c
->playback_streams
= pa_dynarray_new();
138 c
->record_streams
= pa_dynarray_new();
139 c
->client_index
= PA_INVALID_INDEX
;
141 PA_LLIST_HEAD_INIT(pa_stream
, c
->streams
);
142 PA_LLIST_HEAD_INIT(pa_operation
, c
->operations
);
145 c
->state
= PA_CONTEXT_UNCONNECTED
;
149 c
->state_callback
= NULL
;
150 c
->state_userdata
= NULL
;
152 c
->subscribe_callback
= NULL
;
153 c
->subscribe_userdata
= NULL
;
156 c
->server_list
= NULL
;
158 c
->autospawn_lock_fd
= -1;
159 memset(&c
->spawn_api
, 0, sizeof(c
->spawn_api
));
164 pa_check_signal_is_blocked(SIGPIPE
);
168 c
->conf
= pa_client_conf_new();
169 pa_client_conf_load(c
->conf
, NULL
);
171 pa_client_conf_from_x11(c
->conf
, NULL
);
173 pa_client_conf_env(c
->conf
);
175 if (!(c
->mempool
= pa_mempool_new(!c
->conf
->disable_shm
))) {
177 if (!c
->conf
->disable_shm
)
178 c
->mempool
= pa_mempool_new(0);
189 static void context_free(pa_context
*c
) {
192 unlock_autospawn_lock_file(c
);
194 while (c
->operations
)
195 pa_operation_cancel(c
->operations
);
198 pa_stream_set_state(c
->streams
, PA_STREAM_TERMINATED
);
201 pa_socket_client_unref(c
->client
);
203 pa_pdispatch_unref(c
->pdispatch
);
205 pa_pstream_unlink(c
->pstream
);
206 pa_pstream_unref(c
->pstream
);
209 if (c
->record_streams
)
210 pa_dynarray_free(c
->record_streams
, NULL
, NULL
);
211 if (c
->playback_streams
)
212 pa_dynarray_free(c
->playback_streams
, NULL
, NULL
);
215 pa_mempool_free(c
->mempool
);
218 pa_client_conf_free(c
->conf
);
220 pa_strlist_free(c
->server_list
);
223 pa_proplist_free(c
->proplist
);
229 pa_context
* pa_context_ref(pa_context
*c
) {
231 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
237 void pa_context_unref(pa_context
*c
) {
239 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
241 if (PA_REFCNT_DEC(c
) <= 0)
245 void pa_context_set_state(pa_context
*c
, pa_context_state_t st
) {
247 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
255 if (c
->state_callback
)
256 c
->state_callback(c
, c
->state_userdata
);
258 if (st
== PA_CONTEXT_FAILED
|| st
== PA_CONTEXT_TERMINATED
) {
261 s
= c
->streams
? pa_stream_ref(c
->streams
) : NULL
;
263 pa_stream
*n
= s
->next
? pa_stream_ref(s
->next
) : NULL
;
264 pa_stream_set_state(s
, st
== PA_CONTEXT_FAILED
? PA_STREAM_FAILED
: PA_STREAM_TERMINATED
);
270 pa_pdispatch_unref(c
->pdispatch
);
274 pa_pstream_unlink(c
->pstream
);
275 pa_pstream_unref(c
->pstream
);
280 pa_socket_client_unref(c
->client
);
287 void pa_context_fail(pa_context
*c
, int error
) {
289 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
291 pa_context_set_error(c
, error
);
292 pa_context_set_state(c
, PA_CONTEXT_FAILED
);
295 int pa_context_set_error(pa_context
*c
, int error
) {
296 pa_assert(error
>= 0);
297 pa_assert(error
< PA_ERR_MAX
);
305 static void pstream_die_callback(pa_pstream
*p
, void *userdata
) {
306 pa_context
*c
= userdata
;
311 pa_context_fail(c
, PA_ERR_CONNECTIONTERMINATED
);
314 static void pstream_packet_callback(pa_pstream
*p
, pa_packet
*packet
, const pa_creds
*creds
, void *userdata
) {
315 pa_context
*c
= userdata
;
323 if (pa_pdispatch_run(c
->pdispatch
, packet
, creds
, c
) < 0)
324 pa_context_fail(c
, PA_ERR_PROTOCOL
);
329 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
) {
330 pa_context
*c
= userdata
;
335 pa_assert(chunk
->memblock
);
336 pa_assert(chunk
->length
);
338 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
342 if ((s
= pa_dynarray_get(c
->record_streams
, channel
))) {
344 pa_assert(seek
== PA_SEEK_RELATIVE
);
345 pa_assert(offset
== 0);
347 pa_memblockq_seek(s
->record_memblockq
, offset
, seek
);
348 pa_memblockq_push_align(s
->record_memblockq
, chunk
);
350 if (s
->read_callback
) {
353 if ((l
= pa_memblockq_get_length(s
->record_memblockq
)) > 0)
354 s
->read_callback(s
, l
, s
->read_userdata
);
361 int pa_context_handle_error(pa_context
*c
, uint32_t command
, pa_tagstruct
*t
) {
363 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
365 if (command
== PA_COMMAND_ERROR
) {
368 if (pa_tagstruct_getu32(t
, &c
->error
) < 0) {
369 pa_context_fail(c
, PA_ERR_PROTOCOL
);
373 } else if (command
== PA_COMMAND_TIMEOUT
)
374 c
->error
= PA_ERR_TIMEOUT
;
376 pa_context_fail(c
, PA_ERR_PROTOCOL
);
383 static void setup_complete_callback(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
384 pa_context
*c
= userdata
;
388 pa_assert(c
->state
== PA_CONTEXT_AUTHORIZING
|| c
->state
== PA_CONTEXT_SETTING_NAME
);
392 if (command
!= PA_COMMAND_REPLY
) {
394 if (pa_context_handle_error(c
, command
, t
) < 0)
395 pa_context_fail(c
, PA_ERR_PROTOCOL
);
397 pa_context_fail(c
, c
->error
);
402 case PA_CONTEXT_AUTHORIZING
: {
405 if (pa_tagstruct_getu32(t
, &c
->version
) < 0 ||
406 !pa_tagstruct_eof(t
)) {
407 pa_context_fail(c
, PA_ERR_PROTOCOL
);
411 /* Minimum supported version */
412 if (c
->version
< 8) {
413 pa_context_fail(c
, PA_ERR_VERSION
);
417 /* Enable shared memory support if possible */
418 if (c
->version
>= 10 &&
419 pa_mempool_is_shared(c
->mempool
) &&
422 /* Only enable SHM if both sides are owned by the same
423 * user. This is a security measure because otherwise
424 * data private to the user might leak. */
427 const pa_creds
*creds
;
428 if ((creds
= pa_pdispatch_creds(pd
)))
429 if (getuid() == creds
->uid
)
430 pa_pstream_use_shm(c
->pstream
, 1);
434 reply
= pa_tagstruct_command(c
, PA_COMMAND_SET_CLIENT_NAME
, &tag
);
436 if (c
->version
>= 13) {
437 pa_init_proplist(c
->proplist
);
438 pa_tagstruct_put_proplist(reply
, c
->proplist
);
440 pa_tagstruct_puts(reply
, pa_proplist_gets(c
->proplist
, PA_PROP_APPLICATION_NAME
));
442 pa_pstream_send_tagstruct(c
->pstream
, reply
);
443 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, setup_complete_callback
, c
, NULL
);
445 pa_context_set_state(c
, PA_CONTEXT_SETTING_NAME
);
449 case PA_CONTEXT_SETTING_NAME
:
451 if ((c
->version
>= 13 && (pa_tagstruct_getu32(t
, &c
->client_index
) < 0 ||
452 c
->client_index
== PA_INVALID_INDEX
)) ||
453 !pa_tagstruct_eof(t
)) {
454 pa_context_fail(c
, PA_ERR_PROTOCOL
);
458 pa_context_set_state(c
, PA_CONTEXT_READY
);
462 pa_assert_not_reached();
469 static void setup_context(pa_context
*c
, pa_iochannel
*io
) {
478 pa_assert(!c
->pstream
);
479 c
->pstream
= pa_pstream_new(c
->mainloop
, io
, c
->mempool
);
481 pa_pstream_set_die_callback(c
->pstream
, pstream_die_callback
, c
);
482 pa_pstream_set_recieve_packet_callback(c
->pstream
, pstream_packet_callback
, c
);
483 pa_pstream_set_recieve_memblock_callback(c
->pstream
, pstream_memblock_callback
, c
);
485 pa_assert(!c
->pdispatch
);
486 c
->pdispatch
= pa_pdispatch_new(c
->mainloop
, command_table
, PA_COMMAND_MAX
);
488 if (!c
->conf
->cookie_valid
)
489 pa_log_warn("No cookie loaded. Attempting to connect without.");
491 t
= pa_tagstruct_command(c
, PA_COMMAND_AUTH
, &tag
);
492 pa_tagstruct_putu32(t
, PA_PROTOCOL_VERSION
);
493 pa_tagstruct_put_arbitrary(t
, c
->conf
->cookie
, sizeof(c
->conf
->cookie
));
499 if (pa_iochannel_creds_supported(io
))
500 pa_iochannel_creds_enable(io
);
502 ucred
.uid
= getuid();
503 ucred
.gid
= getgid();
505 pa_pstream_send_tagstruct_with_creds(c
->pstream
, t
, &ucred
);
508 pa_pstream_send_tagstruct(c
->pstream
, t
);
511 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, setup_complete_callback
, c
, NULL
);
513 pa_context_set_state(c
, PA_CONTEXT_AUTHORIZING
);
518 static void on_connection(pa_socket_client
*client
, pa_iochannel
*io
, void *userdata
);
522 static int context_connect_spawn(pa_context
*c
) {
525 int fds
[2] = { -1, -1} ;
530 if (socketpair(AF_UNIX
, SOCK_STREAM
, 0, fds
) < 0) {
531 pa_log("socketpair(): %s", pa_cstrerror(errno
));
532 pa_context_fail(c
, PA_ERR_INTERNAL
);
536 pa_make_fd_cloexec(fds
[0]);
538 pa_make_socket_low_delay(fds
[0]);
539 pa_make_socket_low_delay(fds
[1]);
541 if (c
->spawn_api
.prefork
)
542 c
->spawn_api
.prefork();
544 if ((pid
= fork()) < 0) {
545 pa_log("fork(): %s", pa_cstrerror(errno
));
546 pa_context_fail(c
, PA_ERR_INTERNAL
);
548 if (c
->spawn_api
.postfork
)
549 c
->spawn_api
.postfork();
556 const char *state
= NULL
;
558 const char * argv
[MAX_ARGS
+1];
561 /* Not required, since fds[0] has CLOEXEC enabled anyway */
562 pa_assert_se(pa_close(fds
[0]) == 0);
564 if (c
->spawn_api
.atfork
)
565 c
->spawn_api
.atfork();
571 argv
[n
++] = c
->conf
->daemon_binary
;
572 argv
[n
++] = "--daemonize=yes";
574 pa_snprintf(t
, sizeof(t
), "-Lmodule-native-protocol-fd fd=%i", fds
[1]);
575 argv
[n
++] = strdup(t
);
577 while (n
< MAX_ARGS
) {
580 if (!(a
= pa_split_spaces(c
->conf
->extra_arguments
, &state
)))
588 execv(argv
[0], (char * const *) argv
);
595 r
= waitpid(pid
, &status
, 0);
597 if (c
->spawn_api
.postfork
)
598 c
->spawn_api
.postfork();
601 pa_log("waitpid(): %s", pa_cstrerror(errno
));
602 pa_context_fail(c
, PA_ERR_INTERNAL
);
604 } else if (!WIFEXITED(status
) || WEXITSTATUS(status
) != 0) {
605 pa_context_fail(c
, PA_ERR_CONNECTIONREFUSED
);
609 pa_assert_se(pa_close(fds
[1]) == 0);
613 io
= pa_iochannel_new(c
->mainloop
, fds
[0], fds
[0]);
615 setup_context(c
, io
);
616 unlock_autospawn_lock_file(c
);
625 unlock_autospawn_lock_file(c
);
632 #endif /* OS_IS_WIN32 */
634 static int try_next_connection(pa_context
*c
) {
639 pa_assert(!c
->client
);
645 c
->server_list
= pa_strlist_pop(c
->server_list
, &u
);
650 if (c
->do_autospawn
) {
651 r
= context_connect_spawn(c
);
656 pa_context_fail(c
, PA_ERR_CONNECTIONREFUSED
);
660 pa_log_debug("Trying to connect to %s...", u
);
663 c
->server
= pa_xstrdup(u
);
665 if (!(c
->client
= pa_socket_client_new_string(c
->mainloop
, u
, PA_NATIVE_DEFAULT_PORT
)))
668 c
->is_local
= pa_socket_client_is_local(c
->client
);
669 pa_socket_client_set_callback(c
->client
, on_connection
, c
);
681 static void on_connection(pa_socket_client
*client
, pa_iochannel
*io
, void *userdata
) {
682 pa_context
*c
= userdata
;
686 pa_assert(c
->state
== PA_CONTEXT_CONNECTING
);
690 pa_socket_client_unref(client
);
694 /* Try the item in the list */
695 if (errno
== ECONNREFUSED
|| errno
== ETIMEDOUT
|| errno
== EHOSTUNREACH
) {
696 try_next_connection(c
);
700 pa_context_fail(c
, PA_ERR_CONNECTIONREFUSED
);
704 unlock_autospawn_lock_file(c
);
705 setup_context(c
, io
);
711 int pa_context_connect(
714 pa_context_flags_t flags
,
715 const pa_spawn_api
*api
) {
720 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
722 PA_CHECK_VALIDITY(c
, c
->state
== PA_CONTEXT_UNCONNECTED
, PA_ERR_BADSTATE
);
723 PA_CHECK_VALIDITY(c
, !(flags
& ~PA_CONTEXT_NOAUTOSPAWN
), PA_ERR_INVALID
);
724 PA_CHECK_VALIDITY(c
, !server
|| *server
, PA_ERR_INVALID
);
727 server
= c
->conf
->default_server
;
731 pa_assert(!c
->server_list
);
734 if (!(c
->server_list
= pa_strlist_parse(server
))) {
735 pa_context_fail(c
, PA_ERR_INVALIDSERVER
);
742 /* Prepend in reverse order */
744 if ((d
= getenv("DISPLAY"))) {
747 if ((e
= strchr(d
, ':')))
751 c
->server_list
= pa_strlist_prepend(c
->server_list
, d
);
756 c
->server_list
= pa_strlist_prepend(c
->server_list
, "tcp6:localhost");
757 c
->server_list
= pa_strlist_prepend(c
->server_list
, "tcp4:localhost");
759 /* The system wide instance */
760 c
->server_list
= pa_strlist_prepend(c
->server_list
, PA_SYSTEM_RUNTIME_PATH
"/" PA_NATIVE_DEFAULT_UNIX_SOCKET
);
762 /* The per-user instance */
763 c
->server_list
= pa_strlist_prepend(c
->server_list
, pa_runtime_path(PA_NATIVE_DEFAULT_UNIX_SOCKET
, ufn
, sizeof(ufn
)));
765 /* Wrap the connection attempts in a single transaction for sane autospawn locking */
766 if (!(flags
& PA_CONTEXT_NOAUTOSPAWN
) && c
->conf
->autospawn
) {
769 pa_runtime_path(AUTOSPAWN_LOCK
, lf
, sizeof(lf
));
770 pa_make_secure_parent_dir(lf
, 0700, (uid_t
)-1, (gid_t
)-1);
771 pa_assert(c
->autospawn_lock_fd
<= 0);
772 c
->autospawn_lock_fd
= pa_lock_lockfile(lf
);
781 pa_context_set_state(c
, PA_CONTEXT_CONNECTING
);
782 r
= try_next_connection(c
);
790 void pa_context_disconnect(pa_context
*c
) {
792 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
794 pa_context_set_state(c
, PA_CONTEXT_TERMINATED
);
797 pa_context_state_t
pa_context_get_state(pa_context
*c
) {
799 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
804 int pa_context_errno(pa_context
*c
) {
806 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
811 void pa_context_set_state_callback(pa_context
*c
, pa_context_notify_cb_t cb
, void *userdata
) {
813 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
815 c
->state_callback
= cb
;
816 c
->state_userdata
= userdata
;
819 int pa_context_is_pending(pa_context
*c
) {
821 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
824 c
->state
== PA_CONTEXT_CONNECTING
||
825 c
->state
== PA_CONTEXT_AUTHORIZING
||
826 c
->state
== PA_CONTEXT_SETTING_NAME
||
827 c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
829 return (c
->pstream
&& pa_pstream_is_pending(c
->pstream
)) ||
830 (c
->pdispatch
&& pa_pdispatch_is_pending(c
->pdispatch
)) ||
834 static void set_dispatch_callbacks(pa_operation
*o
);
836 static void pdispatch_drain_callback(PA_GCC_UNUSED pa_pdispatch
*pd
, void *userdata
) {
837 set_dispatch_callbacks(userdata
);
840 static void pstream_drain_callback(PA_GCC_UNUSED pa_pstream
*s
, void *userdata
) {
841 set_dispatch_callbacks(userdata
);
844 static void set_dispatch_callbacks(pa_operation
*o
) {
848 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
849 pa_assert(o
->context
);
850 pa_assert(PA_REFCNT_VALUE(o
->context
) >= 1);
851 pa_assert(o
->context
->state
== PA_CONTEXT_READY
);
853 pa_pstream_set_drain_callback(o
->context
->pstream
, NULL
, NULL
);
854 pa_pdispatch_set_drain_callback(o
->context
->pdispatch
, NULL
, NULL
);
856 if (pa_pdispatch_is_pending(o
->context
->pdispatch
)) {
857 pa_pdispatch_set_drain_callback(o
->context
->pdispatch
, pdispatch_drain_callback
, o
);
861 if (pa_pstream_is_pending(o
->context
->pstream
)) {
862 pa_pstream_set_drain_callback(o
->context
->pstream
, pstream_drain_callback
, o
);
868 pa_context_notify_cb_t cb
= (pa_context_notify_cb_t
) o
->callback
;
869 cb(o
->context
, o
->userdata
);
872 pa_operation_done(o
);
873 pa_operation_unref(o
);
877 pa_operation
* pa_context_drain(pa_context
*c
, pa_context_notify_cb_t cb
, void *userdata
) {
881 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
883 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
884 PA_CHECK_VALIDITY_RETURN_NULL(c
, pa_context_is_pending(c
), PA_ERR_BADSTATE
);
886 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
887 set_dispatch_callbacks(pa_operation_ref(o
));
892 void pa_context_simple_ack_callback(pa_pdispatch
*pd
, uint32_t command
, PA_GCC_UNUSED
uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
893 pa_operation
*o
= userdata
;
898 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
903 if (command
!= PA_COMMAND_REPLY
) {
904 if (pa_context_handle_error(o
->context
, command
, t
) < 0)
908 } else if (!pa_tagstruct_eof(t
)) {
909 pa_context_fail(o
->context
, PA_ERR_PROTOCOL
);
914 pa_context_success_cb_t cb
= (pa_context_success_cb_t
) o
->callback
;
915 cb(o
->context
, success
, o
->userdata
);
919 pa_operation_done(o
);
920 pa_operation_unref(o
);
923 pa_operation
* pa_context_exit_daemon(pa_context
*c
, pa_context_success_cb_t cb
, void *userdata
) {
929 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
931 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
933 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
935 t
= pa_tagstruct_command(c
, PA_COMMAND_EXIT
, &tag
);
936 pa_pstream_send_tagstruct(c
->pstream
, t
);
937 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
);
942 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
) {
948 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
950 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
952 o
= pa_operation_new(c
, NULL
, cb
, userdata
);
954 t
= pa_tagstruct_command(c
, command
, &tag
);
955 pa_pstream_send_tagstruct(c
->pstream
, t
);
956 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, internal_cb
, pa_operation_ref(o
), (pa_free_cb_t
) pa_operation_unref
);
961 pa_operation
* pa_context_set_default_sink(pa_context
*c
, const char *name
, pa_context_success_cb_t cb
, void *userdata
) {
967 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
969 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
971 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
973 t
= pa_tagstruct_command(c
, PA_COMMAND_SET_DEFAULT_SINK
, &tag
);
974 pa_tagstruct_puts(t
, name
);
975 pa_pstream_send_tagstruct(c
->pstream
, t
);
976 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
);
981 pa_operation
* pa_context_set_default_source(pa_context
*c
, const char *name
, pa_context_success_cb_t cb
, void *userdata
) {
987 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
989 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
991 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
993 t
= pa_tagstruct_command(c
, PA_COMMAND_SET_DEFAULT_SOURCE
, &tag
);
994 pa_tagstruct_puts(t
, name
);
995 pa_pstream_send_tagstruct(c
->pstream
, t
);
996 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
);
1001 int pa_context_is_local(pa_context
*c
) {
1003 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1005 PA_CHECK_VALIDITY(c
, c
->is_local
>= 0, PA_ERR_BADSTATE
);
1010 pa_operation
* pa_context_set_name(pa_context
*c
, const char *name
, pa_context_success_cb_t cb
, void *userdata
) {
1016 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1019 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
1021 if (c
->version
>= 13) {
1022 pa_proplist
*p
= pa_proplist_new();
1023 pa_proplist_sets(p
, PA_PROP_APPLICATION_NAME
, name
);
1024 o
= pa_context_proplist_update(c
, PA_UPDATE_REPLACE
, p
, cb
, userdata
);
1025 pa_proplist_free(p
);
1028 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
1029 t
= pa_tagstruct_command(c
, PA_COMMAND_SET_CLIENT_NAME
, &tag
);
1030 pa_tagstruct_puts(t
, name
);
1031 pa_pstream_send_tagstruct(c
->pstream
, t
);
1032 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
);
1038 const char* pa_get_library_version(void) {
1039 return PACKAGE_VERSION
;
1042 const char* pa_context_get_server(pa_context
*c
) {
1044 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1049 if (*c
->server
== '{') {
1050 char *e
= strchr(c
->server
+1, '}');
1051 return e
? e
+1 : c
->server
;
1057 uint32_t pa_context_get_protocol_version(PA_GCC_UNUSED pa_context
*c
) {
1058 return PA_PROTOCOL_VERSION
;
1061 uint32_t pa_context_get_server_protocol_version(pa_context
*c
) {
1063 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1065 PA_CHECK_VALIDITY_RETURN_ANY(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
, PA_INVALID_INDEX
);
1070 pa_tagstruct
*pa_tagstruct_command(pa_context
*c
, uint32_t command
, uint32_t *tag
) {
1076 t
= pa_tagstruct_new(NULL
, 0);
1077 pa_tagstruct_putu32(t
, command
);
1078 pa_tagstruct_putu32(t
, *tag
= c
->ctag
++);
1083 uint32_t pa_context_get_index(pa_context
*c
) {
1085 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1087 PA_CHECK_VALIDITY_RETURN_ANY(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
, PA_INVALID_INDEX
);
1088 PA_CHECK_VALIDITY_RETURN_ANY(c
, c
->version
>= 13, PA_ERR_NOTSUPPORTED
, PA_INVALID_INDEX
);
1090 return c
->client_index
;
1093 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
) {
1099 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1101 PA_CHECK_VALIDITY_RETURN_NULL(c
, mode
== PA_UPDATE_SET
|| mode
== PA_UPDATE_MERGE
|| mode
== PA_UPDATE_REPLACE
, PA_ERR_INVALID
);
1102 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
1103 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 13, PA_ERR_NOTSUPPORTED
);
1105 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
1107 t
= pa_tagstruct_command(c
, PA_COMMAND_UPDATE_CLIENT_PROPLIST
, &tag
);
1108 pa_tagstruct_putu32(t
, (uint32_t) mode
);
1109 pa_tagstruct_put_proplist(t
, p
);
1111 pa_pstream_send_tagstruct(c
->pstream
, t
);
1112 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
);
1114 /* Please note that we don't update c->proplist here, because we
1115 * don't export that field */
1120 pa_operation
*pa_context_proplist_remove(pa_context
*c
, const char *const keys
[], pa_context_success_cb_t cb
, void *userdata
) {
1124 const char * const *k
;
1127 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
1129 PA_CHECK_VALIDITY_RETURN_NULL(c
, keys
&& keys
[0], PA_ERR_INVALID
);
1130 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
1131 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 13, PA_ERR_NOTSUPPORTED
);
1133 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
1135 t
= pa_tagstruct_command(c
, PA_COMMAND_REMOVE_CLIENT_PROPLIST
, &tag
);
1137 for (k
= keys
; *k
; k
++)
1138 pa_tagstruct_puts(t
, *k
);
1140 pa_tagstruct_puts(t
, NULL
);
1142 pa_pstream_send_tagstruct(c
->pstream
, t
);
1143 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
);
1145 /* Please note that we don't update c->proplist here, because we
1146 * don't export that field */
1151 void pa_init_proplist(pa_proplist
*p
) {
1153 #ifndef HAVE_DECL_ENVIRON
1154 extern char **environ
;
1160 for (e
= environ
; *e
; e
++) {
1162 if (pa_startswith(*e
, "PULSE_PROP_")) {
1163 size_t kl
= strcspn(*e
+11, "=");
1166 if ((*e
)[11+kl
] != '=')
1169 if (!pa_utf8_valid(*e
+11+kl
+1))
1172 k
= pa_xstrndup(*e
+11, kl
);
1174 if (pa_proplist_contains(p
, k
)) {
1179 pa_proplist_sets(p
, k
, *e
+11+kl
+1);
1184 if (!pa_proplist_contains(p
, PA_PROP_APPLICATION_PROCESS_ID
)) {
1186 pa_snprintf(t
, sizeof(t
), "%lu", (unsigned long) getpid());
1187 pa_proplist_sets(p
, PA_PROP_APPLICATION_PROCESS_ID
, t
);
1190 if (!pa_proplist_contains(p
, PA_PROP_APPLICATION_PROCESS_USER
)) {
1192 if (pa_get_user_name(t
, sizeof(t
))) {
1193 char *c
= pa_utf8_filter(t
);
1194 pa_proplist_sets(p
, PA_PROP_APPLICATION_PROCESS_USER
, c
);
1199 if (!pa_proplist_contains(p
, PA_PROP_APPLICATION_PROCESS_HOST
)) {
1201 if (pa_get_host_name(t
, sizeof(t
))) {
1202 char *c
= pa_utf8_filter(t
);
1203 pa_proplist_sets(p
, PA_PROP_APPLICATION_PROCESS_HOST
, c
);
1208 a
= pa_proplist_contains(p
, PA_PROP_APPLICATION_PROCESS_BINARY
);
1209 b
= pa_proplist_contains(p
, PA_PROP_APPLICATION_NAME
);
1213 if (pa_get_binary_name(t
, sizeof(t
))) {
1214 char *c
= pa_utf8_filter(t
);
1217 pa_proplist_sets(p
, PA_PROP_APPLICATION_PROCESS_BINARY
, c
);
1219 pa_proplist_sets(p
, PA_PROP_APPLICATION_NAME
, c
);
1225 if (!pa_proplist_contains(p
, PA_PROP_APPLICATION_LANGUAGE
)) {
1228 if ((l
= setlocale(LC_MESSAGES
, NULL
)))
1229 pa_proplist_sets(p
, PA_PROP_APPLICATION_LANGUAGE
, l
);