Documentation work
[platform/upstream/pulseaudio.git] / polyp / polyplib-introspect.c
1 /* $Id$ */
2
3 /***
4   This file is part of polypaudio.
5  
6   polypaudio is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published
8   by the Free Software Foundation; either version 2 of the License,
9   or (at your option) any later version.
10  
11   polypaudio is distributed in the hope that it will be useful, but
12   WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14   General Public License for more details.
15  
16   You should have received a copy of the GNU General Public License
17   along with polypaudio; if not, write to the Free Software
18   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19   USA.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <assert.h>
27
28 #include "polyplib-introspect.h"
29 #include "polyplib-context.h"
30 #include "polyplib-internal.h"
31 #include "pstream-util.h"
32
33 /*** Statistics ***/
34
35 static void context_stat_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
36     struct pa_operation *o = userdata;
37     struct pa_stat_info i, *p = &i;
38     assert(pd && o && o->context && o->ref >= 1);
39
40     if (command != PA_COMMAND_REPLY) {
41         if (pa_context_handle_error(o->context, command, t) < 0)
42             goto finish;
43
44         p = NULL;
45     } else if (pa_tagstruct_getu32(t, &i.memblock_count) < 0 ||
46                pa_tagstruct_getu32(t, &i.memblock_total) < 0 ||
47                !pa_tagstruct_eof(t)) {
48         pa_context_fail(o->context, PA_ERROR_PROTOCOL);
49         goto finish;
50     }
51
52     if (o->callback) {
53         void (*cb)(struct pa_context *s, const struct pa_stat_info*i, void *userdata) = o->callback;
54         cb(o->context, p, o->userdata);
55     }
56
57 finish:
58     pa_operation_done(o);
59     pa_operation_unref(o);
60 }
61
62 struct pa_operation* pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_stat_info*i, void *userdata), void *userdata) {
63     return pa_context_send_simple_command(c, PA_COMMAND_STAT, context_stat_callback, cb, userdata);
64 }
65
66 /*** Server Info ***/
67
68 static void context_get_server_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
69     struct pa_operation *o = userdata;
70     struct pa_server_info i, *p = &i;
71     assert(pd && o && o->context && o->ref >= 1);
72
73     if (command != PA_COMMAND_REPLY) {
74         if (pa_context_handle_error(o->context, command, t) < 0)
75             goto finish;
76
77         p = NULL;
78     } else if (pa_tagstruct_gets(t, &i.server_name) < 0 ||
79                pa_tagstruct_gets(t, &i.server_version) < 0 ||
80                pa_tagstruct_gets(t, &i.user_name) < 0 ||
81                pa_tagstruct_gets(t, &i.host_name) < 0 ||
82                pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
83                !pa_tagstruct_eof(t)) {
84         pa_context_fail(o->context, PA_ERROR_PROTOCOL);
85         goto finish;
86     }
87     
88     if (o->callback) {
89         void (*cb)(struct pa_context *s, const struct pa_server_info*i, void *userdata) = o->callback;
90         cb(o->context, p, o->userdata);
91     }
92
93 finish:
94     pa_operation_done(o);
95     pa_operation_unref(o);
96 }
97
98 struct pa_operation* pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata) {
99     return pa_context_send_simple_command(c, PA_COMMAND_GET_SERVER_INFO, context_get_server_info_callback, cb, userdata);
100 }
101
102 /*** Sink Info ***/
103
104 static void context_get_sink_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
105     struct pa_operation *o = userdata;
106     int eof = 1;
107     assert(pd && o && o->context && o->ref >= 1);
108
109     if (command != PA_COMMAND_REPLY) {
110         if (pa_context_handle_error(o->context, command, t) < 0)
111             goto finish;
112
113         eof = -1;
114     } else {
115         
116         while (!pa_tagstruct_eof(t)) {
117             struct pa_sink_info i;
118             
119             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
120                 pa_tagstruct_gets(t, &i.name) < 0 ||
121                 pa_tagstruct_gets(t, &i.description) < 0 ||
122                 pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
123                 pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
124                 pa_tagstruct_getu32(t, &i.volume) < 0 ||
125                 pa_tagstruct_getu32(t, &i.monitor_source) < 0 ||
126                 pa_tagstruct_gets(t, &i.monitor_source_name) < 0 ||
127                 pa_tagstruct_getu32(t, &i.latency) < 0) {
128                 pa_context_fail(o->context, PA_ERROR_PROTOCOL);
129                 goto finish;
130             }
131
132             if (o->callback) {
133                 void (*cb)(struct pa_context *s, const struct pa_sink_info*i, int eof, void *userdata) = o->callback;
134                 cb(o->context, &i, 0, o->userdata);
135             }
136         }
137     }
138     
139     if (o->callback) {
140         void (*cb)(struct pa_context *s, const struct pa_sink_info*i, int eof, void *userdata) = o->callback;
141         cb(o->context, NULL, eof, o->userdata);
142     }
143
144 finish:
145     pa_operation_done(o);
146     pa_operation_unref(o);
147 }
148
149 struct pa_operation* pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) {
150     return pa_context_send_simple_command(c, PA_COMMAND_GET_SINK_INFO_LIST, context_get_sink_info_callback, cb, userdata);
151 }
152
153 struct pa_operation* pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) {
154     struct pa_tagstruct *t;
155     struct pa_operation *o;
156     uint32_t tag;
157     assert(c && cb);
158
159     o = pa_operation_new(c, NULL);
160     o->callback = cb;
161     o->userdata = userdata;
162
163     t = pa_tagstruct_new(NULL, 0);
164     pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO);
165     pa_tagstruct_putu32(t, tag = c->ctag++);
166     pa_tagstruct_putu32(t, index);
167     pa_tagstruct_puts(t, "");
168     pa_pstream_send_tagstruct(c->pstream, t);
169     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, o);
170
171     return pa_operation_ref(o);
172 }
173
174 /*** Source info ***/
175
176 static void context_get_source_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
177     struct pa_operation *o = userdata;
178     int eof = 1;
179     assert(pd && o && o->context && o->ref >= 1);
180
181     if (command != PA_COMMAND_REPLY) {
182         if (pa_context_handle_error(o->context, command, t) < 0)
183             goto finish;
184
185         eof = -1;
186     } else {
187         
188         while (!pa_tagstruct_eof(t)) {
189             struct pa_source_info i;
190             
191             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
192                 pa_tagstruct_gets(t, &i.name) < 0 ||
193                 pa_tagstruct_gets(t, &i.description) < 0 ||
194                 pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
195                 pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
196                 pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 ||
197                 pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0) {
198                 pa_context_fail(o->context, PA_ERROR_PROTOCOL);
199                 goto finish;
200             }
201
202             if (o->callback) {
203                 void (*cb)(struct pa_context *s, const struct pa_source_info*i, int eof, void *userdata) = o->callback;
204                 cb(o->context, &i, 0, o->userdata);
205             }
206         }
207     }
208     
209     if (o->callback) {
210         void (*cb)(struct pa_context *s, const struct pa_source_info*i, int eof, void *userdata) = o->callback;
211         cb(o->context, NULL, eof, o->userdata);
212     }
213
214 finish:
215     pa_operation_done(o);
216     pa_operation_unref(o);
217 }
218
219 struct pa_operation* pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) {
220     return pa_context_send_simple_command(c, PA_COMMAND_GET_SOURCE_INFO_LIST, context_get_source_info_callback, cb, userdata);
221 }
222
223 struct pa_operation* pa_context_get_source_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) {
224     struct pa_tagstruct *t;
225     struct pa_operation *o;
226     uint32_t tag;
227     assert(c && cb);
228
229     o = pa_operation_new(c, NULL);
230     o->callback = cb;
231     o->userdata = userdata;
232
233     t = pa_tagstruct_new(NULL, 0);
234     pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO);
235     pa_tagstruct_putu32(t, tag = c->ctag++);
236     pa_tagstruct_putu32(t, index);
237     pa_tagstruct_puts(t, "");
238     pa_pstream_send_tagstruct(c->pstream, t);
239     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, o);
240
241     return pa_operation_ref(o);
242 }
243
244 /*** Client info ***/
245
246 static void context_get_client_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
247     struct pa_operation *o = userdata;
248     int eof = 1;
249     assert(pd && o && o->context && o->ref >= 1);
250
251     if (command != PA_COMMAND_REPLY) {
252         if (pa_context_handle_error(o->context, command, t) < 0)
253             goto finish;
254
255         eof = -1;
256     } else {
257         
258         while (!pa_tagstruct_eof(t)) {
259             struct pa_client_info i;
260             
261             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
262                 pa_tagstruct_gets(t, &i.name) < 0 ||
263                 pa_tagstruct_gets(t, &i.protocol_name) < 0 ||
264                 pa_tagstruct_getu32(t, &i.owner_module) < 0) {
265                 pa_context_fail(o->context, PA_ERROR_PROTOCOL);
266                 goto finish;
267             }
268
269             if (o->callback) {
270                 void (*cb)(struct pa_context *s, const struct pa_client_info*i, int eof, void *userdata) = o->callback;
271                 cb(o->context, &i, 0, o->userdata);
272             }
273         }
274     }
275     
276     if (o->callback) {
277         void (*cb)(struct pa_context *s, const struct pa_client_info*i, int eof, void *userdata) = o->callback;
278         cb(o->context, NULL, eof, o->userdata);
279     }
280
281 finish:
282     pa_operation_done(o);
283     pa_operation_unref(o);
284 }
285
286 struct pa_operation* pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) {
287     struct pa_tagstruct *t;
288     struct pa_operation *o;
289     uint32_t tag;
290     assert(c && cb);
291
292     o = pa_operation_new(c, NULL);
293     o->callback = cb;
294     o->userdata = userdata;
295
296     t = pa_tagstruct_new(NULL, 0);
297     pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO);
298     pa_tagstruct_putu32(t, tag = c->ctag++);
299     pa_tagstruct_putu32(t, index);
300     pa_pstream_send_tagstruct(c->pstream, t);
301     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, o);
302
303     return pa_operation_ref(o);
304 }
305
306 struct pa_operation* pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) {
307     return pa_context_send_simple_command(c, PA_COMMAND_GET_CLIENT_INFO_LIST, context_get_client_info_callback, cb, userdata);
308 }
309
310 /*** Module info ***/
311
312 static void context_get_module_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
313     struct pa_operation *o = userdata;
314     int eof = 1;
315     assert(pd && o && o->context && o->ref >= 1);
316
317     if (command != PA_COMMAND_REPLY) {
318         if (pa_context_handle_error(o->context, command, t) < 0)
319             goto finish;
320
321         eof = -1;
322     } else {
323         
324         while (!pa_tagstruct_eof(t)) {
325             struct pa_module_info i;
326             
327             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
328                 pa_tagstruct_gets(t, &i.name) < 0 ||
329                 pa_tagstruct_gets(t, &i.argument) < 0 ||
330                 pa_tagstruct_getu32(t, &i.n_used) < 0 ||
331                 pa_tagstruct_getu32(t, &i.auto_unload) < 0) {
332                 pa_context_fail(o->context, PA_ERROR_PROTOCOL);
333                 goto finish;
334             }
335
336             if (o->callback) {
337                 void (*cb)(struct pa_context *s, const struct pa_module_info*i, int eof, void *userdata) = o->callback;
338                 cb(o->context, &i, 0, o->userdata);
339             }
340         }
341     }
342     
343     if (o->callback) {
344         void (*cb)(struct pa_context *s, const struct pa_module_info*i, int eof, void *userdata) = o->callback;
345         cb(o->context, NULL, eof, o->userdata);
346     }
347
348 finish:
349     pa_operation_done(o);
350     pa_operation_unref(o);
351 }
352
353 struct pa_operation* pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) {
354     struct pa_tagstruct *t;
355     struct pa_operation *o;
356     uint32_t tag;
357     assert(c && cb);
358
359     o = pa_operation_new(c, NULL);
360     o->callback = cb;
361     o->userdata = userdata;
362
363     t = pa_tagstruct_new(NULL, 0);
364     pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO);
365     pa_tagstruct_putu32(t, tag = c->ctag++);
366     pa_tagstruct_putu32(t, index);
367     pa_pstream_send_tagstruct(c->pstream, t);
368     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, o);
369
370     return pa_operation_ref(o);
371 }
372
373 struct pa_operation* pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) {
374     return pa_context_send_simple_command(c, PA_COMMAND_GET_MODULE_INFO_LIST, context_get_module_info_callback, cb, userdata);
375 }
376
377 /*** Sink input info ***/
378
379 static void context_get_sink_input_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
380     struct pa_operation *o = userdata;
381     int eof = 1;
382     assert(pd && o && o->context && o->ref >= 1);
383
384     if (command != PA_COMMAND_REPLY) {
385         if (pa_context_handle_error(o->context, command, t) < 0)
386             goto finish;
387
388         eof = -1;
389     } else {
390         
391         while (!pa_tagstruct_eof(t)) {
392             struct pa_sink_input_info i;
393             
394             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
395                 pa_tagstruct_gets(t, &i.name) < 0 ||
396                 pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
397                 pa_tagstruct_getu32(t, &i.client) < 0 ||
398                 pa_tagstruct_getu32(t, &i.sink) < 0 ||
399                 pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
400                 pa_tagstruct_getu32(t, &i.volume) < 0 ||
401                 pa_tagstruct_getu32(t, &i.latency) < 0) {
402                 pa_context_fail(o->context, PA_ERROR_PROTOCOL);
403                 goto finish;
404             }
405
406             if (o->callback) {
407                 void (*cb)(struct pa_context *s, const struct pa_sink_input_info*i, int eof, void *userdata) = o->callback;
408                 cb(o->context, &i, 0, o->userdata);
409             }
410         }
411     }
412     
413     if (o->callback) {
414         void (*cb)(struct pa_context *s, const struct pa_sink_input_info*i, int eof, void *userdata) = o->callback;
415         cb(o->context, NULL, eof, o->userdata);
416     }
417
418 finish:
419     pa_operation_done(o);
420     pa_operation_unref(o);
421 }
422
423 struct pa_operation* pa_context_get_sink_input_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata) {
424     struct pa_tagstruct *t;
425     struct pa_operation *o;
426     uint32_t tag;
427     assert(c && cb);
428
429     o = pa_operation_new(c, NULL);
430     o->callback = cb;
431     o->userdata = userdata;
432
433     t = pa_tagstruct_new(NULL, 0);
434     pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INPUT_INFO);
435     pa_tagstruct_putu32(t, tag = c->ctag++);
436     pa_tagstruct_putu32(t, index);
437     pa_pstream_send_tagstruct(c->pstream, t);
438     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_input_info_callback, o);
439
440     return pa_operation_ref(o);
441 }
442
443 struct pa_operation* pa_context_get_sink_input_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata) {
444     return pa_context_send_simple_command(c, PA_COMMAND_GET_SINK_INPUT_INFO_LIST, context_get_sink_input_info_callback, cb, userdata);
445 }
446
447 /*** Source output info ***/
448
449 static void context_get_source_output_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
450     struct pa_operation *o = userdata;
451     int eof = 1;
452     assert(pd && o && o->context && o->ref >= 1);
453
454     if (command != PA_COMMAND_REPLY) {
455         if (pa_context_handle_error(o->context, command, t) < 0)
456             goto finish;
457
458         eof = -1;
459     } else {
460         
461         while (!pa_tagstruct_eof(t)) {
462             struct pa_source_output_info i;
463             
464             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
465                 pa_tagstruct_gets(t, &i.name) < 0 ||
466                 pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
467                 pa_tagstruct_getu32(t, &i.client) < 0 ||
468                 pa_tagstruct_getu32(t, &i.source) < 0 ||
469                 pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0) {
470                 pa_context_fail(o->context, PA_ERROR_PROTOCOL);
471                 goto finish;
472             }
473
474             if (o->callback) {
475                 void (*cb)(struct pa_context *s, const struct pa_source_output_info*i, int eof, void *userdata) = o->callback;
476                 cb(o->context, &i, 0, o->userdata);
477             }
478         }
479     }
480     
481     if (o->callback) {
482         void (*cb)(struct pa_context *s, const struct pa_source_output_info*i, int eof, void *userdata) = o->callback;
483         cb(o->context, NULL, eof, o->userdata);
484     }
485
486 finish:
487     pa_operation_done(o);
488     pa_operation_unref(o);
489 }
490
491 struct pa_operation* pa_context_get_source_output_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata) {
492     struct pa_tagstruct *t;
493     struct pa_operation *o;
494     uint32_t tag;
495     assert(c && cb);
496
497     o = pa_operation_new(c, NULL);
498     o->callback = cb;
499     o->userdata = userdata;
500
501     t = pa_tagstruct_new(NULL, 0);
502     pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_OUTPUT_INFO);
503     pa_tagstruct_putu32(t, tag = c->ctag++);
504     pa_tagstruct_putu32(t, index);
505     pa_pstream_send_tagstruct(c->pstream, t);
506     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_output_info_callback, o);
507
508     return pa_operation_ref(o);
509 }
510
511 struct pa_operation* pa_context_get_source_output_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata) {
512     return pa_context_send_simple_command(c, PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST, context_get_source_output_info_callback, cb, userdata);
513 }
514
515 /*** Volume manipulation ***/
516
517 struct pa_operation* pa_context_set_sink_volume_by_index(struct pa_context *c, uint32_t index, pa_volume_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
518     struct pa_operation *o;
519     struct pa_tagstruct *t;
520     uint32_t tag;
521     assert(c && index != PA_INVALID_INDEX);
522
523     o = pa_operation_new(c, NULL);
524     o->callback = cb;
525     o->userdata = userdata;
526
527     t = pa_tagstruct_new(NULL, 0);
528     pa_tagstruct_putu32(t, PA_COMMAND_SET_SINK_VOLUME);
529     pa_tagstruct_putu32(t, tag = c->ctag++);
530     pa_tagstruct_putu32(t, index);
531     pa_tagstruct_puts(t, "");
532     pa_tagstruct_putu32(t, volume);
533     pa_pstream_send_tagstruct(c->pstream, t);
534     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o);
535
536     return pa_operation_ref(o);
537 }
538
539 struct pa_operation* pa_context_set_sink_volume_by_name(struct pa_context *c, const char *name, pa_volume_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
540     struct pa_operation *o;
541     struct pa_tagstruct *t;
542     uint32_t tag;
543     assert(c && name);
544
545     o = pa_operation_new(c, NULL);
546     o->callback = cb;
547     o->userdata = userdata;
548
549     t = pa_tagstruct_new(NULL, 0);
550     pa_tagstruct_putu32(t, PA_COMMAND_SET_SINK_VOLUME);
551     pa_tagstruct_putu32(t, tag = c->ctag++);
552     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
553     pa_tagstruct_puts(t, name);
554     pa_tagstruct_putu32(t, volume);
555     pa_pstream_send_tagstruct(c->pstream, t);
556     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o);
557
558     return pa_operation_ref(o);
559 }
560
561 struct pa_operation* pa_context_set_sink_input_volume(struct pa_context *c, uint32_t index, pa_volume_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
562     struct pa_operation *o;
563     struct pa_tagstruct *t;
564     uint32_t tag;
565     assert(c && index != PA_INVALID_INDEX);
566
567     o = pa_operation_new(c, NULL);
568     o->callback = cb;
569     o->userdata = userdata;
570
571     t = pa_tagstruct_new(NULL, 0);
572     pa_tagstruct_putu32(t, PA_COMMAND_SET_SINK_INPUT_VOLUME);
573     pa_tagstruct_putu32(t, tag = c->ctag++);
574     pa_tagstruct_putu32(t, index);
575     pa_tagstruct_putu32(t, volume);
576     pa_pstream_send_tagstruct(c->pstream, t);
577     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o);
578
579     return pa_operation_ref(o);
580 }