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>
53 #include <polypcore/native-common.h>
54 #include <polypcore/pdispatch.h>
55 #include <polypcore/pstream.h>
56 #include <polypcore/dynarray.h>
57 #include <polypcore/socket-client.h>
58 #include <polypcore/pstream-util.h>
59 #include <polypcore/util.h>
60 #include <polypcore/xmalloc.h>
61 #include <polypcore/log.h>
62 #include <polyp/client-conf.h>
63 #include <polypcore/socket-util.h>
66 #include "client-conf-x11.h"
69 #define AUTOSPAWN_LOCK "autospawn.lock"
71 static const pa_pdispatch_callback command_table
[PA_COMMAND_MAX
] = {
72 [PA_COMMAND_REQUEST
] = pa_command_request
,
73 [PA_COMMAND_PLAYBACK_STREAM_KILLED
] = pa_command_stream_killed
,
74 [PA_COMMAND_RECORD_STREAM_KILLED
] = pa_command_stream_killed
,
75 [PA_COMMAND_SUBSCRIBE_EVENT
] = pa_command_subscribe_event
78 static void unlock_autospawn_lock_file(pa_context
*c
) {
81 if (c
->autospawn_lock_fd
>= 0) {
83 pa_runtime_path(AUTOSPAWN_LOCK
, lf
, sizeof(lf
));
85 pa_unlock_lockfile(lf
, c
->autospawn_lock_fd
);
86 c
->autospawn_lock_fd
= -1;
90 pa_context
*pa_context_new(pa_mainloop_api
*mainloop
, const char *name
) {
92 assert(mainloop
&& name
);
94 c
= pa_xmalloc(sizeof(pa_context
));
96 c
->name
= pa_xstrdup(name
);
97 c
->mainloop
= mainloop
;
101 c
->playback_streams
= pa_dynarray_new();
102 c
->record_streams
= pa_dynarray_new();
103 assert(c
->playback_streams
&& c
->record_streams
);
105 PA_LLIST_HEAD_INIT(pa_stream
, c
->streams
);
106 PA_LLIST_HEAD_INIT(pa_operation
, c
->operations
);
108 c
->error
= PA_ERROR_OK
;
109 c
->state
= PA_CONTEXT_UNCONNECTED
;
112 c
->state_callback
= NULL
;
113 c
->state_userdata
= NULL
;
115 c
->subscribe_callback
= NULL
;
116 c
->subscribe_userdata
= NULL
;
118 c
->memblock_stat
= pa_memblock_stat_new();
120 c
->server_list
= NULL
;
122 c
->autospawn_lock_fd
= -1;
123 memset(&c
->spawn_api
, 0, sizeof(c
->spawn_api
));
127 pa_check_signal_is_blocked(SIGPIPE
);
130 c
->conf
= pa_client_conf_new();
131 pa_client_conf_load(c
->conf
, NULL
);
133 pa_client_conf_from_x11(c
->conf
, NULL
);
135 pa_client_conf_env(c
->conf
);
140 static void context_free(pa_context
*c
) {
143 unlock_autospawn_lock_file(c
);
145 while (c
->operations
)
146 pa_operation_cancel(c
->operations
);
149 pa_stream_set_state(c
->streams
, PA_STREAM_TERMINATED
);
152 pa_socket_client_unref(c
->client
);
154 pa_pdispatch_unref(c
->pdispatch
);
156 pa_pstream_close(c
->pstream
);
157 pa_pstream_unref(c
->pstream
);
160 if (c
->record_streams
)
161 pa_dynarray_free(c
->record_streams
, NULL
, NULL
);
162 if (c
->playback_streams
)
163 pa_dynarray_free(c
->playback_streams
, NULL
, NULL
);
165 pa_memblock_stat_unref(c
->memblock_stat
);
168 pa_client_conf_free(c
->conf
);
170 pa_strlist_free(c
->server_list
);
177 pa_context
* pa_context_ref(pa_context
*c
) {
178 assert(c
&& c
->ref
>= 1);
183 void pa_context_unref(pa_context
*c
) {
184 assert(c
&& c
->ref
>= 1);
186 if ((--(c
->ref
)) == 0)
190 void pa_context_set_state(pa_context
*c
, pa_context_state_t st
) {
198 if (st
== PA_CONTEXT_FAILED
|| st
== PA_CONTEXT_TERMINATED
) {
201 s
= c
->streams
? pa_stream_ref(c
->streams
) : NULL
;
203 pa_stream
*n
= s
->next
? pa_stream_ref(s
->next
) : NULL
;
204 pa_stream_set_state(s
, st
== PA_CONTEXT_FAILED
? PA_STREAM_FAILED
: PA_STREAM_TERMINATED
);
210 pa_pdispatch_unref(c
->pdispatch
);
214 pa_pstream_close(c
->pstream
);
215 pa_pstream_unref(c
->pstream
);
220 pa_socket_client_unref(c
->client
);
225 if (c
->state_callback
)
226 c
->state_callback(c
, c
->state_userdata
);
231 void pa_context_fail(pa_context
*c
, int error
) {
234 pa_context_set_state(c
, PA_CONTEXT_FAILED
);
237 static void pstream_die_callback(pa_pstream
*p
, void *userdata
) {
238 pa_context
*c
= userdata
;
240 pa_context_fail(c
, PA_ERROR_CONNECTIONTERMINATED
);
243 static void pstream_packet_callback(pa_pstream
*p
, pa_packet
*packet
, void *userdata
) {
244 pa_context
*c
= userdata
;
245 assert(p
&& packet
&& c
);
249 if (pa_pdispatch_run(c
->pdispatch
, packet
, c
) < 0) {
250 pa_log(__FILE__
": invalid packet.\n");
251 pa_context_fail(c
, PA_ERROR_PROTOCOL
);
257 static void pstream_memblock_callback(pa_pstream
*p
, uint32_t channel
, PA_GCC_UNUSED
uint32_t delta
, const pa_memchunk
*chunk
, void *userdata
) {
258 pa_context
*c
= userdata
;
260 assert(p
&& chunk
&& c
&& chunk
->memblock
&& chunk
->memblock
->data
);
264 if ((s
= pa_dynarray_get(c
->record_streams
, channel
))) {
265 pa_mcalign_push(s
->mcalign
, chunk
);
270 if (pa_mcalign_pop(s
->mcalign
, &t
) < 0)
273 if (s
->read_callback
) {
274 s
->read_callback(s
, (uint8_t*) t
.memblock
->data
+ t
.index
, t
.length
, s
->read_userdata
);
275 s
->counter
+= chunk
->length
;
278 pa_memblock_unref(t
.memblock
);
285 int pa_context_handle_error(pa_context
*c
, uint32_t command
, pa_tagstruct
*t
) {
288 if (command
== PA_COMMAND_ERROR
) {
291 if (pa_tagstruct_getu32(t
, &c
->error
) < 0) {
292 pa_context_fail(c
, PA_ERROR_PROTOCOL
);
296 } else if (command
== PA_COMMAND_TIMEOUT
)
297 c
->error
= PA_ERROR_TIMEOUT
;
299 pa_context_fail(c
, PA_ERROR_PROTOCOL
);
306 static void setup_complete_callback(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
307 pa_context
*c
= userdata
;
308 assert(pd
&& c
&& (c
->state
== PA_CONTEXT_AUTHORIZING
|| c
->state
== PA_CONTEXT_SETTING_NAME
));
312 if (command
!= PA_COMMAND_REPLY
) {
314 if (pa_context_handle_error(c
, command
, t
) < 0)
315 pa_context_fail(c
, PA_ERROR_PROTOCOL
);
317 pa_context_fail(c
, c
->error
);
322 case PA_CONTEXT_AUTHORIZING
: {
324 reply
= pa_tagstruct_new(NULL
, 0);
325 pa_tagstruct_putu32(reply
, PA_COMMAND_SET_CLIENT_NAME
);
326 pa_tagstruct_putu32(reply
, tag
= c
->ctag
++);
327 pa_tagstruct_puts(reply
, c
->name
);
328 pa_pstream_send_tagstruct(c
->pstream
, reply
);
329 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, setup_complete_callback
, c
);
331 pa_context_set_state(c
, PA_CONTEXT_SETTING_NAME
);
335 case PA_CONTEXT_SETTING_NAME
:
336 pa_context_set_state(c
, PA_CONTEXT_READY
);
347 static void setup_context(pa_context
*c
, pa_iochannel
*io
) {
355 c
->pstream
= pa_pstream_new(c
->mainloop
, io
, c
->memblock_stat
);
358 pa_pstream_set_die_callback(c
->pstream
, pstream_die_callback
, c
);
359 pa_pstream_set_recieve_packet_callback(c
->pstream
, pstream_packet_callback
, c
);
360 pa_pstream_set_recieve_memblock_callback(c
->pstream
, pstream_memblock_callback
, c
);
362 assert(!c
->pdispatch
);
363 c
->pdispatch
= pa_pdispatch_new(c
->mainloop
, command_table
, PA_COMMAND_MAX
);
364 assert(c
->pdispatch
);
366 if (!c
->conf
->cookie_valid
) {
367 pa_context_fail(c
, PA_ERROR_AUTHKEY
);
371 t
= pa_tagstruct_new(NULL
, 0);
373 pa_tagstruct_putu32(t
, PA_COMMAND_AUTH
);
374 pa_tagstruct_putu32(t
, tag
= c
->ctag
++);
375 pa_tagstruct_put_arbitrary(t
, c
->conf
->cookie
, sizeof(c
->conf
->cookie
));
376 pa_pstream_send_tagstruct(c
->pstream
, t
);
377 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, setup_complete_callback
, c
);
379 pa_context_set_state(c
, PA_CONTEXT_AUTHORIZING
);
386 static void on_connection(pa_socket_client
*client
, pa_iochannel
*io
, void *userdata
);
390 static int context_connect_spawn(pa_context
*c
) {
393 int fds
[2] = { -1, -1} ;
398 if (socketpair(AF_UNIX
, SOCK_STREAM
, 0, fds
) < 0) {
399 pa_log(__FILE__
": socketpair() failed: %s\n", strerror(errno
));
400 pa_context_fail(c
, PA_ERROR_INTERNAL
);
404 pa_fd_set_cloexec(fds
[0], 1);
406 pa_socket_low_delay(fds
[0]);
407 pa_socket_low_delay(fds
[1]);
409 if (c
->spawn_api
.prefork
)
410 c
->spawn_api
.prefork();
412 if ((pid
= fork()) < 0) {
413 pa_log(__FILE__
": fork() failed: %s\n", strerror(errno
));
414 pa_context_fail(c
, PA_ERROR_INTERNAL
);
416 if (c
->spawn_api
.postfork
)
417 c
->spawn_api
.postfork();
424 const char *state
= NULL
;
426 const char * argv
[MAX_ARGS
+1];
429 /* Not required, since fds[0] has CLOEXEC enabled anyway */
432 if (c
->spawn_api
.atfork
)
433 c
->spawn_api
.atfork();
439 argv
[n
++] = c
->conf
->daemon_binary
;
440 argv
[n
++] = "--daemonize=yes";
442 snprintf(t
, sizeof(t
), "-Lmodule-native-protocol-fd fd=%i", fds
[1]);
443 argv
[n
++] = strdup(t
);
445 while (n
< MAX_ARGS
) {
448 if (!(a
= pa_split_spaces(c
->conf
->extra_arguments
, &state
)))
456 execv(argv
[0], (char * const *) argv
);
463 r
= waitpid(pid
, &status
, 0);
465 if (c
->spawn_api
.postfork
)
466 c
->spawn_api
.postfork();
469 pa_log(__FILE__
": waitpid() failed: %s\n", strerror(errno
));
470 pa_context_fail(c
, PA_ERROR_INTERNAL
);
472 } else if (!WIFEXITED(status
) || WEXITSTATUS(status
) != 0) {
473 pa_context_fail(c
, PA_ERROR_CONNECTIONREFUSED
);
481 io
= pa_iochannel_new(c
->mainloop
, fds
[0], fds
[0]);
483 setup_context(c
, io
);
484 unlock_autospawn_lock_file(c
);
496 unlock_autospawn_lock_file(c
);
503 #endif /* OS_IS_WIN32 */
505 static int try_next_connection(pa_context
*c
) {
508 assert(c
&& !c
->client
);
515 c
->server_list
= pa_strlist_pop(c
->server_list
, &u
);
520 if (c
->do_autospawn
) {
521 r
= context_connect_spawn(c
);
526 pa_context_fail(c
, PA_ERROR_CONNECTIONREFUSED
);
530 pa_log_debug(__FILE__
": Trying to connect to %s...\n", u
);
533 c
->server
= pa_xstrdup(u
);
535 if (!(c
->client
= pa_socket_client_new_string(c
->mainloop
, u
, PA_NATIVE_DEFAULT_PORT
)))
538 c
->local
= pa_socket_client_is_local(c
->client
);
539 pa_socket_client_set_callback(c
->client
, on_connection
, c
);
552 static void on_connection(pa_socket_client
*client
, pa_iochannel
*io
, void *userdata
) {
553 pa_context
*c
= userdata
;
554 assert(client
&& c
&& c
->state
== PA_CONTEXT_CONNECTING
);
558 pa_socket_client_unref(client
);
562 /* Try the item in the list */
563 if (errno
== ECONNREFUSED
|| errno
== ETIMEDOUT
|| errno
== EHOSTUNREACH
) {
564 try_next_connection(c
);
568 pa_context_fail(c
, PA_ERROR_CONNECTIONREFUSED
);
572 unlock_autospawn_lock_file(c
);
573 setup_context(c
, io
);
579 int pa_context_connect(pa_context
*c
, const char *server
, int spawn
, const pa_spawn_api
*api
) {
581 assert(c
&& c
->ref
>= 1 && c
->state
== PA_CONTEXT_UNCONNECTED
);
584 server
= c
->conf
->default_server
;
588 assert(!c
->server_list
);
591 if (!(c
->server_list
= pa_strlist_parse(server
))) {
592 pa_context_fail(c
, PA_ERROR_INVALIDSERVER
);
599 /* Prepend in reverse order */
601 if ((d
= getenv("DISPLAY"))) {
604 if ((e
= strchr(d
, ':')))
608 c
->server_list
= pa_strlist_prepend(c
->server_list
, d
);
613 c
->server_list
= pa_strlist_prepend(c
->server_list
, "tcp6:localhost");
614 c
->server_list
= pa_strlist_prepend(c
->server_list
, "localhost");
615 c
->server_list
= pa_strlist_prepend(c
->server_list
, pa_runtime_path(PA_NATIVE_DEFAULT_UNIX_SOCKET
, ufn
, sizeof(ufn
)));
617 /* Wrap the connection attempts in a single transaction for sane autospawn locking */
618 if (spawn
&& c
->conf
->autospawn
) {
621 pa_runtime_path(AUTOSPAWN_LOCK
, lf
, sizeof(lf
));
622 pa_make_secure_parent_dir(lf
);
623 assert(c
->autospawn_lock_fd
<= 0);
624 c
->autospawn_lock_fd
= pa_lock_lockfile(lf
);
633 pa_context_set_state(c
, PA_CONTEXT_CONNECTING
);
634 r
= try_next_connection(c
);
642 void pa_context_disconnect(pa_context
*c
) {
644 pa_context_set_state(c
, PA_CONTEXT_TERMINATED
);
647 pa_context_state_t
pa_context_get_state(pa_context
*c
) {
648 assert(c
&& c
->ref
>= 1);
652 int pa_context_errno(pa_context
*c
) {
653 assert(c
&& c
->ref
>= 1);
657 void pa_context_set_state_callback(pa_context
*c
, void (*cb
)(pa_context
*c
, void *userdata
), void *userdata
) {
658 assert(c
&& c
->ref
>= 1);
659 c
->state_callback
= cb
;
660 c
->state_userdata
= userdata
;
663 int pa_context_is_pending(pa_context
*c
) {
664 assert(c
&& c
->ref
>= 1);
666 /* pa_log("pstream: %i\n", pa_pstream_is_pending(c->pstream)); */
667 /* pa_log("pdispatch: %i\n", pa_pdispatch_is_pending(c->pdispatch)); */
669 return (c
->pstream
&& pa_pstream_is_pending(c
->pstream
)) ||
670 (c
->pdispatch
&& pa_pdispatch_is_pending(c
->pdispatch
)) ||
674 static void set_dispatch_callbacks(pa_operation
*o
);
676 static void pdispatch_drain_callback(PA_GCC_UNUSED pa_pdispatch
*pd
, void *userdata
) {
677 set_dispatch_callbacks(userdata
);
680 static void pstream_drain_callback(PA_GCC_UNUSED pa_pstream
*s
, void *userdata
) {
681 set_dispatch_callbacks(userdata
);
684 static void set_dispatch_callbacks(pa_operation
*o
) {
686 assert(o
&& o
->context
&& o
->context
->ref
>= 1 && o
->ref
>= 1 && o
->context
->state
== PA_CONTEXT_READY
);
688 pa_pstream_set_drain_callback(o
->context
->pstream
, NULL
, NULL
);
689 pa_pdispatch_set_drain_callback(o
->context
->pdispatch
, NULL
, NULL
);
691 if (pa_pdispatch_is_pending(o
->context
->pdispatch
)) {
692 pa_pdispatch_set_drain_callback(o
->context
->pdispatch
, pdispatch_drain_callback
, o
);
696 if (pa_pstream_is_pending(o
->context
->pstream
)) {
697 pa_pstream_set_drain_callback(o
->context
->pstream
, pstream_drain_callback
, o
);
705 void (*cb
)(pa_context
*c
, void *userdata
);
706 cb
= (void (*)(pa_context
*, void*)) o
->callback
;
707 cb(o
->context
, o
->userdata
);
710 pa_operation_done(o
);
713 pa_operation_unref(o
);
716 pa_operation
* pa_context_drain(pa_context
*c
, void (*cb
) (pa_context
*c
, void *userdata
), void *userdata
) {
718 assert(c
&& c
->ref
>= 1);
720 if (c
->state
!= PA_CONTEXT_READY
)
723 if (!pa_context_is_pending(c
))
726 o
= pa_operation_new(c
, NULL
);
728 o
->callback
= (pa_operation_callback
) cb
;
729 o
->userdata
= userdata
;
731 set_dispatch_callbacks(pa_operation_ref(o
));
736 void pa_context_exit_daemon(pa_context
*c
) {
738 assert(c
&& c
->ref
>= 1);
740 t
= pa_tagstruct_new(NULL
, 0);
742 pa_tagstruct_putu32(t
, PA_COMMAND_EXIT
);
743 pa_tagstruct_putu32(t
, c
->ctag
++);
744 pa_pstream_send_tagstruct(c
->pstream
, t
);
747 void pa_context_simple_ack_callback(pa_pdispatch
*pd
, uint32_t command
, PA_GCC_UNUSED
uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
748 pa_operation
*o
= userdata
;
750 assert(pd
&& o
&& o
->context
&& o
->ref
>= 1);
752 if (command
!= PA_COMMAND_REPLY
) {
753 if (pa_context_handle_error(o
->context
, command
, t
) < 0)
757 } else if (!pa_tagstruct_eof(t
)) {
758 pa_context_fail(o
->context
, PA_ERROR_PROTOCOL
);
763 void (*cb
)(pa_context
*c
, int _success
, void *_userdata
) = (void (*)(pa_context
*c
, int _success
, void *_userdata
)) o
->callback
;
764 cb(o
->context
, success
, o
->userdata
);
768 pa_operation_done(o
);
769 pa_operation_unref(o
);
772 pa_operation
* pa_context_send_simple_command(pa_context
*c
, uint32_t command
, void (*internal_callback
)(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
), void (*cb
)(void), void *userdata
) {
778 o
= pa_operation_new(c
, NULL
);
780 o
->userdata
= userdata
;
782 t
= pa_tagstruct_new(NULL
, 0);
783 pa_tagstruct_putu32(t
, command
);
784 pa_tagstruct_putu32(t
, tag
= c
->ctag
++);
785 pa_pstream_send_tagstruct(c
->pstream
, t
);
786 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, internal_callback
, o
);
788 return pa_operation_ref(o
);
791 pa_operation
* pa_context_set_default_sink(pa_context
*c
, const char *name
, void(*cb
)(pa_context
*c
, int success
, void *userdata
), void *userdata
) {
797 o
= pa_operation_new(c
, NULL
);
798 o
->callback
= (pa_operation_callback
) cb
;
799 o
->userdata
= userdata
;
801 t
= pa_tagstruct_new(NULL
, 0);
802 pa_tagstruct_putu32(t
, PA_COMMAND_SET_DEFAULT_SINK
);
803 pa_tagstruct_putu32(t
, tag
= c
->ctag
++);
804 pa_tagstruct_puts(t
, name
);
805 pa_pstream_send_tagstruct(c
->pstream
, t
);
806 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, pa_context_simple_ack_callback
, o
);
808 return pa_operation_ref(o
);
811 pa_operation
* pa_context_set_default_source(pa_context
*c
, const char *name
, void(*cb
)(pa_context
*c
, int success
, void *userdata
), void *userdata
) {
817 o
= pa_operation_new(c
, NULL
);
818 o
->callback
= (pa_operation_callback
) cb
;
819 o
->userdata
= userdata
;
821 t
= pa_tagstruct_new(NULL
, 0);
822 pa_tagstruct_putu32(t
, PA_COMMAND_SET_DEFAULT_SOURCE
);
823 pa_tagstruct_putu32(t
, tag
= c
->ctag
++);
824 pa_tagstruct_puts(t
, name
);
825 pa_pstream_send_tagstruct(c
->pstream
, t
);
826 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, pa_context_simple_ack_callback
, o
);
828 return pa_operation_ref(o
);
831 int pa_context_is_local(pa_context
*c
) {
836 pa_operation
* pa_context_set_name(pa_context
*c
, const char *name
, void(*cb
)(pa_context
*c
, int success
, void *userdata
), void *userdata
) {
840 assert(c
&& name
&& cb
);
842 o
= pa_operation_new(c
, NULL
);
843 o
->callback
= (pa_operation_callback
) cb
;
844 o
->userdata
= userdata
;
846 t
= pa_tagstruct_new(NULL
, 0);
847 pa_tagstruct_putu32(t
, PA_COMMAND_SET_CLIENT_NAME
);
848 pa_tagstruct_putu32(t
, tag
= c
->ctag
++);
849 pa_tagstruct_puts(t
, name
);
850 pa_pstream_send_tagstruct(c
->pstream
, t
);
851 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, pa_context_simple_ack_callback
, o
);
853 return pa_operation_ref(o
);
856 const char* pa_get_library_version(void) {
857 return PACKAGE_VERSION
;
860 const char* pa_context_get_server(pa_context
*c
) {
865 if (*c
->server
== '{') {
866 char *e
= strchr(c
->server
+1, '}');
867 return e
? e
+1 : c
->server
;