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>
35 #include "native-common.h"
36 #include "pdispatch.h"
39 #include "socket-client.h"
40 #include "pstream-util.h"
45 #define DEFAULT_MAXLENGTH 204800
46 #define DEFAULT_TLENGTH 10240
47 #define DEFAULT_PREBUF 4096
48 #define DEFAULT_MINREQ 1024
49 #define DEFAULT_FRAGSIZE 1024
51 #define DEFAULT_TIMEOUT (5*60)
52 #define DEFAULT_SERVER "/tmp/polypaudio/native"
53 #define DEFAULT_PORT "4713"
57 struct pa_mainloop_api
* mainloop
;
58 struct pa_socket_client
*client
;
59 struct pa_pstream
*pstream
;
60 struct pa_pdispatch
*pdispatch
;
61 struct pa_dynarray
*record_streams
, *playback_streams
;
62 struct pa_stream
*first_stream
;
74 void (*connect_complete_callback
)(struct pa_context
*c
, int success
, void *userdata
);
75 void *connect_complete_userdata
;
77 void (*drain_complete_callback
)(struct pa_context
*c
, void *userdata
);
78 void *drain_complete_userdata
;
80 void (*die_callback
)(struct pa_context
*c
, void *userdata
);
83 void (*stat_callback
)(struct pa_context
*c
, uint32_t count
, uint32_t total
, void *userdata
);
86 void (*play_sample_callback
)(struct pa_context
*c
, int success
, void *userdata
);
87 void *play_sample_userdata
;
89 void (*remove_sample_callback
)(struct pa_context
*c
, int success
, void *userdata
);
90 void *remove_sample_userdata
;
92 uint8_t auth_cookie
[PA_NATIVE_COOKIE_LENGTH
];
96 struct pa_context
*context
;
97 struct pa_stream
*next
, *previous
;
100 struct pa_buffer_attr buffer_attr
;
101 struct pa_sample_spec sample_spec
;
104 uint32_t device_index
;
105 enum pa_stream_direction direction
;
107 enum { STREAM_CREATING
, STREAM_READY
, STREAM_DEAD
} state
;
108 uint32_t requested_bytes
;
110 void (*read_callback
)(struct pa_stream
*p
, const void*data
, size_t length
, void *userdata
);
113 void (*write_callback
)(struct pa_stream
*p
, size_t length
, void *userdata
);
114 void *write_userdata
;
116 void (*create_complete_callback
)(struct pa_stream
*s
, int success
, void *userdata
);
117 void *create_complete_userdata
;
119 void (*drain_complete_callback
)(struct pa_stream
*s
, void *userdata
);
120 void *drain_complete_userdata
;
122 void (*die_callback
)(struct pa_stream
*c
, void *userdata
);
125 void (*get_latency_callback
)(struct pa_stream
*c
, uint32_t latency
, void *userdata
);
126 void *get_latency_userdata
;
128 void (*finish_sample_callback
)(struct pa_stream
*c
, int success
, void *userdata
);
129 void *finish_sample_userdata
;
132 static void command_request(struct pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, struct pa_tagstruct
*t
, void *userdata
);
133 static void command_playback_stream_killed(struct pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, struct pa_tagstruct
*t
, void *userdata
);
135 static const struct pa_pdispatch_command command_table
[PA_COMMAND_MAX
] = {
136 [PA_COMMAND_ERROR
] = { NULL
},
137 [PA_COMMAND_REPLY
] = { NULL
},
138 [PA_COMMAND_CREATE_PLAYBACK_STREAM
] = { NULL
},
139 [PA_COMMAND_DELETE_PLAYBACK_STREAM
] = { NULL
},
140 [PA_COMMAND_CREATE_RECORD_STREAM
] = { NULL
},
141 [PA_COMMAND_DELETE_RECORD_STREAM
] = { NULL
},
142 [PA_COMMAND_EXIT
] = { NULL
},
143 [PA_COMMAND_REQUEST
] = { command_request
},
144 [PA_COMMAND_PLAYBACK_STREAM_KILLED
] = { command_playback_stream_killed
},
145 [PA_COMMAND_RECORD_STREAM_KILLED
] = { command_playback_stream_killed
},
148 struct pa_context
*pa_context_new(struct pa_mainloop_api
*mainloop
, const char *name
) {
149 struct pa_context
*c
;
150 assert(mainloop
&& name
);
152 c
= pa_xmalloc(sizeof(struct pa_context
));
153 c
->name
= pa_xstrdup(name
);
154 c
->mainloop
= mainloop
;
158 c
->playback_streams
= pa_dynarray_new();
159 assert(c
->playback_streams
);
160 c
->record_streams
= pa_dynarray_new();
161 assert(c
->record_streams
);
162 c
->first_stream
= NULL
;
163 c
->error
= PA_ERROR_OK
;
164 c
->state
= CONTEXT_UNCONNECTED
;
167 c
->connect_complete_callback
= NULL
;
168 c
->connect_complete_userdata
= NULL
;
170 c
->drain_complete_callback
= NULL
;
171 c
->drain_complete_userdata
= NULL
;
173 c
->die_callback
= NULL
;
174 c
->die_userdata
= NULL
;
176 c
->stat_callback
= NULL
;
177 c
->stat_userdata
= NULL
;
179 c
->play_sample_callback
= NULL
;
180 c
->play_sample_userdata
= NULL
;
182 c
->remove_sample_callback
= NULL
;
183 c
->remove_sample_userdata
= NULL
;
185 pa_check_for_sigpipe();
189 void pa_context_free(struct pa_context
*c
) {
192 while (c
->first_stream
)
193 pa_stream_free(c
->first_stream
);
196 pa_socket_client_free(c
->client
);
198 pa_pdispatch_free(c
->pdispatch
);
200 pa_pstream_free(c
->pstream
);
201 if (c
->record_streams
)
202 pa_dynarray_free(c
->record_streams
, NULL
, NULL
);
203 if (c
->playback_streams
)
204 pa_dynarray_free(c
->playback_streams
, NULL
, NULL
);
210 static void stream_dead(struct pa_stream
*s
) {
213 if (s
->state
== STREAM_DEAD
)
216 if (s
->state
== STREAM_READY
) {
217 s
->state
= STREAM_DEAD
;
219 s
->die_callback(s
, s
->die_userdata
);
221 s
->state
= STREAM_DEAD
;
224 static void context_dead(struct pa_context
*c
) {
228 if (c
->state
== CONTEXT_DEAD
)
232 pa_pdispatch_free(c
->pdispatch
);
236 pa_pstream_free(c
->pstream
);
240 pa_socket_client_free(c
->client
);
243 for (s
= c
->first_stream
; s
; s
= s
->next
)
246 if (c
->state
== CONTEXT_READY
) {
247 c
->state
= CONTEXT_DEAD
;
249 c
->die_callback(c
, c
->die_userdata
);
251 c
->state
= CONTEXT_DEAD
;
254 static void pstream_die_callback(struct pa_pstream
*p
, void *userdata
) {
255 struct pa_context
*c
= userdata
;
257 c
->error
= PA_ERROR_CONNECTIONTERMINATED
;
261 static void pstream_packet_callback(struct pa_pstream
*p
, struct pa_packet
*packet
, void *userdata
) {
262 struct pa_context
*c
= userdata
;
263 assert(p
&& packet
&& c
);
265 if (pa_pdispatch_run(c
->pdispatch
, packet
, c
) < 0) {
266 fprintf(stderr
, "polyp.c: invalid packet.\n");
267 c
->error
= PA_ERROR_PROTOCOL
;
272 static void pstream_memblock_callback(struct pa_pstream
*p
, uint32_t channel
, int32_t delta
, const struct pa_memchunk
*chunk
, void *userdata
) {
273 struct pa_context
*c
= userdata
;
275 assert(p
&& chunk
&& c
&& chunk
->memblock
&& chunk
->memblock
->data
);
277 if (!(s
= pa_dynarray_get(c
->record_streams
, channel
)))
280 if (s
->read_callback
)
281 s
->read_callback(s
, chunk
->memblock
->data
+ chunk
->index
, chunk
->length
, s
->read_userdata
);
284 static int handle_error(struct pa_context
*c
, uint32_t command
, struct pa_tagstruct
*t
) {
287 if (command
== PA_COMMAND_ERROR
) {
288 if (pa_tagstruct_getu32(t
, &c
->error
) < 0) {
289 c
->error
= PA_ERROR_PROTOCOL
;
296 c
->error
= (command
== PA_COMMAND_TIMEOUT
) ? PA_ERROR_TIMEOUT
: PA_ERROR_INTERNAL
;
300 static void setup_complete_callback(struct pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, struct pa_tagstruct
*t
, void *userdata
) {
301 struct pa_context
*c
= userdata
;
302 assert(pd
&& c
&& (c
->state
== CONTEXT_AUTHORIZING
|| c
->state
== CONTEXT_SETTING_NAME
));
304 if (command
!= PA_COMMAND_REPLY
) {
305 handle_error(c
, command
, t
);
308 if (c
->connect_complete_callback
)
309 c
->connect_complete_callback(c
, 0, c
->connect_complete_userdata
);
314 if (c
->state
== CONTEXT_AUTHORIZING
) {
315 struct pa_tagstruct
*t
;
316 c
->state
= CONTEXT_SETTING_NAME
;
317 t
= pa_tagstruct_new(NULL
, 0);
319 pa_tagstruct_putu32(t
, PA_COMMAND_SET_NAME
);
320 pa_tagstruct_putu32(t
, tag
= c
->ctag
++);
321 pa_tagstruct_puts(t
, c
->name
);
322 pa_pstream_send_tagstruct(c
->pstream
, t
);
323 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, setup_complete_callback
, c
);
325 assert(c
->state
== CONTEXT_SETTING_NAME
);
327 c
->state
= CONTEXT_READY
;
329 if (c
->connect_complete_callback
)
330 c
->connect_complete_callback(c
, 1, c
->connect_complete_userdata
);
336 static void on_connection(struct pa_socket_client
*client
, struct pa_iochannel
*io
, void *userdata
) {
337 struct pa_context
*c
= userdata
;
338 struct pa_tagstruct
*t
;
340 assert(client
&& c
&& c
->state
== CONTEXT_CONNECTING
);
342 pa_socket_client_free(client
);
346 c
->error
= PA_ERROR_CONNECTIONREFUSED
;
349 if (c
->connect_complete_callback
)
350 c
->connect_complete_callback(c
, 0, c
->connect_complete_userdata
);
355 c
->pstream
= pa_pstream_new(c
->mainloop
, io
);
357 pa_pstream_set_die_callback(c
->pstream
, pstream_die_callback
, c
);
358 pa_pstream_set_recieve_packet_callback(c
->pstream
, pstream_packet_callback
, c
);
359 pa_pstream_set_recieve_memblock_callback(c
->pstream
, pstream_memblock_callback
, c
);
361 c
->pdispatch
= pa_pdispatch_new(c
->mainloop
, command_table
, PA_COMMAND_MAX
);
362 assert(c
->pdispatch
);
364 t
= pa_tagstruct_new(NULL
, 0);
366 pa_tagstruct_putu32(t
, PA_COMMAND_AUTH
);
367 pa_tagstruct_putu32(t
, tag
= c
->ctag
++);
368 pa_tagstruct_put_arbitrary(t
, c
->auth_cookie
, sizeof(c
->auth_cookie
));
369 pa_pstream_send_tagstruct(c
->pstream
, t
);
370 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, setup_complete_callback
, c
);
371 c
->state
= CONTEXT_AUTHORIZING
;
374 static struct sockaddr
*resolve_server(const char *server
, size_t *len
) {
376 struct addrinfo hints
, *result
= NULL
;
378 assert(server
&& len
);
380 if ((port
= strrchr(server
, ':')))
385 memset(&hints
, 0, sizeof(hints
));
386 hints
.ai_family
= PF_UNSPEC
;
387 hints
.ai_socktype
= SOCK_STREAM
;
388 hints
.ai_protocol
= 0;
390 if (getaddrinfo(server
, port
, &hints
, &result
) != 0)
394 sa
= pa_xmalloc(*len
= result
->ai_addrlen
);
395 memcpy(sa
, result
->ai_addr
, *len
);
397 freeaddrinfo(result
);
402 int pa_context_connect(struct pa_context
*c
, const char *server
, void (*complete
) (struct pa_context
*c
, int success
, void *userdata
), void *userdata
) {
403 assert(c
&& c
->state
== CONTEXT_UNCONNECTED
);
405 if (pa_authkey_load_from_home(PA_NATIVE_COOKIE_FILE
, c
->auth_cookie
, sizeof(c
->auth_cookie
)) < 0) {
406 c
->error
= PA_ERROR_AUTHKEY
;
411 if (!(server
= getenv("POLYP_SERVER")))
412 server
= DEFAULT_SERVER
;
416 if (*server
== '/') {
417 if (!(c
->client
= pa_socket_client_new_unix(c
->mainloop
, server
))) {
418 c
->error
= PA_ERROR_CONNECTIONREFUSED
;
425 if (!(sa
= resolve_server(server
, &sa_len
))) {
426 c
->error
= PA_ERROR_INVALIDSERVER
;
430 c
->client
= pa_socket_client_new_sockaddr(c
->mainloop
, sa
, sa_len
);
434 c
->error
= PA_ERROR_CONNECTIONREFUSED
;
439 c
->connect_complete_callback
= complete
;
440 c
->connect_complete_userdata
= userdata
;
442 pa_socket_client_set_callback(c
->client
, on_connection
, c
);
443 c
->state
= CONTEXT_CONNECTING
;
448 int pa_context_is_dead(struct pa_context
*c
) {
450 return c
->state
== CONTEXT_DEAD
;
453 int pa_context_is_ready(struct pa_context
*c
) {
455 return c
->state
== CONTEXT_READY
;
458 int pa_context_errno(struct pa_context
*c
) {
463 void pa_context_set_die_callback(struct pa_context
*c
, void (*cb
)(struct pa_context
*c
, void *userdata
), void *userdata
) {
465 c
->die_callback
= cb
;
466 c
->die_userdata
= userdata
;
469 static void command_playback_stream_killed(struct pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, struct pa_tagstruct
*t
, void *userdata
) {
470 struct pa_context
*c
= userdata
;
473 assert(pd
&& (command
== PA_COMMAND_PLAYBACK_STREAM_KILLED
|| command
== PA_COMMAND_RECORD_STREAM_KILLED
) && t
&& c
);
475 if (pa_tagstruct_getu32(t
, &channel
) < 0 ||
476 !pa_tagstruct_eof(t
)) {
477 c
->error
= PA_ERROR_PROTOCOL
;
482 if (!(s
= pa_dynarray_get(command
== PA_COMMAND_PLAYBACK_STREAM_KILLED
? c
->playback_streams
: c
->record_streams
, channel
)))
485 c
->error
= PA_ERROR_KILLED
;
489 static void command_request(struct pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, struct pa_tagstruct
*t
, void *userdata
) {
491 struct pa_context
*c
= userdata
;
492 uint32_t bytes
, channel
;
493 assert(pd
&& command
== PA_COMMAND_REQUEST
&& t
&& c
);
495 if (pa_tagstruct_getu32(t
, &channel
) < 0 ||
496 pa_tagstruct_getu32(t
, &bytes
) < 0 ||
497 !pa_tagstruct_eof(t
)) {
498 c
->error
= PA_ERROR_PROTOCOL
;
503 if (!(s
= pa_dynarray_get(c
->playback_streams
, channel
)))
506 if (s
->state
!= STREAM_READY
)
509 s
->requested_bytes
+= bytes
;
511 if (s
->requested_bytes
&& s
->write_callback
)
512 s
->write_callback(s
, s
->requested_bytes
, s
->write_userdata
);
515 static void create_stream_callback(struct pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, struct pa_tagstruct
*t
, void *userdata
) {
516 struct pa_stream
*s
= userdata
;
517 assert(pd
&& s
&& s
->state
== STREAM_CREATING
);
519 if (command
!= PA_COMMAND_REPLY
) {
520 if (handle_error(s
->context
, command
, t
) < 0) {
521 context_dead(s
->context
);
526 if (s
->create_complete_callback
)
527 s
->create_complete_callback(s
, 0, s
->create_complete_userdata
);
532 if (pa_tagstruct_getu32(t
, &s
->channel
) < 0 ||
533 ((s
->direction
!= PA_STREAM_UPLOAD
) && pa_tagstruct_getu32(t
, &s
->device_index
) < 0) ||
534 !pa_tagstruct_eof(t
)) {
535 s
->context
->error
= PA_ERROR_PROTOCOL
;
536 context_dead(s
->context
);
540 s
->channel_valid
= 1;
541 pa_dynarray_put((s
->direction
== PA_STREAM_RECORD
) ? s
->context
->record_streams
: s
->context
->playback_streams
, s
->channel
, s
);
543 s
->state
= STREAM_READY
;
544 if (s
->create_complete_callback
)
545 s
->create_complete_callback(s
, 1, s
->create_complete_userdata
);
548 static void create_stream(struct pa_stream
*s
, const char *dev
) {
549 struct pa_tagstruct
*t
;
553 s
->state
= STREAM_CREATING
;
555 t
= pa_tagstruct_new(NULL
, 0);
558 pa_tagstruct_putu32(t
, s
->direction
== PA_STREAM_PLAYBACK
? PA_COMMAND_CREATE_PLAYBACK_STREAM
: PA_COMMAND_CREATE_RECORD_STREAM
);
559 pa_tagstruct_putu32(t
, tag
= s
->context
->ctag
++);
560 pa_tagstruct_puts(t
, s
->name
);
561 pa_tagstruct_put_sample_spec(t
, &s
->sample_spec
);
562 pa_tagstruct_putu32(t
, (uint32_t) -1);
563 pa_tagstruct_puts(t
, dev
? dev
: "");
564 pa_tagstruct_putu32(t
, s
->buffer_attr
.maxlength
);
565 if (s
->direction
== PA_STREAM_PLAYBACK
) {
566 pa_tagstruct_putu32(t
, s
->buffer_attr
.tlength
);
567 pa_tagstruct_putu32(t
, s
->buffer_attr
.prebuf
);
568 pa_tagstruct_putu32(t
, s
->buffer_attr
.minreq
);
570 pa_tagstruct_putu32(t
, s
->buffer_attr
.fragsize
);
572 pa_pstream_send_tagstruct(s
->context
->pstream
, t
);
573 pa_pdispatch_register_reply(s
->context
->pdispatch
, tag
, DEFAULT_TIMEOUT
, create_stream_callback
, s
);
576 static struct pa_stream
*internal_stream_new(struct pa_context
*c
) {
579 s
= pa_xmalloc(sizeof(struct pa_stream
));
582 s
->read_callback
= NULL
;
583 s
->read_userdata
= NULL
;
584 s
->write_callback
= NULL
;
585 s
->write_userdata
= NULL
;
586 s
->die_callback
= NULL
;
587 s
->die_userdata
= NULL
;
588 s
->create_complete_callback
= NULL
;
589 s
->create_complete_userdata
= NULL
;
590 s
->get_latency_callback
= NULL
;
591 s
->get_latency_userdata
= NULL
;
592 s
->finish_sample_callback
= NULL
;
593 s
->finish_sample_userdata
= NULL
;
596 s
->state
= STREAM_CREATING
;
597 s
->requested_bytes
= 0;
599 s
->channel_valid
= 0;
600 s
->device_index
= (uint32_t) -1;
602 memset(&s
->buffer_attr
, 0, sizeof(s
->buffer_attr
));
604 s
->next
= c
->first_stream
;
606 s
->next
->previous
= s
;
613 struct pa_stream
* pa_stream_new(
614 struct pa_context
*c
,
615 enum pa_stream_direction dir
,
618 const struct pa_sample_spec
*ss
,
619 const struct pa_buffer_attr
*attr
,
620 void (*complete
) (struct pa_stream
*s
, int success
, void *userdata
),
625 assert(c
&& name
&& ss
&& c
->state
== CONTEXT_READY
&& (dir
== PA_STREAM_PLAYBACK
|| dir
== PA_STREAM_RECORD
));
627 s
= internal_stream_new(c
);
630 s
->create_complete_callback
= complete
;
631 s
->create_complete_userdata
= userdata
;
632 s
->name
= pa_xstrdup(name
);
633 s
->state
= STREAM_CREATING
;
635 s
->sample_spec
= *ss
;
637 s
->buffer_attr
= *attr
;
639 s
->buffer_attr
.maxlength
= DEFAULT_MAXLENGTH
;
640 s
->buffer_attr
.tlength
= DEFAULT_TLENGTH
;
641 s
->buffer_attr
.prebuf
= DEFAULT_PREBUF
;
642 s
->buffer_attr
.minreq
= DEFAULT_MINREQ
;
643 s
->buffer_attr
.fragsize
= DEFAULT_FRAGSIZE
;
646 create_stream(s
, dev
);
651 void pa_stream_free(struct pa_stream
*s
) {
652 assert(s
&& s
->context
);
654 if (s
->context
->pdispatch
)
655 pa_pdispatch_unregister_reply(s
->context
->pdispatch
, s
);
659 if (s
->channel_valid
&& s
->context
->state
== CONTEXT_READY
) {
660 struct pa_tagstruct
*t
= pa_tagstruct_new(NULL
, 0);
663 pa_tagstruct_putu32(t
, s
->direction
== PA_STREAM_PLAYBACK
? PA_COMMAND_DELETE_PLAYBACK_STREAM
:
664 (s
->direction
== PA_STREAM_RECORD
? PA_COMMAND_DELETE_RECORD_STREAM
: PA_COMMAND_DELETE_UPLOAD_STREAM
));
665 pa_tagstruct_putu32(t
, s
->context
->ctag
++);
666 pa_tagstruct_putu32(t
, s
->channel
);
667 pa_pstream_send_tagstruct(s
->context
->pstream
, t
);
670 if (s
->channel_valid
)
671 pa_dynarray_put((s
->direction
== PA_STREAM_PLAYBACK
) ? s
->context
->playback_streams
: s
->context
->record_streams
, s
->channel
, NULL
);
674 s
->next
->previous
= s
->previous
;
676 s
->previous
->next
= s
->next
;
678 s
->context
->first_stream
= s
->next
;
683 void pa_stream_set_write_callback(struct pa_stream
*s
, void (*cb
)(struct pa_stream
*p
, size_t length
, void *userdata
), void *userdata
) {
684 s
->write_callback
= cb
;
685 s
->write_userdata
= userdata
;
688 void pa_stream_write(struct pa_stream
*s
, const void *data
, size_t length
) {
689 struct pa_memchunk chunk
;
690 assert(s
&& s
->context
&& data
&& length
&& s
->state
== STREAM_READY
);
692 chunk
.memblock
= pa_memblock_new(length
);
693 assert(chunk
.memblock
&& chunk
.memblock
->data
);
694 memcpy(chunk
.memblock
->data
, data
, length
);
696 chunk
.length
= length
;
698 pa_pstream_send_memblock(s
->context
->pstream
, s
->channel
, 0, &chunk
);
699 pa_memblock_unref(chunk
.memblock
);
701 /*fprintf(stderr, "Sent %u bytes\n", length);*/
703 if (length
< s
->requested_bytes
)
704 s
->requested_bytes
-= length
;
706 s
->requested_bytes
= 0;
709 size_t pa_stream_writable_size(struct pa_stream
*s
) {
710 assert(s
&& s
->state
== STREAM_READY
);
711 return s
->requested_bytes
;
714 void pa_stream_set_read_callback(struct pa_stream
*s
, void (*cb
)(struct pa_stream
*p
, const void*data
, size_t length
, void *userdata
), void *userdata
) {
716 s
->read_callback
= cb
;
717 s
->read_userdata
= userdata
;
720 int pa_stream_is_dead(struct pa_stream
*s
) {
721 return s
->state
== STREAM_DEAD
;
724 int pa_stream_is_ready(struct pa_stream
*s
) {
725 return s
->state
== STREAM_READY
;
728 void pa_stream_set_die_callback(struct pa_stream
*s
, void (*cb
)(struct pa_stream
*s
, void *userdata
), void *userdata
) {
730 s
->die_callback
= cb
;
731 s
->die_userdata
= userdata
;
734 int pa_context_is_pending(struct pa_context
*c
) {
737 if (c
->state
!= CONTEXT_READY
)
740 return pa_pstream_is_pending(c
->pstream
) || pa_pdispatch_is_pending(c
->pdispatch
);
743 struct pa_context
* pa_stream_get_context(struct pa_stream
*p
) {
748 static void set_dispatch_callbacks(struct pa_context
*c
);
750 static void pdispatch_drain_callback(struct pa_pdispatch
*pd
, void *userdata
) {
751 set_dispatch_callbacks(userdata
);
754 static void pstream_drain_callback(struct pa_pstream
*s
, void *userdata
) {
755 set_dispatch_callbacks(userdata
);
758 static void set_dispatch_callbacks(struct pa_context
*c
) {
759 assert(c
&& c
->state
== CONTEXT_READY
);
761 pa_pstream_set_drain_callback(c
->pstream
, NULL
, NULL
);
762 pa_pdispatch_set_drain_callback(c
->pdispatch
, NULL
, NULL
);
764 if (pa_pdispatch_is_pending(c
->pdispatch
)) {
765 pa_pdispatch_set_drain_callback(c
->pdispatch
, pdispatch_drain_callback
, c
);
769 if (pa_pstream_is_pending(c
->pstream
)) {
770 pa_pstream_set_drain_callback(c
->pstream
, pstream_drain_callback
, c
);
774 assert(c
->drain_complete_callback
);
775 c
->drain_complete_callback(c
, c
->drain_complete_userdata
);
778 int pa_context_drain(
779 struct pa_context
*c
,
780 void (*complete
) (struct pa_context
*c
, void *userdata
),
783 assert(c
&& c
->state
== CONTEXT_READY
);
785 if (complete
== NULL
) {
786 c
->drain_complete_callback
= NULL
;
787 pa_pstream_set_drain_callback(c
->pstream
, NULL
, NULL
);
788 pa_pdispatch_set_drain_callback(c
->pdispatch
, NULL
, NULL
);
792 if (!pa_context_is_pending(c
))
795 c
->drain_complete_callback
= complete
;
796 c
->drain_complete_userdata
= userdata
;
798 set_dispatch_callbacks(c
);
803 static void stream_drain_callback(struct pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, struct pa_tagstruct
*t
, void *userdata
) {
804 struct pa_stream
*s
= userdata
;
807 if (command
!= PA_COMMAND_REPLY
) {
808 if (handle_error(s
->context
, command
, t
) < 0) {
809 context_dead(s
->context
);
817 if (s
->state
!= STREAM_READY
)
820 if (!pa_tagstruct_eof(t
)) {
821 s
->context
->error
= PA_ERROR_PROTOCOL
;
822 context_dead(s
->context
);
826 if (s
->drain_complete_callback
) {
827 void (*temp
) (struct pa_stream
*s
, void *userdata
) = s
->drain_complete_callback
;
828 s
->drain_complete_callback
= NULL
;
829 temp(s
, s
->drain_complete_userdata
);
834 void pa_stream_drain(struct pa_stream
*s
, void (*complete
) (struct pa_stream
*s
, void *userdata
), void *userdata
) {
835 struct pa_tagstruct
*t
;
837 assert(s
&& s
->state
== STREAM_READY
);
840 s
->drain_complete_callback
= NULL
;
844 s
->drain_complete_callback
= complete
;
845 s
->drain_complete_userdata
= userdata
;
847 t
= pa_tagstruct_new(NULL
, 0);
850 pa_tagstruct_putu32(t
, PA_COMMAND_DRAIN_PLAYBACK_STREAM
);
851 pa_tagstruct_putu32(t
, tag
= s
->context
->ctag
++);
852 pa_tagstruct_putu32(t
, s
->channel
);
853 pa_pstream_send_tagstruct(s
->context
->pstream
, t
);
854 pa_pdispatch_register_reply(s
->context
->pdispatch
, tag
, DEFAULT_TIMEOUT
, stream_drain_callback
, s
);
857 void pa_context_exit(struct pa_context
*c
) {
858 struct pa_tagstruct
*t
;
859 t
= pa_tagstruct_new(NULL
, 0);
861 pa_tagstruct_putu32(t
, PA_COMMAND_EXIT
);
862 pa_tagstruct_putu32(t
, c
->ctag
++);
863 pa_pstream_send_tagstruct(c
->pstream
, t
);
866 static void context_stat_callback(struct pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, struct pa_tagstruct
*t
, void *userdata
) {
867 struct pa_context
*c
= userdata
;
868 uint32_t total
, count
;
871 if (command
!= PA_COMMAND_REPLY
) {
872 if (handle_error(c
, command
, t
) < 0) {
877 if (c
->stat_callback
)
878 c
->stat_callback(c
, (uint32_t) -1, (uint32_t) -1, c
->stat_userdata
);
882 if (pa_tagstruct_getu32(t
, &count
) < 0 ||
883 pa_tagstruct_getu32(t
, &total
) < 0 ||
884 !pa_tagstruct_eof(t
)) {
885 c
->error
= PA_ERROR_PROTOCOL
;
890 if (c
->stat_callback
)
891 c
->stat_callback(c
, count
, total
, c
->stat_userdata
);
894 void pa_context_stat(struct pa_context
*c
, void (*cb
)(struct pa_context
*c
, uint32_t count
, uint32_t total
, void *userdata
), void *userdata
) {
896 struct pa_tagstruct
*t
;
898 c
->stat_callback
= cb
;
899 c
->stat_userdata
= userdata
;
904 t
= pa_tagstruct_new(NULL
, 0);
906 pa_tagstruct_putu32(t
, PA_COMMAND_STAT
);
907 pa_tagstruct_putu32(t
, tag
= c
->ctag
++);
908 pa_pstream_send_tagstruct(c
->pstream
, t
);
909 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, context_stat_callback
, c
);
912 static void stream_get_latency_callback(struct pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, struct pa_tagstruct
*t
, void *userdata
) {
913 struct pa_stream
*s
= userdata
;
917 if (command
!= PA_COMMAND_REPLY
) {
918 if (handle_error(s
->context
, command
, t
) < 0) {
919 context_dead(s
->context
);
923 if (s
->get_latency_callback
)
924 s
->get_latency_callback(s
, (uint32_t) -1, s
->get_latency_userdata
);
928 if (pa_tagstruct_getu32(t
, &latency
) < 0 ||
929 !pa_tagstruct_eof(t
)) {
930 s
->context
->error
= PA_ERROR_PROTOCOL
;
931 context_dead(s
->context
);
935 if (s
->get_latency_callback
)
936 s
->get_latency_callback(s
, latency
, s
->get_latency_userdata
);
939 void pa_stream_get_latency(struct pa_stream
*p
, void (*cb
)(struct pa_stream
*p
, uint32_t latency
, void *userdata
), void *userdata
) {
941 struct pa_tagstruct
*t
;
943 p
->get_latency_callback
= cb
;
944 p
->get_latency_userdata
= userdata
;
949 t
= pa_tagstruct_new(NULL
, 0);
951 pa_tagstruct_putu32(t
, PA_COMMAND_GET_PLAYBACK_LATENCY
);
952 pa_tagstruct_putu32(t
, tag
= p
->context
->ctag
++);
953 pa_tagstruct_putu32(t
, p
->channel
);
954 pa_pstream_send_tagstruct(p
->context
->pstream
, t
);
955 pa_pdispatch_register_reply(p
->context
->pdispatch
, tag
, DEFAULT_TIMEOUT
, stream_get_latency_callback
, p
);
958 struct pa_stream
* pa_context_upload_sample(struct pa_context
*c
, const char *name
, const struct pa_sample_spec
*ss
, size_t length
, void (*cb
) (struct pa_stream
*s
, int success
, void *userdata
), void *userdata
) {
960 struct pa_tagstruct
*t
;
963 s
= internal_stream_new(c
);
966 s
->create_complete_callback
= cb
;
967 s
->create_complete_userdata
= userdata
;
968 s
->name
= pa_xstrdup(name
);
969 s
->state
= STREAM_CREATING
;
970 s
->direction
= PA_STREAM_UPLOAD
;
971 s
->sample_spec
= *ss
;
973 t
= pa_tagstruct_new(NULL
, 0);
975 pa_tagstruct_putu32(t
, PA_COMMAND_CREATE_UPLOAD_STREAM
);
976 pa_tagstruct_putu32(t
, tag
= c
->ctag
++);
977 pa_tagstruct_puts(t
, name
);
978 pa_tagstruct_put_sample_spec(t
, ss
);
979 pa_tagstruct_putu32(t
, length
);
980 pa_pstream_send_tagstruct(c
->pstream
, t
);
981 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, create_stream_callback
, s
);
986 static void stream_finish_sample_callback(struct pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, struct pa_tagstruct
*t
, void *userdata
) {
987 struct pa_stream
*s
= userdata
;
990 if (command
!= PA_COMMAND_REPLY
) {
991 if (handle_error(s
->context
, command
, t
) < 0) {
992 context_dead(s
->context
);
996 if (s
->finish_sample_callback
)
997 s
->finish_sample_callback(s
, 0, s
->finish_sample_userdata
);
1001 if (!pa_tagstruct_eof(t
)) {
1002 s
->context
->error
= PA_ERROR_PROTOCOL
;
1003 context_dead(s
->context
);
1007 if (s
->finish_sample_callback
)
1008 s
->finish_sample_callback(s
, 1, s
->finish_sample_userdata
);
1011 void pa_stream_finish_sample(struct pa_stream
*p
, void (*cb
)(struct pa_stream
*s
, int success
, void *userdata
), void *userdata
) {
1012 struct pa_tagstruct
*t
;
1016 p
->finish_sample_callback
= cb
;
1017 p
->finish_sample_userdata
= userdata
;
1019 t
= pa_tagstruct_new(NULL
, 0);
1021 pa_tagstruct_putu32(t
, PA_COMMAND_FINISH_UPLOAD_STREAM
);
1022 pa_tagstruct_putu32(t
, tag
= p
->context
->ctag
++);
1023 pa_tagstruct_putu32(t
, p
->channel
);
1024 pa_pstream_send_tagstruct(p
->context
->pstream
, t
);
1025 pa_pdispatch_register_reply(p
->context
->pdispatch
, tag
, DEFAULT_TIMEOUT
, stream_finish_sample_callback
, p
);
1028 static void context_play_sample_callback(struct pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, struct pa_tagstruct
*t
, void *userdata
) {
1029 struct pa_context
*c
= userdata
;
1032 if (command
!= PA_COMMAND_REPLY
) {
1033 if (handle_error(c
, command
, t
) < 0) {
1038 if (c
->play_sample_callback
)
1039 c
->play_sample_callback(c
, 0, c
->play_sample_userdata
);
1043 if (!pa_tagstruct_eof(t
)) {
1044 c
->error
= PA_ERROR_PROTOCOL
;
1049 if (c
->play_sample_callback
)
1050 c
->play_sample_callback(c
, 1, c
->play_sample_userdata
);
1053 void pa_context_play_sample(struct pa_context
*c
, const char *name
, const char *dev
, uint32_t volume
, void (*cb
)(struct pa_context
*c
, int success
, void *userdata
), void *userdata
) {
1054 struct pa_tagstruct
*t
;
1056 assert(c
&& name
&& *name
&& (!dev
|| *dev
));
1061 c
->play_sample_callback
= cb
;
1062 c
->play_sample_userdata
= userdata
;
1064 t
= pa_tagstruct_new(NULL
, 0);
1066 pa_tagstruct_putu32(t
, PA_COMMAND_PLAY_SAMPLE
);
1067 pa_tagstruct_putu32(t
, tag
= c
->ctag
++);
1068 pa_tagstruct_putu32(t
, (uint32_t) -1);
1069 pa_tagstruct_puts(t
, dev
? dev
: "");
1070 pa_tagstruct_putu32(t
, volume
);
1071 pa_tagstruct_puts(t
, name
);
1072 pa_pstream_send_tagstruct(c
->pstream
, t
);
1073 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, context_play_sample_callback
, c
);
1076 static void context_remove_sample_callback(struct pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, struct pa_tagstruct
*t
, void *userdata
) {
1077 struct pa_context
*c
= userdata
;
1080 if (command
!= PA_COMMAND_REPLY
) {
1081 if (handle_error(c
, command
, t
) < 0) {
1086 if (c
->remove_sample_callback
)
1087 c
->remove_sample_callback(c
, 0, c
->remove_sample_userdata
);
1091 if (!pa_tagstruct_eof(t
)) {
1092 c
->error
= PA_ERROR_PROTOCOL
;
1097 if (c
->remove_sample_callback
)
1098 c
->remove_sample_callback(c
, 1, c
->remove_sample_userdata
);
1101 void pa_context_remove_sample(struct pa_context
*c
, const char *name
, void (*cb
)(struct pa_context
*c
, int success
, void *userdata
), void *userdata
) {
1102 struct pa_tagstruct
*t
;
1106 c
->remove_sample_callback
= cb
;
1107 c
->remove_sample_userdata
= userdata
;
1109 t
= pa_tagstruct_new(NULL
, 0);
1111 pa_tagstruct_putu32(t
, PA_COMMAND_REMOVE_SAMPLE
);
1112 pa_tagstruct_putu32(t
, tag
= c
->ctag
++);
1113 pa_tagstruct_puts(t
, name
);
1114 pa_pstream_send_tagstruct(c
->pstream
, t
);
1115 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, context_remove_sample_callback
, c
);