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 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 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>
38 #include "polyplib-internal.h"
39 #include "polyplib-context.h"
40 #include "native-common.h"
41 #include "pdispatch.h"
44 #include "socket-client.h"
45 #include "pstream-util.h"
50 #include "client-conf.h"
51 #include "socket-util.h"
53 #define DEFAULT_SERVER "/tmp/polypaudio/native"
54 #define AUTOSPAWN_LOCK "/tmp/polypaudio/autospawn.lock"
56 static const struct pa_pdispatch_command command_table
[PA_COMMAND_MAX
] = {
57 [PA_COMMAND_REQUEST
] = { pa_command_request
},
58 [PA_COMMAND_PLAYBACK_STREAM_KILLED
] = { pa_command_stream_killed
},
59 [PA_COMMAND_RECORD_STREAM_KILLED
] = { pa_command_stream_killed
},
60 [PA_COMMAND_SUBSCRIBE_EVENT
] = { pa_command_subscribe_event
},
63 struct pa_context
*pa_context_new(struct pa_mainloop_api
*mainloop
, const char *name
) {
65 assert(mainloop
&& name
);
67 c
= pa_xmalloc(sizeof(struct pa_context
));
69 c
->name
= pa_xstrdup(name
);
70 c
->mainloop
= mainloop
;
74 c
->playback_streams
= pa_dynarray_new();
75 c
->record_streams
= pa_dynarray_new();
76 assert(c
->playback_streams
&& c
->record_streams
);
78 PA_LLIST_HEAD_INIT(struct pa_stream
, c
->streams
);
79 PA_LLIST_HEAD_INIT(struct pa_operation
, c
->operations
);
81 c
->error
= PA_ERROR_OK
;
82 c
->state
= PA_CONTEXT_UNCONNECTED
;
85 c
->state_callback
= NULL
;
86 c
->state_userdata
= NULL
;
88 c
->subscribe_callback
= NULL
;
89 c
->subscribe_userdata
= NULL
;
91 c
->memblock_stat
= pa_memblock_stat_new();
94 pa_check_signal_is_blocked(SIGPIPE
);
96 c
->conf
= pa_client_conf_new();
97 pa_client_conf_load(c
->conf
, NULL
);
98 pa_client_conf_env(c
->conf
);
103 static void context_free(struct pa_context
*c
) {
106 while (c
->operations
)
107 pa_operation_cancel(c
->operations
);
110 pa_stream_set_state(c
->streams
, PA_STREAM_TERMINATED
);
113 pa_socket_client_unref(c
->client
);
115 pa_pdispatch_unref(c
->pdispatch
);
117 pa_pstream_close(c
->pstream
);
118 pa_pstream_unref(c
->pstream
);
121 if (c
->record_streams
)
122 pa_dynarray_free(c
->record_streams
, NULL
, NULL
);
123 if (c
->playback_streams
)
124 pa_dynarray_free(c
->playback_streams
, NULL
, NULL
);
126 pa_memblock_stat_unref(c
->memblock_stat
);
129 pa_client_conf_free(c
->conf
);
135 struct pa_context
* pa_context_ref(struct pa_context
*c
) {
136 assert(c
&& c
->ref
>= 1);
141 void pa_context_unref(struct pa_context
*c
) {
142 assert(c
&& c
->ref
>= 1);
144 if ((--(c
->ref
)) == 0)
148 void pa_context_set_state(struct pa_context
*c
, enum pa_context_state st
) {
156 if (st
== PA_CONTEXT_FAILED
|| st
== PA_CONTEXT_TERMINATED
) {
159 s
= c
->streams
? pa_stream_ref(c
->streams
) : NULL
;
161 struct pa_stream
*n
= s
->next
? pa_stream_ref(s
->next
) : NULL
;
162 pa_stream_set_state(s
, st
== PA_CONTEXT_FAILED
? PA_STREAM_FAILED
: PA_STREAM_TERMINATED
);
168 pa_pdispatch_unref(c
->pdispatch
);
172 pa_pstream_close(c
->pstream
);
173 pa_pstream_unref(c
->pstream
);
178 pa_socket_client_unref(c
->client
);
183 if (c
->state_callback
)
184 c
->state_callback(c
, c
->state_userdata
);
189 void pa_context_fail(struct pa_context
*c
, int error
) {
192 pa_context_set_state(c
, PA_CONTEXT_FAILED
);
195 static void pstream_die_callback(struct pa_pstream
*p
, void *userdata
) {
196 struct pa_context
*c
= userdata
;
198 pa_context_fail(c
, PA_ERROR_CONNECTIONTERMINATED
);
201 static void pstream_packet_callback(struct pa_pstream
*p
, struct pa_packet
*packet
, void *userdata
) {
202 struct pa_context
*c
= userdata
;
203 assert(p
&& packet
&& c
);
207 if (pa_pdispatch_run(c
->pdispatch
, packet
, c
) < 0) {
208 pa_log(__FILE__
": invalid packet.\n");
209 pa_context_fail(c
, PA_ERROR_PROTOCOL
);
215 static void pstream_memblock_callback(struct pa_pstream
*p
, uint32_t channel
, uint32_t delta
, const struct pa_memchunk
*chunk
, void *userdata
) {
216 struct pa_context
*c
= userdata
;
218 assert(p
&& chunk
&& c
&& chunk
->memblock
&& chunk
->memblock
->data
);
222 if ((s
= pa_dynarray_get(c
->record_streams
, channel
))) {
223 if (s
->read_callback
) {
224 s
->read_callback(s
, (uint8_t*) chunk
->memblock
->data
+ chunk
->index
, chunk
->length
, s
->read_userdata
);
225 s
->counter
+= chunk
->length
;
232 int pa_context_handle_error(struct pa_context
*c
, uint32_t command
, struct pa_tagstruct
*t
) {
235 if (command
== PA_COMMAND_ERROR
) {
236 if (pa_tagstruct_getu32(t
, &c
->error
) < 0) {
237 pa_context_fail(c
, PA_ERROR_PROTOCOL
);
241 } else if (command
== PA_COMMAND_TIMEOUT
)
242 c
->error
= PA_ERROR_TIMEOUT
;
244 pa_context_fail(c
, PA_ERROR_PROTOCOL
);
251 static void setup_complete_callback(struct pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, struct pa_tagstruct
*t
, void *userdata
) {
252 struct pa_context
*c
= userdata
;
253 assert(pd
&& c
&& (c
->state
== PA_CONTEXT_AUTHORIZING
|| c
->state
== PA_CONTEXT_SETTING_NAME
));
257 if (command
!= PA_COMMAND_REPLY
) {
259 if (pa_context_handle_error(c
, command
, t
) < 0)
260 pa_context_fail(c
, PA_ERROR_PROTOCOL
);
262 pa_context_fail(c
, c
->error
);
267 case PA_CONTEXT_AUTHORIZING
: {
268 struct pa_tagstruct
*t
;
269 t
= pa_tagstruct_new(NULL
, 0);
271 pa_tagstruct_putu32(t
, PA_COMMAND_SET_CLIENT_NAME
);
272 pa_tagstruct_putu32(t
, tag
= c
->ctag
++);
273 pa_tagstruct_puts(t
, c
->name
);
274 pa_pstream_send_tagstruct(c
->pstream
, t
);
275 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, setup_complete_callback
, c
);
277 pa_context_set_state(c
, PA_CONTEXT_SETTING_NAME
);
281 case PA_CONTEXT_SETTING_NAME
:
282 pa_context_set_state(c
, PA_CONTEXT_READY
);
293 static void setup_context(struct pa_context
*c
, struct pa_iochannel
*io
) {
294 struct pa_tagstruct
*t
;
301 c
->pstream
= pa_pstream_new(c
->mainloop
, io
, c
->memblock_stat
);
304 pa_pstream_set_die_callback(c
->pstream
, pstream_die_callback
, c
);
305 pa_pstream_set_recieve_packet_callback(c
->pstream
, pstream_packet_callback
, c
);
306 pa_pstream_set_recieve_memblock_callback(c
->pstream
, pstream_memblock_callback
, c
);
308 assert(!c
->pdispatch
);
309 c
->pdispatch
= pa_pdispatch_new(c
->mainloop
, command_table
, PA_COMMAND_MAX
);
310 assert(c
->pdispatch
);
312 if (pa_authkey_load_from_home(PA_NATIVE_COOKIE_FILE
, c
->auth_cookie
, sizeof(c
->auth_cookie
)) < 0) {
313 pa_context_fail(c
, PA_ERROR_AUTHKEY
);
317 t
= pa_tagstruct_new(NULL
, 0);
319 pa_tagstruct_putu32(t
, PA_COMMAND_AUTH
);
320 pa_tagstruct_putu32(t
, tag
= c
->ctag
++);
321 pa_tagstruct_put_arbitrary(t
, c
->auth_cookie
, sizeof(c
->auth_cookie
));
322 pa_pstream_send_tagstruct(c
->pstream
, t
);
323 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, setup_complete_callback
, c
);
325 pa_context_set_state(c
, PA_CONTEXT_AUTHORIZING
);
332 static void on_connection(struct pa_socket_client
*client
, struct pa_iochannel
*io
, void *userdata
) {
333 struct pa_context
*c
= userdata
;
334 assert(client
&& c
&& c
->state
== PA_CONTEXT_CONNECTING
);
338 pa_socket_client_unref(client
);
342 pa_context_fail(c
, PA_ERROR_CONNECTIONREFUSED
);
346 setup_context(c
, io
);
352 static int default_server_is_running(void) {
355 if (DEFAULT_SERVER
[0] != '/')
358 if (stat(DEFAULT_SERVER
, &st
) < 0)
363 static int context_connect_spawn(struct pa_context
*c
, const struct pa_spawn_api
*api
) {
366 int fds
[2] = { -1, -1} ;
367 struct pa_iochannel
*io
;
371 if (socketpair(AF_UNIX
, SOCK_STREAM
, 0, fds
) < 0) {
372 pa_log(__FILE__
": socketpair() failed: %s\n", strerror(errno
));
373 pa_context_fail(c
, PA_ERROR_INTERNAL
);
377 if (api
&& api
->prefork
)
380 if ((pid
= fork()) < 0) {
381 pa_log(__FILE__
": fork() failed: %s\n", strerror(errno
));
382 pa_context_fail(c
, PA_ERROR_INTERNAL
);
384 if (api
&& api
->postfork
)
392 const char *state
= NULL
;
394 char *argv
[MAX_ARGS
+1];
399 if (api
&& api
->atfork
)
406 argv
[n
++] = c
->conf
->daemon_binary
;
407 argv
[n
++] = "--daemonize=yes";
409 snprintf(t
, sizeof(t
), "-Lmodule-native-protocol-fd fd=%i", fds
[1]);
410 argv
[n
++] = strdup(t
);
412 while (n
< MAX_ARGS
) {
415 if (!(a
= pa_split_spaces(c
->conf
->extra_arguments
, &state
)))
423 execv(argv
[0], argv
);
429 r
= waitpid(pid
, &status
, 0);
431 if (api
&& api
->postfork
)
435 pa_log(__FILE__
": waitpid() failed: %s\n", strerror(errno
));
436 pa_context_fail(c
, PA_ERROR_INTERNAL
);
438 } else if (!WIFEXITED(status
) || WEXITSTATUS(status
) != 0) {
439 pa_context_fail(c
, PA_ERROR_CONNECTIONREFUSED
);
447 io
= pa_iochannel_new(c
->mainloop
, fds
[0], fds
[0]);
448 setup_context(c
, io
);
465 int pa_context_connect(struct pa_context
*c
, const char *server
, int spawn
, const struct pa_spawn_api
*api
) {
467 assert(c
&& c
->ref
>= 1 && c
->state
== PA_CONTEXT_UNCONNECTED
);
470 server
= c
->conf
->default_server
;
472 if (!server
&& spawn
&& c
->conf
->autospawn
) {
473 int lock_fd
= pa_lock_lockfile(AUTOSPAWN_LOCK
);
475 if (!default_server_is_running()) {
476 int r
= context_connect_spawn(c
, api
);
479 pa_unlock_lockfile(lock_fd
);
484 pa_unlock_lockfile(lock_fd
);
488 server
= DEFAULT_SERVER
;
494 if (*server
== '/') {
495 if (!(c
->client
= pa_socket_client_new_unix(c
->mainloop
, server
))) {
496 pa_context_fail(c
, PA_ERROR_CONNECTIONREFUSED
);
505 if (!(sa
= pa_resolve_server(server
, &sa_len
, PA_NATIVE_DEFAULT_PORT
))) {
506 pa_context_fail(c
, PA_ERROR_INVALIDSERVER
);
510 c
->client
= pa_socket_client_new_sockaddr(c
->mainloop
, sa
, sa_len
);
514 pa_context_fail(c
, PA_ERROR_CONNECTIONREFUSED
);
521 pa_socket_client_set_callback(c
->client
, on_connection
, c
);
522 pa_context_set_state(c
, PA_CONTEXT_CONNECTING
);
532 void pa_context_disconnect(struct pa_context
*c
) {
534 pa_context_set_state(c
, PA_CONTEXT_TERMINATED
);
537 enum pa_context_state
pa_context_get_state(struct pa_context
*c
) {
538 assert(c
&& c
->ref
>= 1);
542 int pa_context_errno(struct pa_context
*c
) {
543 assert(c
&& c
->ref
>= 1);
547 void pa_context_set_state_callback(struct pa_context
*c
, void (*cb
)(struct pa_context
*c
, void *userdata
), void *userdata
) {
548 assert(c
&& c
->ref
>= 1);
549 c
->state_callback
= cb
;
550 c
->state_userdata
= userdata
;
553 int pa_context_is_pending(struct pa_context
*c
) {
554 assert(c
&& c
->ref
>= 1);
556 /* pa_log("pstream: %i\n", pa_pstream_is_pending(c->pstream)); */
557 /* pa_log("pdispatch: %i\n", pa_pdispatch_is_pending(c->pdispatch)); */
559 return (c
->pstream
&& pa_pstream_is_pending(c
->pstream
)) || (c
->pdispatch
&& pa_pdispatch_is_pending(c
->pdispatch
)) || c
->client
;
562 static void set_dispatch_callbacks(struct pa_operation
*o
);
564 static void pdispatch_drain_callback(struct pa_pdispatch
*pd
, void *userdata
) {
565 set_dispatch_callbacks(userdata
);
568 static void pstream_drain_callback(struct pa_pstream
*s
, void *userdata
) {
569 set_dispatch_callbacks(userdata
);
572 static void set_dispatch_callbacks(struct pa_operation
*o
) {
574 assert(o
&& o
->context
&& o
->context
->ref
>= 1 && o
->ref
>= 1 && o
->context
->state
== PA_CONTEXT_READY
);
576 pa_pstream_set_drain_callback(o
->context
->pstream
, NULL
, NULL
);
577 pa_pdispatch_set_drain_callback(o
->context
->pdispatch
, NULL
, NULL
);
579 if (pa_pdispatch_is_pending(o
->context
->pdispatch
)) {
580 pa_pdispatch_set_drain_callback(o
->context
->pdispatch
, pdispatch_drain_callback
, o
);
584 if (pa_pstream_is_pending(o
->context
->pstream
)) {
585 pa_pstream_set_drain_callback(o
->context
->pstream
, pstream_drain_callback
, o
);
593 void (*cb
)(struct pa_context
*c
, void *userdata
);
594 cb
= (void (*)(struct pa_context
*, void*)) o
->callback
;
595 cb(o
->context
, o
->userdata
);
598 pa_operation_done(o
);
601 pa_operation_unref(o
);
604 struct pa_operation
* pa_context_drain(struct pa_context
*c
, void (*cb
) (struct pa_context
*c
, void *userdata
), void *userdata
) {
605 struct pa_operation
*o
;
606 assert(c
&& c
->ref
>= 1);
608 if (c
->state
!= PA_CONTEXT_READY
)
611 if (!pa_context_is_pending(c
))
614 o
= pa_operation_new(c
, NULL
);
617 o
->userdata
= userdata
;
619 set_dispatch_callbacks(pa_operation_ref(o
));
624 void pa_context_exit_daemon(struct pa_context
*c
) {
625 struct pa_tagstruct
*t
;
626 assert(c
&& c
->ref
>= 1);
628 t
= pa_tagstruct_new(NULL
, 0);
630 pa_tagstruct_putu32(t
, PA_COMMAND_EXIT
);
631 pa_tagstruct_putu32(t
, c
->ctag
++);
632 pa_pstream_send_tagstruct(c
->pstream
, t
);
635 void pa_context_simple_ack_callback(struct pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, struct pa_tagstruct
*t
, void *userdata
) {
636 struct pa_operation
*o
= userdata
;
638 assert(pd
&& o
&& o
->context
&& o
->ref
>= 1);
640 if (command
!= PA_COMMAND_REPLY
) {
641 if (pa_context_handle_error(o
->context
, command
, t
) < 0)
645 } else if (!pa_tagstruct_eof(t
)) {
646 pa_context_fail(o
->context
, PA_ERROR_PROTOCOL
);
651 void (*cb
)(struct pa_context
*c
, int success
, void *userdata
) = o
->callback
;
652 cb(o
->context
, success
, o
->userdata
);
656 pa_operation_done(o
);
657 pa_operation_unref(o
);
660 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
) {
661 struct pa_tagstruct
*t
;
662 struct pa_operation
*o
;
666 o
= pa_operation_new(c
, NULL
);
668 o
->userdata
= userdata
;
670 t
= pa_tagstruct_new(NULL
, 0);
671 pa_tagstruct_putu32(t
, command
);
672 pa_tagstruct_putu32(t
, tag
= c
->ctag
++);
673 pa_pstream_send_tagstruct(c
->pstream
, t
);
674 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, internal_callback
, o
);
676 return pa_operation_ref(o
);
679 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
) {
680 struct pa_tagstruct
*t
;
681 struct pa_operation
*o
;
685 o
= pa_operation_new(c
, NULL
);
687 o
->userdata
= userdata
;
689 t
= pa_tagstruct_new(NULL
, 0);
690 pa_tagstruct_putu32(t
, PA_COMMAND_SET_DEFAULT_SINK
);
691 pa_tagstruct_putu32(t
, tag
= c
->ctag
++);
692 pa_tagstruct_puts(t
, name
);
693 pa_pstream_send_tagstruct(c
->pstream
, t
);
694 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, pa_context_simple_ack_callback
, o
);
696 return pa_operation_ref(o
);
699 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
) {
700 struct pa_tagstruct
*t
;
701 struct pa_operation
*o
;
705 o
= pa_operation_new(c
, NULL
);
707 o
->userdata
= userdata
;
709 t
= pa_tagstruct_new(NULL
, 0);
710 pa_tagstruct_putu32(t
, PA_COMMAND_SET_DEFAULT_SOURCE
);
711 pa_tagstruct_putu32(t
, tag
= c
->ctag
++);
712 pa_tagstruct_puts(t
, name
);
713 pa_pstream_send_tagstruct(c
->pstream
, t
);
714 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, pa_context_simple_ack_callback
, o
);
716 return pa_operation_ref(o
);
719 int pa_context_is_local(struct pa_context
*c
) {
724 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
) {
725 struct pa_tagstruct
*t
;
726 struct pa_operation
*o
;
728 assert(c
&& name
&& cb
);
730 o
= pa_operation_new(c
, NULL
);
732 o
->userdata
= userdata
;
734 t
= pa_tagstruct_new(NULL
, 0);
735 pa_tagstruct_putu32(t
, PA_COMMAND_SET_CLIENT_NAME
);
736 pa_tagstruct_putu32(t
, tag
= c
->ctag
++);
737 pa_tagstruct_puts(t
, name
);
738 pa_pstream_send_tagstruct(c
->pstream
, t
);
739 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, pa_context_simple_ack_callback
, o
);
741 return pa_operation_ref(o
);
744 const char* pa_get_library_version(void) {
745 return PACKAGE_VERSION
;