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