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