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_callback command_table
[PA_COMMAND_MAX
] = {
76 [PA_COMMAND_REQUEST
] = pa_command_request
,
77 [PA_COMMAND_PLAYBACK_STREAM_KILLED
] = pa_command_stream_killed
,
78 [PA_COMMAND_RECORD_STREAM_KILLED
] = pa_command_stream_killed
,
79 [PA_COMMAND_SUBSCRIBE_EVENT
] = pa_command_subscribe_event
82 static void unlock_autospawn_lock_file(pa_context
*c
) {
85 if (c
->autospawn_lock_fd
>= 0) {
87 pa_runtime_path(AUTOSPAWN_LOCK
, lf
, sizeof(lf
));
89 pa_unlock_lockfile(lf
, c
->autospawn_lock_fd
);
90 c
->autospawn_lock_fd
= -1;
94 pa_context
*pa_context_new(pa_mainloop_api
*mainloop
, const char *name
) {
96 assert(mainloop
&& name
);
98 c
= pa_xmalloc(sizeof(pa_context
));
100 c
->name
= pa_xstrdup(name
);
101 c
->mainloop
= mainloop
;
105 c
->playback_streams
= pa_dynarray_new();
106 c
->record_streams
= pa_dynarray_new();
107 assert(c
->playback_streams
&& c
->record_streams
);
109 PA_LLIST_HEAD_INIT(pa_stream
, c
->streams
);
110 PA_LLIST_HEAD_INIT(pa_operation
, c
->operations
);
112 c
->error
= PA_ERROR_OK
;
113 c
->state
= PA_CONTEXT_UNCONNECTED
;
116 c
->state_callback
= NULL
;
117 c
->state_userdata
= NULL
;
119 c
->subscribe_callback
= NULL
;
120 c
->subscribe_userdata
= NULL
;
122 c
->memblock_stat
= pa_memblock_stat_new();
124 c
->server_list
= NULL
;
126 c
->autospawn_lock_fd
= -1;
127 memset(&c
->spawn_api
, 0, sizeof(c
->spawn_api
));
131 pa_check_signal_is_blocked(SIGPIPE
);
134 c
->conf
= pa_client_conf_new();
135 pa_client_conf_load(c
->conf
, NULL
);
137 pa_client_conf_from_x11(c
->conf
, NULL
);
139 pa_client_conf_env(c
->conf
);
144 static void context_free(pa_context
*c
) {
147 unlock_autospawn_lock_file(c
);
149 while (c
->operations
)
150 pa_operation_cancel(c
->operations
);
153 pa_stream_set_state(c
->streams
, PA_STREAM_TERMINATED
);
156 pa_socket_client_unref(c
->client
);
158 pa_pdispatch_unref(c
->pdispatch
);
160 pa_pstream_close(c
->pstream
);
161 pa_pstream_unref(c
->pstream
);
164 if (c
->record_streams
)
165 pa_dynarray_free(c
->record_streams
, NULL
, NULL
);
166 if (c
->playback_streams
)
167 pa_dynarray_free(c
->playback_streams
, NULL
, NULL
);
169 pa_memblock_stat_unref(c
->memblock_stat
);
172 pa_client_conf_free(c
->conf
);
174 pa_strlist_free(c
->server_list
);
181 pa_context
* pa_context_ref(pa_context
*c
) {
182 assert(c
&& c
->ref
>= 1);
187 void pa_context_unref(pa_context
*c
) {
188 assert(c
&& c
->ref
>= 1);
190 if ((--(c
->ref
)) == 0)
194 void pa_context_set_state(pa_context
*c
, pa_context_state_t st
) {
202 if (st
== PA_CONTEXT_FAILED
|| st
== PA_CONTEXT_TERMINATED
) {
205 s
= c
->streams
? pa_stream_ref(c
->streams
) : NULL
;
207 pa_stream
*n
= s
->next
? pa_stream_ref(s
->next
) : NULL
;
208 pa_stream_set_state(s
, st
== PA_CONTEXT_FAILED
? PA_STREAM_FAILED
: PA_STREAM_TERMINATED
);
214 pa_pdispatch_unref(c
->pdispatch
);
218 pa_pstream_close(c
->pstream
);
219 pa_pstream_unref(c
->pstream
);
224 pa_socket_client_unref(c
->client
);
229 if (c
->state_callback
)
230 c
->state_callback(c
, c
->state_userdata
);
235 void pa_context_fail(pa_context
*c
, int error
) {
238 pa_context_set_state(c
, PA_CONTEXT_FAILED
);
241 static void pstream_die_callback(pa_pstream
*p
, void *userdata
) {
242 pa_context
*c
= userdata
;
244 pa_context_fail(c
, PA_ERROR_CONNECTIONTERMINATED
);
247 static void pstream_packet_callback(pa_pstream
*p
, pa_packet
*packet
, void *userdata
) {
248 pa_context
*c
= userdata
;
249 assert(p
&& packet
&& c
);
253 if (pa_pdispatch_run(c
->pdispatch
, packet
, c
) < 0) {
254 pa_log(__FILE__
": invalid packet.\n");
255 pa_context_fail(c
, PA_ERROR_PROTOCOL
);
261 static void pstream_memblock_callback(pa_pstream
*p
, uint32_t channel
, PA_GCC_UNUSED
uint32_t delta
, const pa_memchunk
*chunk
, void *userdata
) {
262 pa_context
*c
= userdata
;
264 assert(p
&& chunk
&& c
&& chunk
->memblock
&& chunk
->memblock
->data
);
268 if ((s
= pa_dynarray_get(c
->record_streams
, channel
))) {
269 pa_mcalign_push(s
->mcalign
, chunk
);
274 if (pa_mcalign_pop(s
->mcalign
, &t
) < 0)
277 if (s
->read_callback
) {
278 s
->read_callback(s
, (uint8_t*) t
.memblock
->data
+ t
.index
, t
.length
, s
->read_userdata
);
279 s
->counter
+= chunk
->length
;
282 pa_memblock_unref(t
.memblock
);
289 int pa_context_handle_error(pa_context
*c
, uint32_t command
, pa_tagstruct
*t
) {
292 if (command
== PA_COMMAND_ERROR
) {
295 if (pa_tagstruct_getu32(t
, &c
->error
) < 0) {
296 pa_context_fail(c
, PA_ERROR_PROTOCOL
);
300 } else if (command
== PA_COMMAND_TIMEOUT
)
301 c
->error
= PA_ERROR_TIMEOUT
;
303 pa_context_fail(c
, PA_ERROR_PROTOCOL
);
310 static void setup_complete_callback(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
311 pa_context
*c
= userdata
;
312 assert(pd
&& c
&& (c
->state
== PA_CONTEXT_AUTHORIZING
|| c
->state
== PA_CONTEXT_SETTING_NAME
));
316 if (command
!= PA_COMMAND_REPLY
) {
318 if (pa_context_handle_error(c
, command
, t
) < 0)
319 pa_context_fail(c
, PA_ERROR_PROTOCOL
);
321 pa_context_fail(c
, c
->error
);
326 case PA_CONTEXT_AUTHORIZING
: {
328 reply
= pa_tagstruct_new(NULL
, 0);
329 pa_tagstruct_putu32(reply
, PA_COMMAND_SET_CLIENT_NAME
);
330 pa_tagstruct_putu32(reply
, tag
= c
->ctag
++);
331 pa_tagstruct_puts(reply
, c
->name
);
332 pa_pstream_send_tagstruct(c
->pstream
, reply
);
333 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, setup_complete_callback
, c
);
335 pa_context_set_state(c
, PA_CONTEXT_SETTING_NAME
);
339 case PA_CONTEXT_SETTING_NAME
:
340 pa_context_set_state(c
, PA_CONTEXT_READY
);
351 static void setup_context(pa_context
*c
, pa_iochannel
*io
) {
359 c
->pstream
= pa_pstream_new(c
->mainloop
, io
, c
->memblock_stat
);
362 pa_pstream_set_die_callback(c
->pstream
, pstream_die_callback
, c
);
363 pa_pstream_set_recieve_packet_callback(c
->pstream
, pstream_packet_callback
, c
);
364 pa_pstream_set_recieve_memblock_callback(c
->pstream
, pstream_memblock_callback
, c
);
366 assert(!c
->pdispatch
);
367 c
->pdispatch
= pa_pdispatch_new(c
->mainloop
, command_table
, PA_COMMAND_MAX
);
368 assert(c
->pdispatch
);
370 if (!c
->conf
->cookie_valid
) {
371 pa_context_fail(c
, PA_ERROR_AUTHKEY
);
375 t
= pa_tagstruct_new(NULL
, 0);
377 pa_tagstruct_putu32(t
, PA_COMMAND_AUTH
);
378 pa_tagstruct_putu32(t
, tag
= c
->ctag
++);
379 pa_tagstruct_put_arbitrary(t
, c
->conf
->cookie
, sizeof(c
->conf
->cookie
));
380 pa_pstream_send_tagstruct(c
->pstream
, t
);
381 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, setup_complete_callback
, c
);
383 pa_context_set_state(c
, PA_CONTEXT_AUTHORIZING
);
390 static void on_connection(pa_socket_client
*client
, pa_iochannel
*io
, void *userdata
);
394 static int context_connect_spawn(pa_context
*c
) {
397 int fds
[2] = { -1, -1} ;
402 if (socketpair(AF_UNIX
, SOCK_STREAM
, 0, fds
) < 0) {
403 pa_log(__FILE__
": socketpair() failed: %s\n", strerror(errno
));
404 pa_context_fail(c
, PA_ERROR_INTERNAL
);
408 pa_fd_set_cloexec(fds
[0], 1);
410 pa_socket_low_delay(fds
[0]);
411 pa_socket_low_delay(fds
[1]);
413 if (c
->spawn_api
.prefork
)
414 c
->spawn_api
.prefork();
416 if ((pid
= fork()) < 0) {
417 pa_log(__FILE__
": fork() failed: %s\n", strerror(errno
));
418 pa_context_fail(c
, PA_ERROR_INTERNAL
);
420 if (c
->spawn_api
.postfork
)
421 c
->spawn_api
.postfork();
428 const char *state
= NULL
;
430 const char * argv
[MAX_ARGS
+1];
433 /* Not required, since fds[0] has CLOEXEC enabled anyway */
436 if (c
->spawn_api
.atfork
)
437 c
->spawn_api
.atfork();
443 argv
[n
++] = c
->conf
->daemon_binary
;
444 argv
[n
++] = "--daemonize=yes";
446 snprintf(t
, sizeof(t
), "-Lmodule-native-protocol-fd fd=%i", fds
[1]);
447 argv
[n
++] = strdup(t
);
449 while (n
< MAX_ARGS
) {
452 if (!(a
= pa_split_spaces(c
->conf
->extra_arguments
, &state
)))
460 execv(argv
[0], (char * const *) argv
);
467 r
= waitpid(pid
, &status
, 0);
469 if (c
->spawn_api
.postfork
)
470 c
->spawn_api
.postfork();
473 pa_log(__FILE__
": waitpid() failed: %s\n", strerror(errno
));
474 pa_context_fail(c
, PA_ERROR_INTERNAL
);
476 } else if (!WIFEXITED(status
) || WEXITSTATUS(status
) != 0) {
477 pa_context_fail(c
, PA_ERROR_CONNECTIONREFUSED
);
485 io
= pa_iochannel_new(c
->mainloop
, fds
[0], fds
[0]);
487 setup_context(c
, io
);
488 unlock_autospawn_lock_file(c
);
500 unlock_autospawn_lock_file(c
);
507 #endif /* OS_IS_WIN32 */
509 static int try_next_connection(pa_context
*c
) {
512 assert(c
&& !c
->client
);
519 c
->server_list
= pa_strlist_pop(c
->server_list
, &u
);
524 if (c
->do_autospawn
) {
525 r
= context_connect_spawn(c
);
530 pa_context_fail(c
, PA_ERROR_CONNECTIONREFUSED
);
534 pa_log_debug(__FILE__
": Trying to connect to %s...\n", u
);
537 c
->server
= pa_xstrdup(u
);
539 if (!(c
->client
= pa_socket_client_new_string(c
->mainloop
, u
, PA_NATIVE_DEFAULT_PORT
)))
542 c
->local
= pa_socket_client_is_local(c
->client
);
543 pa_socket_client_set_callback(c
->client
, on_connection
, c
);
556 static void on_connection(pa_socket_client
*client
, pa_iochannel
*io
, void *userdata
) {
557 pa_context
*c
= userdata
;
558 assert(client
&& c
&& c
->state
== PA_CONTEXT_CONNECTING
);
562 pa_socket_client_unref(client
);
566 /* Try the item in the list */
567 if (errno
== ECONNREFUSED
|| errno
== ETIMEDOUT
|| errno
== EHOSTUNREACH
) {
568 try_next_connection(c
);
572 pa_context_fail(c
, PA_ERROR_CONNECTIONREFUSED
);
576 unlock_autospawn_lock_file(c
);
577 setup_context(c
, io
);
583 int pa_context_connect(pa_context
*c
, const char *server
, int spawn
, const pa_spawn_api
*api
) {
585 assert(c
&& c
->ref
>= 1 && c
->state
== PA_CONTEXT_UNCONNECTED
);
588 server
= c
->conf
->default_server
;
592 assert(!c
->server_list
);
595 if (!(c
->server_list
= pa_strlist_parse(server
))) {
596 pa_context_fail(c
, PA_ERROR_INVALIDSERVER
);
603 /* Prepend in reverse order */
605 if ((d
= getenv("DISPLAY"))) {
608 if ((e
= strchr(d
, ':')))
612 c
->server_list
= pa_strlist_prepend(c
->server_list
, d
);
617 c
->server_list
= pa_strlist_prepend(c
->server_list
, "tcp6:localhost");
618 c
->server_list
= pa_strlist_prepend(c
->server_list
, "localhost");
619 c
->server_list
= pa_strlist_prepend(c
->server_list
, pa_runtime_path(PA_NATIVE_DEFAULT_UNIX_SOCKET
, ufn
, sizeof(ufn
)));
621 /* Wrap the connection attempts in a single transaction for sane autospawn locking */
622 if (spawn
&& c
->conf
->autospawn
) {
625 pa_runtime_path(AUTOSPAWN_LOCK
, lf
, sizeof(lf
));
626 pa_make_secure_parent_dir(lf
);
627 assert(c
->autospawn_lock_fd
<= 0);
628 c
->autospawn_lock_fd
= pa_lock_lockfile(lf
);
637 pa_context_set_state(c
, PA_CONTEXT_CONNECTING
);
638 r
= try_next_connection(c
);
646 void pa_context_disconnect(pa_context
*c
) {
648 pa_context_set_state(c
, PA_CONTEXT_TERMINATED
);
651 pa_context_state_t
pa_context_get_state(pa_context
*c
) {
652 assert(c
&& c
->ref
>= 1);
656 int pa_context_errno(pa_context
*c
) {
657 assert(c
&& c
->ref
>= 1);
661 void pa_context_set_state_callback(pa_context
*c
, void (*cb
)(pa_context
*c
, void *userdata
), void *userdata
) {
662 assert(c
&& c
->ref
>= 1);
663 c
->state_callback
= cb
;
664 c
->state_userdata
= userdata
;
667 int pa_context_is_pending(pa_context
*c
) {
668 assert(c
&& c
->ref
>= 1);
670 /* pa_log("pstream: %i\n", pa_pstream_is_pending(c->pstream)); */
671 /* pa_log("pdispatch: %i\n", pa_pdispatch_is_pending(c->pdispatch)); */
673 return (c
->pstream
&& pa_pstream_is_pending(c
->pstream
)) ||
674 (c
->pdispatch
&& pa_pdispatch_is_pending(c
->pdispatch
)) ||
678 static void set_dispatch_callbacks(pa_operation
*o
);
680 static void pdispatch_drain_callback(PA_GCC_UNUSED pa_pdispatch
*pd
, void *userdata
) {
681 set_dispatch_callbacks(userdata
);
684 static void pstream_drain_callback(PA_GCC_UNUSED pa_pstream
*s
, void *userdata
) {
685 set_dispatch_callbacks(userdata
);
688 static void set_dispatch_callbacks(pa_operation
*o
) {
690 assert(o
&& o
->context
&& o
->context
->ref
>= 1 && o
->ref
>= 1 && o
->context
->state
== PA_CONTEXT_READY
);
692 pa_pstream_set_drain_callback(o
->context
->pstream
, NULL
, NULL
);
693 pa_pdispatch_set_drain_callback(o
->context
->pdispatch
, NULL
, NULL
);
695 if (pa_pdispatch_is_pending(o
->context
->pdispatch
)) {
696 pa_pdispatch_set_drain_callback(o
->context
->pdispatch
, pdispatch_drain_callback
, o
);
700 if (pa_pstream_is_pending(o
->context
->pstream
)) {
701 pa_pstream_set_drain_callback(o
->context
->pstream
, pstream_drain_callback
, o
);
709 void (*cb
)(pa_context
*c
, void *userdata
);
710 cb
= (void (*)(pa_context
*, void*)) o
->callback
;
711 cb(o
->context
, o
->userdata
);
714 pa_operation_done(o
);
717 pa_operation_unref(o
);
720 pa_operation
* pa_context_drain(pa_context
*c
, void (*cb
) (pa_context
*c
, void *userdata
), void *userdata
) {
722 assert(c
&& c
->ref
>= 1);
724 if (c
->state
!= PA_CONTEXT_READY
)
727 if (!pa_context_is_pending(c
))
730 o
= pa_operation_new(c
, NULL
);
732 o
->callback
= (pa_operation_callback
) cb
;
733 o
->userdata
= userdata
;
735 set_dispatch_callbacks(pa_operation_ref(o
));
740 void pa_context_exit_daemon(pa_context
*c
) {
742 assert(c
&& c
->ref
>= 1);
744 t
= pa_tagstruct_new(NULL
, 0);
746 pa_tagstruct_putu32(t
, PA_COMMAND_EXIT
);
747 pa_tagstruct_putu32(t
, c
->ctag
++);
748 pa_pstream_send_tagstruct(c
->pstream
, t
);
751 void pa_context_simple_ack_callback(pa_pdispatch
*pd
, uint32_t command
, PA_GCC_UNUSED
uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
752 pa_operation
*o
= userdata
;
754 assert(pd
&& o
&& o
->context
&& o
->ref
>= 1);
756 if (command
!= PA_COMMAND_REPLY
) {
757 if (pa_context_handle_error(o
->context
, command
, t
) < 0)
761 } else if (!pa_tagstruct_eof(t
)) {
762 pa_context_fail(o
->context
, PA_ERROR_PROTOCOL
);
767 void (*cb
)(pa_context
*c
, int _success
, void *_userdata
) = (void (*)(pa_context
*c
, int _success
, void *_userdata
)) o
->callback
;
768 cb(o
->context
, success
, o
->userdata
);
772 pa_operation_done(o
);
773 pa_operation_unref(o
);
776 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
) {
782 o
= pa_operation_new(c
, NULL
);
784 o
->userdata
= userdata
;
786 t
= pa_tagstruct_new(NULL
, 0);
787 pa_tagstruct_putu32(t
, command
);
788 pa_tagstruct_putu32(t
, tag
= c
->ctag
++);
789 pa_pstream_send_tagstruct(c
->pstream
, t
);
790 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, internal_callback
, o
);
792 return pa_operation_ref(o
);
795 pa_operation
* pa_context_set_default_sink(pa_context
*c
, const char *name
, void(*cb
)(pa_context
*c
, int success
, void *userdata
), void *userdata
) {
801 o
= pa_operation_new(c
, NULL
);
802 o
->callback
= (pa_operation_callback
) cb
;
803 o
->userdata
= userdata
;
805 t
= pa_tagstruct_new(NULL
, 0);
806 pa_tagstruct_putu32(t
, PA_COMMAND_SET_DEFAULT_SINK
);
807 pa_tagstruct_putu32(t
, tag
= c
->ctag
++);
808 pa_tagstruct_puts(t
, name
);
809 pa_pstream_send_tagstruct(c
->pstream
, t
);
810 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, pa_context_simple_ack_callback
, o
);
812 return pa_operation_ref(o
);
815 pa_operation
* pa_context_set_default_source(pa_context
*c
, const char *name
, void(*cb
)(pa_context
*c
, int success
, void *userdata
), void *userdata
) {
821 o
= pa_operation_new(c
, NULL
);
822 o
->callback
= (pa_operation_callback
) cb
;
823 o
->userdata
= userdata
;
825 t
= pa_tagstruct_new(NULL
, 0);
826 pa_tagstruct_putu32(t
, PA_COMMAND_SET_DEFAULT_SOURCE
);
827 pa_tagstruct_putu32(t
, tag
= c
->ctag
++);
828 pa_tagstruct_puts(t
, name
);
829 pa_pstream_send_tagstruct(c
->pstream
, t
);
830 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, pa_context_simple_ack_callback
, o
);
832 return pa_operation_ref(o
);
835 int pa_context_is_local(pa_context
*c
) {
840 pa_operation
* pa_context_set_name(pa_context
*c
, const char *name
, void(*cb
)(pa_context
*c
, int success
, void *userdata
), void *userdata
) {
844 assert(c
&& name
&& cb
);
846 o
= pa_operation_new(c
, NULL
);
847 o
->callback
= (pa_operation_callback
) cb
;
848 o
->userdata
= userdata
;
850 t
= pa_tagstruct_new(NULL
, 0);
851 pa_tagstruct_putu32(t
, PA_COMMAND_SET_CLIENT_NAME
);
852 pa_tagstruct_putu32(t
, tag
= c
->ctag
++);
853 pa_tagstruct_puts(t
, name
);
854 pa_pstream_send_tagstruct(c
->pstream
, t
);
855 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, pa_context_simple_ack_callback
, o
);
857 return pa_operation_ref(o
);
860 const char* pa_get_library_version(void) {
861 return PACKAGE_VERSION
;
864 const char* pa_context_get_server(pa_context
*c
) {
869 if (*c
->server
== '{') {
870 char *e
= strchr(c
->server
+1, '}');
871 return e
? e
+1 : c
->server
;