Merge commit 'origin/master-tx'
[platform/upstream/pulseaudio.git] / src / pulse / introspect.c
1 /***
2   This file is part of PulseAudio.
3
4   Copyright 2004-2006 Lennart Poettering
5   Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
6
7   PulseAudio is free software; you can redistribute it and/or modify
8   it under the terms of the GNU Lesser General Public License as published
9   by the Free Software Foundation; either version 2.1 of the License,
10   or (at your option) any later version.
11
12   PulseAudio is distributed in the hope that it will be useful, but
13   WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   General Public License for more details.
16
17   You should have received a copy of the GNU Lesser General Public License
18   along with PulseAudio; if not, write to the Free Software
19   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20   USA.
21 ***/
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <string.h>
28
29 #include <pulse/context.h>
30 #include <pulse/gccmacro.h>
31 #include <pulse/xmalloc.h>
32
33 #include <pulsecore/macro.h>
34 #include <pulsecore/core-util.h>
35 #include <pulsecore/pstream-util.h>
36
37 #include "internal.h"
38 #include "fork-detect.h"
39
40 #include "introspect.h"
41
42 /*** Statistics ***/
43
44 static void context_stat_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
45     pa_operation *o = userdata;
46     pa_stat_info i, *p = &i;
47
48     pa_assert(pd);
49     pa_assert(o);
50     pa_assert(PA_REFCNT_VALUE(o) >= 1);
51
52     pa_zero(i);
53
54     if (!o->context)
55         goto finish;
56
57     if (command != PA_COMMAND_REPLY) {
58         if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
59             goto finish;
60
61         p = NULL;
62     } else if (pa_tagstruct_getu32(t, &i.memblock_total) < 0 ||
63                pa_tagstruct_getu32(t, &i.memblock_total_size) < 0 ||
64                pa_tagstruct_getu32(t, &i.memblock_allocated) < 0 ||
65                pa_tagstruct_getu32(t, &i.memblock_allocated_size) < 0 ||
66                pa_tagstruct_getu32(t, &i.scache_size) < 0 ||
67                !pa_tagstruct_eof(t)) {
68         pa_context_fail(o->context, PA_ERR_PROTOCOL);
69         goto finish;
70     }
71
72     if (o->callback) {
73         pa_stat_info_cb_t cb = (pa_stat_info_cb_t) o->callback;
74         cb(o->context, p, o->userdata);
75     }
76
77 finish:
78     pa_operation_done(o);
79     pa_operation_unref(o);
80 }
81
82 pa_operation* pa_context_stat(pa_context *c, pa_stat_info_cb_t cb, void *userdata) {
83     return pa_context_send_simple_command(c, PA_COMMAND_STAT, context_stat_callback, (pa_operation_cb_t) cb, userdata);
84 }
85
86 /*** Server Info ***/
87
88 static void context_get_server_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
89     pa_operation *o = userdata;
90     pa_server_info i, *p = &i;
91
92     pa_assert(pd);
93     pa_assert(o);
94     pa_assert(PA_REFCNT_VALUE(o) >= 1);
95
96     pa_zero(i);
97
98     if (!o->context)
99         goto finish;
100
101     if (command != PA_COMMAND_REPLY) {
102         if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
103             goto finish;
104
105         p = NULL;
106     } else if (pa_tagstruct_gets(t, &i.server_name) < 0 ||
107                pa_tagstruct_gets(t, &i.server_version) < 0 ||
108                pa_tagstruct_gets(t, &i.user_name) < 0 ||
109                pa_tagstruct_gets(t, &i.host_name) < 0 ||
110                pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
111                pa_tagstruct_gets(t, &i.default_sink_name) < 0 ||
112                pa_tagstruct_gets(t, &i.default_source_name) < 0 ||
113                pa_tagstruct_getu32(t, &i.cookie) < 0 ||
114                (o->context->version >= 15 &&
115                 pa_tagstruct_get_channel_map(t, &i.channel_map) < 0) ||
116                !pa_tagstruct_eof(t)) {
117
118         pa_context_fail(o->context, PA_ERR_PROTOCOL);
119         goto finish;
120     }
121
122     if (p && o->context->version < 15)
123         pa_channel_map_init_extend(&i.channel_map, i.sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
124
125     if (o->callback) {
126         pa_server_info_cb_t cb = (pa_server_info_cb_t) o->callback;
127         cb(o->context, p, o->userdata);
128     }
129
130 finish:
131     pa_operation_done(o);
132     pa_operation_unref(o);
133 }
134
135 pa_operation* pa_context_get_server_info(pa_context *c, pa_server_info_cb_t cb, void *userdata) {
136     return pa_context_send_simple_command(c, PA_COMMAND_GET_SERVER_INFO, context_get_server_info_callback, (pa_operation_cb_t) cb, userdata);
137 }
138
139 /*** Sink Info ***/
140
141 static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
142     pa_operation *o = userdata;
143     int eol = 1;
144
145     pa_assert(pd);
146     pa_assert(o);
147     pa_assert(PA_REFCNT_VALUE(o) >= 1);
148
149     if (!o->context)
150         goto finish;
151
152     if (command != PA_COMMAND_REPLY) {
153         if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
154             goto finish;
155
156         eol = -1;
157     } else {
158
159         while (!pa_tagstruct_eof(t)) {
160             pa_sink_info i;
161             pa_bool_t mute;
162             uint32_t flags;
163             uint32_t state;
164             uint32_t j;
165             const char *ap = NULL;
166
167             pa_zero(i);
168             i.proplist = pa_proplist_new();
169             i.base_volume = PA_VOLUME_NORM;
170             i.n_volume_steps = PA_VOLUME_NORM+1;
171             mute = FALSE;
172             state = PA_SINK_INVALID_STATE;
173             i.card = PA_INVALID_INDEX;
174
175             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
176                 pa_tagstruct_gets(t, &i.name) < 0 ||
177                 pa_tagstruct_gets(t, &i.description) < 0 ||
178                 pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
179                 pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 ||
180                 pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
181                 pa_tagstruct_get_cvolume(t, &i.volume) < 0 ||
182                 pa_tagstruct_get_boolean(t, &mute) < 0 ||
183                 pa_tagstruct_getu32(t, &i.monitor_source) < 0 ||
184                 pa_tagstruct_gets(t, &i.monitor_source_name) < 0 ||
185                 pa_tagstruct_get_usec(t, &i.latency) < 0 ||
186                 pa_tagstruct_gets(t, &i.driver) < 0 ||
187                 pa_tagstruct_getu32(t, &flags) < 0 ||
188                 (o->context->version >= 13 &&
189                  (pa_tagstruct_get_proplist(t, i.proplist) < 0 ||
190                   pa_tagstruct_get_usec(t, &i.configured_latency) < 0)) ||
191                 (o->context->version >= 15 &&
192                  (pa_tagstruct_get_volume(t, &i.base_volume) < 0 ||
193                   pa_tagstruct_getu32(t, &state) < 0 ||
194                   pa_tagstruct_getu32(t, &i.n_volume_steps) < 0 ||
195                   pa_tagstruct_getu32(t, &i.card) < 0)) ||
196                 (o->context->version >= 16 &&
197                  (pa_tagstruct_getu32(t, &i.n_ports)))) {
198
199                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
200                 pa_proplist_free(i.proplist);
201                 goto finish;
202             }
203
204             if (i.n_ports > 0) {
205                 i.ports = pa_xnew(pa_sink_port_info*, i.n_ports+1);
206                 i.ports[0] = pa_xnew(pa_sink_port_info, i.n_ports);
207
208                 for (j = 0; j < i.n_ports; j++) {
209                     if (pa_tagstruct_gets(t, &i.ports[0][j].name) < 0 ||
210                         pa_tagstruct_gets(t, &i.ports[0][j].description) < 0 ||
211                         pa_tagstruct_getu32(t, &i.ports[0][j].priority) < 0) {
212
213                         pa_context_fail(o->context, PA_ERR_PROTOCOL);
214                         pa_xfree(i.ports);
215                         pa_xfree(i.ports[0]);
216                         pa_proplist_free(i.proplist);
217                         goto finish;
218                     }
219
220                     i.ports[j] = &i.ports[0][j];
221                 }
222
223                 i.ports[j] = NULL;
224             }
225
226             if (pa_tagstruct_gets(t, &ap) < 0) {
227                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
228                 pa_xfree(i.ports[0]);
229                 pa_xfree(i.ports);
230                 pa_proplist_free(i.proplist);
231                 goto finish;
232             }
233
234             if (ap) {
235                 for (j = 0; j < i.n_ports; j++)
236                     if (pa_streq(i.ports[j]->name, ap)) {
237                         i.active_port = i.ports[j];
238                         break;
239                     }
240             }
241
242             i.mute = (int) mute;
243             i.flags = (pa_sink_flags_t) flags;
244             i.state = (pa_sink_state_t) state;
245
246             if (o->callback) {
247                 pa_sink_info_cb_t cb = (pa_sink_info_cb_t) o->callback;
248                 cb(o->context, &i, 0, o->userdata);
249             }
250
251             pa_proplist_free(i.proplist);
252         }
253     }
254
255     if (o->callback) {
256         pa_sink_info_cb_t cb = (pa_sink_info_cb_t) o->callback;
257         cb(o->context, NULL, eol, o->userdata);
258     }
259
260 finish:
261     pa_operation_done(o);
262     pa_operation_unref(o);
263 }
264
265 pa_operation* pa_context_get_sink_info_list(pa_context *c, pa_sink_info_cb_t cb, void *userdata) {
266     return pa_context_send_simple_command(c, PA_COMMAND_GET_SINK_INFO_LIST, context_get_sink_info_callback, (pa_operation_cb_t) cb, userdata);
267 }
268
269 pa_operation* pa_context_get_sink_info_by_index(pa_context *c, uint32_t idx, pa_sink_info_cb_t cb, void *userdata) {
270     pa_tagstruct *t;
271     pa_operation *o;
272     uint32_t tag;
273
274     pa_assert(c);
275     pa_assert(PA_REFCNT_VALUE(c) >= 1);
276     pa_assert(cb);
277
278     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
279     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
280
281     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
282
283     t = pa_tagstruct_command(c, PA_COMMAND_GET_SINK_INFO, &tag);
284     pa_tagstruct_putu32(t, idx);
285     pa_tagstruct_puts(t, NULL);
286     pa_pstream_send_tagstruct(c->pstream, t);
287     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
288
289     return o;
290 }
291
292 pa_operation* pa_context_get_sink_info_by_name(pa_context *c, const char *name, pa_sink_info_cb_t cb, void *userdata) {
293     pa_tagstruct *t;
294     pa_operation *o;
295     uint32_t tag;
296
297     pa_assert(c);
298     pa_assert(PA_REFCNT_VALUE(c) >= 1);
299     pa_assert(cb);
300
301     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
302     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
303     PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
304
305     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
306
307     t = pa_tagstruct_command(c, PA_COMMAND_GET_SINK_INFO, &tag);
308     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
309     pa_tagstruct_puts(t, name);
310     pa_pstream_send_tagstruct(c->pstream, t);
311     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
312
313     return o;
314 }
315
316 pa_operation* pa_context_set_sink_port_by_index(pa_context *c, uint32_t idx, const char*port, pa_context_success_cb_t cb, void *userdata) {
317     pa_operation *o;
318     pa_tagstruct *t;
319     uint32_t tag;
320
321     pa_assert(c);
322     pa_assert(PA_REFCNT_VALUE(c) >= 1);
323
324     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
325     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
326     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
327     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 16, PA_ERR_NOTSUPPORTED);
328
329     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
330
331     t = pa_tagstruct_command(c, PA_COMMAND_SET_SINK_PORT, &tag);
332     pa_tagstruct_putu32(t, idx);
333     pa_tagstruct_puts(t, NULL);
334     pa_tagstruct_puts(t, port);
335     pa_pstream_send_tagstruct(c->pstream, t);
336     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
337
338     return o;
339 }
340
341 pa_operation* pa_context_set_sink_port_by_name(pa_context *c, const char *name, const char*port, pa_context_success_cb_t cb, void *userdata) {
342     pa_operation *o;
343     pa_tagstruct *t;
344     uint32_t tag;
345
346     pa_assert(c);
347     pa_assert(PA_REFCNT_VALUE(c) >= 1);
348
349     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
350     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
351     PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
352     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 16, PA_ERR_NOTSUPPORTED);
353
354     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
355
356     t = pa_tagstruct_command(c, PA_COMMAND_SET_SINK_PORT, &tag);
357     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
358     pa_tagstruct_puts(t, name);
359     pa_tagstruct_puts(t, port);
360     pa_pstream_send_tagstruct(c->pstream, t);
361     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
362
363     return o;
364 }
365
366 /*** Source info ***/
367
368 static void context_get_source_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
369     pa_operation *o = userdata;
370     int eol = 1;
371
372     pa_assert(pd);
373     pa_assert(o);
374     pa_assert(PA_REFCNT_VALUE(o) >= 1);
375
376     if (!o->context)
377         goto finish;
378
379     if (command != PA_COMMAND_REPLY) {
380         if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
381             goto finish;
382
383         eol = -1;
384     } else {
385
386         while (!pa_tagstruct_eof(t)) {
387             pa_source_info i;
388             pa_bool_t mute;
389             uint32_t flags;
390             uint32_t state;
391             unsigned j;
392             const char *ap;
393
394             pa_zero(i);
395             i.proplist = pa_proplist_new();
396             i.base_volume = PA_VOLUME_NORM;
397             i.n_volume_steps = PA_VOLUME_NORM+1;
398             mute = FALSE;
399             state = PA_SOURCE_INVALID_STATE;
400             i.card = PA_INVALID_INDEX;
401
402             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
403                 pa_tagstruct_gets(t, &i.name) < 0 ||
404                 pa_tagstruct_gets(t, &i.description) < 0 ||
405                 pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
406                 pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 ||
407                 pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
408                 pa_tagstruct_get_cvolume(t, &i.volume) < 0 ||
409                 pa_tagstruct_get_boolean(t, &mute) < 0 ||
410                 pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 ||
411                 pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0 ||
412                 pa_tagstruct_get_usec(t, &i.latency) < 0 ||
413                 pa_tagstruct_gets(t, &i.driver) < 0 ||
414                 pa_tagstruct_getu32(t, &flags) < 0 ||
415                 (o->context->version >= 13 &&
416                  (pa_tagstruct_get_proplist(t, i.proplist) < 0 ||
417                   pa_tagstruct_get_usec(t, &i.configured_latency) < 0)) ||
418                 (o->context->version >= 15 &&
419                  (pa_tagstruct_get_volume(t, &i.base_volume) < 0 ||
420                   pa_tagstruct_getu32(t, &state) < 0 ||
421                   pa_tagstruct_getu32(t, &i.n_volume_steps) < 0 ||
422                   pa_tagstruct_getu32(t, &i.card) < 0)) ||
423                 (o->context->version >= 16 &&
424                  (pa_tagstruct_getu32(t, &i.n_ports)))) {
425
426                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
427                 pa_proplist_free(i.proplist);
428                 goto finish;
429             }
430
431             if (i.n_ports > 0) {
432                 i.ports = pa_xnew(pa_source_port_info*, i.n_ports+1);
433                 i.ports[0] = pa_xnew(pa_source_port_info, i.n_ports);
434
435                 for (j = 0; j < i.n_ports; j++) {
436                     if (pa_tagstruct_gets(t, &i.ports[0][j].name) < 0 ||
437                         pa_tagstruct_gets(t, &i.ports[0][j].description) < 0 ||
438                         pa_tagstruct_getu32(t, &i.ports[0][j].priority) < 0) {
439
440                         pa_context_fail(o->context, PA_ERR_PROTOCOL);
441                         pa_xfree(i.ports[0]);
442                         pa_xfree(i.ports);
443                         pa_proplist_free(i.proplist);
444                         goto finish;
445                     }
446
447                     i.ports[j] = &i.ports[0][j];
448                 }
449
450                 i.ports[j] = NULL;
451             }
452
453             if (pa_tagstruct_gets(t, &ap) < 0) {
454                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
455                 pa_xfree(i.ports[0]);
456                 pa_xfree(i.ports);
457                 pa_proplist_free(i.proplist);
458                 goto finish;
459             }
460
461             if (ap) {
462                 for (j = 0; j < i.n_ports; j++)
463                     if (pa_streq(i.ports[j]->name, ap)) {
464                         i.active_port = i.ports[j];
465                         break;
466                     }
467             }
468
469             i.mute = (int) mute;
470             i.flags = (pa_source_flags_t) flags;
471             i.state = (pa_source_state_t) state;
472
473             if (o->callback) {
474                 pa_source_info_cb_t cb = (pa_source_info_cb_t) o->callback;
475                 cb(o->context, &i, 0, o->userdata);
476             }
477
478             pa_proplist_free(i.proplist);
479         }
480     }
481
482     if (o->callback) {
483         pa_source_info_cb_t cb = (pa_source_info_cb_t) o->callback;
484         cb(o->context, NULL, eol, o->userdata);
485     }
486
487 finish:
488     pa_operation_done(o);
489     pa_operation_unref(o);
490 }
491
492 pa_operation* pa_context_get_source_info_list(pa_context *c, pa_source_info_cb_t cb, void *userdata) {
493     return pa_context_send_simple_command(c, PA_COMMAND_GET_SOURCE_INFO_LIST, context_get_source_info_callback, (pa_operation_cb_t) cb, userdata);
494 }
495
496 pa_operation* pa_context_get_source_info_by_index(pa_context *c, uint32_t idx, pa_source_info_cb_t cb, void *userdata) {
497     pa_tagstruct *t;
498     pa_operation *o;
499     uint32_t tag;
500
501     pa_assert(c);
502     pa_assert(PA_REFCNT_VALUE(c) >= 1);
503     pa_assert(cb);
504
505     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
506     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
507
508     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
509
510     t = pa_tagstruct_command(c, PA_COMMAND_GET_SOURCE_INFO, &tag);
511     pa_tagstruct_putu32(t, idx);
512     pa_tagstruct_puts(t, NULL);
513     pa_pstream_send_tagstruct(c->pstream, t);
514     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
515
516     return o;
517 }
518
519 pa_operation* pa_context_get_source_info_by_name(pa_context *c, const char *name, pa_source_info_cb_t cb, void *userdata) {
520     pa_tagstruct *t;
521     pa_operation *o;
522     uint32_t tag;
523
524     pa_assert(c);
525     pa_assert(PA_REFCNT_VALUE(c) >= 1);
526     pa_assert(cb);
527
528     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
529     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
530     PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
531
532     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
533
534     t = pa_tagstruct_command(c, PA_COMMAND_GET_SOURCE_INFO, &tag);
535     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
536     pa_tagstruct_puts(t, name);
537     pa_pstream_send_tagstruct(c->pstream, t);
538     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
539
540     return o;
541 }
542
543 pa_operation* pa_context_set_source_port_by_index(pa_context *c, uint32_t idx, const char*port, pa_context_success_cb_t cb, void *userdata) {
544     pa_operation *o;
545     pa_tagstruct *t;
546     uint32_t tag;
547
548     pa_assert(c);
549     pa_assert(PA_REFCNT_VALUE(c) >= 1);
550
551     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
552     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
553     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
554     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 16, PA_ERR_NOTSUPPORTED);
555
556     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
557
558     t = pa_tagstruct_command(c, PA_COMMAND_SET_SOURCE_PORT, &tag);
559     pa_tagstruct_putu32(t, idx);
560     pa_tagstruct_puts(t, NULL);
561     pa_tagstruct_puts(t, port);
562     pa_pstream_send_tagstruct(c->pstream, t);
563     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
564
565     return o;
566 }
567
568 pa_operation* pa_context_set_source_port_by_name(pa_context *c, const char *name, const char*port, pa_context_success_cb_t cb, void *userdata) {
569     pa_operation *o;
570     pa_tagstruct *t;
571     uint32_t tag;
572
573     pa_assert(c);
574     pa_assert(PA_REFCNT_VALUE(c) >= 1);
575
576     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
577     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
578     PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
579     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 16, PA_ERR_NOTSUPPORTED);
580
581     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
582
583     t = pa_tagstruct_command(c, PA_COMMAND_SET_SOURCE_PORT, &tag);
584     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
585     pa_tagstruct_puts(t, name);
586     pa_tagstruct_puts(t, port);
587     pa_pstream_send_tagstruct(c->pstream, t);
588     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
589
590     return o;
591 }
592
593 /*** Client info ***/
594
595 static void context_get_client_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
596     pa_operation *o = userdata;
597     int eol = 1;
598
599     pa_assert(pd);
600     pa_assert(o);
601     pa_assert(PA_REFCNT_VALUE(o) >= 1);
602
603     if (!o->context)
604         goto finish;
605
606     if (command != PA_COMMAND_REPLY) {
607         if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
608             goto finish;
609
610         eol = -1;
611     } else {
612
613         while (!pa_tagstruct_eof(t)) {
614             pa_client_info i;
615
616             pa_zero(i);
617             i.proplist = pa_proplist_new();
618
619             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
620                 pa_tagstruct_gets(t, &i.name) < 0 ||
621                 pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
622                 pa_tagstruct_gets(t, &i.driver) < 0 ||
623                 (o->context->version >= 13 && pa_tagstruct_get_proplist(t, i.proplist) < 0)) {
624
625                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
626                 pa_proplist_free(i.proplist);
627                 goto finish;
628             }
629
630             if (o->callback) {
631                 pa_client_info_cb_t cb = (pa_client_info_cb_t) o->callback;
632                 cb(o->context, &i, 0, o->userdata);
633             }
634
635             pa_proplist_free(i.proplist);
636         }
637     }
638
639     if (o->callback) {
640         pa_client_info_cb_t cb = (pa_client_info_cb_t) o->callback;
641         cb(o->context, NULL, eol, o->userdata);
642     }
643
644 finish:
645     pa_operation_done(o);
646     pa_operation_unref(o);
647 }
648
649 pa_operation* pa_context_get_client_info(pa_context *c, uint32_t idx, pa_client_info_cb_t cb, void *userdata) {
650     pa_tagstruct *t;
651     pa_operation *o;
652     uint32_t tag;
653
654     pa_assert(c);
655     pa_assert(PA_REFCNT_VALUE(c) >= 1);
656     pa_assert(cb);
657
658     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
659     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
660     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
661
662     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
663
664     t = pa_tagstruct_command(c, PA_COMMAND_GET_CLIENT_INFO, &tag);
665     pa_tagstruct_putu32(t, idx);
666     pa_pstream_send_tagstruct(c->pstream, t);
667     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
668
669     return o;
670 }
671
672 pa_operation* pa_context_get_client_info_list(pa_context *c, pa_client_info_cb_t cb, void *userdata) {
673     return pa_context_send_simple_command(c, PA_COMMAND_GET_CLIENT_INFO_LIST, context_get_client_info_callback, (pa_operation_cb_t) cb, userdata);
674 }
675
676 /*** Card info ***/
677
678 static void context_get_card_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
679     pa_operation *o = userdata;
680     int eol = 1;
681
682     pa_assert(pd);
683     pa_assert(o);
684     pa_assert(PA_REFCNT_VALUE(o) >= 1);
685
686     if (!o->context)
687         goto finish;
688
689     if (command != PA_COMMAND_REPLY) {
690         if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
691             goto finish;
692
693         eol = -1;
694     } else {
695
696         while (!pa_tagstruct_eof(t)) {
697             pa_card_info i;
698             uint32_t j;
699             const char*ap;
700
701             pa_zero(i);
702
703             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
704                 pa_tagstruct_gets(t, &i.name) < 0 ||
705                 pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
706                 pa_tagstruct_gets(t, &i.driver) < 0 ||
707                 pa_tagstruct_getu32(t, &i.n_profiles) < 0) {
708
709                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
710                 goto finish;
711             }
712
713             if (i.n_profiles > 0) {
714                 i.profiles = pa_xnew0(pa_card_profile_info, i.n_profiles+1);
715
716                 for (j = 0; j < i.n_profiles; j++) {
717
718                     if (pa_tagstruct_gets(t, &i.profiles[j].name) < 0 ||
719                         pa_tagstruct_gets(t, &i.profiles[j].description) < 0 ||
720                         pa_tagstruct_getu32(t, &i.profiles[j].n_sinks) < 0 ||
721                         pa_tagstruct_getu32(t, &i.profiles[j].n_sources) < 0 ||
722                         pa_tagstruct_getu32(t, &i.profiles[j].priority) < 0) {
723
724                         pa_context_fail(o->context, PA_ERR_PROTOCOL);
725                         pa_xfree(i.profiles);
726                         goto finish;
727                     }
728                 }
729
730                 /* Terminate with an extra NULL entry, just to make sure */
731                 i.profiles[j].name = NULL;
732                 i.profiles[j].description = NULL;
733             }
734
735             i.proplist = pa_proplist_new();
736
737             if (pa_tagstruct_gets(t, &ap) < 0 ||
738                 pa_tagstruct_get_proplist(t, i.proplist) < 0) {
739
740                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
741                 pa_xfree(i.profiles);
742                 pa_proplist_free(i.proplist);
743                 goto finish;
744             }
745
746             if (ap) {
747                 for (j = 0; j < i.n_profiles; j++)
748                     if (pa_streq(i.profiles[j].name, ap)) {
749                         i.active_profile = &i.profiles[j];
750                         break;
751                     }
752             }
753
754             if (o->callback) {
755                 pa_card_info_cb_t cb = (pa_card_info_cb_t) o->callback;
756                 cb(o->context, &i, 0, o->userdata);
757             }
758
759             pa_proplist_free(i.proplist);
760             pa_xfree(i.profiles);
761         }
762     }
763
764     if (o->callback) {
765         pa_card_info_cb_t cb = (pa_card_info_cb_t) o->callback;
766         cb(o->context, NULL, eol, o->userdata);
767     }
768
769 finish:
770     pa_operation_done(o);
771     pa_operation_unref(o);
772 }
773
774 pa_operation* pa_context_get_card_info_by_index(pa_context *c, uint32_t idx, pa_card_info_cb_t cb, void *userdata) {
775     pa_tagstruct *t;
776     pa_operation *o;
777     uint32_t tag;
778
779     pa_assert(c);
780     pa_assert(PA_REFCNT_VALUE(c) >= 1);
781     pa_assert(cb);
782
783     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
784     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
785     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
786     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 15, PA_ERR_NOTSUPPORTED);
787
788     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
789
790     t = pa_tagstruct_command(c, PA_COMMAND_GET_CARD_INFO, &tag);
791     pa_tagstruct_putu32(t, idx);
792     pa_tagstruct_puts(t, NULL);
793     pa_pstream_send_tagstruct(c->pstream, t);
794     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_card_info_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
795
796     return o;
797 }
798
799 pa_operation* pa_context_get_card_info_by_name(pa_context *c, const char*name, pa_card_info_cb_t cb, void *userdata) {
800     pa_tagstruct *t;
801     pa_operation *o;
802     uint32_t tag;
803
804     pa_assert(c);
805     pa_assert(PA_REFCNT_VALUE(c) >= 1);
806     pa_assert(cb);
807
808     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
809     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
810     PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
811     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 15, PA_ERR_NOTSUPPORTED);
812
813     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
814
815     t = pa_tagstruct_command(c, PA_COMMAND_GET_CARD_INFO, &tag);
816     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
817     pa_tagstruct_puts(t, name);
818     pa_pstream_send_tagstruct(c->pstream, t);
819     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_card_info_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
820
821     return o;
822 }
823
824 pa_operation* pa_context_get_card_info_list(pa_context *c, pa_card_info_cb_t cb, void *userdata) {
825     return pa_context_send_simple_command(c, PA_COMMAND_GET_CARD_INFO_LIST, context_get_card_info_callback, (pa_operation_cb_t) cb, userdata);
826 }
827
828 pa_operation* pa_context_set_card_profile_by_index(pa_context *c, uint32_t idx, const char*profile, pa_context_success_cb_t cb, void *userdata) {
829     pa_operation *o;
830     pa_tagstruct *t;
831     uint32_t tag;
832
833     pa_assert(c);
834     pa_assert(PA_REFCNT_VALUE(c) >= 1);
835
836     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
837     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
838     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
839     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 15, PA_ERR_NOTSUPPORTED);
840
841     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
842
843     t = pa_tagstruct_command(c, PA_COMMAND_SET_CARD_PROFILE, &tag);
844     pa_tagstruct_putu32(t, idx);
845     pa_tagstruct_puts(t, NULL);
846     pa_tagstruct_puts(t, profile);
847     pa_pstream_send_tagstruct(c->pstream, t);
848     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
849
850     return o;
851 }
852
853 pa_operation* pa_context_set_card_profile_by_name(pa_context *c, const char *name, const char*profile, pa_context_success_cb_t cb, void *userdata) {
854     pa_operation *o;
855     pa_tagstruct *t;
856     uint32_t tag;
857
858     pa_assert(c);
859     pa_assert(PA_REFCNT_VALUE(c) >= 1);
860
861     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
862     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
863     PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
864     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 15, PA_ERR_NOTSUPPORTED);
865
866     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
867
868     t = pa_tagstruct_command(c, PA_COMMAND_SET_CARD_PROFILE, &tag);
869     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
870     pa_tagstruct_puts(t, name);
871     pa_tagstruct_puts(t, profile);
872     pa_pstream_send_tagstruct(c->pstream, t);
873     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
874
875     return o;
876 }
877
878 /*** Module info ***/
879
880 static void context_get_module_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
881     pa_operation *o = userdata;
882     int eol = 1;
883
884     pa_assert(pd);
885     pa_assert(o);
886     pa_assert(PA_REFCNT_VALUE(o) >= 1);
887
888     if (!o->context)
889         goto finish;
890
891     if (command != PA_COMMAND_REPLY) {
892         if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
893             goto finish;
894
895         eol = -1;
896     } else {
897
898         while (!pa_tagstruct_eof(t)) {
899             pa_module_info i;
900             pa_bool_t auto_unload = FALSE;
901
902             pa_zero(i);
903             i.proplist = pa_proplist_new();
904
905             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
906                 pa_tagstruct_gets(t, &i.name) < 0 ||
907                 pa_tagstruct_gets(t, &i.argument) < 0 ||
908                 pa_tagstruct_getu32(t, &i.n_used) < 0 ||
909                 (o->context->version < 15 && pa_tagstruct_get_boolean(t, &auto_unload) < 0) ||
910                 (o->context->version >= 15 && pa_tagstruct_get_proplist(t, i.proplist) < 0)) {
911                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
912                 goto finish;
913             }
914
915             i.auto_unload = (int) auto_unload;
916
917             if (o->callback) {
918                 pa_module_info_cb_t cb = (pa_module_info_cb_t) o->callback;
919                 cb(o->context, &i, 0, o->userdata);
920             }
921
922             pa_proplist_free(i.proplist);
923         }
924     }
925
926     if (o->callback) {
927         pa_module_info_cb_t cb = (pa_module_info_cb_t) o->callback;
928         cb(o->context, NULL, eol, o->userdata);
929     }
930
931 finish:
932     pa_operation_done(o);
933     pa_operation_unref(o);
934 }
935
936 pa_operation* pa_context_get_module_info(pa_context *c, uint32_t idx, pa_module_info_cb_t cb, void *userdata) {
937     pa_tagstruct *t;
938     pa_operation *o;
939     uint32_t tag;
940
941     pa_assert(c);
942     pa_assert(PA_REFCNT_VALUE(c) >= 1);
943     pa_assert(cb);
944
945     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
946     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
947     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
948
949     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
950
951     t = pa_tagstruct_command(c, PA_COMMAND_GET_MODULE_INFO, &tag);
952     pa_tagstruct_putu32(t, idx);
953     pa_pstream_send_tagstruct(c->pstream, t);
954     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
955
956     return o;
957 }
958
959 pa_operation* pa_context_get_module_info_list(pa_context *c, pa_module_info_cb_t cb, void *userdata) {
960     return pa_context_send_simple_command(c, PA_COMMAND_GET_MODULE_INFO_LIST, context_get_module_info_callback, (pa_operation_cb_t) cb, userdata);
961 }
962
963 /*** Sink input info ***/
964
965 static void context_get_sink_input_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
966     pa_operation *o = userdata;
967     int eol = 1;
968
969     pa_assert(pd);
970     pa_assert(o);
971     pa_assert(PA_REFCNT_VALUE(o) >= 1);
972
973     if (!o->context)
974         goto finish;
975
976     if (command != PA_COMMAND_REPLY) {
977         if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
978             goto finish;
979
980         eol = -1;
981     } else {
982
983         while (!pa_tagstruct_eof(t)) {
984             pa_sink_input_info i;
985             pa_bool_t mute = FALSE;
986
987             pa_zero(i);
988             i.proplist = pa_proplist_new();
989
990             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
991                 pa_tagstruct_gets(t, &i.name) < 0 ||
992                 pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
993                 pa_tagstruct_getu32(t, &i.client) < 0 ||
994                 pa_tagstruct_getu32(t, &i.sink) < 0 ||
995                 pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
996                 pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 ||
997                 pa_tagstruct_get_cvolume(t, &i.volume) < 0 ||
998                 pa_tagstruct_get_usec(t, &i.buffer_usec) < 0 ||
999                 pa_tagstruct_get_usec(t, &i.sink_usec) < 0 ||
1000                 pa_tagstruct_gets(t, &i.resample_method) < 0 ||
1001                 pa_tagstruct_gets(t, &i.driver) < 0 ||
1002                 (o->context->version >= 11 && pa_tagstruct_get_boolean(t, &mute) < 0) ||
1003                 (o->context->version >= 13 && pa_tagstruct_get_proplist(t, i.proplist) < 0)) {
1004
1005                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
1006                 pa_proplist_free(i.proplist);
1007                 goto finish;
1008             }
1009
1010             i.mute = (int) mute;
1011
1012             if (o->callback) {
1013                 pa_sink_input_info_cb_t cb = (pa_sink_input_info_cb_t) o->callback;
1014                 cb(o->context, &i, 0, o->userdata);
1015             }
1016
1017             pa_proplist_free(i.proplist);
1018         }
1019     }
1020
1021     if (o->callback) {
1022         pa_sink_input_info_cb_t cb = (pa_sink_input_info_cb_t) o->callback;
1023         cb(o->context, NULL, eol, o->userdata);
1024     }
1025
1026 finish:
1027     pa_operation_done(o);
1028     pa_operation_unref(o);
1029 }
1030
1031 pa_operation* pa_context_get_sink_input_info(pa_context *c, uint32_t idx, pa_sink_input_info_cb_t cb, void *userdata) {
1032     pa_tagstruct *t;
1033     pa_operation *o;
1034     uint32_t tag;
1035
1036     pa_assert(c);
1037     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1038     pa_assert(cb);
1039
1040     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1041     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1042     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
1043
1044     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1045
1046     t = pa_tagstruct_command(c, PA_COMMAND_GET_SINK_INPUT_INFO, &tag);
1047     pa_tagstruct_putu32(t, idx);
1048     pa_pstream_send_tagstruct(c->pstream, t);
1049     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_input_info_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1050
1051     return o;
1052 }
1053
1054 pa_operation* pa_context_get_sink_input_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_sink_input_info*i, int is_last, void *userdata), void *userdata) {
1055     return pa_context_send_simple_command(c, PA_COMMAND_GET_SINK_INPUT_INFO_LIST, context_get_sink_input_info_callback, (pa_operation_cb_t) cb, userdata);
1056 }
1057
1058 /*** Source output info ***/
1059
1060 static void context_get_source_output_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1061     pa_operation *o = userdata;
1062     int eol = 1;
1063
1064     pa_assert(pd);
1065     pa_assert(o);
1066     pa_assert(PA_REFCNT_VALUE(o) >= 1);
1067
1068     if (!o->context)
1069         goto finish;
1070
1071     if (command != PA_COMMAND_REPLY) {
1072         if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
1073             goto finish;
1074
1075         eol = -1;
1076     } else {
1077
1078         while (!pa_tagstruct_eof(t)) {
1079             pa_source_output_info i;
1080
1081             pa_zero(i);
1082             i.proplist = pa_proplist_new();
1083
1084             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
1085                 pa_tagstruct_gets(t, &i.name) < 0 ||
1086                 pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
1087                 pa_tagstruct_getu32(t, &i.client) < 0 ||
1088                 pa_tagstruct_getu32(t, &i.source) < 0 ||
1089                 pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
1090                 pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 ||
1091                 pa_tagstruct_get_usec(t, &i.buffer_usec) < 0 ||
1092                 pa_tagstruct_get_usec(t, &i.source_usec) < 0 ||
1093                 pa_tagstruct_gets(t, &i.resample_method) < 0 ||
1094                 pa_tagstruct_gets(t, &i.driver) < 0 ||
1095                 (o->context->version >= 13 && pa_tagstruct_get_proplist(t, i.proplist) < 0)) {
1096
1097                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
1098                 pa_proplist_free(i.proplist);
1099                 goto finish;
1100             }
1101
1102             if (o->callback) {
1103                 pa_source_output_info_cb_t cb = (pa_source_output_info_cb_t) o->callback;
1104                 cb(o->context, &i, 0, o->userdata);
1105             }
1106
1107             pa_proplist_free(i.proplist);
1108         }
1109     }
1110
1111     if (o->callback) {
1112         pa_source_output_info_cb_t cb = (pa_source_output_info_cb_t) o->callback;
1113         cb(o->context, NULL, eol, o->userdata);
1114     }
1115
1116 finish:
1117     pa_operation_done(o);
1118     pa_operation_unref(o);
1119 }
1120
1121 pa_operation* pa_context_get_source_output_info(pa_context *c, uint32_t idx, pa_source_output_info_cb_t cb, void *userdata) {
1122     pa_tagstruct *t;
1123     pa_operation *o;
1124     uint32_t tag;
1125
1126     pa_assert(c);
1127     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1128     pa_assert(cb);
1129
1130     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1131     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1132     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
1133
1134     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1135
1136     t = pa_tagstruct_command(c, PA_COMMAND_GET_SOURCE_OUTPUT_INFO, &tag);
1137     pa_tagstruct_putu32(t, idx);
1138     pa_pstream_send_tagstruct(c->pstream, t);
1139     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_output_info_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1140
1141     return o;
1142 }
1143
1144 pa_operation* pa_context_get_source_output_info_list(pa_context *c,  pa_source_output_info_cb_t cb, void *userdata) {
1145     return pa_context_send_simple_command(c, PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST, context_get_source_output_info_callback, (pa_operation_cb_t) cb, userdata);
1146 }
1147
1148 /*** Volume manipulation ***/
1149
1150 pa_operation* pa_context_set_sink_volume_by_index(pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata) {
1151     pa_operation *o;
1152     pa_tagstruct *t;
1153     uint32_t tag;
1154
1155     pa_assert(c);
1156     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1157     pa_assert(volume);
1158
1159     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1160     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1161     PA_CHECK_VALIDITY_RETURN_NULL(c, pa_cvolume_valid(volume), PA_ERR_INVALID);
1162
1163     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1164
1165     t = pa_tagstruct_command(c, PA_COMMAND_SET_SINK_VOLUME, &tag);
1166     pa_tagstruct_putu32(t, idx);
1167     pa_tagstruct_puts(t, NULL);
1168     pa_tagstruct_put_cvolume(t, volume);
1169     pa_pstream_send_tagstruct(c->pstream, t);
1170     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1171
1172     return o;
1173 }
1174
1175 pa_operation* pa_context_set_sink_volume_by_name(pa_context *c, const char *name, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata) {
1176     pa_operation *o;
1177     pa_tagstruct *t;
1178     uint32_t tag;
1179
1180     pa_assert(c);
1181     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1182     pa_assert(name);
1183     pa_assert(volume);
1184
1185     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1186     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1187     PA_CHECK_VALIDITY_RETURN_NULL(c, pa_cvolume_valid(volume), PA_ERR_INVALID);
1188     PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
1189
1190     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1191
1192     t = pa_tagstruct_command(c, PA_COMMAND_SET_SINK_VOLUME, &tag);
1193     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
1194     pa_tagstruct_puts(t, name);
1195     pa_tagstruct_put_cvolume(t, volume);
1196     pa_pstream_send_tagstruct(c->pstream, t);
1197     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1198
1199     return o;
1200 }
1201
1202 pa_operation* pa_context_set_sink_mute_by_index(pa_context *c, uint32_t idx, int mute, pa_context_success_cb_t cb, void *userdata) {
1203     pa_operation *o;
1204     pa_tagstruct *t;
1205     uint32_t tag;
1206
1207     pa_assert(c);
1208     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1209
1210     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1211     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1212
1213     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1214
1215     t = pa_tagstruct_command(c, PA_COMMAND_SET_SINK_MUTE, &tag);
1216     pa_tagstruct_putu32(t, idx);
1217     pa_tagstruct_puts(t, NULL);
1218     pa_tagstruct_put_boolean(t, mute);
1219     pa_pstream_send_tagstruct(c->pstream, t);
1220     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1221
1222     return o;
1223 }
1224
1225 pa_operation* pa_context_set_sink_mute_by_name(pa_context *c, const char *name, int mute, pa_context_success_cb_t cb, void *userdata) {
1226     pa_operation *o;
1227     pa_tagstruct *t;
1228     uint32_t tag;
1229
1230     pa_assert(c);
1231     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1232     pa_assert(name);
1233
1234     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1235     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1236     PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
1237
1238     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1239
1240     t = pa_tagstruct_command(c, PA_COMMAND_SET_SINK_MUTE, &tag);
1241     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
1242     pa_tagstruct_puts(t, name);
1243     pa_tagstruct_put_boolean(t, mute);
1244     pa_pstream_send_tagstruct(c->pstream, t);
1245     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1246
1247     return o;
1248 }
1249
1250 pa_operation* pa_context_set_sink_input_volume(pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata) {
1251     pa_operation *o;
1252     pa_tagstruct *t;
1253     uint32_t tag;
1254
1255     pa_assert(c);
1256     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1257     pa_assert(volume);
1258
1259     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1260     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1261     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
1262     PA_CHECK_VALIDITY_RETURN_NULL(c, pa_cvolume_valid(volume), PA_ERR_INVALID);
1263
1264     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1265
1266     t = pa_tagstruct_command(c, PA_COMMAND_SET_SINK_INPUT_VOLUME, &tag);
1267     pa_tagstruct_putu32(t, idx);
1268     pa_tagstruct_put_cvolume(t, volume);
1269     pa_pstream_send_tagstruct(c->pstream, t);
1270     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1271
1272     return o;
1273 }
1274
1275 pa_operation* pa_context_set_sink_input_mute(pa_context *c, uint32_t idx, int mute, pa_context_success_cb_t cb, void *userdata) {
1276     pa_operation *o;
1277     pa_tagstruct *t;
1278     uint32_t tag;
1279
1280     pa_assert(c);
1281     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1282
1283     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1284     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1285     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
1286     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 11, PA_ERR_NOTSUPPORTED);
1287
1288     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1289
1290     t = pa_tagstruct_command(c, PA_COMMAND_SET_SINK_INPUT_MUTE, &tag);
1291     pa_tagstruct_putu32(t, idx);
1292     pa_tagstruct_put_boolean(t, mute);
1293     pa_pstream_send_tagstruct(c->pstream, t);
1294     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1295
1296     return o;
1297 }
1298
1299 pa_operation* pa_context_set_source_volume_by_index(pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata) {
1300     pa_operation *o;
1301     pa_tagstruct *t;
1302     uint32_t tag;
1303
1304     pa_assert(c);
1305     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1306     pa_assert(volume);
1307
1308     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1309     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1310     PA_CHECK_VALIDITY_RETURN_NULL(c, pa_cvolume_valid(volume), PA_ERR_INVALID);
1311
1312     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1313
1314     t = pa_tagstruct_command(c, PA_COMMAND_SET_SOURCE_VOLUME, &tag);
1315     pa_tagstruct_putu32(t, idx);
1316     pa_tagstruct_puts(t, NULL);
1317     pa_tagstruct_put_cvolume(t, volume);
1318     pa_pstream_send_tagstruct(c->pstream, t);
1319     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1320
1321     return o;
1322 }
1323
1324 pa_operation* pa_context_set_source_volume_by_name(pa_context *c, const char *name, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata) {
1325     pa_operation *o;
1326     pa_tagstruct *t;
1327     uint32_t tag;
1328
1329     pa_assert(c);
1330     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1331     pa_assert(name);
1332     pa_assert(volume);
1333
1334     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1335     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1336     PA_CHECK_VALIDITY_RETURN_NULL(c, pa_cvolume_valid(volume), PA_ERR_INVALID);
1337     PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
1338
1339     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1340
1341     t = pa_tagstruct_command(c, PA_COMMAND_SET_SOURCE_VOLUME, &tag);
1342     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
1343     pa_tagstruct_puts(t, name);
1344     pa_tagstruct_put_cvolume(t, volume);
1345     pa_pstream_send_tagstruct(c->pstream, t);
1346     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1347
1348     return o;
1349 }
1350
1351 pa_operation* pa_context_set_source_mute_by_index(pa_context *c, uint32_t idx, int mute, pa_context_success_cb_t cb, void *userdata) {
1352     pa_operation *o;
1353     pa_tagstruct *t;
1354     uint32_t tag;
1355
1356     pa_assert(c);
1357     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1358
1359     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1360     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1361
1362     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1363
1364     t = pa_tagstruct_command(c, PA_COMMAND_SET_SOURCE_MUTE, &tag);
1365     pa_tagstruct_putu32(t, idx);
1366     pa_tagstruct_puts(t, NULL);
1367     pa_tagstruct_put_boolean(t, mute);
1368     pa_pstream_send_tagstruct(c->pstream, t);
1369     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1370
1371     return o;
1372 }
1373
1374 pa_operation* pa_context_set_source_mute_by_name(pa_context *c, const char *name, int mute, pa_context_success_cb_t cb, void *userdata) {
1375     pa_operation *o;
1376     pa_tagstruct *t;
1377     uint32_t tag;
1378
1379     pa_assert(c);
1380     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1381     pa_assert(name);
1382
1383     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1384     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1385     PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
1386
1387     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1388
1389     t = pa_tagstruct_command(c, PA_COMMAND_SET_SOURCE_MUTE, &tag);
1390     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
1391     pa_tagstruct_puts(t, name);
1392     pa_tagstruct_put_boolean(t, mute);
1393     pa_pstream_send_tagstruct(c->pstream, t);
1394     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1395
1396     return o;
1397 }
1398
1399 /** Sample Cache **/
1400
1401 static void context_get_sample_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1402     pa_operation *o = userdata;
1403     int eol = 1;
1404
1405     pa_assert(pd);
1406     pa_assert(o);
1407     pa_assert(PA_REFCNT_VALUE(o) >= 1);
1408
1409     if (!o->context)
1410         goto finish;
1411
1412     if (command != PA_COMMAND_REPLY) {
1413         if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
1414             goto finish;
1415
1416         eol = -1;
1417     } else {
1418
1419         while (!pa_tagstruct_eof(t)) {
1420             pa_sample_info i;
1421             pa_bool_t lazy = FALSE;
1422
1423             pa_zero(i);
1424             i.proplist = pa_proplist_new();
1425
1426             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
1427                 pa_tagstruct_gets(t, &i.name) < 0 ||
1428                 pa_tagstruct_get_cvolume(t, &i.volume) < 0 ||
1429                 pa_tagstruct_get_usec(t, &i.duration) < 0 ||
1430                 pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
1431                 pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 ||
1432                 pa_tagstruct_getu32(t, &i.bytes) < 0 ||
1433                 pa_tagstruct_get_boolean(t, &lazy) < 0 ||
1434                 pa_tagstruct_gets(t, &i.filename) < 0 ||
1435                 (o->context->version >= 13 && pa_tagstruct_get_proplist(t, i.proplist) < 0)) {
1436
1437                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
1438                 goto finish;
1439             }
1440
1441             i.lazy = (int) lazy;
1442
1443             if (o->callback) {
1444                 pa_sample_info_cb_t cb = (pa_sample_info_cb_t) o->callback;
1445                 cb(o->context, &i, 0, o->userdata);
1446             }
1447
1448             pa_proplist_free(i.proplist);
1449         }
1450     }
1451
1452     if (o->callback) {
1453         pa_sample_info_cb_t cb = (pa_sample_info_cb_t) o->callback;
1454         cb(o->context, NULL, eol, o->userdata);
1455     }
1456
1457 finish:
1458     pa_operation_done(o);
1459     pa_operation_unref(o);
1460 }
1461
1462 pa_operation* pa_context_get_sample_info_by_name(pa_context *c, const char *name, pa_sample_info_cb_t cb, void *userdata) {
1463     pa_tagstruct *t;
1464     pa_operation *o;
1465     uint32_t tag;
1466
1467     pa_assert(c);
1468     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1469     pa_assert(cb);
1470
1471     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1472     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1473     PA_CHECK_VALIDITY_RETURN_NULL(c, name && *name, PA_ERR_INVALID);
1474
1475     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1476
1477     t = pa_tagstruct_command(c, PA_COMMAND_GET_SAMPLE_INFO, &tag);
1478     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
1479     pa_tagstruct_puts(t, name);
1480     pa_pstream_send_tagstruct(c->pstream, t);
1481     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sample_info_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1482
1483     return o;
1484 }
1485
1486 pa_operation* pa_context_get_sample_info_by_index(pa_context *c, uint32_t idx, pa_sample_info_cb_t cb, void *userdata) {
1487     pa_tagstruct *t;
1488     pa_operation *o;
1489     uint32_t tag;
1490
1491     pa_assert(c);
1492     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1493     pa_assert(cb);
1494
1495     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1496     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1497     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
1498
1499     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1500
1501     t = pa_tagstruct_command(c, PA_COMMAND_GET_SAMPLE_INFO, &tag);
1502     pa_tagstruct_putu32(t, idx);
1503     pa_tagstruct_puts(t, NULL);
1504     pa_pstream_send_tagstruct(c->pstream, t);
1505     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sample_info_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1506
1507     return o;
1508 }
1509
1510 pa_operation* pa_context_get_sample_info_list(pa_context *c, pa_sample_info_cb_t cb, void *userdata) {
1511     return pa_context_send_simple_command(c, PA_COMMAND_GET_SAMPLE_INFO_LIST, context_get_sample_info_callback, (pa_operation_cb_t) cb, userdata);
1512 }
1513
1514 static pa_operation* command_kill(pa_context *c, uint32_t command, uint32_t idx, pa_context_success_cb_t cb, void *userdata) {
1515     pa_operation *o;
1516     pa_tagstruct *t;
1517     uint32_t tag;
1518
1519     pa_assert(c);
1520     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1521
1522     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1523     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1524     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
1525
1526     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1527
1528     t = pa_tagstruct_command(c, command, &tag);
1529     pa_tagstruct_putu32(t, idx);
1530     pa_pstream_send_tagstruct(c->pstream, t);
1531     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1532
1533     return o;
1534 }
1535
1536 pa_operation* pa_context_kill_client(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata) {
1537     return command_kill(c, PA_COMMAND_KILL_CLIENT, idx, cb, userdata);
1538 }
1539
1540 pa_operation* pa_context_kill_sink_input(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata) {
1541     return command_kill(c, PA_COMMAND_KILL_SINK_INPUT, idx, cb, userdata);
1542 }
1543
1544 pa_operation* pa_context_kill_source_output(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata) {
1545     return command_kill(c, PA_COMMAND_KILL_SOURCE_OUTPUT, idx, cb, userdata);
1546 }
1547
1548 static void context_index_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1549     pa_operation *o = userdata;
1550     uint32_t idx;
1551
1552     pa_assert(pd);
1553     pa_assert(o);
1554     pa_assert(PA_REFCNT_VALUE(o) >= 1);
1555
1556     if (!o->context)
1557         goto finish;
1558
1559     if (command != PA_COMMAND_REPLY) {
1560         if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
1561             goto finish;
1562
1563         idx = PA_INVALID_INDEX;
1564     } else if (pa_tagstruct_getu32(t, &idx) ||
1565                !pa_tagstruct_eof(t)) {
1566         pa_context_fail(o->context, PA_ERR_PROTOCOL);
1567         goto finish;
1568     }
1569
1570     if (o->callback) {
1571         pa_context_index_cb_t cb = (pa_context_index_cb_t) o->callback;
1572         cb(o->context, idx, o->userdata);
1573     }
1574
1575
1576 finish:
1577     pa_operation_done(o);
1578     pa_operation_unref(o);
1579 }
1580
1581 pa_operation* pa_context_load_module(pa_context *c, const char*name, const char *argument, pa_context_index_cb_t cb, void *userdata) {
1582     pa_operation *o;
1583     pa_tagstruct *t;
1584     uint32_t tag;
1585
1586     pa_assert(c);
1587     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1588
1589     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1590     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1591     PA_CHECK_VALIDITY_RETURN_NULL(c, name && *name, PA_ERR_INVALID);
1592
1593     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1594
1595     t = pa_tagstruct_command(c, PA_COMMAND_LOAD_MODULE, &tag);
1596     pa_tagstruct_puts(t, name);
1597     pa_tagstruct_puts(t, argument);
1598     pa_pstream_send_tagstruct(c->pstream, t);
1599     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_index_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1600
1601     return o;
1602 }
1603
1604 pa_operation* pa_context_unload_module(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata) {
1605     return command_kill(c, PA_COMMAND_UNLOAD_MODULE, idx, cb, userdata);
1606 }
1607
1608 /*** Autoload stuff ***/
1609
1610 PA_WARN_REFERENCE(pa_context_get_autoload_info_by_name, "Module auto-loading no longer supported.");
1611
1612 pa_operation* pa_context_get_autoload_info_by_name(pa_context *c, const char *name, pa_autoload_type_t type, pa_autoload_info_cb_t cb, void *userdata) {
1613
1614     pa_assert(c);
1615     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1616
1617     PA_FAIL_RETURN_NULL(c, PA_ERR_OBSOLETE);
1618 }
1619
1620 PA_WARN_REFERENCE(pa_context_get_autoload_info_by_index, "Module auto-loading no longer supported.");
1621
1622 pa_operation* pa_context_get_autoload_info_by_index(pa_context *c, uint32_t idx, pa_autoload_info_cb_t cb, void *userdata) {
1623     pa_assert(c);
1624     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1625
1626     PA_FAIL_RETURN_NULL(c, PA_ERR_OBSOLETE);
1627 }
1628
1629 PA_WARN_REFERENCE(pa_context_get_autoload_info_list, "Module auto-loading no longer supported.");
1630
1631 pa_operation* pa_context_get_autoload_info_list(pa_context *c, pa_autoload_info_cb_t cb, void *userdata) {
1632     pa_assert(c);
1633     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1634
1635     PA_FAIL_RETURN_NULL(c, PA_ERR_OBSOLETE);
1636 }
1637
1638 PA_WARN_REFERENCE(pa_context_add_autoload, "Module auto-loading no longer supported.");
1639
1640 pa_operation* pa_context_add_autoload(pa_context *c, const char *name, pa_autoload_type_t type, const char *module, const char*argument, pa_context_index_cb_t cb, void* userdata) {
1641     pa_assert(c);
1642     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1643
1644     PA_FAIL_RETURN_NULL(c, PA_ERR_OBSOLETE);
1645 }
1646
1647 PA_WARN_REFERENCE(pa_context_remove_autoload_by_name, "Module auto-loading no longer supported.");
1648
1649 pa_operation* pa_context_remove_autoload_by_name(pa_context *c, const char *name, pa_autoload_type_t type, pa_context_success_cb_t cb, void* userdata) {
1650     pa_assert(c);
1651     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1652
1653     PA_FAIL_RETURN_NULL(c, PA_ERR_OBSOLETE);
1654 }
1655
1656 PA_WARN_REFERENCE(pa_context_remove_autoload_by_index, "Module auto-loading no longer supported.");
1657
1658 pa_operation* pa_context_remove_autoload_by_index(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void* userdata) {
1659     pa_assert(c);
1660     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1661
1662     PA_FAIL_RETURN_NULL(c, PA_ERR_OBSOLETE);
1663 }
1664
1665 pa_operation* pa_context_move_sink_input_by_name(pa_context *c, uint32_t idx, const char *sink_name, pa_context_success_cb_t cb, void* userdata) {
1666     pa_operation *o;
1667     pa_tagstruct *t;
1668     uint32_t tag;
1669
1670     pa_assert(c);
1671     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1672
1673     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1674     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1675     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 10, PA_ERR_NOTSUPPORTED);
1676     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
1677     PA_CHECK_VALIDITY_RETURN_NULL(c, sink_name && *sink_name, PA_ERR_INVALID);
1678
1679     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1680
1681     t = pa_tagstruct_command(c, PA_COMMAND_MOVE_SINK_INPUT, &tag);
1682     pa_tagstruct_putu32(t, idx);
1683     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
1684     pa_tagstruct_puts(t, sink_name);
1685     pa_pstream_send_tagstruct(c->pstream, t);
1686     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1687
1688     return o;
1689 }
1690
1691 pa_operation* pa_context_move_sink_input_by_index(pa_context *c, uint32_t idx, uint32_t sink_idx, pa_context_success_cb_t cb, void* userdata) {
1692     pa_operation *o;
1693     pa_tagstruct *t;
1694     uint32_t tag;
1695
1696     pa_assert(c);
1697     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1698
1699     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1700     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1701     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 10, PA_ERR_NOTSUPPORTED);
1702     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
1703     PA_CHECK_VALIDITY_RETURN_NULL(c, sink_idx != PA_INVALID_INDEX, PA_ERR_INVALID);
1704
1705     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1706
1707     t = pa_tagstruct_command(c, PA_COMMAND_MOVE_SINK_INPUT, &tag);
1708     pa_tagstruct_putu32(t, idx);
1709     pa_tagstruct_putu32(t, sink_idx);
1710     pa_tagstruct_puts(t, NULL);
1711     pa_pstream_send_tagstruct(c->pstream, t);
1712     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1713
1714     return o;
1715 }
1716
1717 pa_operation* pa_context_move_source_output_by_name(pa_context *c, uint32_t idx, const char *source_name, pa_context_success_cb_t cb, void* userdata) {
1718     pa_operation *o;
1719     pa_tagstruct *t;
1720     uint32_t tag;
1721
1722     pa_assert(c);
1723     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1724
1725     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1726     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1727     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 10, PA_ERR_NOTSUPPORTED);
1728     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
1729     PA_CHECK_VALIDITY_RETURN_NULL(c, source_name && *source_name, PA_ERR_INVALID);
1730
1731     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1732
1733     t = pa_tagstruct_command(c, PA_COMMAND_MOVE_SOURCE_OUTPUT, &tag);
1734     pa_tagstruct_putu32(t, idx);
1735     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
1736     pa_tagstruct_puts(t, source_name);
1737     pa_pstream_send_tagstruct(c->pstream, t);
1738     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1739
1740     return o;
1741 }
1742
1743 pa_operation* pa_context_move_source_output_by_index(pa_context *c, uint32_t idx, uint32_t source_idx, pa_context_success_cb_t cb, void* userdata) {
1744     pa_operation *o;
1745     pa_tagstruct *t;
1746     uint32_t tag;
1747
1748     pa_assert(c);
1749     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1750
1751     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1752     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1753     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 10, PA_ERR_NOTSUPPORTED);
1754     PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
1755     PA_CHECK_VALIDITY_RETURN_NULL(c, source_idx != PA_INVALID_INDEX, PA_ERR_INVALID);
1756
1757     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1758
1759     t = pa_tagstruct_command(c, PA_COMMAND_MOVE_SOURCE_OUTPUT, &tag);
1760     pa_tagstruct_putu32(t, idx);
1761     pa_tagstruct_putu32(t, source_idx);
1762     pa_tagstruct_puts(t, NULL);
1763     pa_pstream_send_tagstruct(c->pstream, t);
1764     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1765
1766     return o;
1767 }
1768
1769 pa_operation* pa_context_suspend_sink_by_name(pa_context *c, const char *sink_name, int suspend, pa_context_success_cb_t cb, void* userdata) {
1770     pa_operation *o;
1771     pa_tagstruct *t;
1772     uint32_t tag;
1773
1774     pa_assert(c);
1775     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1776
1777     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1778     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1779     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 11, PA_ERR_NOTSUPPORTED);
1780     PA_CHECK_VALIDITY_RETURN_NULL(c, !sink_name || *sink_name, PA_ERR_INVALID);
1781
1782     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1783
1784     t = pa_tagstruct_command(c, PA_COMMAND_SUSPEND_SINK, &tag);
1785     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
1786     pa_tagstruct_puts(t, sink_name);
1787     pa_tagstruct_put_boolean(t, suspend);
1788     pa_pstream_send_tagstruct(c->pstream, t);
1789     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1790
1791     return o;
1792 }
1793
1794 pa_operation* pa_context_suspend_sink_by_index(pa_context *c, uint32_t idx, int suspend, pa_context_success_cb_t cb, void* userdata) {
1795     pa_operation *o;
1796     pa_tagstruct *t;
1797     uint32_t tag;
1798
1799     pa_assert(c);
1800     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1801
1802     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1803     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1804     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 11, PA_ERR_NOTSUPPORTED);
1805
1806     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1807
1808     t = pa_tagstruct_command(c, PA_COMMAND_SUSPEND_SINK, &tag);
1809     pa_tagstruct_putu32(t, idx);
1810     pa_tagstruct_puts(t, idx == PA_INVALID_INDEX ? "" : NULL);
1811     pa_tagstruct_put_boolean(t, suspend);
1812     pa_pstream_send_tagstruct(c->pstream, t);
1813     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1814
1815     return o;
1816 }
1817
1818 pa_operation* pa_context_suspend_source_by_name(pa_context *c, const char *source_name, int suspend, pa_context_success_cb_t cb, void* userdata) {
1819     pa_operation *o;
1820     pa_tagstruct *t;
1821     uint32_t tag;
1822
1823     pa_assert(c);
1824     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1825
1826     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1827     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1828     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 11, PA_ERR_NOTSUPPORTED);
1829     PA_CHECK_VALIDITY_RETURN_NULL(c, !source_name || *source_name, PA_ERR_INVALID);
1830
1831     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1832
1833     t = pa_tagstruct_command(c, PA_COMMAND_SUSPEND_SOURCE, &tag);
1834     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
1835     pa_tagstruct_puts(t, source_name);
1836     pa_tagstruct_put_boolean(t, suspend);
1837     pa_pstream_send_tagstruct(c->pstream, t);
1838     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1839
1840     return o;
1841 }
1842
1843 pa_operation* pa_context_suspend_source_by_index(pa_context *c, uint32_t idx, int suspend, pa_context_success_cb_t cb, void* userdata) {
1844     pa_operation *o;
1845     pa_tagstruct *t;
1846     uint32_t tag;
1847
1848     pa_assert(c);
1849     pa_assert(PA_REFCNT_VALUE(c) >= 1);
1850
1851     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
1852     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
1853     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 11, PA_ERR_NOTSUPPORTED);
1854
1855     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
1856
1857     t = pa_tagstruct_command(c, PA_COMMAND_SUSPEND_SOURCE, &tag);
1858     pa_tagstruct_putu32(t, idx);
1859     pa_tagstruct_puts(t, idx == PA_INVALID_INDEX ? "" : NULL);
1860     pa_tagstruct_put_boolean(t, suspend);
1861     pa_pstream_send_tagstruct(c->pstream, t);
1862     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
1863
1864     return o;
1865 }