remove obnoxious assert from module-combine
[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_total) < 0 ||
46                pa_tagstruct_getu32(t, &i.memblock_total_size) < 0 ||
47                pa_tagstruct_getu32(t, &i.memblock_allocated) < 0 ||
48                pa_tagstruct_getu32(t, &i.memblock_allocated_size) < 0 ||
49                pa_tagstruct_getu32(t, &i.scache_size) < 0 ||
50                !pa_tagstruct_eof(t)) {
51         pa_context_fail(o->context, PA_ERROR_PROTOCOL);
52         goto finish;
53     }
54
55     if (o->callback) {
56         void (*cb)(struct pa_context *s, const struct pa_stat_info*i, void *userdata) = o->callback;
57         cb(o->context, p, o->userdata);
58     }
59
60 finish:
61     pa_operation_done(o);
62     pa_operation_unref(o);
63 }
64
65 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) {
66     return pa_context_send_simple_command(c, PA_COMMAND_STAT, context_stat_callback, cb, userdata);
67 }
68
69 /*** Server Info ***/
70
71 static void context_get_server_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
72     struct pa_operation *o = userdata;
73     struct pa_server_info i, *p = &i;
74     assert(pd && o && o->context && o->ref >= 1);
75
76     if (command != PA_COMMAND_REPLY) {
77         if (pa_context_handle_error(o->context, command, t) < 0)
78             goto finish;
79
80         p = NULL;
81     } else if (pa_tagstruct_gets(t, &i.server_name) < 0 ||
82                pa_tagstruct_gets(t, &i.server_version) < 0 ||
83                pa_tagstruct_gets(t, &i.user_name) < 0 ||
84                pa_tagstruct_gets(t, &i.host_name) < 0 ||
85                pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
86                pa_tagstruct_gets(t, &i.default_sink_name) < 0 ||
87                pa_tagstruct_gets(t, &i.default_source_name) < 0 ||
88                !pa_tagstruct_eof(t)) {
89
90         pa_context_fail(o->context, PA_ERROR_PROTOCOL);
91         goto finish;
92     }
93     
94     if (o->callback) {
95         void (*cb)(struct pa_context *s, const struct pa_server_info*i, void *userdata) = o->callback;
96         cb(o->context, p, o->userdata);
97     }
98
99 finish:
100     pa_operation_done(o);
101     pa_operation_unref(o);
102 }
103
104 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) {
105     return pa_context_send_simple_command(c, PA_COMMAND_GET_SERVER_INFO, context_get_server_info_callback, cb, userdata);
106 }
107
108 /*** Sink Info ***/
109
110 static void context_get_sink_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
111     struct pa_operation *o = userdata;
112     int eof = 1;
113     assert(pd && o && o->context && o->ref >= 1);
114
115     if (command != PA_COMMAND_REPLY) {
116         if (pa_context_handle_error(o->context, command, t) < 0)
117             goto finish;
118
119         eof = -1;
120     } else {
121         
122         while (!pa_tagstruct_eof(t)) {
123             struct pa_sink_info i;
124             
125             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
126                 pa_tagstruct_gets(t, &i.name) < 0 ||
127                 pa_tagstruct_gets(t, &i.description) < 0 ||
128                 pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
129                 pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
130                 pa_tagstruct_getu32(t, &i.volume) < 0 ||
131                 pa_tagstruct_getu32(t, &i.monitor_source) < 0 ||
132                 pa_tagstruct_gets(t, &i.monitor_source_name) < 0 ||
133                 pa_tagstruct_get_usec(t, &i.latency) < 0) {
134                 pa_context_fail(o->context, PA_ERROR_PROTOCOL);
135                 goto finish;
136             }
137
138             if (o->callback) {
139                 void (*cb)(struct pa_context *s, const struct pa_sink_info*i, int eof, void *userdata) = o->callback;
140                 cb(o->context, &i, 0, o->userdata);
141             }
142         }
143     }
144     
145     if (o->callback) {
146         void (*cb)(struct pa_context *s, const struct pa_sink_info*i, int eof, void *userdata) = o->callback;
147         cb(o->context, NULL, eof, o->userdata);
148     }
149
150 finish:
151     pa_operation_done(o);
152     pa_operation_unref(o);
153 }
154
155 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) {
156     return pa_context_send_simple_command(c, PA_COMMAND_GET_SINK_INFO_LIST, context_get_sink_info_callback, cb, userdata);
157 }
158
159 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) {
160     struct pa_tagstruct *t;
161     struct pa_operation *o;
162     uint32_t tag;
163     assert(c && cb);
164
165     o = pa_operation_new(c, NULL);
166     o->callback = cb;
167     o->userdata = userdata;
168
169     t = pa_tagstruct_new(NULL, 0);
170     pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO);
171     pa_tagstruct_putu32(t, tag = c->ctag++);
172     pa_tagstruct_putu32(t, index);
173     pa_tagstruct_puts(t, NULL);
174     pa_pstream_send_tagstruct(c->pstream, t);
175     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, o);
176
177     return pa_operation_ref(o);
178 }
179
180 struct pa_operation* pa_context_get_sink_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) {
181     struct pa_tagstruct *t;
182     struct pa_operation *o;
183     uint32_t tag;
184     assert(c && cb);
185
186     o = pa_operation_new(c, NULL);
187     o->callback = cb;
188     o->userdata = userdata;
189
190     t = pa_tagstruct_new(NULL, 0);
191     pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO);
192     pa_tagstruct_putu32(t, tag = c->ctag++);
193     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
194     pa_tagstruct_puts(t, name);
195     pa_pstream_send_tagstruct(c->pstream, t);
196     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, o);
197
198     return pa_operation_ref(o);
199 }
200
201 /*** Source info ***/
202
203 static void context_get_source_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
204     struct pa_operation *o = userdata;
205     int eof = 1;
206     assert(pd && o && o->context && o->ref >= 1);
207
208     if (command != PA_COMMAND_REPLY) {
209         if (pa_context_handle_error(o->context, command, t) < 0)
210             goto finish;
211
212         eof = -1;
213     } else {
214         
215         while (!pa_tagstruct_eof(t)) {
216             struct pa_source_info i;
217             
218             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
219                 pa_tagstruct_gets(t, &i.name) < 0 ||
220                 pa_tagstruct_gets(t, &i.description) < 0 ||
221                 pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
222                 pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
223                 pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 ||
224                 pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0 ||
225                 pa_tagstruct_get_usec(t, &i.latency) < 0) {
226                 
227                 pa_context_fail(o->context, PA_ERROR_PROTOCOL);
228                 goto finish;
229             }
230
231             if (o->callback) {
232                 void (*cb)(struct pa_context *s, const struct pa_source_info*i, int eof, void *userdata) = o->callback;
233                 cb(o->context, &i, 0, o->userdata);
234             }
235         }
236     }
237     
238     if (o->callback) {
239         void (*cb)(struct pa_context *s, const struct pa_source_info*i, int eof, void *userdata) = o->callback;
240         cb(o->context, NULL, eof, o->userdata);
241     }
242
243 finish:
244     pa_operation_done(o);
245     pa_operation_unref(o);
246 }
247
248 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) {
249     return pa_context_send_simple_command(c, PA_COMMAND_GET_SOURCE_INFO_LIST, context_get_source_info_callback, cb, userdata);
250 }
251
252 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) {
253     struct pa_tagstruct *t;
254     struct pa_operation *o;
255     uint32_t tag;
256     assert(c && cb);
257
258     o = pa_operation_new(c, NULL);
259     o->callback = cb;
260     o->userdata = userdata;
261
262     t = pa_tagstruct_new(NULL, 0);
263     pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO);
264     pa_tagstruct_putu32(t, tag = c->ctag++);
265     pa_tagstruct_putu32(t, index);
266     pa_tagstruct_puts(t, NULL);
267     pa_pstream_send_tagstruct(c->pstream, t);
268     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, o);
269
270     return pa_operation_ref(o);
271 }
272
273 struct pa_operation* pa_context_get_source_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) {
274     struct pa_tagstruct *t;
275     struct pa_operation *o;
276     uint32_t tag;
277     assert(c && cb);
278
279     o = pa_operation_new(c, NULL);
280     o->callback = cb;
281     o->userdata = userdata;
282
283     t = pa_tagstruct_new(NULL, 0);
284     pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO);
285     pa_tagstruct_putu32(t, tag = c->ctag++);
286     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
287     pa_tagstruct_puts(t, name);
288     pa_pstream_send_tagstruct(c->pstream, t);
289     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, o);
290
291     return pa_operation_ref(o);
292 }
293
294 /*** Client info ***/
295
296 static void context_get_client_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
297     struct pa_operation *o = userdata;
298     int eof = 1;
299     assert(pd && o && o->context && o->ref >= 1);
300
301     if (command != PA_COMMAND_REPLY) {
302         if (pa_context_handle_error(o->context, command, t) < 0)
303             goto finish;
304
305         eof = -1;
306     } else {
307         
308         while (!pa_tagstruct_eof(t)) {
309             struct pa_client_info i;
310             
311             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
312                 pa_tagstruct_gets(t, &i.name) < 0 ||
313                 pa_tagstruct_gets(t, &i.protocol_name) < 0 ||
314                 pa_tagstruct_getu32(t, &i.owner_module) < 0) {
315                 pa_context_fail(o->context, PA_ERROR_PROTOCOL);
316                 goto finish;
317             }
318
319             if (o->callback) {
320                 void (*cb)(struct pa_context *s, const struct pa_client_info*i, int eof, void *userdata) = o->callback;
321                 cb(o->context, &i, 0, o->userdata);
322             }
323         }
324     }
325     
326     if (o->callback) {
327         void (*cb)(struct pa_context *s, const struct pa_client_info*i, int eof, void *userdata) = o->callback;
328         cb(o->context, NULL, eof, o->userdata);
329     }
330
331 finish:
332     pa_operation_done(o);
333     pa_operation_unref(o);
334 }
335
336 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) {
337     struct pa_tagstruct *t;
338     struct pa_operation *o;
339     uint32_t tag;
340     assert(c && cb);
341
342     o = pa_operation_new(c, NULL);
343     o->callback = cb;
344     o->userdata = userdata;
345
346     t = pa_tagstruct_new(NULL, 0);
347     pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO);
348     pa_tagstruct_putu32(t, tag = c->ctag++);
349     pa_tagstruct_putu32(t, index);
350     pa_pstream_send_tagstruct(c->pstream, t);
351     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, o);
352
353     return pa_operation_ref(o);
354 }
355
356 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) {
357     return pa_context_send_simple_command(c, PA_COMMAND_GET_CLIENT_INFO_LIST, context_get_client_info_callback, cb, userdata);
358 }
359
360 /*** Module info ***/
361
362 static void context_get_module_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
363     struct pa_operation *o = userdata;
364     int eof = 1;
365     assert(pd && o && o->context && o->ref >= 1);
366
367     if (command != PA_COMMAND_REPLY) {
368         if (pa_context_handle_error(o->context, command, t) < 0)
369             goto finish;
370
371         eof = -1;
372     } else {
373         
374         while (!pa_tagstruct_eof(t)) {
375             struct pa_module_info i;
376             
377             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
378                 pa_tagstruct_gets(t, &i.name) < 0 ||
379                 pa_tagstruct_gets(t, &i.argument) < 0 ||
380                 pa_tagstruct_getu32(t, &i.n_used) < 0 ||
381                 pa_tagstruct_get_boolean(t, &i.auto_unload) < 0) {
382                 pa_context_fail(o->context, PA_ERROR_PROTOCOL);
383                 goto finish;
384             }
385
386             if (o->callback) {
387                 void (*cb)(struct pa_context *s, const struct pa_module_info*i, int eof, void *userdata) = o->callback;
388                 cb(o->context, &i, 0, o->userdata);
389             }
390         }
391     }
392     
393     if (o->callback) {
394         void (*cb)(struct pa_context *s, const struct pa_module_info*i, int eof, void *userdata) = o->callback;
395         cb(o->context, NULL, eof, o->userdata);
396     }
397
398 finish:
399     pa_operation_done(o);
400     pa_operation_unref(o);
401 }
402
403 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) {
404     struct pa_tagstruct *t;
405     struct pa_operation *o;
406     uint32_t tag;
407     assert(c && cb);
408
409     o = pa_operation_new(c, NULL);
410     o->callback = cb;
411     o->userdata = userdata;
412
413     t = pa_tagstruct_new(NULL, 0);
414     pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO);
415     pa_tagstruct_putu32(t, tag = c->ctag++);
416     pa_tagstruct_putu32(t, index);
417     pa_pstream_send_tagstruct(c->pstream, t);
418     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, o);
419
420     return pa_operation_ref(o);
421 }
422
423 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) {
424     return pa_context_send_simple_command(c, PA_COMMAND_GET_MODULE_INFO_LIST, context_get_module_info_callback, cb, userdata);
425 }
426
427 /*** Sink input info ***/
428
429 static void context_get_sink_input_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
430     struct pa_operation *o = userdata;
431     int eof = 1;
432     assert(pd && o && o->context && o->ref >= 1);
433
434     if (command != PA_COMMAND_REPLY) {
435         if (pa_context_handle_error(o->context, command, t) < 0)
436             goto finish;
437
438         eof = -1;
439     } else {
440         
441         while (!pa_tagstruct_eof(t)) {
442             struct pa_sink_input_info i;
443             
444             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
445                 pa_tagstruct_gets(t, &i.name) < 0 ||
446                 pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
447                 pa_tagstruct_getu32(t, &i.client) < 0 ||
448                 pa_tagstruct_getu32(t, &i.sink) < 0 ||
449                 pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
450                 pa_tagstruct_getu32(t, &i.volume) < 0 ||
451                 pa_tagstruct_get_usec(t, &i.buffer_usec) < 0 ||
452                 pa_tagstruct_get_usec(t, &i.sink_usec) < 0) {
453                 pa_context_fail(o->context, PA_ERROR_PROTOCOL);
454                 goto finish;
455             }
456
457             if (o->callback) {
458                 void (*cb)(struct pa_context *s, const struct pa_sink_input_info*i, int eof, void *userdata) = o->callback;
459                 cb(o->context, &i, 0, o->userdata);
460             }
461         }
462     }
463     
464     if (o->callback) {
465         void (*cb)(struct pa_context *s, const struct pa_sink_input_info*i, int eof, void *userdata) = o->callback;
466         cb(o->context, NULL, eof, o->userdata);
467     }
468
469 finish:
470     pa_operation_done(o);
471     pa_operation_unref(o);
472 }
473
474 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) {
475     struct pa_tagstruct *t;
476     struct pa_operation *o;
477     uint32_t tag;
478     assert(c && cb);
479
480     o = pa_operation_new(c, NULL);
481     o->callback = cb;
482     o->userdata = userdata;
483
484     t = pa_tagstruct_new(NULL, 0);
485     pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INPUT_INFO);
486     pa_tagstruct_putu32(t, tag = c->ctag++);
487     pa_tagstruct_putu32(t, index);
488     pa_pstream_send_tagstruct(c->pstream, t);
489     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_input_info_callback, o);
490
491     return pa_operation_ref(o);
492 }
493
494 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) {
495     return pa_context_send_simple_command(c, PA_COMMAND_GET_SINK_INPUT_INFO_LIST, context_get_sink_input_info_callback, cb, userdata);
496 }
497
498 /*** Source output info ***/
499
500 static void context_get_source_output_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
501     struct pa_operation *o = userdata;
502     int eof = 1;
503     assert(pd && o && o->context && o->ref >= 1);
504
505     if (command != PA_COMMAND_REPLY) {
506         if (pa_context_handle_error(o->context, command, t) < 0)
507             goto finish;
508
509         eof = -1;
510     } else {
511         
512         while (!pa_tagstruct_eof(t)) {
513             struct pa_source_output_info i;
514             
515             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
516                 pa_tagstruct_gets(t, &i.name) < 0 ||
517                 pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
518                 pa_tagstruct_getu32(t, &i.client) < 0 ||
519                 pa_tagstruct_getu32(t, &i.source) < 0 ||
520                 pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
521                 pa_tagstruct_get_usec(t, &i.buffer_usec) < 0 ||
522                 pa_tagstruct_get_usec(t, &i.source_usec) < 0) {
523                 pa_context_fail(o->context, PA_ERROR_PROTOCOL);
524                 goto finish;
525             }
526
527             if (o->callback) {
528                 void (*cb)(struct pa_context *s, const struct pa_source_output_info*i, int eof, void *userdata) = o->callback;
529                 cb(o->context, &i, 0, o->userdata);
530             }
531         }
532     }
533     
534     if (o->callback) {
535         void (*cb)(struct pa_context *s, const struct pa_source_output_info*i, int eof, void *userdata) = o->callback;
536         cb(o->context, NULL, eof, o->userdata);
537     }
538
539 finish:
540     pa_operation_done(o);
541     pa_operation_unref(o);
542 }
543
544 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) {
545     struct pa_tagstruct *t;
546     struct pa_operation *o;
547     uint32_t tag;
548     assert(c && cb);
549
550     o = pa_operation_new(c, NULL);
551     o->callback = cb;
552     o->userdata = userdata;
553
554     t = pa_tagstruct_new(NULL, 0);
555     pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_OUTPUT_INFO);
556     pa_tagstruct_putu32(t, tag = c->ctag++);
557     pa_tagstruct_putu32(t, index);
558     pa_pstream_send_tagstruct(c->pstream, t);
559     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_output_info_callback, o);
560
561     return pa_operation_ref(o);
562 }
563
564 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) {
565     return pa_context_send_simple_command(c, PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST, context_get_source_output_info_callback, cb, userdata);
566 }
567
568 /*** Volume manipulation ***/
569
570 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) {
571     struct pa_operation *o;
572     struct pa_tagstruct *t;
573     uint32_t tag;
574     assert(c && index != PA_INVALID_INDEX);
575
576     o = pa_operation_new(c, NULL);
577     o->callback = cb;
578     o->userdata = userdata;
579
580     t = pa_tagstruct_new(NULL, 0);
581     pa_tagstruct_putu32(t, PA_COMMAND_SET_SINK_VOLUME);
582     pa_tagstruct_putu32(t, tag = c->ctag++);
583     pa_tagstruct_putu32(t, index);
584     pa_tagstruct_puts(t, NULL);
585     pa_tagstruct_putu32(t, volume);
586     pa_pstream_send_tagstruct(c->pstream, t);
587     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o);
588
589     return pa_operation_ref(o);
590 }
591
592 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) {
593     struct pa_operation *o;
594     struct pa_tagstruct *t;
595     uint32_t tag;
596     assert(c && name);
597
598     o = pa_operation_new(c, NULL);
599     o->callback = cb;
600     o->userdata = userdata;
601
602     t = pa_tagstruct_new(NULL, 0);
603     pa_tagstruct_putu32(t, PA_COMMAND_SET_SINK_VOLUME);
604     pa_tagstruct_putu32(t, tag = c->ctag++);
605     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
606     pa_tagstruct_puts(t, name);
607     pa_tagstruct_putu32(t, volume);
608     pa_pstream_send_tagstruct(c->pstream, t);
609     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o);
610
611     return pa_operation_ref(o);
612 }
613
614 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) {
615     struct pa_operation *o;
616     struct pa_tagstruct *t;
617     uint32_t tag;
618     assert(c && index != PA_INVALID_INDEX);
619
620     o = pa_operation_new(c, NULL);
621     o->callback = cb;
622     o->userdata = userdata;
623
624     t = pa_tagstruct_new(NULL, 0);
625     pa_tagstruct_putu32(t, PA_COMMAND_SET_SINK_INPUT_VOLUME);
626     pa_tagstruct_putu32(t, tag = c->ctag++);
627     pa_tagstruct_putu32(t, index);
628     pa_tagstruct_putu32(t, volume);
629     pa_pstream_send_tagstruct(c->pstream, t);
630     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o);
631
632     return pa_operation_ref(o);
633 }
634
635 /** Sample Cache **/
636
637 static void context_get_sample_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
638     struct pa_operation *o = userdata;
639     int eof = 1;
640     assert(pd && o && o->context && o->ref >= 1);
641
642     if (command != PA_COMMAND_REPLY) {
643         if (pa_context_handle_error(o->context, command, t) < 0)
644             goto finish;
645
646         eof = -1;
647     } else {
648         
649         while (!pa_tagstruct_eof(t)) {
650             struct pa_sample_info i;
651             
652             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
653                 pa_tagstruct_gets(t, &i.name) < 0 ||
654                 pa_tagstruct_getu32(t, &i.volume) < 0 ||
655                 pa_tagstruct_get_usec(t, &i.duration) < 0 ||
656                 pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
657                 pa_tagstruct_getu32(t, &i.bytes) < 0 ||
658                 pa_tagstruct_get_boolean(t, &i.lazy) < 0 ||
659                 pa_tagstruct_gets(t, &i.filename) < 0) {
660                 pa_context_fail(o->context, PA_ERROR_PROTOCOL);
661                 goto finish;
662             }
663
664             if (o->callback) {
665                 void (*cb)(struct pa_context *s, const struct pa_sample_info*i, int eof, void *userdata) = o->callback;
666                 cb(o->context, &i, 0, o->userdata);
667             }
668         }
669     }
670     
671     if (o->callback) {
672         void (*cb)(struct pa_context *s, const struct pa_sample_info*i, int eof, void *userdata) = o->callback;
673         cb(o->context, NULL, eof, o->userdata);
674     }
675
676 finish:
677     pa_operation_done(o);
678     pa_operation_unref(o);
679 }
680
681 struct pa_operation* pa_context_get_sample_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sample_info *i, int is_last, void *userdata), void *userdata) {
682     struct pa_tagstruct *t;
683     struct pa_operation *o;
684     uint32_t tag;
685     assert(c && cb && name);
686
687     o = pa_operation_new(c, NULL);
688     o->callback = cb;
689     o->userdata = userdata;
690
691     t = pa_tagstruct_new(NULL, 0);
692     pa_tagstruct_putu32(t, PA_COMMAND_GET_SAMPLE_INFO);
693     pa_tagstruct_putu32(t, tag = c->ctag++);
694     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
695     pa_tagstruct_puts(t, name);
696     pa_pstream_send_tagstruct(c->pstream, t);
697     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sample_info_callback, o);
698
699     return pa_operation_ref(o);
700 }
701
702 struct pa_operation* pa_context_get_sample_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sample_info *i, int is_last, void *userdata), void *userdata) {
703     struct pa_tagstruct *t;
704     struct pa_operation *o;
705     uint32_t tag;
706     assert(c && cb);
707
708     o = pa_operation_new(c, NULL);
709     o->callback = cb;
710     o->userdata = userdata;
711
712     t = pa_tagstruct_new(NULL, 0);
713     pa_tagstruct_putu32(t, PA_COMMAND_GET_SAMPLE_INFO);
714     pa_tagstruct_putu32(t, tag = c->ctag++);
715     pa_tagstruct_putu32(t, index);
716     pa_tagstruct_puts(t, NULL);
717     pa_pstream_send_tagstruct(c->pstream, t);
718     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sample_info_callback, o);
719
720     return pa_operation_ref(o);
721 }
722
723 struct pa_operation* pa_context_get_sample_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sample_info *i, int is_last, void *userdata), void *userdata) {
724     return pa_context_send_simple_command(c, PA_COMMAND_GET_SAMPLE_INFO_LIST, context_get_sample_info_callback, cb, userdata);
725 }
726
727 static struct pa_operation* command_kill(struct pa_context *c, uint32_t command, uint32_t index, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
728     struct pa_operation *o;
729     struct pa_tagstruct *t;
730     uint32_t tag;
731     assert(c && index != PA_INVALID_INDEX);
732
733     o = pa_operation_new(c, NULL);
734     o->callback = cb;
735     o->userdata = userdata;
736
737     t = pa_tagstruct_new(NULL, 0);
738     pa_tagstruct_putu32(t, command);
739     pa_tagstruct_putu32(t, tag = c->ctag++);
740     pa_tagstruct_putu32(t, index);
741     pa_pstream_send_tagstruct(c->pstream, t);
742     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o);
743
744     return pa_operation_ref(o);
745 }
746
747 struct pa_operation* pa_context_kill_client(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
748     return command_kill(c, PA_COMMAND_KILL_CLIENT, index, cb, userdata);
749 }
750                                             
751 struct pa_operation* pa_context_kill_sink_input(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
752     return command_kill(c, PA_COMMAND_KILL_SINK_INPUT, index, cb, userdata);
753 }
754
755 struct pa_operation* pa_context_kill_source_output(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
756     return command_kill(c, PA_COMMAND_KILL_SOURCE_OUTPUT, index, cb, userdata);
757 }
758
759 static void load_module_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
760     struct pa_operation *o = userdata;
761     uint32_t index = -1;
762     assert(pd && o && o->context && o->ref >= 1);
763
764     if (command != PA_COMMAND_REPLY) {
765         if (pa_context_handle_error(o->context, command, t) < 0)
766             goto finish;
767
768     } else if (pa_tagstruct_getu32(t, &index) < 0 ||
769                !pa_tagstruct_eof(t)) {
770         pa_context_fail(o->context, PA_ERROR_PROTOCOL);
771         goto finish;
772     }
773     
774     if (o->callback) {
775         void (*cb)(struct pa_context *c, uint32_t index, void *userdata) = o->callback;
776         cb(o->context, index, o->userdata);
777     }
778
779 finish:
780     pa_operation_done(o);
781     pa_operation_unref(o);
782 }
783
784 struct pa_operation* pa_context_load_module(struct pa_context *c, const char*name, const char *argument, void (*cb)(struct pa_context *c, uint32_t index, void *userdata), void *userdata) {
785     struct pa_operation *o;
786     struct pa_tagstruct *t;
787     uint32_t tag;
788     assert(c && name && argument);
789
790     o = pa_operation_new(c, NULL);
791     o->callback = cb;
792     o->userdata = userdata;
793
794     t = pa_tagstruct_new(NULL, 0);
795     pa_tagstruct_putu32(t, PA_COMMAND_LOAD_MODULE);
796     pa_tagstruct_putu32(t, tag = c->ctag++);
797     pa_tagstruct_puts(t, name);
798     pa_tagstruct_puts(t, argument);
799     pa_pstream_send_tagstruct(c->pstream, t);
800     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, load_module_callback, o);
801
802     return pa_operation_ref(o);
803 }
804
805 struct pa_operation* pa_context_unload_module(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
806     return command_kill(c, PA_COMMAND_UNLOAD_MODULE, index, cb, userdata);
807 }
808
809 /*** Autoload stuff ***/
810
811 static void context_get_autoload_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
812     struct pa_operation *o = userdata;
813     int eof = 1;
814     assert(pd && o && o->context && o->ref >= 1);
815
816     if (command != PA_COMMAND_REPLY) {
817         if (pa_context_handle_error(o->context, command, t) < 0)
818             goto finish;
819
820         eof = -1;
821     } else {
822         
823         while (!pa_tagstruct_eof(t)) {
824             struct pa_autoload_info i;
825             
826             if (pa_tagstruct_gets(t, &i.name) < 0 ||
827                 pa_tagstruct_getu32(t, &i.type) < 0 ||
828                 pa_tagstruct_gets(t, &i.module) < 0 ||
829                 pa_tagstruct_gets(t, &i.argument) < 0) {
830                 pa_context_fail(o->context, PA_ERROR_PROTOCOL);
831                 goto finish;
832             }
833
834             if (o->callback) {
835                 void (*cb)(struct pa_context *s, const struct pa_autoload_info*i, int eof, void *userdata) = o->callback;
836                 cb(o->context, &i, 0, o->userdata);
837             }
838         }
839     }
840     
841     if (o->callback) {
842         void (*cb)(struct pa_context *s, const struct pa_autoload_info*i, int eof, void *userdata) = o->callback;
843         cb(o->context, NULL, eof, o->userdata);
844     }
845
846 finish:
847     pa_operation_done(o);
848     pa_operation_unref(o);
849 }
850
851 struct pa_operation* pa_context_get_autoload_info(struct pa_context *c, const char *name, enum pa_autoload_type type, void (*cb)(struct pa_context *c, const struct pa_autoload_info *i, int is_last, void *userdata), void *userdata) {
852     struct pa_tagstruct *t;
853     struct pa_operation *o;
854     uint32_t tag;
855     assert(c && cb && name);
856
857     o = pa_operation_new(c, NULL);
858     o->callback = cb;
859     o->userdata = userdata;
860
861     t = pa_tagstruct_new(NULL, 0);
862     pa_tagstruct_putu32(t, PA_COMMAND_GET_AUTOLOAD_INFO);
863     pa_tagstruct_putu32(t, tag = c->ctag++);
864     pa_tagstruct_puts(t, name);
865     pa_tagstruct_putu32(t, type);
866     pa_pstream_send_tagstruct(c->pstream, t);
867     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_autoload_info_callback, o);
868
869     return pa_operation_ref(o);
870 }
871
872 struct pa_operation* pa_context_get_autoload_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_autoload_info *i, int is_last, void *userdata), void *userdata) {
873     return pa_context_send_simple_command(c, PA_COMMAND_GET_AUTOLOAD_INFO_LIST, context_get_autoload_info_callback, cb, userdata);
874 }
875
876 struct pa_operation* pa_context_add_autoload(struct pa_context *c, const char *name, enum pa_autoload_type type, const char *module, const char*argument, void (*cb)(struct pa_context *c, int success, void *userdata), void* userdata) {
877     struct pa_operation *o;
878     struct pa_tagstruct *t;
879     uint32_t tag;
880     assert(c && name && module && argument);
881
882     o = pa_operation_new(c, NULL);
883     o->callback = cb;
884     o->userdata = userdata;
885
886     t = pa_tagstruct_new(NULL, 0);
887     pa_tagstruct_putu32(t, PA_COMMAND_ADD_AUTOLOAD);
888     pa_tagstruct_putu32(t, tag = c->ctag++);
889     pa_tagstruct_puts(t, name);
890     pa_tagstruct_putu32(t, type);
891     pa_tagstruct_puts(t, module);
892     pa_tagstruct_puts(t, argument);
893     pa_pstream_send_tagstruct(c->pstream, t);
894     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o);
895
896     return pa_operation_ref(o);
897 }
898
899 struct pa_operation* pa_context_remove_autoload(struct pa_context *c, const char *name, enum pa_autoload_type type, void (*cb)(struct pa_context *c, int success, void *userdata), void* userdata) {
900     struct pa_operation *o;
901     struct pa_tagstruct *t;
902     uint32_t tag;
903     assert(c && name);
904
905     o = pa_operation_new(c, NULL);
906     o->callback = cb;
907     o->userdata = userdata;
908
909     t = pa_tagstruct_new(NULL, 0);
910     pa_tagstruct_putu32(t, PA_COMMAND_REMOVE_AUTOLOAD);
911     pa_tagstruct_putu32(t, tag = c->ctag++);
912     pa_tagstruct_puts(t, name);
913     pa_tagstruct_putu32(t, type);
914     pa_pstream_send_tagstruct(c->pstream, t);
915     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o);
916
917     return pa_operation_ref(o);
918 }