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 void (*get_server_info_callback
)(struct pa_context
*c
, const struct pa_server_info
* i
, void *userdata
);
93 void *get_server_info_userdata
;
95 void (*get_sink_info_callback
)(struct pa_context
*c
, const struct pa_sink_info
* i
, int is_last
, void *userdata
);
96 void *get_sink_info_userdata
;
98 void (*get_source_info_callback
)(struct pa_context
*c
, const struct pa_source_info
* i
, int is_last
, void *userdata
);
99 void *get_source_info_userdata
;
101 void (*subscribe_callback
)(struct pa_context
*c
, enum pa_subscription_event_type t
, uint32_t index
, void *userdata
);
102 void *subscribe_userdata
;
103 enum pa_subscription_mask subscribe_mask
;
105 uint8_t auth_cookie
[PA_NATIVE_COOKIE_LENGTH
];
109 struct pa_context
*context
;
110 struct pa_stream
*next
, *previous
;
113 struct pa_buffer_attr buffer_attr
;
114 struct pa_sample_spec sample_spec
;
117 uint32_t device_index
;
118 enum pa_stream_direction direction
;
120 enum { STREAM_CREATING
, STREAM_READY
, STREAM_DEAD
} state
;
121 uint32_t requested_bytes
;
123 void (*read_callback
)(struct pa_stream
*p
, const void*data
, size_t length
, void *userdata
);
126 void (*write_callback
)(struct pa_stream
*p
, size_t length
, void *userdata
);
127 void *write_userdata
;
129 void (*create_complete_callback
)(struct pa_stream
*s
, int success
, void *userdata
);
130 void *create_complete_userdata
;
132 void (*drain_complete_callback
)(struct pa_stream
*s
, void *userdata
);
133 void *drain_complete_userdata
;
135 void (*die_callback
)(struct pa_stream
*c
, void *userdata
);
138 void (*get_latency_callback
)(struct pa_stream
*c
, uint32_t latency
, void *userdata
);
139 void *get_latency_userdata
;
141 void (*finish_sample_callback
)(struct pa_stream
*c
, int success
, void *userdata
);
142 void *finish_sample_userdata
;
145 static void command_request(struct pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, struct pa_tagstruct
*t
, void *userdata
);
146 static void command_playback_stream_killed(struct pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, struct pa_tagstruct
*t
, void *userdata
);
147 static void command_subscribe_event(struct pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, struct pa_tagstruct
*t
, void *userdata
);
149 static const struct pa_pdispatch_command command_table
[PA_COMMAND_MAX
] = {
150 [PA_COMMAND_ERROR
] = { NULL
},
151 [PA_COMMAND_REPLY
] = { NULL
},
152 [PA_COMMAND_CREATE_PLAYBACK_STREAM
] = { NULL
},
153 [PA_COMMAND_DELETE_PLAYBACK_STREAM
] = { NULL
},
154 [PA_COMMAND_CREATE_RECORD_STREAM
] = { NULL
},
155 [PA_COMMAND_DELETE_RECORD_STREAM
] = { NULL
},
156 [PA_COMMAND_EXIT
] = { NULL
},
157 [PA_COMMAND_REQUEST
] = { command_request
},
158 [PA_COMMAND_PLAYBACK_STREAM_KILLED
] = { command_playback_stream_killed
},
159 [PA_COMMAND_RECORD_STREAM_KILLED
] = { command_playback_stream_killed
},
160 [PA_COMMAND_SUBSCRIBE_EVENT
] = { command_subscribe_event
},
163 struct pa_context
*pa_context_new(struct pa_mainloop_api
*mainloop
, const char *name
) {
164 struct pa_context
*c
;
165 assert(mainloop
&& name
);
167 c
= pa_xmalloc(sizeof(struct pa_context
));
168 c
->name
= pa_xstrdup(name
);
169 c
->mainloop
= mainloop
;
173 c
->playback_streams
= pa_dynarray_new();
174 assert(c
->playback_streams
);
175 c
->record_streams
= pa_dynarray_new();
176 assert(c
->record_streams
);
177 c
->first_stream
= NULL
;
178 c
->error
= PA_ERROR_OK
;
179 c
->state
= CONTEXT_UNCONNECTED
;
182 c
->connect_complete_callback
= NULL
;
183 c
->connect_complete_userdata
= NULL
;
185 c
->drain_complete_callback
= NULL
;
186 c
->drain_complete_userdata
= NULL
;
188 c
->die_callback
= NULL
;
189 c
->die_userdata
= NULL
;
191 c
->stat_callback
= NULL
;
192 c
->stat_userdata
= NULL
;
194 c
->play_sample_callback
= NULL
;
195 c
->play_sample_userdata
= NULL
;
197 c
->remove_sample_callback
= NULL
;
198 c
->remove_sample_userdata
= NULL
;
200 c
->get_server_info_callback
= NULL
;
201 c
->get_server_info_userdata
= NULL
;
203 c
->get_sink_info_callback
= NULL
;
204 c
->get_sink_info_userdata
= NULL
;
206 c
->get_source_info_callback
= NULL
;
207 c
->get_source_info_userdata
= NULL
;
209 c
->subscribe_callback
= NULL
;
210 c
->subscribe_userdata
= NULL
;
212 pa_check_for_sigpipe();
216 void pa_context_free(struct pa_context
*c
) {
219 while (c
->first_stream
)
220 pa_stream_free(c
->first_stream
);
223 pa_socket_client_free(c
->client
);
225 pa_pdispatch_free(c
->pdispatch
);
227 pa_pstream_free(c
->pstream
);
228 if (c
->record_streams
)
229 pa_dynarray_free(c
->record_streams
, NULL
, NULL
);
230 if (c
->playback_streams
)
231 pa_dynarray_free(c
->playback_streams
, NULL
, NULL
);
237 static void stream_dead(struct pa_stream
*s
) {
240 if (s
->state
== STREAM_DEAD
)
243 if (s
->state
== STREAM_READY
) {
244 s
->state
= STREAM_DEAD
;
246 s
->die_callback(s
, s
->die_userdata
);
248 s
->state
= STREAM_DEAD
;
251 static void context_dead(struct pa_context
*c
) {
255 if (c
->state
== CONTEXT_DEAD
)
259 pa_pdispatch_free(c
->pdispatch
);
263 pa_pstream_free(c
->pstream
);
267 pa_socket_client_free(c
->client
);
270 for (s
= c
->first_stream
; s
; s
= s
->next
)
273 if (c
->state
== CONTEXT_READY
) {
274 c
->state
= CONTEXT_DEAD
;
276 c
->die_callback(c
, c
->die_userdata
);
278 c
->state
= CONTEXT_DEAD
;
281 static void pstream_die_callback(struct pa_pstream
*p
, void *userdata
) {
282 struct pa_context
*c
= userdata
;
284 c
->error
= PA_ERROR_CONNECTIONTERMINATED
;
288 static void pstream_packet_callback(struct pa_pstream
*p
, struct pa_packet
*packet
, void *userdata
) {
289 struct pa_context
*c
= userdata
;
290 assert(p
&& packet
&& c
);
292 if (pa_pdispatch_run(c
->pdispatch
, packet
, c
) < 0) {
293 fprintf(stderr
, "polyp.c: invalid packet.\n");
294 c
->error
= PA_ERROR_PROTOCOL
;
299 static void pstream_memblock_callback(struct pa_pstream
*p
, uint32_t channel
, int32_t delta
, const struct pa_memchunk
*chunk
, void *userdata
) {
300 struct pa_context
*c
= userdata
;
302 assert(p
&& chunk
&& c
&& chunk
->memblock
&& chunk
->memblock
->data
);
304 if (!(s
= pa_dynarray_get(c
->record_streams
, channel
)))
307 if (s
->read_callback
)
308 s
->read_callback(s
, chunk
->memblock
->data
+ chunk
->index
, chunk
->length
, s
->read_userdata
);
311 static int handle_error(struct pa_context
*c
, uint32_t command
, struct pa_tagstruct
*t
) {
314 if (command
== PA_COMMAND_ERROR
) {
315 if (pa_tagstruct_getu32(t
, &c
->error
) < 0) {
316 c
->error
= PA_ERROR_PROTOCOL
;
323 c
->error
= (command
== PA_COMMAND_TIMEOUT
) ? PA_ERROR_TIMEOUT
: PA_ERROR_INTERNAL
;
327 static void setup_complete_callback(struct pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, struct pa_tagstruct
*t
, void *userdata
) {
328 struct pa_context
*c
= userdata
;
329 assert(pd
&& c
&& (c
->state
== CONTEXT_AUTHORIZING
|| c
->state
== CONTEXT_SETTING_NAME
));
331 if (command
!= PA_COMMAND_REPLY
) {
332 handle_error(c
, command
, t
);
335 if (c
->connect_complete_callback
)
336 c
->connect_complete_callback(c
, 0, c
->connect_complete_userdata
);
341 if (c
->state
== CONTEXT_AUTHORIZING
) {
342 struct pa_tagstruct
*t
;
343 c
->state
= CONTEXT_SETTING_NAME
;
344 t
= pa_tagstruct_new(NULL
, 0);
346 pa_tagstruct_putu32(t
, PA_COMMAND_SET_NAME
);
347 pa_tagstruct_putu32(t
, tag
= c
->ctag
++);
348 pa_tagstruct_puts(t
, c
->name
);
349 pa_pstream_send_tagstruct(c
->pstream
, t
);
350 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, setup_complete_callback
, c
);
352 assert(c
->state
== CONTEXT_SETTING_NAME
);
354 c
->state
= CONTEXT_READY
;
356 if (c
->connect_complete_callback
)
357 c
->connect_complete_callback(c
, 1, c
->connect_complete_userdata
);
363 static void on_connection(struct pa_socket_client
*client
, struct pa_iochannel
*io
, void *userdata
) {
364 struct pa_context
*c
= userdata
;
365 struct pa_tagstruct
*t
;
367 assert(client
&& c
&& c
->state
== CONTEXT_CONNECTING
);
369 pa_socket_client_free(client
);
373 c
->error
= PA_ERROR_CONNECTIONREFUSED
;
376 if (c
->connect_complete_callback
)
377 c
->connect_complete_callback(c
, 0, c
->connect_complete_userdata
);
382 c
->pstream
= pa_pstream_new(c
->mainloop
, io
);
384 pa_pstream_set_die_callback(c
->pstream
, pstream_die_callback
, c
);
385 pa_pstream_set_recieve_packet_callback(c
->pstream
, pstream_packet_callback
, c
);
386 pa_pstream_set_recieve_memblock_callback(c
->pstream
, pstream_memblock_callback
, c
);
388 c
->pdispatch
= pa_pdispatch_new(c
->mainloop
, command_table
, PA_COMMAND_MAX
);
389 assert(c
->pdispatch
);
391 t
= pa_tagstruct_new(NULL
, 0);
393 pa_tagstruct_putu32(t
, PA_COMMAND_AUTH
);
394 pa_tagstruct_putu32(t
, tag
= c
->ctag
++);
395 pa_tagstruct_put_arbitrary(t
, c
->auth_cookie
, sizeof(c
->auth_cookie
));
396 pa_pstream_send_tagstruct(c
->pstream
, t
);
397 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, setup_complete_callback
, c
);
398 c
->state
= CONTEXT_AUTHORIZING
;
401 static struct sockaddr
*resolve_server(const char *server
, size_t *len
) {
403 struct addrinfo hints
, *result
= NULL
;
405 assert(server
&& len
);
407 if ((port
= strrchr(server
, ':')))
412 memset(&hints
, 0, sizeof(hints
));
413 hints
.ai_family
= PF_UNSPEC
;
414 hints
.ai_socktype
= SOCK_STREAM
;
415 hints
.ai_protocol
= 0;
417 if (getaddrinfo(server
, port
, &hints
, &result
) != 0)
421 sa
= pa_xmalloc(*len
= result
->ai_addrlen
);
422 memcpy(sa
, result
->ai_addr
, *len
);
424 freeaddrinfo(result
);
429 int pa_context_connect(struct pa_context
*c
, const char *server
, void (*complete
) (struct pa_context
*c
, int success
, void *userdata
), void *userdata
) {
430 assert(c
&& c
->state
== CONTEXT_UNCONNECTED
);
432 if (pa_authkey_load_from_home(PA_NATIVE_COOKIE_FILE
, c
->auth_cookie
, sizeof(c
->auth_cookie
)) < 0) {
433 c
->error
= PA_ERROR_AUTHKEY
;
438 if (!(server
= getenv("POLYP_SERVER")))
439 server
= DEFAULT_SERVER
;
443 if (*server
== '/') {
444 if (!(c
->client
= pa_socket_client_new_unix(c
->mainloop
, server
))) {
445 c
->error
= PA_ERROR_CONNECTIONREFUSED
;
452 if (!(sa
= resolve_server(server
, &sa_len
))) {
453 c
->error
= PA_ERROR_INVALIDSERVER
;
457 c
->client
= pa_socket_client_new_sockaddr(c
->mainloop
, sa
, sa_len
);
461 c
->error
= PA_ERROR_CONNECTIONREFUSED
;
466 c
->connect_complete_callback
= complete
;
467 c
->connect_complete_userdata
= userdata
;
469 pa_socket_client_set_callback(c
->client
, on_connection
, c
);
470 c
->state
= CONTEXT_CONNECTING
;
475 int pa_context_is_dead(struct pa_context
*c
) {
477 return c
->state
== CONTEXT_DEAD
;
480 int pa_context_is_ready(struct pa_context
*c
) {
482 return c
->state
== CONTEXT_READY
;
485 int pa_context_errno(struct pa_context
*c
) {
490 void pa_context_set_die_callback(struct pa_context
*c
, void (*cb
)(struct pa_context
*c
, void *userdata
), void *userdata
) {
492 c
->die_callback
= cb
;
493 c
->die_userdata
= userdata
;
496 static void command_playback_stream_killed(struct pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, struct pa_tagstruct
*t
, void *userdata
) {
497 struct pa_context
*c
= userdata
;
500 assert(pd
&& (command
== PA_COMMAND_PLAYBACK_STREAM_KILLED
|| command
== PA_COMMAND_RECORD_STREAM_KILLED
) && t
&& c
);
502 if (pa_tagstruct_getu32(t
, &channel
) < 0 ||
503 !pa_tagstruct_eof(t
)) {
504 c
->error
= PA_ERROR_PROTOCOL
;
509 if (!(s
= pa_dynarray_get(command
== PA_COMMAND_PLAYBACK_STREAM_KILLED
? c
->playback_streams
: c
->record_streams
, channel
)))
512 c
->error
= PA_ERROR_KILLED
;
516 static void command_request(struct pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, struct pa_tagstruct
*t
, void *userdata
) {
518 struct pa_context
*c
= userdata
;
519 uint32_t bytes
, channel
;
520 assert(pd
&& command
== PA_COMMAND_REQUEST
&& t
&& c
);
522 if (pa_tagstruct_getu32(t
, &channel
) < 0 ||
523 pa_tagstruct_getu32(t
, &bytes
) < 0 ||
524 !pa_tagstruct_eof(t
)) {
525 c
->error
= PA_ERROR_PROTOCOL
;
530 if (!(s
= pa_dynarray_get(c
->playback_streams
, channel
)))
533 if (s
->state
!= STREAM_READY
)
536 s
->requested_bytes
+= bytes
;
538 if (s
->requested_bytes
&& s
->write_callback
)
539 s
->write_callback(s
, s
->requested_bytes
, s
->write_userdata
);
542 static void create_stream_callback(struct pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, struct pa_tagstruct
*t
, void *userdata
) {
543 struct pa_stream
*s
= userdata
;
544 assert(pd
&& s
&& s
->state
== STREAM_CREATING
);
546 if (command
!= PA_COMMAND_REPLY
) {
547 if (handle_error(s
->context
, command
, t
) < 0) {
548 context_dead(s
->context
);
553 if (s
->create_complete_callback
)
554 s
->create_complete_callback(s
, 0, s
->create_complete_userdata
);
559 if (pa_tagstruct_getu32(t
, &s
->channel
) < 0 ||
560 ((s
->direction
!= PA_STREAM_UPLOAD
) && pa_tagstruct_getu32(t
, &s
->device_index
) < 0) ||
561 !pa_tagstruct_eof(t
)) {
562 s
->context
->error
= PA_ERROR_PROTOCOL
;
563 context_dead(s
->context
);
567 s
->channel_valid
= 1;
568 pa_dynarray_put((s
->direction
== PA_STREAM_RECORD
) ? s
->context
->record_streams
: s
->context
->playback_streams
, s
->channel
, s
);
570 s
->state
= STREAM_READY
;
571 if (s
->create_complete_callback
)
572 s
->create_complete_callback(s
, 1, s
->create_complete_userdata
);
575 static void create_stream(struct pa_stream
*s
, const char *dev
) {
576 struct pa_tagstruct
*t
;
580 s
->state
= STREAM_CREATING
;
582 t
= pa_tagstruct_new(NULL
, 0);
585 pa_tagstruct_putu32(t
, s
->direction
== PA_STREAM_PLAYBACK
? PA_COMMAND_CREATE_PLAYBACK_STREAM
: PA_COMMAND_CREATE_RECORD_STREAM
);
586 pa_tagstruct_putu32(t
, tag
= s
->context
->ctag
++);
587 pa_tagstruct_puts(t
, s
->name
);
588 pa_tagstruct_put_sample_spec(t
, &s
->sample_spec
);
589 pa_tagstruct_putu32(t
, (uint32_t) -1);
590 pa_tagstruct_puts(t
, dev
? dev
: "");
591 pa_tagstruct_putu32(t
, s
->buffer_attr
.maxlength
);
592 if (s
->direction
== PA_STREAM_PLAYBACK
) {
593 pa_tagstruct_putu32(t
, s
->buffer_attr
.tlength
);
594 pa_tagstruct_putu32(t
, s
->buffer_attr
.prebuf
);
595 pa_tagstruct_putu32(t
, s
->buffer_attr
.minreq
);
597 pa_tagstruct_putu32(t
, s
->buffer_attr
.fragsize
);
599 pa_pstream_send_tagstruct(s
->context
->pstream
, t
);
600 pa_pdispatch_register_reply(s
->context
->pdispatch
, tag
, DEFAULT_TIMEOUT
, create_stream_callback
, s
);
603 static struct pa_stream
*internal_stream_new(struct pa_context
*c
) {
606 s
= pa_xmalloc(sizeof(struct pa_stream
));
609 s
->read_callback
= NULL
;
610 s
->read_userdata
= NULL
;
611 s
->write_callback
= NULL
;
612 s
->write_userdata
= NULL
;
613 s
->die_callback
= NULL
;
614 s
->die_userdata
= NULL
;
615 s
->create_complete_callback
= NULL
;
616 s
->create_complete_userdata
= NULL
;
617 s
->get_latency_callback
= NULL
;
618 s
->get_latency_userdata
= NULL
;
619 s
->finish_sample_callback
= NULL
;
620 s
->finish_sample_userdata
= NULL
;
623 s
->state
= STREAM_CREATING
;
624 s
->requested_bytes
= 0;
626 s
->channel_valid
= 0;
627 s
->device_index
= (uint32_t) -1;
629 memset(&s
->buffer_attr
, 0, sizeof(s
->buffer_attr
));
631 s
->next
= c
->first_stream
;
633 s
->next
->previous
= s
;
640 struct pa_stream
* pa_stream_new(
641 struct pa_context
*c
,
642 enum pa_stream_direction dir
,
645 const struct pa_sample_spec
*ss
,
646 const struct pa_buffer_attr
*attr
,
647 void (*complete
) (struct pa_stream
*s
, int success
, void *userdata
),
652 assert(c
&& name
&& ss
&& c
->state
== CONTEXT_READY
&& (dir
== PA_STREAM_PLAYBACK
|| dir
== PA_STREAM_RECORD
));
654 s
= internal_stream_new(c
);
657 s
->create_complete_callback
= complete
;
658 s
->create_complete_userdata
= userdata
;
659 s
->name
= pa_xstrdup(name
);
660 s
->state
= STREAM_CREATING
;
662 s
->sample_spec
= *ss
;
664 s
->buffer_attr
= *attr
;
666 s
->buffer_attr
.maxlength
= DEFAULT_MAXLENGTH
;
667 s
->buffer_attr
.tlength
= DEFAULT_TLENGTH
;
668 s
->buffer_attr
.prebuf
= DEFAULT_PREBUF
;
669 s
->buffer_attr
.minreq
= DEFAULT_MINREQ
;
670 s
->buffer_attr
.fragsize
= DEFAULT_FRAGSIZE
;
673 create_stream(s
, dev
);
678 void pa_stream_free(struct pa_stream
*s
) {
679 assert(s
&& s
->context
);
681 if (s
->context
->pdispatch
)
682 pa_pdispatch_unregister_reply(s
->context
->pdispatch
, s
);
686 if (s
->channel_valid
&& s
->context
->state
== CONTEXT_READY
) {
687 struct pa_tagstruct
*t
= pa_tagstruct_new(NULL
, 0);
690 pa_tagstruct_putu32(t
, s
->direction
== PA_STREAM_PLAYBACK
? PA_COMMAND_DELETE_PLAYBACK_STREAM
:
691 (s
->direction
== PA_STREAM_RECORD
? PA_COMMAND_DELETE_RECORD_STREAM
: PA_COMMAND_DELETE_UPLOAD_STREAM
));
692 pa_tagstruct_putu32(t
, s
->context
->ctag
++);
693 pa_tagstruct_putu32(t
, s
->channel
);
694 pa_pstream_send_tagstruct(s
->context
->pstream
, t
);
697 if (s
->channel_valid
)
698 pa_dynarray_put((s
->direction
== PA_STREAM_PLAYBACK
) ? s
->context
->playback_streams
: s
->context
->record_streams
, s
->channel
, NULL
);
701 s
->next
->previous
= s
->previous
;
703 s
->previous
->next
= s
->next
;
705 s
->context
->first_stream
= s
->next
;
710 void pa_stream_set_write_callback(struct pa_stream
*s
, void (*cb
)(struct pa_stream
*p
, size_t length
, void *userdata
), void *userdata
) {
711 s
->write_callback
= cb
;
712 s
->write_userdata
= userdata
;
715 void pa_stream_write(struct pa_stream
*s
, const void *data
, size_t length
) {
716 struct pa_memchunk chunk
;
717 assert(s
&& s
->context
&& data
&& length
&& s
->state
== STREAM_READY
);
719 chunk
.memblock
= pa_memblock_new(length
);
720 assert(chunk
.memblock
&& chunk
.memblock
->data
);
721 memcpy(chunk
.memblock
->data
, data
, length
);
723 chunk
.length
= length
;
725 pa_pstream_send_memblock(s
->context
->pstream
, s
->channel
, 0, &chunk
);
726 pa_memblock_unref(chunk
.memblock
);
728 /*fprintf(stderr, "Sent %u bytes\n", length);*/
730 if (length
< s
->requested_bytes
)
731 s
->requested_bytes
-= length
;
733 s
->requested_bytes
= 0;
736 size_t pa_stream_writable_size(struct pa_stream
*s
) {
737 assert(s
&& s
->state
== STREAM_READY
);
738 return s
->requested_bytes
;
741 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
) {
743 s
->read_callback
= cb
;
744 s
->read_userdata
= userdata
;
747 int pa_stream_is_dead(struct pa_stream
*s
) {
748 return s
->state
== STREAM_DEAD
;
751 int pa_stream_is_ready(struct pa_stream
*s
) {
752 return s
->state
== STREAM_READY
;
755 void pa_stream_set_die_callback(struct pa_stream
*s
, void (*cb
)(struct pa_stream
*s
, void *userdata
), void *userdata
) {
757 s
->die_callback
= cb
;
758 s
->die_userdata
= userdata
;
761 int pa_context_is_pending(struct pa_context
*c
) {
764 if (c
->state
!= CONTEXT_READY
)
767 return pa_pstream_is_pending(c
->pstream
) || pa_pdispatch_is_pending(c
->pdispatch
);
770 struct pa_context
* pa_stream_get_context(struct pa_stream
*p
) {
775 static void set_dispatch_callbacks(struct pa_context
*c
);
777 static void pdispatch_drain_callback(struct pa_pdispatch
*pd
, void *userdata
) {
778 set_dispatch_callbacks(userdata
);
781 static void pstream_drain_callback(struct pa_pstream
*s
, void *userdata
) {
782 set_dispatch_callbacks(userdata
);
785 static void set_dispatch_callbacks(struct pa_context
*c
) {
786 assert(c
&& c
->state
== CONTEXT_READY
);
788 pa_pstream_set_drain_callback(c
->pstream
, NULL
, NULL
);
789 pa_pdispatch_set_drain_callback(c
->pdispatch
, NULL
, NULL
);
791 if (pa_pdispatch_is_pending(c
->pdispatch
)) {
792 pa_pdispatch_set_drain_callback(c
->pdispatch
, pdispatch_drain_callback
, c
);
796 if (pa_pstream_is_pending(c
->pstream
)) {
797 pa_pstream_set_drain_callback(c
->pstream
, pstream_drain_callback
, c
);
801 assert(c
->drain_complete_callback
);
802 c
->drain_complete_callback(c
, c
->drain_complete_userdata
);
805 int pa_context_drain(
806 struct pa_context
*c
,
807 void (*complete
) (struct pa_context
*c
, void *userdata
),
810 assert(c
&& c
->state
== CONTEXT_READY
);
812 if (complete
== NULL
) {
813 c
->drain_complete_callback
= NULL
;
814 pa_pstream_set_drain_callback(c
->pstream
, NULL
, NULL
);
815 pa_pdispatch_set_drain_callback(c
->pdispatch
, NULL
, NULL
);
819 if (!pa_context_is_pending(c
))
822 c
->drain_complete_callback
= complete
;
823 c
->drain_complete_userdata
= userdata
;
825 set_dispatch_callbacks(c
);
830 static void stream_drain_callback(struct pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, struct pa_tagstruct
*t
, void *userdata
) {
831 struct pa_stream
*s
= userdata
;
834 if (command
!= PA_COMMAND_REPLY
) {
835 if (handle_error(s
->context
, command
, t
) < 0) {
836 context_dead(s
->context
);
844 if (s
->state
!= STREAM_READY
)
847 if (!pa_tagstruct_eof(t
)) {
848 s
->context
->error
= PA_ERROR_PROTOCOL
;
849 context_dead(s
->context
);
853 if (s
->drain_complete_callback
) {
854 void (*temp
) (struct pa_stream
*s
, void *userdata
) = s
->drain_complete_callback
;
855 s
->drain_complete_callback
= NULL
;
856 temp(s
, s
->drain_complete_userdata
);
861 void pa_stream_drain(struct pa_stream
*s
, void (*complete
) (struct pa_stream
*s
, void *userdata
), void *userdata
) {
862 struct pa_tagstruct
*t
;
864 assert(s
&& s
->state
== STREAM_READY
);
867 s
->drain_complete_callback
= NULL
;
871 s
->drain_complete_callback
= complete
;
872 s
->drain_complete_userdata
= userdata
;
874 t
= pa_tagstruct_new(NULL
, 0);
877 pa_tagstruct_putu32(t
, PA_COMMAND_DRAIN_PLAYBACK_STREAM
);
878 pa_tagstruct_putu32(t
, tag
= s
->context
->ctag
++);
879 pa_tagstruct_putu32(t
, s
->channel
);
880 pa_pstream_send_tagstruct(s
->context
->pstream
, t
);
881 pa_pdispatch_register_reply(s
->context
->pdispatch
, tag
, DEFAULT_TIMEOUT
, stream_drain_callback
, s
);
884 void pa_context_exit(struct pa_context
*c
) {
885 struct pa_tagstruct
*t
;
886 t
= pa_tagstruct_new(NULL
, 0);
888 pa_tagstruct_putu32(t
, PA_COMMAND_EXIT
);
889 pa_tagstruct_putu32(t
, c
->ctag
++);
890 pa_pstream_send_tagstruct(c
->pstream
, t
);
893 static void context_stat_callback(struct pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, struct pa_tagstruct
*t
, void *userdata
) {
894 struct pa_context
*c
= userdata
;
895 uint32_t total
, count
;
898 if (command
!= PA_COMMAND_REPLY
) {
899 if (handle_error(c
, command
, t
) < 0) {
904 if (c
->stat_callback
)
905 c
->stat_callback(c
, (uint32_t) -1, (uint32_t) -1, c
->stat_userdata
);
909 if (pa_tagstruct_getu32(t
, &count
) < 0 ||
910 pa_tagstruct_getu32(t
, &total
) < 0 ||
911 !pa_tagstruct_eof(t
)) {
912 c
->error
= PA_ERROR_PROTOCOL
;
917 if (c
->stat_callback
)
918 c
->stat_callback(c
, count
, total
, c
->stat_userdata
);
921 void pa_context_stat(struct pa_context
*c
, void (*cb
)(struct pa_context
*c
, uint32_t count
, uint32_t total
, void *userdata
), void *userdata
) {
923 struct pa_tagstruct
*t
;
925 c
->stat_callback
= cb
;
926 c
->stat_userdata
= userdata
;
931 t
= pa_tagstruct_new(NULL
, 0);
933 pa_tagstruct_putu32(t
, PA_COMMAND_STAT
);
934 pa_tagstruct_putu32(t
, tag
= c
->ctag
++);
935 pa_pstream_send_tagstruct(c
->pstream
, t
);
936 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, context_stat_callback
, c
);
939 static void stream_get_latency_callback(struct pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, struct pa_tagstruct
*t
, void *userdata
) {
940 struct pa_stream
*s
= userdata
;
944 if (command
!= PA_COMMAND_REPLY
) {
945 if (handle_error(s
->context
, command
, t
) < 0) {
946 context_dead(s
->context
);
950 if (s
->get_latency_callback
)
951 s
->get_latency_callback(s
, (uint32_t) -1, s
->get_latency_userdata
);
955 if (pa_tagstruct_getu32(t
, &latency
) < 0 ||
956 !pa_tagstruct_eof(t
)) {
957 s
->context
->error
= PA_ERROR_PROTOCOL
;
958 context_dead(s
->context
);
962 if (s
->get_latency_callback
)
963 s
->get_latency_callback(s
, latency
, s
->get_latency_userdata
);
966 void pa_stream_get_latency(struct pa_stream
*p
, void (*cb
)(struct pa_stream
*p
, uint32_t latency
, void *userdata
), void *userdata
) {
968 struct pa_tagstruct
*t
;
970 p
->get_latency_callback
= cb
;
971 p
->get_latency_userdata
= userdata
;
976 t
= pa_tagstruct_new(NULL
, 0);
978 pa_tagstruct_putu32(t
, PA_COMMAND_GET_PLAYBACK_LATENCY
);
979 pa_tagstruct_putu32(t
, tag
= p
->context
->ctag
++);
980 pa_tagstruct_putu32(t
, p
->channel
);
981 pa_pstream_send_tagstruct(p
->context
->pstream
, t
);
982 pa_pdispatch_register_reply(p
->context
->pdispatch
, tag
, DEFAULT_TIMEOUT
, stream_get_latency_callback
, p
);
985 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
) {
987 struct pa_tagstruct
*t
;
990 s
= internal_stream_new(c
);
993 s
->create_complete_callback
= cb
;
994 s
->create_complete_userdata
= userdata
;
995 s
->name
= pa_xstrdup(name
);
996 s
->state
= STREAM_CREATING
;
997 s
->direction
= PA_STREAM_UPLOAD
;
998 s
->sample_spec
= *ss
;
1000 t
= pa_tagstruct_new(NULL
, 0);
1002 pa_tagstruct_putu32(t
, PA_COMMAND_CREATE_UPLOAD_STREAM
);
1003 pa_tagstruct_putu32(t
, tag
= c
->ctag
++);
1004 pa_tagstruct_puts(t
, name
);
1005 pa_tagstruct_put_sample_spec(t
, ss
);
1006 pa_tagstruct_putu32(t
, length
);
1007 pa_pstream_send_tagstruct(c
->pstream
, t
);
1008 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, create_stream_callback
, s
);
1013 static void stream_finish_sample_callback(struct pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, struct pa_tagstruct
*t
, void *userdata
) {
1014 struct pa_stream
*s
= userdata
;
1017 if (command
!= PA_COMMAND_REPLY
) {
1018 if (handle_error(s
->context
, command
, t
) < 0) {
1019 context_dead(s
->context
);
1023 if (s
->finish_sample_callback
)
1024 s
->finish_sample_callback(s
, 0, s
->finish_sample_userdata
);
1028 if (!pa_tagstruct_eof(t
)) {
1029 s
->context
->error
= PA_ERROR_PROTOCOL
;
1030 context_dead(s
->context
);
1034 if (s
->finish_sample_callback
)
1035 s
->finish_sample_callback(s
, 1, s
->finish_sample_userdata
);
1038 void pa_stream_finish_sample(struct pa_stream
*p
, void (*cb
)(struct pa_stream
*s
, int success
, void *userdata
), void *userdata
) {
1039 struct pa_tagstruct
*t
;
1043 p
->finish_sample_callback
= cb
;
1044 p
->finish_sample_userdata
= userdata
;
1046 t
= pa_tagstruct_new(NULL
, 0);
1048 pa_tagstruct_putu32(t
, PA_COMMAND_FINISH_UPLOAD_STREAM
);
1049 pa_tagstruct_putu32(t
, tag
= p
->context
->ctag
++);
1050 pa_tagstruct_putu32(t
, p
->channel
);
1051 pa_pstream_send_tagstruct(p
->context
->pstream
, t
);
1052 pa_pdispatch_register_reply(p
->context
->pdispatch
, tag
, DEFAULT_TIMEOUT
, stream_finish_sample_callback
, p
);
1055 static void context_play_sample_callback(struct pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, struct pa_tagstruct
*t
, void *userdata
) {
1056 struct pa_context
*c
= userdata
;
1059 if (command
!= PA_COMMAND_REPLY
) {
1060 if (handle_error(c
, command
, t
) < 0) {
1065 if (c
->play_sample_callback
)
1066 c
->play_sample_callback(c
, 0, c
->play_sample_userdata
);
1070 if (!pa_tagstruct_eof(t
)) {
1071 c
->error
= PA_ERROR_PROTOCOL
;
1076 if (c
->play_sample_callback
)
1077 c
->play_sample_callback(c
, 1, c
->play_sample_userdata
);
1080 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
) {
1081 struct pa_tagstruct
*t
;
1083 assert(c
&& name
&& *name
&& (!dev
|| *dev
));
1085 c
->play_sample_callback
= cb
;
1086 c
->play_sample_userdata
= userdata
;
1091 t
= pa_tagstruct_new(NULL
, 0);
1093 pa_tagstruct_putu32(t
, PA_COMMAND_PLAY_SAMPLE
);
1094 pa_tagstruct_putu32(t
, tag
= c
->ctag
++);
1095 pa_tagstruct_putu32(t
, (uint32_t) -1);
1096 pa_tagstruct_puts(t
, dev
? dev
: "");
1097 pa_tagstruct_putu32(t
, volume
);
1098 pa_tagstruct_puts(t
, name
);
1099 pa_pstream_send_tagstruct(c
->pstream
, t
);
1100 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, context_play_sample_callback
, c
);
1103 static void context_remove_sample_callback(struct pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, struct pa_tagstruct
*t
, void *userdata
) {
1104 struct pa_context
*c
= userdata
;
1107 if (command
!= PA_COMMAND_REPLY
) {
1108 if (handle_error(c
, command
, t
) < 0) {
1113 if (c
->remove_sample_callback
)
1114 c
->remove_sample_callback(c
, 0, c
->remove_sample_userdata
);
1118 if (!pa_tagstruct_eof(t
)) {
1119 c
->error
= PA_ERROR_PROTOCOL
;
1124 if (c
->remove_sample_callback
)
1125 c
->remove_sample_callback(c
, 1, c
->remove_sample_userdata
);
1128 void pa_context_remove_sample(struct pa_context
*c
, const char *name
, void (*cb
)(struct pa_context
*c
, int success
, void *userdata
), void *userdata
) {
1129 struct pa_tagstruct
*t
;
1133 c
->remove_sample_callback
= cb
;
1134 c
->remove_sample_userdata
= userdata
;
1139 t
= pa_tagstruct_new(NULL
, 0);
1141 pa_tagstruct_putu32(t
, PA_COMMAND_REMOVE_SAMPLE
);
1142 pa_tagstruct_putu32(t
, tag
= c
->ctag
++);
1143 pa_tagstruct_puts(t
, name
);
1144 pa_pstream_send_tagstruct(c
->pstream
, t
);
1145 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, context_remove_sample_callback
, c
);
1148 static void context_get_server_info_callback(struct pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, struct pa_tagstruct
*t
, void *userdata
) {
1149 struct pa_context
*c
= userdata
;
1150 struct pa_server_info i
;
1153 if (command
!= PA_COMMAND_REPLY
) {
1154 if (handle_error(c
, command
, t
) < 0) {
1159 if (c
->get_server_info_callback
)
1160 c
->get_server_info_callback(c
, NULL
, c
->get_server_info_userdata
);
1164 if (pa_tagstruct_gets(t
, &i
.server_name
) < 0 ||
1165 pa_tagstruct_gets(t
, &i
.server_version
) < 0 ||
1166 pa_tagstruct_gets(t
, &i
.user_name
) < 0 ||
1167 pa_tagstruct_gets(t
, &i
.host_name
) < 0 ||
1168 pa_tagstruct_get_sample_spec(t
, &i
.sample_spec
) < 0 ||
1169 !pa_tagstruct_eof(t
)) {
1170 c
->error
= PA_ERROR_PROTOCOL
;
1175 if (c
->get_server_info_callback
)
1176 c
->get_server_info_callback(c
, &i
, c
->get_server_info_userdata
);
1179 void pa_context_get_server_info(struct pa_context
*c
, void (*cb
)(struct pa_context
*c
, const struct pa_server_info
*i
, void *userdata
), void *userdata
) {
1180 struct pa_tagstruct
*t
;
1184 c
->get_server_info_callback
= cb
;
1185 c
->get_server_info_userdata
= userdata
;
1190 t
= pa_tagstruct_new(NULL
, 0);
1192 pa_tagstruct_putu32(t
, PA_COMMAND_GET_SERVER_INFO
);
1193 pa_tagstruct_putu32(t
, tag
= c
->ctag
++);
1194 pa_pstream_send_tagstruct(c
->pstream
, t
);
1195 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, context_get_server_info_callback
, c
);
1198 static void context_get_sink_info_callback(struct pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, struct pa_tagstruct
*t
, void *userdata
) {
1199 struct pa_context
*c
= userdata
;
1202 if (command
!= PA_COMMAND_REPLY
) {
1203 if (handle_error(c
, command
, t
) < 0) {
1208 if (c
->get_sink_info_callback
)
1209 c
->get_sink_info_callback(c
, NULL
, 0, c
->get_sink_info_userdata
);
1213 while (!pa_tagstruct_eof(t
)) {
1214 struct pa_sink_info i
;
1216 if (pa_tagstruct_getu32(t
, &i
.index
) < 0 ||
1217 pa_tagstruct_gets(t
, &i
.name
) < 0 ||
1218 pa_tagstruct_gets(t
, &i
.description
) < 0 ||
1219 pa_tagstruct_get_sample_spec(t
, &i
.sample_spec
) < 0 ||
1220 pa_tagstruct_getu32(t
, &i
.owner_module
) < 0 ||
1221 pa_tagstruct_getu32(t
, &i
.volume
) < 0 ||
1222 pa_tagstruct_getu32(t
, &i
.monitor_source
) < 0 ||
1223 pa_tagstruct_gets(t
, &i
.monitor_source_name
) < 0 ||
1224 pa_tagstruct_getu32(t
, &i
.latency
) < 0) {
1225 c
->error
= PA_ERROR_PROTOCOL
;
1230 if (c
->get_sink_info_callback
)
1231 c
->get_sink_info_callback(c
, &i
, 0, c
->get_sink_info_userdata
);
1234 if (c
->get_sink_info_callback
)
1235 c
->get_sink_info_callback(c
, NULL
, 1, c
->get_sink_info_userdata
);
1238 void pa_context_get_sink_info_list(struct pa_context
*c
, void (*cb
)(struct pa_context
*c
, const struct pa_sink_info
*i
, int is_last
, void *userdata
), void *userdata
) {
1239 struct pa_tagstruct
*t
;
1243 c
->get_sink_info_callback
= cb
;
1244 c
->get_sink_info_userdata
= userdata
;
1249 t
= pa_tagstruct_new(NULL
, 0);
1251 pa_tagstruct_putu32(t
, PA_COMMAND_GET_SINK_INFO_LIST
);
1252 pa_tagstruct_putu32(t
, tag
= c
->ctag
++);
1253 pa_pstream_send_tagstruct(c
->pstream
, t
);
1254 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, context_get_sink_info_callback
, c
);
1257 static void context_get_source_info_callback(struct pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, struct pa_tagstruct
*t
, void *userdata
) {
1258 struct pa_context
*c
= userdata
;
1261 if (command
!= PA_COMMAND_REPLY
) {
1262 if (handle_error(c
, command
, t
) < 0) {
1267 if (c
->get_source_info_callback
)
1268 c
->get_source_info_callback(c
, NULL
, 0, c
->get_source_info_userdata
);
1272 while (!pa_tagstruct_eof(t
)) {
1273 struct pa_source_info i
;
1275 if (pa_tagstruct_getu32(t
, &i
.index
) < 0 ||
1276 pa_tagstruct_gets(t
, &i
.name
) < 0 ||
1277 pa_tagstruct_gets(t
, &i
.description
) < 0 ||
1278 pa_tagstruct_get_sample_spec(t
, &i
.sample_spec
) < 0 ||
1279 pa_tagstruct_getu32(t
, &i
.owner_module
) < 0 ||
1280 pa_tagstruct_getu32(t
, &i
.monitor_of_sink
) < 0 ||
1281 pa_tagstruct_gets(t
, &i
.monitor_of_sink_name
) < 0) {
1282 c
->error
= PA_ERROR_PROTOCOL
;
1287 if (c
->get_source_info_callback
)
1288 c
->get_source_info_callback(c
, &i
, 0, c
->get_source_info_userdata
);
1291 if (c
->get_source_info_callback
)
1292 c
->get_source_info_callback(c
, NULL
, 1, c
->get_source_info_userdata
);
1295 void pa_context_get_source_info_list(struct pa_context
*c
, void (*cb
)(struct pa_context
*c
, const struct pa_source_info
*i
, int is_last
, void *userdata
), void *userdata
) {
1296 struct pa_tagstruct
*t
;
1300 c
->get_source_info_callback
= cb
;
1301 c
->get_source_info_userdata
= userdata
;
1306 t
= pa_tagstruct_new(NULL
, 0);
1308 pa_tagstruct_putu32(t
, PA_COMMAND_GET_SOURCE_INFO_LIST
);
1309 pa_tagstruct_putu32(t
, tag
= c
->ctag
++);
1310 pa_pstream_send_tagstruct(c
->pstream
, t
);
1311 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, context_get_source_info_callback
, c
);
1314 void pa_context_subscribe(struct pa_context
*c
, enum pa_subscription_mask m
, void (*cb
)(struct pa_context
*c
, enum pa_subscription_event_type t
, uint32_t index
, void *userdata
), void *userdata
) {
1315 struct pa_tagstruct
*t
;
1318 c
->subscribe_callback
= cb
;
1319 c
->subscribe_userdata
= userdata
;
1320 c
->subscribe_mask
= m
;
1322 t
= pa_tagstruct_new(NULL
, 0);
1324 pa_tagstruct_putu32(t
, PA_COMMAND_SUBSCRIBE
);
1325 pa_tagstruct_putu32(t
, c
->ctag
++);
1326 pa_tagstruct_putu32(t
, cb
? m
: 0);
1327 pa_pstream_send_tagstruct(c
->pstream
, t
);
1330 static void command_subscribe_event(struct pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, struct pa_tagstruct
*t
, void *userdata
) {
1331 struct pa_context
*c
= userdata
;
1332 enum pa_subscription_event_type e
;
1334 assert(pd
&& command
== PA_COMMAND_SUBSCRIBE_EVENT
&& t
&& c
);
1336 if (pa_tagstruct_getu32(t
, &e
) < 0 ||
1337 pa_tagstruct_getu32(t
, &index
) < 0 ||
1338 !pa_tagstruct_eof(t
)) {
1339 c
->error
= PA_ERROR_PROTOCOL
;
1344 if (pa_subscription_match_flags(c
->subscribe_mask
, e
) && c
->subscribe_callback
)
1345 c
->subscribe_callback(c
, e
, index
, c
->subscribe_userdata
);
1348 void pa_context_get_sink_info_by_index(struct pa_context
*c
, uint32_t index
, void (*cb
)(struct pa_context
*c
, const struct pa_sink_info
*i
, int is_last
, void *userdata
), void *userdata
) {
1349 struct pa_tagstruct
*t
;
1353 c
->get_sink_info_callback
= cb
;
1354 c
->get_sink_info_userdata
= userdata
;
1359 t
= pa_tagstruct_new(NULL
, 0);
1361 pa_tagstruct_putu32(t
, PA_COMMAND_GET_SINK_INFO
);
1362 pa_tagstruct_putu32(t
, tag
= c
->ctag
++);
1363 pa_tagstruct_putu32(t
, index
);
1364 pa_tagstruct_puts(t
, "");
1365 pa_pstream_send_tagstruct(c
->pstream
, t
);
1366 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, context_get_sink_info_callback
, c
);
1369 void pa_context_get_source_info_by_index(struct pa_context
*c
, uint32_t index
, void (*cb
)(struct pa_context
*c
, const struct pa_source_info
*i
, int is_last
, void *userdata
), void *userdata
) {
1370 struct pa_tagstruct
*t
;
1374 c
->get_source_info_callback
= cb
;
1375 c
->get_source_info_userdata
= userdata
;
1380 t
= pa_tagstruct_new(NULL
, 0);
1382 pa_tagstruct_putu32(t
, PA_COMMAND_GET_SOURCE_INFO
);
1383 pa_tagstruct_putu32(t
, tag
= c
->ctag
++);
1384 pa_tagstruct_putu32(t
, index
);
1385 pa_tagstruct_puts(t
, "");
1386 pa_pstream_send_tagstruct(c
->pstream
, t
);
1387 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, context_get_source_info_callback
, c
);