Squash the last gcc warnings
[profile/ivi/pulseaudio.git] / src / pulse / ext-device-restore.c
1 /***
2   This file is part of PulseAudio.
3
4   Copyright 2008 Lennart Poettering
5   Copyright 2011 Colin Guthrie
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/gccmacro.h>
29 #include <pulse/xmalloc.h>
30 #include <pulse/fork-detect.h>
31 #include <pulse/operation.h>
32 #include <pulse/format.h>
33
34 #include <pulsecore/macro.h>
35 #include <pulsecore/pstream-util.h>
36
37 #include "internal.h"
38 #include "ext-device-restore.h"
39
40 /* Protocol extension commands */
41 enum {
42     SUBCOMMAND_TEST,
43     SUBCOMMAND_SUBSCRIBE,
44     SUBCOMMAND_EVENT,
45     SUBCOMMAND_READ_FORMATS_ALL,
46     SUBCOMMAND_READ_FORMATS,
47     SUBCOMMAND_SAVE_FORMATS
48 };
49
50 static void ext_device_restore_test_cb(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
51     pa_operation *o = userdata;
52     uint32_t version = PA_INVALID_INDEX;
53
54     pa_assert(pd);
55     pa_assert(o);
56     pa_assert(PA_REFCNT_VALUE(o) >= 1);
57
58     if (!o->context)
59         goto finish;
60
61     if (command != PA_COMMAND_REPLY) {
62         if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
63             goto finish;
64
65     } else if (pa_tagstruct_getu32(t, &version) < 0 ||
66                !pa_tagstruct_eof(t)) {
67
68         pa_context_fail(o->context, PA_ERR_PROTOCOL);
69         goto finish;
70     }
71
72     if (o->callback) {
73         pa_ext_device_restore_test_cb_t cb = (pa_ext_device_restore_test_cb_t) o->callback;
74         cb(o->context, version, o->userdata);
75     }
76
77 finish:
78     pa_operation_done(o);
79     pa_operation_unref(o);
80 }
81
82 pa_operation *pa_ext_device_restore_test(
83         pa_context *c,
84         pa_ext_device_restore_test_cb_t cb,
85         void *userdata) {
86
87     uint32_t tag;
88     pa_operation *o;
89     pa_tagstruct *t;
90
91     pa_assert(c);
92     pa_assert(PA_REFCNT_VALUE(c) >= 1);
93
94     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
95     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
96     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED);
97
98     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
99
100     t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag);
101     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
102     pa_tagstruct_puts(t, "module-device-restore");
103     pa_tagstruct_putu32(t, SUBCOMMAND_TEST);
104     pa_pstream_send_tagstruct(c->pstream, t);
105     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, ext_device_restore_test_cb, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
106
107     return o;
108 }
109
110 pa_operation *pa_ext_device_restore_subscribe(
111         pa_context *c,
112         int enable,
113         pa_context_success_cb_t cb,
114         void *userdata) {
115
116     uint32_t tag;
117     pa_operation *o;
118     pa_tagstruct *t;
119
120     pa_assert(c);
121     pa_assert(PA_REFCNT_VALUE(c) >= 1);
122
123     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
124     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
125     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED);
126
127     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
128
129     t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag);
130     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
131     pa_tagstruct_puts(t, "module-device-restore");
132     pa_tagstruct_putu32(t, SUBCOMMAND_SUBSCRIBE);
133     pa_tagstruct_put_boolean(t, enable);
134     pa_pstream_send_tagstruct(c->pstream, t);
135     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);
136
137     return o;
138 }
139
140 void pa_ext_device_restore_set_subscribe_cb(
141         pa_context *c,
142         pa_ext_device_restore_subscribe_cb_t cb,
143         void *userdata) {
144
145     pa_assert(c);
146     pa_assert(PA_REFCNT_VALUE(c) >= 1);
147
148     if (pa_detect_fork())
149         return;
150
151     c->ext_device_restore.callback = cb;
152     c->ext_device_restore.userdata = userdata;
153 }
154
155 static void ext_device_restore_read_device_formats_cb(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
156     pa_operation *o = userdata;
157     int eol = 1;
158
159     pa_assert(pd);
160     pa_assert(o);
161     pa_assert(PA_REFCNT_VALUE(o) >= 1);
162
163     if (!o->context)
164         goto finish;
165
166     if (command != PA_COMMAND_REPLY) {
167         if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
168             goto finish;
169
170         eol = -1;
171     } else {
172         uint8_t j;
173
174         while (!pa_tagstruct_eof(t)) {
175             pa_ext_device_restore_info i;
176             pa_zero(i);
177
178             if (pa_tagstruct_getu32(t, &i.type) < 0 ||
179                 pa_tagstruct_getu32(t, &i.index) < 0 ||
180                 pa_tagstruct_getu8(t, &i.n_formats) < 0) {
181
182                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
183                 goto finish;
184             }
185
186             if (PA_DEVICE_TYPE_SINK != i.type && PA_DEVICE_TYPE_SOURCE != i.type) {
187                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
188                 goto finish;
189             }
190
191             if (i.index == PA_INVALID_INDEX) {
192                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
193                 goto finish;
194             }
195
196             if (i.n_formats > 0) {
197                 i.formats = pa_xnew0(pa_format_info*, i.n_formats);
198
199                 for (j = 0; j < i.n_formats; j++) {
200
201                     pa_format_info *f = i.formats[j] = pa_format_info_new();
202                     if (pa_tagstruct_get_format_info(t, f) < 0) {
203                         uint8_t k;
204
205                         pa_context_fail(o->context, PA_ERR_PROTOCOL);
206                         for (k = 0; k < j+1; k++)
207                             pa_format_info_free(i.formats[k]);
208                         pa_xfree(i.formats);
209                         goto finish;
210                     }
211                 }
212             }
213
214             if (o->callback) {
215                 pa_ext_device_restore_read_device_formats_cb_t cb = (pa_ext_device_restore_read_device_formats_cb_t) o->callback;
216                 cb(o->context, &i, 0, o->userdata);
217             }
218
219             for (j = 0; j < i.n_formats; j++)
220                 pa_format_info_free(i.formats[j]);
221             pa_xfree(i.formats);
222         }
223     }
224
225     if (o->callback) {
226         pa_ext_device_restore_read_device_formats_cb_t cb = (pa_ext_device_restore_read_device_formats_cb_t) o->callback;
227         cb(o->context, NULL, eol, o->userdata);
228     }
229
230 finish:
231     pa_operation_done(o);
232     pa_operation_unref(o);
233 }
234
235 pa_operation *pa_ext_device_restore_read_formats_all(
236         pa_context *c,
237         pa_ext_device_restore_read_device_formats_cb_t cb,
238         void *userdata) {
239
240     uint32_t tag;
241     pa_operation *o;
242     pa_tagstruct *t;
243
244     pa_assert(c);
245     pa_assert(PA_REFCNT_VALUE(c) >= 1);
246
247     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
248     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
249     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED);
250
251     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
252
253     t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag);
254     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
255     pa_tagstruct_puts(t, "module-device-restore");
256     pa_tagstruct_putu32(t, SUBCOMMAND_READ_FORMATS_ALL);
257     pa_pstream_send_tagstruct(c->pstream, t);
258     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, ext_device_restore_read_device_formats_cb, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
259
260     return o;
261 }
262
263 pa_operation *pa_ext_device_restore_read_formats(
264         pa_context *c,
265         pa_device_type_t type,
266         uint32_t idx,
267         pa_ext_device_restore_read_device_formats_cb_t cb,
268         void *userdata) {
269
270     uint32_t tag;
271     pa_operation *o;
272     pa_tagstruct *t;
273
274     pa_assert(c);
275     pa_assert(PA_REFCNT_VALUE(c) >= 1);
276     pa_assert(idx != PA_INVALID_INDEX);
277
278     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
279     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
280     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED);
281
282     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
283
284     t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag);
285     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
286     pa_tagstruct_puts(t, "module-device-restore");
287     pa_tagstruct_putu32(t, SUBCOMMAND_READ_FORMATS);
288     pa_tagstruct_putu32(t, type);
289     pa_tagstruct_putu32(t, idx);
290     pa_pstream_send_tagstruct(c->pstream, t);
291     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, ext_device_restore_read_device_formats_cb, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
292
293     return o;
294 }
295
296 pa_operation *pa_ext_device_restore_save_formats(
297         pa_context *c,
298         pa_device_type_t type,
299         uint32_t idx,
300         uint8_t n_formats,
301         pa_format_info **formats,
302         pa_context_success_cb_t cb,
303         void *userdata) {
304
305     uint32_t tag;
306     pa_operation *o;
307     pa_tagstruct *t;
308     uint8_t j;
309
310     pa_assert(c);
311     pa_assert(PA_REFCNT_VALUE(c) >= 1);
312     pa_assert(idx != PA_INVALID_INDEX);
313     pa_assert(n_formats > 0);
314     pa_assert(formats && *formats);
315
316     PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
317     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
318     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED);
319
320     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
321
322     t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag);
323     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
324     pa_tagstruct_puts(t, "module-device-restore");
325     pa_tagstruct_putu32(t, SUBCOMMAND_SAVE_FORMATS);
326
327     pa_tagstruct_putu32(t, type);
328     pa_tagstruct_putu32(t, idx);
329     pa_tagstruct_putu8(t, n_formats);
330     for (j = 0; j < n_formats; j++)
331         pa_tagstruct_put_format_info(t, formats[j]);
332
333     pa_pstream_send_tagstruct(c->pstream, t);
334     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);
335
336     return o;
337 }
338
339 /* Command function defined in internal.h */
340 void pa_ext_device_restore_command(pa_context *c, uint32_t tag, pa_tagstruct *t) {
341     uint32_t subcommand;
342     pa_device_type_t type;
343     uint32_t idx;
344
345     pa_assert(c);
346     pa_assert(PA_REFCNT_VALUE(c) >= 1);
347     pa_assert(t);
348
349     if (pa_tagstruct_getu32(t, &subcommand) < 0 ||
350         pa_tagstruct_getu32(t, &type) < 0 ||
351         pa_tagstruct_getu32(t, &idx) < 0 ||
352         !pa_tagstruct_eof(t)) {
353
354         pa_context_fail(c, PA_ERR_PROTOCOL);
355         return;
356     }
357
358     if (subcommand != SUBCOMMAND_EVENT) {
359         pa_context_fail(c, PA_ERR_PROTOCOL);
360         return;
361     }
362
363     if (PA_DEVICE_TYPE_SINK != type && PA_DEVICE_TYPE_SOURCE != type) {
364         pa_context_fail(c, PA_ERR_PROTOCOL);
365         return;
366     }
367
368     if (idx == PA_INVALID_INDEX) {
369         pa_context_fail(c, PA_ERR_PROTOCOL);
370         return;
371     }
372
373     if (c->ext_device_restore.callback)
374         c->ext_device_restore.callback(c, type, idx, c->ext_device_restore.userdata);
375 }