~binli/ubuntu/vivid/pulseaudio/fix-atoi

« back to all changes in this revision

Viewing changes to src/pulse/ext-device-restore.c

  • Committer: Bin Li
  • Date: 2016-07-05 03:39:49 UTC
  • Revision ID: bin.li@canonical.com-20160705033949-rz4p9x4hbi2danxk
first version based on pulseaudio_6.0-0ubuntu9.27

Show diffs side-by-side

added added

removed removed

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