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