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"
44 #define DEFAULT_MAXLENGTH 204800
45 #define DEFAULT_TLENGTH 10240
46 #define DEFAULT_PREBUF 4096
47 #define DEFAULT_MINREQ 1024
48 #define DEFAULT_FRAGSIZE 1024
50 #define DEFAULT_TIMEOUT (5*60)
51 #define DEFAULT_SERVER "/tmp/polypaudio/native"
52 #define DEFAULT_PORT "4713"
56 struct pa_mainloop_api
* mainloop
;
57 struct pa_socket_client
*client
;
58 struct pa_pstream
*pstream
;
59 struct pa_pdispatch
*pdispatch
;
60 struct pa_dynarray
*record_streams
, *playback_streams
;
61 struct pa_stream
*first_stream
;
73 void (*connect_complete_callback
)(struct pa_context
*c
, int success
, void *userdata
);
74 void *connect_complete_userdata
;
76 void (*drain_complete_callback
)(struct pa_context
*c
, void *userdata
);
77 void *drain_complete_userdata
;
79 void (*die_callback
)(struct pa_context
*c
, void *userdata
);
82 void (*stat_callback
)(struct pa_context
*c
, uint32_t count
, uint32_t total
, void *userdata
);
85 void (*play_sample_callback
)(struct pa_context
*c
, int success
, void *userdata
);
86 void *play_sample_userdata
;
88 void (*remove_sample_callback
)(struct pa_context
*c
, int success
, void *userdata
);
89 void *remove_sample_userdata
;
91 uint8_t auth_cookie
[PA_NATIVE_COOKIE_LENGTH
];
95 struct pa_context
*context
;
96 struct pa_stream
*next
, *previous
;
99 struct pa_buffer_attr buffer_attr
;
100 struct pa_sample_spec sample_spec
;
103 uint32_t device_index
;
104 enum pa_stream_direction direction
;
106 enum { STREAM_CREATING
, STREAM_READY
, STREAM_DEAD
} state
;
107 uint32_t requested_bytes
;
109 void (*read_callback
)(struct pa_stream
*p
, const void*data
, size_t length
, void *userdata
);
112 void (*write_callback
)(struct pa_stream
*p
, size_t length
, void *userdata
);
113 void *write_userdata
;
115 void (*create_complete_callback
)(struct pa_stream
*s
, int success
, void *userdata
);
116 void *create_complete_userdata
;
118 void (*drain_complete_callback
)(struct pa_stream
*s
, void *userdata
);
119 void *drain_complete_userdata
;
121 void (*die_callback
)(struct pa_stream
*c
, void *userdata
);
124 void (*get_latency_callback
)(struct pa_stream
*c
, uint32_t latency
, void *userdata
);
125 void *get_latency_userdata
;
127 void (*finish_sample_callback
)(struct pa_stream
*c
, int success
, void *userdata
);
128 void *finish_sample_userdata
;
131 static void command_request(struct pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, struct pa_tagstruct
*t
, void *userdata
);
132 static void command_playback_stream_killed(struct pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, struct pa_tagstruct
*t
, void *userdata
);
134 static const struct pa_pdispatch_command command_table
[PA_COMMAND_MAX
] = {
135 [PA_COMMAND_ERROR
] = { NULL
},
136 [PA_COMMAND_REPLY
] = { NULL
},
137 [PA_COMMAND_CREATE_PLAYBACK_STREAM
] = { NULL
},
138 [PA_COMMAND_DELETE_PLAYBACK_STREAM
] = { NULL
},
139 [PA_COMMAND_CREATE_RECORD_STREAM
] = { NULL
},
140 [PA_COMMAND_DELETE_RECORD_STREAM
] = { NULL
},
141 [PA_COMMAND_EXIT
] = { NULL
},
142 [PA_COMMAND_REQUEST
] = { command_request
},
143 [PA_COMMAND_PLAYBACK_STREAM_KILLED
] = { command_playback_stream_killed
},
144 [PA_COMMAND_RECORD_STREAM_KILLED
] = { command_playback_stream_killed
},
147 struct pa_context
*pa_context_new(struct pa_mainloop_api
*mainloop
, const char *name
) {
148 struct pa_context
*c
;
149 assert(mainloop
&& name
);
151 c
= malloc(sizeof(struct pa_context
));
153 c
->name
= strdup(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
= malloc(*len
= result
->ai_addrlen
);
396 memcpy(sa
, result
->ai_addr
, *len
);
398 freeaddrinfo(result
);
404 int pa_context_connect(struct pa_context
*c
, const char *server
, void (*complete
) (struct pa_context
*c
, int success
, void *userdata
), void *userdata
) {
405 assert(c
&& c
->state
== CONTEXT_UNCONNECTED
);
407 if (pa_authkey_load_from_home(PA_NATIVE_COOKIE_FILE
, c
->auth_cookie
, sizeof(c
->auth_cookie
)) < 0) {
408 c
->error
= PA_ERROR_AUTHKEY
;
413 if (!(server
= getenv("POLYP_SERVER")))
414 server
= DEFAULT_SERVER
;
418 if (*server
== '/') {
419 if (!(c
->client
= pa_socket_client_new_unix(c
->mainloop
, server
))) {
420 c
->error
= PA_ERROR_CONNECTIONREFUSED
;
427 if (!(sa
= resolve_server(server
, &sa_len
))) {
428 c
->error
= PA_ERROR_INVALIDSERVER
;
432 c
->client
= pa_socket_client_new_sockaddr(c
->mainloop
, sa
, sa_len
);
436 c
->error
= PA_ERROR_CONNECTIONREFUSED
;
441 c
->connect_complete_callback
= complete
;
442 c
->connect_complete_userdata
= userdata
;
444 pa_socket_client_set_callback(c
->client
, on_connection
, c
);
445 c
->state
= CONTEXT_CONNECTING
;
450 int pa_context_is_dead(struct pa_context
*c
) {
452 return c
->state
== CONTEXT_DEAD
;
455 int pa_context_is_ready(struct pa_context
*c
) {
457 return c
->state
== CONTEXT_READY
;
460 int pa_context_errno(struct pa_context
*c
) {
465 void pa_context_set_die_callback(struct pa_context
*c
, void (*cb
)(struct pa_context
*c
, void *userdata
), void *userdata
) {
467 c
->die_callback
= cb
;
468 c
->die_userdata
= userdata
;
471 static void command_playback_stream_killed(struct pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, struct pa_tagstruct
*t
, void *userdata
) {
472 struct pa_context
*c
= userdata
;
475 assert(pd
&& (command
== PA_COMMAND_PLAYBACK_STREAM_KILLED
|| command
== PA_COMMAND_RECORD_STREAM_KILLED
) && t
&& c
);
477 if (pa_tagstruct_getu32(t
, &channel
) < 0 ||
478 !pa_tagstruct_eof(t
)) {
479 c
->error
= PA_ERROR_PROTOCOL
;
484 if (!(s
= pa_dynarray_get(command
== PA_COMMAND_PLAYBACK_STREAM_KILLED
? c
->playback_streams
: c
->record_streams
, channel
)))
487 c
->error
= PA_ERROR_KILLED
;
491 static void command_request(struct pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, struct pa_tagstruct
*t
, void *userdata
) {
493 struct pa_context
*c
= userdata
;
494 uint32_t bytes
, channel
;
495 assert(pd
&& command
== PA_COMMAND_REQUEST
&& t
&& c
);
497 if (pa_tagstruct_getu32(t
, &channel
) < 0 ||
498 pa_tagstruct_getu32(t
, &bytes
) < 0 ||
499 !pa_tagstruct_eof(t
)) {
500 c
->error
= PA_ERROR_PROTOCOL
;
505 if (!(s
= pa_dynarray_get(c
->playback_streams
, channel
)))
508 if (s
->state
!= STREAM_READY
)
511 s
->requested_bytes
+= bytes
;
513 if (s
->requested_bytes
&& s
->write_callback
)
514 s
->write_callback(s
, s
->requested_bytes
, s
->write_userdata
);
517 static void create_stream_callback(struct pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, struct pa_tagstruct
*t
, void *userdata
) {
518 struct pa_stream
*s
= userdata
;
519 assert(pd
&& s
&& s
->state
== STREAM_CREATING
);
521 if (command
!= PA_COMMAND_REPLY
) {
522 if (handle_error(s
->context
, command
, t
) < 0) {
523 context_dead(s
->context
);
528 if (s
->create_complete_callback
)
529 s
->create_complete_callback(s
, 0, s
->create_complete_userdata
);
534 if (pa_tagstruct_getu32(t
, &s
->channel
) < 0 ||
535 ((s
->direction
!= PA_STREAM_UPLOAD
) && pa_tagstruct_getu32(t
, &s
->device_index
) < 0) ||
536 !pa_tagstruct_eof(t
)) {
537 s
->context
->error
= PA_ERROR_PROTOCOL
;
538 context_dead(s
->context
);
542 s
->channel_valid
= 1;
543 pa_dynarray_put((s
->direction
== PA_STREAM_RECORD
) ? s
->context
->record_streams
: s
->context
->playback_streams
, s
->channel
, s
);
545 s
->state
= STREAM_READY
;
546 if (s
->create_complete_callback
)
547 s
->create_complete_callback(s
, 1, s
->create_complete_userdata
);
550 static void create_stream(struct pa_stream
*s
, const char *dev
) {
551 struct pa_tagstruct
*t
;
555 s
->state
= STREAM_CREATING
;
557 t
= pa_tagstruct_new(NULL
, 0);
560 pa_tagstruct_putu32(t
, s
->direction
== PA_STREAM_PLAYBACK
? PA_COMMAND_CREATE_PLAYBACK_STREAM
: PA_COMMAND_CREATE_RECORD_STREAM
);
561 pa_tagstruct_putu32(t
, tag
= s
->context
->ctag
++);
562 pa_tagstruct_puts(t
, s
->name
);
563 pa_tagstruct_put_sample_spec(t
, &s
->sample_spec
);
564 pa_tagstruct_putu32(t
, (uint32_t) -1);
565 pa_tagstruct_puts(t
, dev
? dev
: "");
566 pa_tagstruct_putu32(t
, s
->buffer_attr
.maxlength
);
567 if (s
->direction
== PA_STREAM_PLAYBACK
) {
568 pa_tagstruct_putu32(t
, s
->buffer_attr
.tlength
);
569 pa_tagstruct_putu32(t
, s
->buffer_attr
.prebuf
);
570 pa_tagstruct_putu32(t
, s
->buffer_attr
.minreq
);
572 pa_tagstruct_putu32(t
, s
->buffer_attr
.fragsize
);
574 pa_pstream_send_tagstruct(s
->context
->pstream
, t
);
575 pa_pdispatch_register_reply(s
->context
->pdispatch
, tag
, DEFAULT_TIMEOUT
, create_stream_callback
, s
);
578 static struct pa_stream
*internal_stream_new(struct pa_context
*c
) {
581 s
= malloc(sizeof(struct pa_stream
));
585 s
->read_callback
= NULL
;
586 s
->read_userdata
= NULL
;
587 s
->write_callback
= NULL
;
588 s
->write_userdata
= NULL
;
589 s
->die_callback
= NULL
;
590 s
->die_userdata
= NULL
;
591 s
->create_complete_callback
= NULL
;
592 s
->create_complete_userdata
= NULL
;
593 s
->get_latency_callback
= NULL
;
594 s
->get_latency_userdata
= NULL
;
595 s
->finish_sample_callback
= NULL
;
596 s
->finish_sample_userdata
= NULL
;
599 s
->state
= STREAM_CREATING
;
600 s
->requested_bytes
= 0;
602 s
->channel_valid
= 0;
603 s
->device_index
= (uint32_t) -1;
605 memset(&s
->buffer_attr
, 0, sizeof(s
->buffer_attr
));
607 s
->next
= c
->first_stream
;
609 s
->next
->previous
= s
;
616 struct pa_stream
* pa_stream_new(
617 struct pa_context
*c
,
618 enum pa_stream_direction dir
,
621 const struct pa_sample_spec
*ss
,
622 const struct pa_buffer_attr
*attr
,
623 void (*complete
) (struct pa_stream
*s
, int success
, void *userdata
),
628 assert(c
&& name
&& ss
&& c
->state
== CONTEXT_READY
&& (dir
== PA_STREAM_PLAYBACK
|| dir
== PA_STREAM_RECORD
));
630 s
= internal_stream_new(c
);
633 s
->create_complete_callback
= complete
;
634 s
->create_complete_userdata
= userdata
;
635 s
->name
= strdup(name
);
636 s
->state
= STREAM_CREATING
;
638 s
->sample_spec
= *ss
;
640 s
->buffer_attr
= *attr
;
642 s
->buffer_attr
.maxlength
= DEFAULT_MAXLENGTH
;
643 s
->buffer_attr
.tlength
= DEFAULT_TLENGTH
;
644 s
->buffer_attr
.prebuf
= DEFAULT_PREBUF
;
645 s
->buffer_attr
.minreq
= DEFAULT_MINREQ
;
646 s
->buffer_attr
.fragsize
= DEFAULT_FRAGSIZE
;
649 create_stream(s
, dev
);
654 void pa_stream_free(struct pa_stream
*s
) {
655 assert(s
&& s
->context
);
657 if (s
->context
->pdispatch
)
658 pa_pdispatch_unregister_reply(s
->context
->pdispatch
, s
);
662 if (s
->channel_valid
&& s
->context
->state
== CONTEXT_READY
) {
663 struct pa_tagstruct
*t
= pa_tagstruct_new(NULL
, 0);
666 pa_tagstruct_putu32(t
, s
->direction
== PA_STREAM_PLAYBACK
? PA_COMMAND_DELETE_PLAYBACK_STREAM
:
667 (s
->direction
== PA_STREAM_RECORD
? PA_COMMAND_DELETE_RECORD_STREAM
: PA_COMMAND_DELETE_UPLOAD_STREAM
));
668 pa_tagstruct_putu32(t
, s
->context
->ctag
++);
669 pa_tagstruct_putu32(t
, s
->channel
);
670 pa_pstream_send_tagstruct(s
->context
->pstream
, t
);
673 if (s
->channel_valid
)
674 pa_dynarray_put((s
->direction
== PA_STREAM_PLAYBACK
) ? s
->context
->playback_streams
: s
->context
->record_streams
, s
->channel
, NULL
);
677 s
->next
->previous
= s
->previous
;
679 s
->previous
->next
= s
->next
;
681 s
->context
->first_stream
= s
->next
;
686 void pa_stream_set_write_callback(struct pa_stream
*s
, void (*cb
)(struct pa_stream
*p
, size_t length
, void *userdata
), void *userdata
) {
687 s
->write_callback
= cb
;
688 s
->write_userdata
= userdata
;
691 void pa_stream_write(struct pa_stream
*s
, const void *data
, size_t length
) {
692 struct pa_memchunk chunk
;
693 assert(s
&& s
->context
&& data
&& length
&& s
->state
== STREAM_READY
);
695 chunk
.memblock
= pa_memblock_new(length
);
696 assert(chunk
.memblock
&& chunk
.memblock
->data
);
697 memcpy(chunk
.memblock
->data
, data
, length
);
699 chunk
.length
= length
;
701 pa_pstream_send_memblock(s
->context
->pstream
, s
->channel
, 0, &chunk
);
702 pa_memblock_unref(chunk
.memblock
);
704 /*fprintf(stderr, "Sent %u bytes\n", length);*/
706 if (length
< s
->requested_bytes
)
707 s
->requested_bytes
-= length
;
709 s
->requested_bytes
= 0;
712 size_t pa_stream_writable_size(struct pa_stream
*s
) {
713 assert(s
&& s
->state
== STREAM_READY
);
714 return s
->requested_bytes
;
717 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
) {
719 s
->read_callback
= cb
;
720 s
->read_userdata
= userdata
;
723 int pa_stream_is_dead(struct pa_stream
*s
) {
724 return s
->state
== STREAM_DEAD
;
727 int pa_stream_is_ready(struct pa_stream
*s
) {
728 return s
->state
== STREAM_READY
;
731 void pa_stream_set_die_callback(struct pa_stream
*s
, void (*cb
)(struct pa_stream
*s
, void *userdata
), void *userdata
) {
733 s
->die_callback
= cb
;
734 s
->die_userdata
= userdata
;
737 int pa_context_is_pending(struct pa_context
*c
) {
740 if (c
->state
!= CONTEXT_READY
)
743 return pa_pstream_is_pending(c
->pstream
) || pa_pdispatch_is_pending(c
->pdispatch
);
746 struct pa_context
* pa_stream_get_context(struct pa_stream
*p
) {
751 static void set_dispatch_callbacks(struct pa_context
*c
);
753 static void pdispatch_drain_callback(struct pa_pdispatch
*pd
, void *userdata
) {
754 set_dispatch_callbacks(userdata
);
757 static void pstream_drain_callback(struct pa_pstream
*s
, void *userdata
) {
758 set_dispatch_callbacks(userdata
);
761 static void set_dispatch_callbacks(struct pa_context
*c
) {
762 assert(c
&& c
->state
== CONTEXT_READY
);
764 pa_pstream_set_drain_callback(c
->pstream
, NULL
, NULL
);
765 pa_pdispatch_set_drain_callback(c
->pdispatch
, NULL
, NULL
);
767 if (pa_pdispatch_is_pending(c
->pdispatch
)) {
768 pa_pdispatch_set_drain_callback(c
->pdispatch
, pdispatch_drain_callback
, c
);
772 if (pa_pstream_is_pending(c
->pstream
)) {
773 pa_pstream_set_drain_callback(c
->pstream
, pstream_drain_callback
, c
);
777 assert(c
->drain_complete_callback
);
778 c
->drain_complete_callback(c
, c
->drain_complete_userdata
);
781 int pa_context_drain(
782 struct pa_context
*c
,
783 void (*complete
) (struct pa_context
*c
, void *userdata
),
786 assert(c
&& c
->state
== CONTEXT_READY
);
788 if (complete
== NULL
) {
789 c
->drain_complete_callback
= NULL
;
790 pa_pstream_set_drain_callback(c
->pstream
, NULL
, NULL
);
791 pa_pdispatch_set_drain_callback(c
->pdispatch
, NULL
, NULL
);
795 if (!pa_context_is_pending(c
))
798 c
->drain_complete_callback
= complete
;
799 c
->drain_complete_userdata
= userdata
;
801 set_dispatch_callbacks(c
);
806 static void stream_drain_callback(struct pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, struct pa_tagstruct
*t
, void *userdata
) {
807 struct pa_stream
*s
= userdata
;
810 if (command
!= PA_COMMAND_REPLY
) {
811 if (handle_error(s
->context
, command
, t
) < 0) {
812 context_dead(s
->context
);
820 if (s
->state
!= STREAM_READY
)
823 if (!pa_tagstruct_eof(t
)) {
824 s
->context
->error
= PA_ERROR_PROTOCOL
;
825 context_dead(s
->context
);
829 if (s
->drain_complete_callback
) {
830 void (*temp
) (struct pa_stream
*s
, void *userdata
) = s
->drain_complete_callback
;
831 s
->drain_complete_callback
= NULL
;
832 temp(s
, s
->drain_complete_userdata
);
837 void pa_stream_drain(struct pa_stream
*s
, void (*complete
) (struct pa_stream
*s
, void *userdata
), void *userdata
) {
838 struct pa_tagstruct
*t
;
840 assert(s
&& s
->state
== STREAM_READY
);
843 s
->drain_complete_callback
= NULL
;
847 s
->drain_complete_callback
= complete
;
848 s
->drain_complete_userdata
= userdata
;
850 t
= pa_tagstruct_new(NULL
, 0);
853 pa_tagstruct_putu32(t
, PA_COMMAND_DRAIN_PLAYBACK_STREAM
);
854 pa_tagstruct_putu32(t
, tag
= s
->context
->ctag
++);
855 pa_tagstruct_putu32(t
, s
->channel
);
856 pa_pstream_send_tagstruct(s
->context
->pstream
, t
);
857 pa_pdispatch_register_reply(s
->context
->pdispatch
, tag
, DEFAULT_TIMEOUT
, stream_drain_callback
, s
);
860 void pa_context_exit(struct pa_context
*c
) {
861 struct pa_tagstruct
*t
;
862 t
= pa_tagstruct_new(NULL
, 0);
864 pa_tagstruct_putu32(t
, PA_COMMAND_EXIT
);
865 pa_tagstruct_putu32(t
, c
->ctag
++);
866 pa_pstream_send_tagstruct(c
->pstream
, t
);
869 static void context_stat_callback(struct pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, struct pa_tagstruct
*t
, void *userdata
) {
870 struct pa_context
*c
= userdata
;
871 uint32_t total
, count
;
874 if (command
!= PA_COMMAND_REPLY
) {
875 if (handle_error(c
, command
, t
) < 0) {
880 if (c
->stat_callback
)
881 c
->stat_callback(c
, (uint32_t) -1, (uint32_t) -1, c
->stat_userdata
);
885 if (pa_tagstruct_getu32(t
, &count
) < 0 ||
886 pa_tagstruct_getu32(t
, &total
) < 0 ||
887 !pa_tagstruct_eof(t
)) {
888 c
->error
= PA_ERROR_PROTOCOL
;
893 if (c
->stat_callback
)
894 c
->stat_callback(c
, count
, total
, c
->stat_userdata
);
897 void pa_context_stat(struct pa_context
*c
, void (*cb
)(struct pa_context
*c
, uint32_t count
, uint32_t total
, void *userdata
), void *userdata
) {
899 struct pa_tagstruct
*t
;
901 c
->stat_callback
= cb
;
902 c
->stat_userdata
= userdata
;
907 t
= pa_tagstruct_new(NULL
, 0);
909 pa_tagstruct_putu32(t
, PA_COMMAND_STAT
);
910 pa_tagstruct_putu32(t
, tag
= c
->ctag
++);
911 pa_pstream_send_tagstruct(c
->pstream
, t
);
912 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, context_stat_callback
, c
);
915 static void stream_get_latency_callback(struct pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, struct pa_tagstruct
*t
, void *userdata
) {
916 struct pa_stream
*s
= userdata
;
920 if (command
!= PA_COMMAND_REPLY
) {
921 if (handle_error(s
->context
, command
, t
) < 0) {
922 context_dead(s
->context
);
926 if (s
->get_latency_callback
)
927 s
->get_latency_callback(s
, (uint32_t) -1, s
->get_latency_userdata
);
931 if (pa_tagstruct_getu32(t
, &latency
) < 0 ||
932 !pa_tagstruct_eof(t
)) {
933 s
->context
->error
= PA_ERROR_PROTOCOL
;
934 context_dead(s
->context
);
938 if (s
->get_latency_callback
)
939 s
->get_latency_callback(s
, latency
, s
->get_latency_userdata
);
942 void pa_stream_get_latency(struct pa_stream
*p
, void (*cb
)(struct pa_stream
*p
, uint32_t latency
, void *userdata
), void *userdata
) {
944 struct pa_tagstruct
*t
;
946 p
->get_latency_callback
= cb
;
947 p
->get_latency_userdata
= userdata
;
952 t
= pa_tagstruct_new(NULL
, 0);
954 pa_tagstruct_putu32(t
, PA_COMMAND_GET_PLAYBACK_LATENCY
);
955 pa_tagstruct_putu32(t
, tag
= p
->context
->ctag
++);
956 pa_tagstruct_putu32(t
, p
->channel
);
957 pa_pstream_send_tagstruct(p
->context
->pstream
, t
);
958 pa_pdispatch_register_reply(p
->context
->pdispatch
, tag
, DEFAULT_TIMEOUT
, stream_get_latency_callback
, p
);
961 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
) {
963 struct pa_tagstruct
*t
;
966 s
= internal_stream_new(c
);
969 s
->create_complete_callback
= cb
;
970 s
->create_complete_userdata
= userdata
;
971 s
->name
= strdup(name
);
972 s
->state
= STREAM_CREATING
;
973 s
->direction
= PA_STREAM_UPLOAD
;
974 s
->sample_spec
= *ss
;
976 t
= pa_tagstruct_new(NULL
, 0);
978 pa_tagstruct_putu32(t
, PA_COMMAND_CREATE_UPLOAD_STREAM
);
979 pa_tagstruct_putu32(t
, tag
= c
->ctag
++);
980 pa_tagstruct_puts(t
, name
);
981 pa_tagstruct_put_sample_spec(t
, ss
);
982 pa_tagstruct_putu32(t
, length
);
983 pa_pstream_send_tagstruct(c
->pstream
, t
);
984 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, create_stream_callback
, s
);
989 static void stream_finish_sample_callback(struct pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, struct pa_tagstruct
*t
, void *userdata
) {
990 struct pa_stream
*s
= userdata
;
993 if (command
!= PA_COMMAND_REPLY
) {
994 if (handle_error(s
->context
, command
, t
) < 0) {
995 context_dead(s
->context
);
999 if (s
->finish_sample_callback
)
1000 s
->finish_sample_callback(s
, 0, s
->finish_sample_userdata
);
1004 if (!pa_tagstruct_eof(t
)) {
1005 s
->context
->error
= PA_ERROR_PROTOCOL
;
1006 context_dead(s
->context
);
1010 if (s
->finish_sample_callback
)
1011 s
->finish_sample_callback(s
, 1, s
->finish_sample_userdata
);
1014 void pa_stream_finish_sample(struct pa_stream
*p
, void (*cb
)(struct pa_stream
*s
, int success
, void *userdata
), void *userdata
) {
1015 struct pa_tagstruct
*t
;
1019 p
->finish_sample_callback
= cb
;
1020 p
->finish_sample_userdata
= userdata
;
1022 t
= pa_tagstruct_new(NULL
, 0);
1024 pa_tagstruct_putu32(t
, PA_COMMAND_FINISH_UPLOAD_STREAM
);
1025 pa_tagstruct_putu32(t
, tag
= p
->context
->ctag
++);
1026 pa_tagstruct_putu32(t
, p
->channel
);
1027 pa_pstream_send_tagstruct(p
->context
->pstream
, t
);
1028 pa_pdispatch_register_reply(p
->context
->pdispatch
, tag
, DEFAULT_TIMEOUT
, stream_finish_sample_callback
, p
);
1031 static void context_play_sample_callback(struct pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, struct pa_tagstruct
*t
, void *userdata
) {
1032 struct pa_context
*c
= userdata
;
1035 if (command
!= PA_COMMAND_REPLY
) {
1036 if (handle_error(c
, command
, t
) < 0) {
1041 if (c
->play_sample_callback
)
1042 c
->play_sample_callback(c
, 0, c
->play_sample_userdata
);
1046 if (!pa_tagstruct_eof(t
)) {
1047 c
->error
= PA_ERROR_PROTOCOL
;
1052 if (c
->play_sample_callback
)
1053 c
->play_sample_callback(c
, 1, c
->play_sample_userdata
);
1056 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
) {
1057 struct pa_tagstruct
*t
;
1059 assert(c
&& name
&& *name
&& (!dev
|| *dev
));
1064 c
->play_sample_callback
= cb
;
1065 c
->play_sample_userdata
= userdata
;
1067 t
= pa_tagstruct_new(NULL
, 0);
1069 pa_tagstruct_putu32(t
, PA_COMMAND_PLAY_SAMPLE
);
1070 pa_tagstruct_putu32(t
, tag
= c
->ctag
++);
1071 pa_tagstruct_putu32(t
, (uint32_t) -1);
1072 pa_tagstruct_puts(t
, dev
? dev
: "");
1073 pa_tagstruct_putu32(t
, volume
);
1074 pa_tagstruct_puts(t
, name
);
1075 pa_pstream_send_tagstruct(c
->pstream
, t
);
1076 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, context_play_sample_callback
, c
);
1079 static void context_remove_sample_callback(struct pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, struct pa_tagstruct
*t
, void *userdata
) {
1080 struct pa_context
*c
= userdata
;
1083 if (command
!= PA_COMMAND_REPLY
) {
1084 if (handle_error(c
, command
, t
) < 0) {
1089 if (c
->remove_sample_callback
)
1090 c
->remove_sample_callback(c
, 0, c
->remove_sample_userdata
);
1094 if (!pa_tagstruct_eof(t
)) {
1095 c
->error
= PA_ERROR_PROTOCOL
;
1100 if (c
->remove_sample_callback
)
1101 c
->remove_sample_callback(c
, 1, c
->remove_sample_userdata
);
1104 void pa_context_remove_sample(struct pa_context
*c
, const char *name
, void (*cb
)(struct pa_context
*c
, int success
, void *userdata
), void *userdata
) {
1105 struct pa_tagstruct
*t
;
1109 c
->remove_sample_callback
= cb
;
1110 c
->remove_sample_userdata
= userdata
;
1112 t
= pa_tagstruct_new(NULL
, 0);
1114 pa_tagstruct_putu32(t
, PA_COMMAND_REMOVE_SAMPLE
);
1115 pa_tagstruct_putu32(t
, tag
= c
->ctag
++);
1116 pa_tagstruct_puts(t
, name
);
1117 pa_pstream_send_tagstruct(c
->pstream
, t
);
1118 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, context_remove_sample_callback
, c
);