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>
31 #include <sys/socket.h>
39 #include "polyplib-internal.h"
40 #include "polyplib-context.h"
41 #include "native-common.h"
42 #include "pdispatch.h"
45 #include "socket-client.h"
46 #include "pstream-util.h"
50 #include "client-conf.h"
51 #include "socket-util.h"
54 #include "client-conf-x11.h"
57 #define AUTOSPAWN_LOCK "autospawn.lock"
59 static const struct pa_pdispatch_command command_table
[PA_COMMAND_MAX
] = {
60 [PA_COMMAND_REQUEST
] = { pa_command_request
},
61 [PA_COMMAND_PLAYBACK_STREAM_KILLED
] = { pa_command_stream_killed
},
62 [PA_COMMAND_RECORD_STREAM_KILLED
] = { pa_command_stream_killed
},
63 [PA_COMMAND_SUBSCRIBE_EVENT
] = { pa_command_subscribe_event
},
66 static void unlock_autospawn_lock_file(struct pa_context
*c
) {
69 if (c
->autospawn_lock_fd
>= 0) {
70 pa_unlock_lockfile(c
->autospawn_lock_fd
);
71 c
->autospawn_lock_fd
= -1;
75 struct pa_context
*pa_context_new(struct pa_mainloop_api
*mainloop
, const char *name
) {
77 assert(mainloop
&& name
);
79 c
= pa_xmalloc(sizeof(struct pa_context
));
81 c
->name
= pa_xstrdup(name
);
82 c
->mainloop
= mainloop
;
86 c
->playback_streams
= pa_dynarray_new();
87 c
->record_streams
= pa_dynarray_new();
88 assert(c
->playback_streams
&& c
->record_streams
);
90 PA_LLIST_HEAD_INIT(struct pa_stream
, c
->streams
);
91 PA_LLIST_HEAD_INIT(struct pa_operation
, c
->operations
);
93 c
->error
= PA_ERROR_OK
;
94 c
->state
= PA_CONTEXT_UNCONNECTED
;
97 c
->state_callback
= NULL
;
98 c
->state_userdata
= NULL
;
100 c
->subscribe_callback
= NULL
;
101 c
->subscribe_userdata
= NULL
;
103 c
->memblock_stat
= pa_memblock_stat_new();
105 c
->server_list
= NULL
;
107 c
->autospawn_lock_fd
= -1;
108 memset(&c
->spawn_api
, 0, sizeof(c
->spawn_api
));
111 pa_check_signal_is_blocked(SIGPIPE
);
113 c
->conf
= pa_client_conf_new();
114 pa_client_conf_load(c
->conf
, NULL
);
116 pa_client_conf_from_x11(c
->conf
, NULL
);
118 pa_client_conf_env(c
->conf
);
123 static void context_free(struct pa_context
*c
) {
126 unlock_autospawn_lock_file(c
);
128 while (c
->operations
)
129 pa_operation_cancel(c
->operations
);
132 pa_stream_set_state(c
->streams
, PA_STREAM_TERMINATED
);
135 pa_socket_client_unref(c
->client
);
137 pa_pdispatch_unref(c
->pdispatch
);
139 pa_pstream_close(c
->pstream
);
140 pa_pstream_unref(c
->pstream
);
143 if (c
->record_streams
)
144 pa_dynarray_free(c
->record_streams
, NULL
, NULL
);
145 if (c
->playback_streams
)
146 pa_dynarray_free(c
->playback_streams
, NULL
, NULL
);
148 pa_memblock_stat_unref(c
->memblock_stat
);
151 pa_client_conf_free(c
->conf
);
153 pa_strlist_free(c
->server_list
);
160 struct pa_context
* pa_context_ref(struct pa_context
*c
) {
161 assert(c
&& c
->ref
>= 1);
166 void pa_context_unref(struct pa_context
*c
) {
167 assert(c
&& c
->ref
>= 1);
169 if ((--(c
->ref
)) == 0)
173 void pa_context_set_state(struct pa_context
*c
, enum pa_context_state st
) {
181 if (st
== PA_CONTEXT_FAILED
|| st
== PA_CONTEXT_TERMINATED
) {
184 s
= c
->streams
? pa_stream_ref(c
->streams
) : NULL
;
186 struct pa_stream
*n
= s
->next
? pa_stream_ref(s
->next
) : NULL
;
187 pa_stream_set_state(s
, st
== PA_CONTEXT_FAILED
? PA_STREAM_FAILED
: PA_STREAM_TERMINATED
);
193 pa_pdispatch_unref(c
->pdispatch
);
197 pa_pstream_close(c
->pstream
);
198 pa_pstream_unref(c
->pstream
);
203 pa_socket_client_unref(c
->client
);
208 if (c
->state_callback
)
209 c
->state_callback(c
, c
->state_userdata
);
214 void pa_context_fail(struct pa_context
*c
, int error
) {
217 pa_context_set_state(c
, PA_CONTEXT_FAILED
);
220 static void pstream_die_callback(struct pa_pstream
*p
, void *userdata
) {
221 struct pa_context
*c
= userdata
;
223 pa_context_fail(c
, PA_ERROR_CONNECTIONTERMINATED
);
226 static void pstream_packet_callback(struct pa_pstream
*p
, struct pa_packet
*packet
, void *userdata
) {
227 struct pa_context
*c
= userdata
;
228 assert(p
&& packet
&& c
);
232 if (pa_pdispatch_run(c
->pdispatch
, packet
, c
) < 0) {
233 pa_log(__FILE__
": invalid packet.\n");
234 pa_context_fail(c
, PA_ERROR_PROTOCOL
);
240 static void pstream_memblock_callback(struct pa_pstream
*p
, uint32_t channel
, uint32_t delta
, const struct pa_memchunk
*chunk
, void *userdata
) {
241 struct pa_context
*c
= userdata
;
243 assert(p
&& chunk
&& c
&& chunk
->memblock
&& chunk
->memblock
->data
);
247 if ((s
= pa_dynarray_get(c
->record_streams
, channel
))) {
248 pa_mcalign_push(s
->mcalign
, chunk
);
251 struct pa_memchunk t
;
253 if (pa_mcalign_pop(s
->mcalign
, &t
) < 0)
256 if (s
->read_callback
) {
257 s
->read_callback(s
, (uint8_t*) t
.memblock
->data
+ t
.index
, t
.length
, s
->read_userdata
);
258 s
->counter
+= chunk
->length
;
261 pa_memblock_unref(t
.memblock
);
268 int pa_context_handle_error(struct pa_context
*c
, uint32_t command
, struct pa_tagstruct
*t
) {
271 if (command
== PA_COMMAND_ERROR
) {
274 if (pa_tagstruct_getu32(t
, &c
->error
) < 0) {
275 pa_context_fail(c
, PA_ERROR_PROTOCOL
);
279 } else if (command
== PA_COMMAND_TIMEOUT
)
280 c
->error
= PA_ERROR_TIMEOUT
;
282 pa_context_fail(c
, PA_ERROR_PROTOCOL
);
289 static void setup_complete_callback(struct pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, struct pa_tagstruct
*t
, void *userdata
) {
290 struct pa_context
*c
= userdata
;
291 assert(pd
&& c
&& (c
->state
== PA_CONTEXT_AUTHORIZING
|| c
->state
== PA_CONTEXT_SETTING_NAME
));
295 if (command
!= PA_COMMAND_REPLY
) {
297 if (pa_context_handle_error(c
, command
, t
) < 0)
298 pa_context_fail(c
, PA_ERROR_PROTOCOL
);
300 pa_context_fail(c
, c
->error
);
305 case PA_CONTEXT_AUTHORIZING
: {
306 struct pa_tagstruct
*t
;
307 t
= pa_tagstruct_new(NULL
, 0);
309 pa_tagstruct_putu32(t
, PA_COMMAND_SET_CLIENT_NAME
);
310 pa_tagstruct_putu32(t
, tag
= c
->ctag
++);
311 pa_tagstruct_puts(t
, c
->name
);
312 pa_pstream_send_tagstruct(c
->pstream
, t
);
313 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, setup_complete_callback
, c
);
315 pa_context_set_state(c
, PA_CONTEXT_SETTING_NAME
);
319 case PA_CONTEXT_SETTING_NAME
:
320 pa_context_set_state(c
, PA_CONTEXT_READY
);
331 static void setup_context(struct pa_context
*c
, struct pa_iochannel
*io
) {
332 struct pa_tagstruct
*t
;
339 c
->pstream
= pa_pstream_new(c
->mainloop
, io
, c
->memblock_stat
);
342 pa_pstream_set_die_callback(c
->pstream
, pstream_die_callback
, c
);
343 pa_pstream_set_recieve_packet_callback(c
->pstream
, pstream_packet_callback
, c
);
344 pa_pstream_set_recieve_memblock_callback(c
->pstream
, pstream_memblock_callback
, c
);
346 assert(!c
->pdispatch
);
347 c
->pdispatch
= pa_pdispatch_new(c
->mainloop
, command_table
, PA_COMMAND_MAX
);
348 assert(c
->pdispatch
);
350 if (!c
->conf
->cookie_valid
) {
351 pa_context_fail(c
, PA_ERROR_AUTHKEY
);
355 t
= pa_tagstruct_new(NULL
, 0);
357 pa_tagstruct_putu32(t
, PA_COMMAND_AUTH
);
358 pa_tagstruct_putu32(t
, tag
= c
->ctag
++);
359 pa_tagstruct_put_arbitrary(t
, c
->conf
->cookie
, sizeof(c
->conf
->cookie
));
360 pa_pstream_send_tagstruct(c
->pstream
, t
);
361 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, setup_complete_callback
, c
);
363 pa_context_set_state(c
, PA_CONTEXT_AUTHORIZING
);
370 static void on_connection(struct pa_socket_client
*client
, struct pa_iochannel
*io
, void *userdata
);
372 static int context_connect_spawn(struct pa_context
*c
) {
375 int fds
[2] = { -1, -1} ;
376 struct pa_iochannel
*io
;
380 if (socketpair(AF_UNIX
, SOCK_STREAM
, 0, fds
) < 0) {
381 pa_log(__FILE__
": socketpair() failed: %s\n", strerror(errno
));
382 pa_context_fail(c
, PA_ERROR_INTERNAL
);
386 pa_fd_set_cloexec(fds
[0], 1);
388 pa_socket_low_delay(fds
[0]);
389 pa_socket_low_delay(fds
[1]);
391 if (c
->spawn_api
.prefork
)
392 c
->spawn_api
.prefork();
394 if ((pid
= fork()) < 0) {
395 pa_log(__FILE__
": fork() failed: %s\n", strerror(errno
));
396 pa_context_fail(c
, PA_ERROR_INTERNAL
);
398 if (c
->spawn_api
.postfork
)
399 c
->spawn_api
.postfork();
406 const char *state
= NULL
;
408 char *argv
[MAX_ARGS
+1];
411 /* Not required, since fds[0] has CLOEXEC enabled anyway */
414 if (c
->spawn_api
.atfork
)
415 c
->spawn_api
.atfork();
421 argv
[n
++] = c
->conf
->daemon_binary
;
422 argv
[n
++] = "--daemonize=yes";
424 snprintf(t
, sizeof(t
), "-Lmodule-native-protocol-fd fd=%i", fds
[1]);
425 argv
[n
++] = strdup(t
);
427 while (n
< MAX_ARGS
) {
430 if (!(a
= pa_split_spaces(c
->conf
->extra_arguments
, &state
)))
438 execv(argv
[0], argv
);
445 r
= waitpid(pid
, &status
, 0);
447 if (c
->spawn_api
.postfork
)
448 c
->spawn_api
.postfork();
451 pa_log(__FILE__
": waitpid() failed: %s\n", strerror(errno
));
452 pa_context_fail(c
, PA_ERROR_INTERNAL
);
454 } else if (!WIFEXITED(status
) || WEXITSTATUS(status
) != 0) {
455 pa_context_fail(c
, PA_ERROR_CONNECTIONREFUSED
);
463 io
= pa_iochannel_new(c
->mainloop
, fds
[0], fds
[0]);
465 setup_context(c
, io
);
466 unlock_autospawn_lock_file(c
);
478 unlock_autospawn_lock_file(c
);
485 static int try_next_connection(struct pa_context
*c
) {
488 assert(c
&& !c
->client
);
495 c
->server_list
= pa_strlist_pop(c
->server_list
, &u
);
499 if (c
->do_autospawn
) {
500 r
= context_connect_spawn(c
);
504 pa_context_fail(c
, PA_ERROR_CONNECTIONREFUSED
);
508 /* pa_log(__FILE__": Trying to connect to %s...\n", u); */
511 c
->server
= pa_xstrdup(u
);
513 if (!(c
->client
= pa_socket_client_new_string(c
->mainloop
, u
, PA_NATIVE_DEFAULT_PORT
)))
516 c
->local
= pa_socket_client_is_local(c
->client
);
517 pa_socket_client_set_callback(c
->client
, on_connection
, c
);
530 static void on_connection(struct pa_socket_client
*client
, struct pa_iochannel
*io
, void *userdata
) {
531 struct pa_context
*c
= userdata
;
532 assert(client
&& c
&& c
->state
== PA_CONTEXT_CONNECTING
);
536 pa_socket_client_unref(client
);
540 /* Try the item in the list */
541 if (errno
== ECONNREFUSED
|| errno
== ETIMEDOUT
|| errno
== EHOSTUNREACH
) {
542 try_next_connection(c
);
546 pa_context_fail(c
, PA_ERROR_CONNECTIONREFUSED
);
550 unlock_autospawn_lock_file(c
);
551 setup_context(c
, io
);
557 int pa_context_connect(struct pa_context
*c
, const char *server
, int spawn
, const struct pa_spawn_api
*api
) {
559 assert(c
&& c
->ref
>= 1 && c
->state
== PA_CONTEXT_UNCONNECTED
);
562 server
= c
->conf
->default_server
;
567 assert(!c
->server_list
);
570 if (!(c
->server_list
= pa_strlist_parse(server
))) {
571 pa_context_fail(c
, PA_ERROR_INVALIDSERVER
);
578 /* Prepend in reverse order */
580 if ((d
= getenv("DISPLAY")))
581 c
->server_list
= pa_strlist_prepend(c
->server_list
, d
);
583 c
->server_list
= pa_strlist_prepend(c
->server_list
, "tcp6:localhost");
584 c
->server_list
= pa_strlist_prepend(c
->server_list
, "localhost");
585 c
->server_list
= pa_strlist_prepend(c
->server_list
, pa_runtime_path(PA_NATIVE_DEFAULT_UNIX_SOCKET
, ufn
, sizeof(ufn
)));
587 /* Wrap the connection attempts in a single transaction for sane autospwan locking */
588 if (spawn
&& c
->conf
->autospawn
) {
591 pa_runtime_path(AUTOSPAWN_LOCK
, lf
, sizeof(lf
));
592 assert(c
->autospawn_lock_fd
<= 0);
593 c
->autospawn_lock_fd
= pa_lock_lockfile(lf
);
602 pa_context_set_state(c
, PA_CONTEXT_CONNECTING
);
603 r
= try_next_connection(c
);
611 void pa_context_disconnect(struct pa_context
*c
) {
613 pa_context_set_state(c
, PA_CONTEXT_TERMINATED
);
616 enum pa_context_state
pa_context_get_state(struct pa_context
*c
) {
617 assert(c
&& c
->ref
>= 1);
621 int pa_context_errno(struct pa_context
*c
) {
622 assert(c
&& c
->ref
>= 1);
626 void pa_context_set_state_callback(struct pa_context
*c
, void (*cb
)(struct pa_context
*c
, void *userdata
), void *userdata
) {
627 assert(c
&& c
->ref
>= 1);
628 c
->state_callback
= cb
;
629 c
->state_userdata
= userdata
;
632 int pa_context_is_pending(struct pa_context
*c
) {
633 assert(c
&& c
->ref
>= 1);
635 /* pa_log("pstream: %i\n", pa_pstream_is_pending(c->pstream)); */
636 /* pa_log("pdispatch: %i\n", pa_pdispatch_is_pending(c->pdispatch)); */
638 return (c
->pstream
&& pa_pstream_is_pending(c
->pstream
)) || (c
->pdispatch
&& pa_pdispatch_is_pending(c
->pdispatch
)) || c
->client
;
641 static void set_dispatch_callbacks(struct pa_operation
*o
);
643 static void pdispatch_drain_callback(struct pa_pdispatch
*pd
, void *userdata
) {
644 set_dispatch_callbacks(userdata
);
647 static void pstream_drain_callback(struct pa_pstream
*s
, void *userdata
) {
648 set_dispatch_callbacks(userdata
);
651 static void set_dispatch_callbacks(struct pa_operation
*o
) {
653 assert(o
&& o
->context
&& o
->context
->ref
>= 1 && o
->ref
>= 1 && o
->context
->state
== PA_CONTEXT_READY
);
655 pa_pstream_set_drain_callback(o
->context
->pstream
, NULL
, NULL
);
656 pa_pdispatch_set_drain_callback(o
->context
->pdispatch
, NULL
, NULL
);
658 if (pa_pdispatch_is_pending(o
->context
->pdispatch
)) {
659 pa_pdispatch_set_drain_callback(o
->context
->pdispatch
, pdispatch_drain_callback
, o
);
663 if (pa_pstream_is_pending(o
->context
->pstream
)) {
664 pa_pstream_set_drain_callback(o
->context
->pstream
, pstream_drain_callback
, o
);
672 void (*cb
)(struct pa_context
*c
, void *userdata
);
673 cb
= (void (*)(struct pa_context
*, void*)) o
->callback
;
674 cb(o
->context
, o
->userdata
);
677 pa_operation_done(o
);
680 pa_operation_unref(o
);
683 struct pa_operation
* pa_context_drain(struct pa_context
*c
, void (*cb
) (struct pa_context
*c
, void *userdata
), void *userdata
) {
684 struct pa_operation
*o
;
685 assert(c
&& c
->ref
>= 1);
687 if (c
->state
!= PA_CONTEXT_READY
)
690 if (!pa_context_is_pending(c
))
693 o
= pa_operation_new(c
, NULL
);
696 o
->userdata
= userdata
;
698 set_dispatch_callbacks(pa_operation_ref(o
));
703 void pa_context_exit_daemon(struct pa_context
*c
) {
704 struct pa_tagstruct
*t
;
705 assert(c
&& c
->ref
>= 1);
707 t
= pa_tagstruct_new(NULL
, 0);
709 pa_tagstruct_putu32(t
, PA_COMMAND_EXIT
);
710 pa_tagstruct_putu32(t
, c
->ctag
++);
711 pa_pstream_send_tagstruct(c
->pstream
, t
);
714 void pa_context_simple_ack_callback(struct pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, struct pa_tagstruct
*t
, void *userdata
) {
715 struct pa_operation
*o
= userdata
;
717 assert(pd
&& o
&& o
->context
&& o
->ref
>= 1);
719 if (command
!= PA_COMMAND_REPLY
) {
720 if (pa_context_handle_error(o
->context
, command
, t
) < 0)
724 } else if (!pa_tagstruct_eof(t
)) {
725 pa_context_fail(o
->context
, PA_ERROR_PROTOCOL
);
730 void (*cb
)(struct pa_context
*c
, int success
, void *userdata
) = o
->callback
;
731 cb(o
->context
, success
, o
->userdata
);
735 pa_operation_done(o
);
736 pa_operation_unref(o
);
739 struct pa_operation
* pa_context_send_simple_command(struct pa_context
*c
, uint32_t command
, void (*internal_callback
)(struct pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, struct pa_tagstruct
*t
, void *userdata
), void (*cb
)(), void *userdata
) {
740 struct pa_tagstruct
*t
;
741 struct pa_operation
*o
;
745 o
= pa_operation_new(c
, NULL
);
747 o
->userdata
= userdata
;
749 t
= pa_tagstruct_new(NULL
, 0);
750 pa_tagstruct_putu32(t
, command
);
751 pa_tagstruct_putu32(t
, tag
= c
->ctag
++);
752 pa_pstream_send_tagstruct(c
->pstream
, t
);
753 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, internal_callback
, o
);
755 return pa_operation_ref(o
);
758 struct pa_operation
* pa_context_set_default_sink(struct pa_context
*c
, const char *name
, void(*cb
)(struct pa_context
*c
, int success
, void *userdata
), void *userdata
) {
759 struct pa_tagstruct
*t
;
760 struct pa_operation
*o
;
764 o
= pa_operation_new(c
, NULL
);
766 o
->userdata
= userdata
;
768 t
= pa_tagstruct_new(NULL
, 0);
769 pa_tagstruct_putu32(t
, PA_COMMAND_SET_DEFAULT_SINK
);
770 pa_tagstruct_putu32(t
, tag
= c
->ctag
++);
771 pa_tagstruct_puts(t
, name
);
772 pa_pstream_send_tagstruct(c
->pstream
, t
);
773 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, pa_context_simple_ack_callback
, o
);
775 return pa_operation_ref(o
);
778 struct pa_operation
* pa_context_set_default_source(struct pa_context
*c
, const char *name
, void(*cb
)(struct pa_context
*c
, int success
, void *userdata
), void *userdata
) {
779 struct pa_tagstruct
*t
;
780 struct pa_operation
*o
;
784 o
= pa_operation_new(c
, NULL
);
786 o
->userdata
= userdata
;
788 t
= pa_tagstruct_new(NULL
, 0);
789 pa_tagstruct_putu32(t
, PA_COMMAND_SET_DEFAULT_SOURCE
);
790 pa_tagstruct_putu32(t
, tag
= c
->ctag
++);
791 pa_tagstruct_puts(t
, name
);
792 pa_pstream_send_tagstruct(c
->pstream
, t
);
793 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, pa_context_simple_ack_callback
, o
);
795 return pa_operation_ref(o
);
798 int pa_context_is_local(struct pa_context
*c
) {
803 struct pa_operation
* pa_context_set_name(struct pa_context
*c
, const char *name
, void(*cb
)(struct pa_context
*c
, int success
, void *userdata
), void *userdata
) {
804 struct pa_tagstruct
*t
;
805 struct pa_operation
*o
;
807 assert(c
&& name
&& cb
);
809 o
= pa_operation_new(c
, NULL
);
811 o
->userdata
= userdata
;
813 t
= pa_tagstruct_new(NULL
, 0);
814 pa_tagstruct_putu32(t
, PA_COMMAND_SET_CLIENT_NAME
);
815 pa_tagstruct_putu32(t
, tag
= c
->ctag
++);
816 pa_tagstruct_puts(t
, name
);
817 pa_pstream_send_tagstruct(c
->pstream
, t
);
818 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, pa_context_simple_ack_callback
, o
);
820 return pa_operation_ref(o
);
823 const char* pa_get_library_version(void) {
824 return PACKAGE_VERSION
;
827 const char* pa_context_get_server(struct pa_context
*c
) {
832 if (*c
->server
== '{') {
833 char *e
= strchr(c
->server
+1, '}');
834 return e
? e
+1 : c
->server
;