4 This file is part of polypaudio.
6 polypaudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published
8 by the Free Software Foundation; either version 2 of the License,
9 or (at your option) any later version.
11 polypaudio is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with polypaudio; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
30 #include <sys/types.h>
37 #ifdef HAVE_SYS_WAIT_H
41 #ifdef HAVE_SYS_SOCKET_H
42 #include <sys/socket.h>
48 #include "../polypcore/winsock.h"
50 #include <polyp/version.h>
52 #include <polypcore/native-common.h>
53 #include <polypcore/pdispatch.h>
54 #include <polypcore/pstream.h>
55 #include <polypcore/dynarray.h>
56 #include <polypcore/socket-client.h>
57 #include <polypcore/pstream-util.h>
58 #include <polypcore/util.h>
59 #include <polypcore/xmalloc.h>
60 #include <polypcore/log.h>
61 #include <polypcore/socket-util.h>
65 #include "client-conf.h"
68 #include "client-conf-x11.h"
73 #define AUTOSPAWN_LOCK "autospawn.lock"
75 static const pa_pdispatch_cb_t command_table
[PA_COMMAND_MAX
] = {
76 [PA_COMMAND_REQUEST
] = pa_command_request
,
77 [PA_COMMAND_OVERFLOW
] = pa_command_overflow_or_underflow
,
78 [PA_COMMAND_UNDERFLOW
] = pa_command_overflow_or_underflow
,
79 [PA_COMMAND_PLAYBACK_STREAM_KILLED
] = pa_command_stream_killed
,
80 [PA_COMMAND_RECORD_STREAM_KILLED
] = pa_command_stream_killed
,
81 [PA_COMMAND_SUBSCRIBE_EVENT
] = pa_command_subscribe_event
84 static void unlock_autospawn_lock_file(pa_context
*c
) {
87 if (c
->autospawn_lock_fd
>= 0) {
89 pa_runtime_path(AUTOSPAWN_LOCK
, lf
, sizeof(lf
));
91 pa_unlock_lockfile(lf
, c
->autospawn_lock_fd
);
92 c
->autospawn_lock_fd
= -1;
96 pa_context
*pa_context_new(pa_mainloop_api
*mainloop
, const char *name
) {
102 c
= pa_xnew(pa_context
, 1);
104 c
->name
= pa_xstrdup(name
);
105 c
->mainloop
= mainloop
;
109 c
->playback_streams
= pa_dynarray_new();
110 c
->record_streams
= pa_dynarray_new();
112 PA_LLIST_HEAD_INIT(pa_stream
, c
->streams
);
113 PA_LLIST_HEAD_INIT(pa_operation
, c
->operations
);
116 c
->state
= PA_CONTEXT_UNCONNECTED
;
120 c
->state_callback
= NULL
;
121 c
->state_userdata
= NULL
;
123 c
->subscribe_callback
= NULL
;
124 c
->subscribe_userdata
= NULL
;
126 c
->memblock_stat
= pa_memblock_stat_new();
128 c
->server_list
= NULL
;
130 c
->autospawn_lock_fd
= -1;
131 memset(&c
->spawn_api
, 0, sizeof(c
->spawn_api
));
135 pa_check_signal_is_blocked(SIGPIPE
);
138 c
->conf
= pa_client_conf_new();
139 pa_client_conf_load(c
->conf
, NULL
);
141 pa_client_conf_from_x11(c
->conf
, NULL
);
143 pa_client_conf_env(c
->conf
);
148 WSAStartup(MAKEWORD(2, 0), &data
);
155 static void context_free(pa_context
*c
) {
158 unlock_autospawn_lock_file(c
);
160 while (c
->operations
)
161 pa_operation_cancel(c
->operations
);
164 pa_stream_set_state(c
->streams
, PA_STREAM_TERMINATED
);
167 pa_socket_client_unref(c
->client
);
169 pa_pdispatch_unref(c
->pdispatch
);
171 pa_pstream_close(c
->pstream
);
172 pa_pstream_unref(c
->pstream
);
175 if (c
->record_streams
)
176 pa_dynarray_free(c
->record_streams
, NULL
, NULL
);
177 if (c
->playback_streams
)
178 pa_dynarray_free(c
->playback_streams
, NULL
, NULL
);
180 pa_memblock_stat_unref(c
->memblock_stat
);
183 pa_client_conf_free(c
->conf
);
185 pa_strlist_free(c
->server_list
);
196 pa_context
* pa_context_ref(pa_context
*c
) {
204 void pa_context_unref(pa_context
*c
) {
212 void pa_context_set_state(pa_context
*c
, pa_context_state_t st
) {
222 if (c
->state_callback
)
223 c
->state_callback(c
, c
->state_userdata
);
225 if (st
== PA_CONTEXT_FAILED
|| st
== PA_CONTEXT_TERMINATED
) {
228 s
= c
->streams
? pa_stream_ref(c
->streams
) : NULL
;
230 pa_stream
*n
= s
->next
? pa_stream_ref(s
->next
) : NULL
;
231 pa_stream_set_state(s
, st
== PA_CONTEXT_FAILED
? PA_STREAM_FAILED
: PA_STREAM_TERMINATED
);
237 pa_pdispatch_unref(c
->pdispatch
);
241 pa_pstream_close(c
->pstream
);
242 pa_pstream_unref(c
->pstream
);
247 pa_socket_client_unref(c
->client
);
254 void pa_context_fail(pa_context
*c
, int error
) {
258 pa_context_set_error(c
, error
);
259 pa_context_set_state(c
, PA_CONTEXT_FAILED
);
262 int pa_context_set_error(pa_context
*c
, int error
) {
264 assert(error
< PA_ERR_MAX
);
272 static void pstream_die_callback(pa_pstream
*p
, void *userdata
) {
273 pa_context
*c
= userdata
;
278 pa_context_fail(c
, PA_ERR_CONNECTIONTERMINATED
);
281 static void pstream_packet_callback(pa_pstream
*p
, pa_packet
*packet
, const void *creds
, void *userdata
) {
282 pa_context
*c
= userdata
;
290 if (pa_pdispatch_run(c
->pdispatch
, packet
, creds
, c
) < 0)
291 pa_context_fail(c
, PA_ERR_PROTOCOL
);
296 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
) {
297 pa_context
*c
= userdata
;
302 assert(chunk
->memblock
);
303 assert(chunk
->length
);
309 if ((s
= pa_dynarray_get(c
->record_streams
, channel
))) {
311 assert(seek
== PA_SEEK_RELATIVE
&& offset
== 0);
313 pa_memblockq_seek(s
->record_memblockq
, offset
, seek
);
314 pa_memblockq_push_align(s
->record_memblockq
, chunk
);
316 if (s
->read_callback
) {
319 if ((l
= pa_memblockq_get_length(s
->record_memblockq
)) > 0)
320 s
->read_callback(s
, l
, s
->read_userdata
);
327 int pa_context_handle_error(pa_context
*c
, uint32_t command
, pa_tagstruct
*t
) {
331 if (command
== PA_COMMAND_ERROR
) {
334 if (pa_tagstruct_getu32(t
, &c
->error
) < 0) {
335 pa_context_fail(c
, PA_ERR_PROTOCOL
);
339 } else if (command
== PA_COMMAND_TIMEOUT
)
340 c
->error
= PA_ERR_TIMEOUT
;
342 pa_context_fail(c
, PA_ERR_PROTOCOL
);
349 static void setup_complete_callback(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
350 pa_context
*c
= userdata
;
354 assert(c
->state
== PA_CONTEXT_AUTHORIZING
|| c
->state
== PA_CONTEXT_SETTING_NAME
);
358 if (command
!= PA_COMMAND_REPLY
) {
360 if (pa_context_handle_error(c
, command
, t
) < 0)
361 pa_context_fail(c
, PA_ERR_PROTOCOL
);
363 pa_context_fail(c
, c
->error
);
368 case PA_CONTEXT_AUTHORIZING
: {
371 if (pa_tagstruct_getu32(t
, &c
->version
) < 0 ||
372 !pa_tagstruct_eof(t
)) {
373 pa_context_fail(c
, PA_ERR_PROTOCOL
);
377 /* Minimum supported version */
378 if (c
->version
< 8) {
379 pa_context_fail(c
, PA_ERR_VERSION
);
383 reply
= pa_tagstruct_command(c
, PA_COMMAND_SET_CLIENT_NAME
, &tag
);
384 pa_tagstruct_puts(reply
, c
->name
);
385 pa_pstream_send_tagstruct(c
->pstream
, reply
);
386 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, setup_complete_callback
, c
, NULL
);
388 pa_context_set_state(c
, PA_CONTEXT_SETTING_NAME
);
392 case PA_CONTEXT_SETTING_NAME
:
393 pa_context_set_state(c
, PA_CONTEXT_READY
);
404 static void setup_context(pa_context
*c
, pa_iochannel
*io
) {
414 c
->pstream
= pa_pstream_new(c
->mainloop
, io
, c
->memblock_stat
);
416 pa_pstream_set_die_callback(c
->pstream
, pstream_die_callback
, c
);
417 pa_pstream_set_recieve_packet_callback(c
->pstream
, pstream_packet_callback
, c
);
418 pa_pstream_set_recieve_memblock_callback(c
->pstream
, pstream_memblock_callback
, c
);
420 assert(!c
->pdispatch
);
421 c
->pdispatch
= pa_pdispatch_new(c
->mainloop
, command_table
, PA_COMMAND_MAX
);
423 if (!c
->conf
->cookie_valid
) {
424 pa_context_fail(c
, PA_ERR_AUTHKEY
);
428 t
= pa_tagstruct_command(c
, PA_COMMAND_AUTH
, &tag
);
429 pa_tagstruct_putu32(t
, PA_PROTOCOL_VERSION
);
430 pa_tagstruct_put_arbitrary(t
, c
->conf
->cookie
, sizeof(c
->conf
->cookie
));
431 pa_pstream_send_tagstruct_with_creds(c
->pstream
, t
, 1);
432 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, setup_complete_callback
, c
, NULL
);
434 pa_context_set_state(c
, PA_CONTEXT_AUTHORIZING
);
441 static void on_connection(pa_socket_client
*client
, pa_iochannel
*io
, void *userdata
);
445 static int context_connect_spawn(pa_context
*c
) {
448 int fds
[2] = { -1, -1} ;
453 if (socketpair(AF_UNIX
, SOCK_STREAM
, 0, fds
) < 0) {
454 pa_log(__FILE__
": socketpair() failed: %s", strerror(errno
));
455 pa_context_fail(c
, PA_ERR_INTERNAL
);
459 pa_fd_set_cloexec(fds
[0], 1);
461 pa_socket_low_delay(fds
[0]);
462 pa_socket_low_delay(fds
[1]);
464 if (c
->spawn_api
.prefork
)
465 c
->spawn_api
.prefork();
467 if ((pid
= fork()) < 0) {
468 pa_log(__FILE__
": fork() failed: %s", strerror(errno
));
469 pa_context_fail(c
, PA_ERR_INTERNAL
);
471 if (c
->spawn_api
.postfork
)
472 c
->spawn_api
.postfork();
479 const char *state
= NULL
;
481 const char * argv
[MAX_ARGS
+1];
484 /* Not required, since fds[0] has CLOEXEC enabled anyway */
487 if (c
->spawn_api
.atfork
)
488 c
->spawn_api
.atfork();
494 argv
[n
++] = c
->conf
->daemon_binary
;
495 argv
[n
++] = "--daemonize=yes";
497 snprintf(t
, sizeof(t
), "-Lmodule-native-protocol-fd fd=%i", fds
[1]);
498 argv
[n
++] = strdup(t
);
500 while (n
< MAX_ARGS
) {
503 if (!(a
= pa_split_spaces(c
->conf
->extra_arguments
, &state
)))
511 execv(argv
[0], (char * const *) argv
);
518 r
= waitpid(pid
, &status
, 0);
520 if (c
->spawn_api
.postfork
)
521 c
->spawn_api
.postfork();
524 pa_log(__FILE__
": waitpid() failed: %s", strerror(errno
));
525 pa_context_fail(c
, PA_ERR_INTERNAL
);
527 } else if (!WIFEXITED(status
) || WEXITSTATUS(status
) != 0) {
528 pa_context_fail(c
, PA_ERR_CONNECTIONREFUSED
);
536 io
= pa_iochannel_new(c
->mainloop
, fds
[0], fds
[0]);
538 setup_context(c
, io
);
539 unlock_autospawn_lock_file(c
);
551 unlock_autospawn_lock_file(c
);
558 #endif /* OS_IS_WIN32 */
560 static int try_next_connection(pa_context
*c
) {
571 c
->server_list
= pa_strlist_pop(c
->server_list
, &u
);
576 if (c
->do_autospawn
) {
577 r
= context_connect_spawn(c
);
582 pa_context_fail(c
, PA_ERR_CONNECTIONREFUSED
);
586 pa_log_debug(__FILE__
": Trying to connect to %s...", u
);
589 c
->server
= pa_xstrdup(u
);
591 if (!(c
->client
= pa_socket_client_new_string(c
->mainloop
, u
, PA_NATIVE_DEFAULT_PORT
)))
594 c
->local
= pa_socket_client_is_local(c
->client
);
595 pa_socket_client_set_callback(c
->client
, on_connection
, c
);
607 static void on_connection(pa_socket_client
*client
, pa_iochannel
*io
, void *userdata
) {
608 pa_context
*c
= userdata
;
612 assert(c
->state
== PA_CONTEXT_CONNECTING
);
616 pa_socket_client_unref(client
);
620 /* Try the item in the list */
621 if (errno
== ECONNREFUSED
|| errno
== ETIMEDOUT
|| errno
== EHOSTUNREACH
) {
622 try_next_connection(c
);
626 pa_context_fail(c
, PA_ERR_CONNECTIONREFUSED
);
630 unlock_autospawn_lock_file(c
);
631 setup_context(c
, io
);
637 int pa_context_connect(
640 pa_context_flags_t flags
,
641 const pa_spawn_api
*api
) {
648 PA_CHECK_VALIDITY(c
, c
->state
== PA_CONTEXT_UNCONNECTED
, PA_ERR_BADSTATE
);
649 PA_CHECK_VALIDITY(c
, !(flags
& ~PA_CONTEXT_NOAUTOSPAWN
), PA_ERR_INVALID
);
650 PA_CHECK_VALIDITY(c
, !server
|| *server
, PA_ERR_INVALID
);
653 server
= c
->conf
->default_server
;
657 assert(!c
->server_list
);
660 if (!(c
->server_list
= pa_strlist_parse(server
))) {
661 pa_context_fail(c
, PA_ERR_INVALIDSERVER
);
668 /* Prepend in reverse order */
670 if ((d
= getenv("DISPLAY"))) {
673 if ((e
= strchr(d
, ':')))
677 c
->server_list
= pa_strlist_prepend(c
->server_list
, d
);
682 c
->server_list
= pa_strlist_prepend(c
->server_list
, "tcp6:localhost");
683 c
->server_list
= pa_strlist_prepend(c
->server_list
, "localhost");
684 c
->server_list
= pa_strlist_prepend(c
->server_list
, pa_runtime_path(PA_NATIVE_DEFAULT_UNIX_SOCKET
, ufn
, sizeof(ufn
)));
686 /* Wrap the connection attempts in a single transaction for sane autospawn locking */
687 if (!(flags
& PA_CONTEXT_NOAUTOSPAWN
) && c
->conf
->autospawn
) {
690 pa_runtime_path(AUTOSPAWN_LOCK
, lf
, sizeof(lf
));
691 pa_make_secure_parent_dir(lf
);
692 assert(c
->autospawn_lock_fd
<= 0);
693 c
->autospawn_lock_fd
= pa_lock_lockfile(lf
);
702 pa_context_set_state(c
, PA_CONTEXT_CONNECTING
);
703 r
= try_next_connection(c
);
711 void pa_context_disconnect(pa_context
*c
) {
715 pa_context_set_state(c
, PA_CONTEXT_TERMINATED
);
718 pa_context_state_t
pa_context_get_state(pa_context
*c
) {
725 int pa_context_errno(pa_context
*c
) {
732 void pa_context_set_state_callback(pa_context
*c
, pa_context_notify_cb_t cb
, void *userdata
) {
736 c
->state_callback
= cb
;
737 c
->state_userdata
= userdata
;
740 int pa_context_is_pending(pa_context
*c
) {
745 c
->state
== PA_CONTEXT_CONNECTING
||
746 c
->state
== PA_CONTEXT_AUTHORIZING
||
747 c
->state
== PA_CONTEXT_SETTING_NAME
||
748 c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
750 return (c
->pstream
&& pa_pstream_is_pending(c
->pstream
)) ||
751 (c
->pdispatch
&& pa_pdispatch_is_pending(c
->pdispatch
)) ||
755 static void set_dispatch_callbacks(pa_operation
*o
);
757 static void pdispatch_drain_callback(PA_GCC_UNUSED pa_pdispatch
*pd
, void *userdata
) {
758 set_dispatch_callbacks(userdata
);
761 static void pstream_drain_callback(PA_GCC_UNUSED pa_pstream
*s
, void *userdata
) {
762 set_dispatch_callbacks(userdata
);
765 static void set_dispatch_callbacks(pa_operation
*o
) {
771 assert(o
->context
->ref
>= 1);
772 assert(o
->context
->state
== PA_CONTEXT_READY
);
774 pa_pstream_set_drain_callback(o
->context
->pstream
, NULL
, NULL
);
775 pa_pdispatch_set_drain_callback(o
->context
->pdispatch
, NULL
, NULL
);
777 if (pa_pdispatch_is_pending(o
->context
->pdispatch
)) {
778 pa_pdispatch_set_drain_callback(o
->context
->pdispatch
, pdispatch_drain_callback
, o
);
782 if (pa_pstream_is_pending(o
->context
->pstream
)) {
783 pa_pstream_set_drain_callback(o
->context
->pstream
, pstream_drain_callback
, o
);
789 pa_context_notify_cb_t cb
= (pa_context_notify_cb_t
) o
->callback
;
790 cb(o
->context
, o
->userdata
);
793 pa_operation_done(o
);
794 pa_operation_unref(o
);
798 pa_operation
* pa_context_drain(pa_context
*c
, pa_context_notify_cb_t cb
, void *userdata
) {
804 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
805 PA_CHECK_VALIDITY_RETURN_NULL(c
, pa_context_is_pending(c
), PA_ERR_BADSTATE
);
807 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
808 set_dispatch_callbacks(pa_operation_ref(o
));
813 void pa_context_simple_ack_callback(pa_pdispatch
*pd
, uint32_t command
, PA_GCC_UNUSED
uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
814 pa_operation
*o
= userdata
;
824 if (command
!= PA_COMMAND_REPLY
) {
825 if (pa_context_handle_error(o
->context
, command
, t
) < 0)
829 } else if (!pa_tagstruct_eof(t
)) {
830 pa_context_fail(o
->context
, PA_ERR_PROTOCOL
);
835 pa_context_success_cb_t cb
= (pa_context_success_cb_t
) o
->callback
;
836 cb(o
->context
, success
, o
->userdata
);
840 pa_operation_done(o
);
841 pa_operation_unref(o
);
844 pa_operation
* pa_context_exit_daemon(pa_context
*c
, pa_context_success_cb_t cb
, void *userdata
) {
852 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
854 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
856 t
= pa_tagstruct_command(c
, PA_COMMAND_EXIT
, &tag
);
857 pa_pstream_send_tagstruct(c
->pstream
, t
);
858 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
);
863 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
) {
871 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
873 o
= pa_operation_new(c
, NULL
, cb
, userdata
);
875 t
= pa_tagstruct_command(c
, command
, &tag
);
876 pa_pstream_send_tagstruct(c
->pstream
, t
);
877 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, internal_cb
, pa_operation_ref(o
), (pa_free_cb_t
) pa_operation_unref
);
882 pa_operation
* pa_context_set_default_sink(pa_context
*c
, const char *name
, pa_context_success_cb_t cb
, void *userdata
) {
890 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
892 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
894 t
= pa_tagstruct_command(c
, PA_COMMAND_SET_DEFAULT_SINK
, &tag
);
895 pa_tagstruct_puts(t
, name
);
896 pa_pstream_send_tagstruct(c
->pstream
, t
);
897 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
);
902 pa_operation
* pa_context_set_default_source(pa_context
*c
, const char *name
, pa_context_success_cb_t cb
, void *userdata
) {
910 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
912 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
914 t
= pa_tagstruct_command(c
, PA_COMMAND_SET_DEFAULT_SOURCE
, &tag
);
915 pa_tagstruct_puts(t
, name
);
916 pa_pstream_send_tagstruct(c
->pstream
, t
);
917 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
);
922 int pa_context_is_local(pa_context
*c
) {
928 pa_operation
* pa_context_set_name(pa_context
*c
, const char *name
, pa_context_success_cb_t cb
, void *userdata
) {
937 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
939 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
941 t
= pa_tagstruct_command(c
, PA_COMMAND_SET_CLIENT_NAME
, &tag
);
942 pa_tagstruct_puts(t
, name
);
943 pa_pstream_send_tagstruct(c
->pstream
, t
);
944 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
);
949 const char* pa_get_library_version(void) {
950 return PACKAGE_VERSION
;
953 const char* pa_context_get_server(pa_context
*c
) {
960 if (*c
->server
== '{') {
961 char *e
= strchr(c
->server
+1, '}');
962 return e
? e
+1 : c
->server
;
968 uint32_t pa_context_get_protocol_version(PA_GCC_UNUSED pa_context
*c
) {
969 return PA_PROTOCOL_VERSION
;
972 uint32_t pa_context_get_server_protocol_version(pa_context
*c
) {
979 pa_tagstruct
*pa_tagstruct_command(pa_context
*c
, uint32_t command
, uint32_t *tag
) {
985 t
= pa_tagstruct_new(NULL
, 0);
986 pa_tagstruct_putu32(t
, command
);
987 pa_tagstruct_putu32(t
, *tag
= c
->ctag
++);