]> code.delx.au - pulseaudio/blob - src/pulse/ext-device-manager.c
Fixup #include directives according to Coding Style
[pulseaudio] / src / pulse / ext-device-manager.c
1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2008 Lennart Poettering
5 Copyright 2009 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
33 #include <pulsecore/macro.h>
34 #include <pulsecore/pstream-util.h>
35
36 #include "internal.h"
37 #include "ext-device-manager.h"
38
39 enum {
40 SUBCOMMAND_TEST,
41 SUBCOMMAND_READ,
42 SUBCOMMAND_RENAME,
43 SUBCOMMAND_DELETE,
44 SUBCOMMAND_ROLE_DEVICE_PRIORITY_ROUTING,
45 SUBCOMMAND_REORDER,
46 SUBCOMMAND_SUBSCRIBE,
47 SUBCOMMAND_EVENT
48 };
49
50 static void ext_device_manager_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_manager_test_cb_t cb = (pa_ext_device_manager_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_manager_test(
83 pa_context *c,
84 pa_ext_device_manager_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-manager");
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_manager_test_cb, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
106
107 return o;
108 }
109
110 static void ext_device_manager_read_cb(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
111 pa_operation *o = userdata;
112 int eol = 1;
113
114 pa_assert(pd);
115 pa_assert(o);
116 pa_assert(PA_REFCNT_VALUE(o) >= 1);
117
118 if (!o->context)
119 goto finish;
120
121 if (command != PA_COMMAND_REPLY) {
122 if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
123 goto finish;
124
125 eol = -1;
126 } else {
127
128 while (!pa_tagstruct_eof(t)) {
129 pa_ext_device_manager_info i;
130
131 memset(&i, 0, sizeof(i));
132
133 if (pa_tagstruct_gets(t, &i.name) < 0 ||
134 pa_tagstruct_gets(t, &i.description) < 0 ||
135 pa_tagstruct_gets(t, &i.icon) < 0 ||
136 pa_tagstruct_getu32(t, &i.index) < 0 ||
137 pa_tagstruct_getu32(t, &i.n_role_priorities) < 0) {
138
139 pa_context_fail(o->context, PA_ERR_PROTOCOL);
140 goto finish;
141 }
142
143 if (i.n_role_priorities > 0) {
144 uint32_t j;
145 i.role_priorities = pa_xnew0(pa_ext_device_manager_role_priority_info, i.n_role_priorities+1);
146
147 for (j = 0; j < i.n_role_priorities; j++) {
148
149 if (pa_tagstruct_gets(t, &i.role_priorities[j].role) < 0 ||
150 pa_tagstruct_getu32(t, &i.role_priorities[j].priority) < 0) {
151
152 pa_context_fail(o->context, PA_ERR_PROTOCOL);
153 pa_xfree(i.role_priorities);
154 goto finish;
155 }
156 }
157
158 /* Terminate with an extra NULL entry, just to make sure */
159 i.role_priorities[j].role = NULL;
160 i.role_priorities[j].priority = 0;
161 }
162
163 if (o->callback) {
164 pa_ext_device_manager_read_cb_t cb = (pa_ext_device_manager_read_cb_t) o->callback;
165 cb(o->context, &i, 0, o->userdata);
166 }
167
168 pa_xfree(i.role_priorities);
169 }
170 }
171
172 if (o->callback) {
173 pa_ext_device_manager_read_cb_t cb = (pa_ext_device_manager_read_cb_t) o->callback;
174 cb(o->context, NULL, eol, o->userdata);
175 }
176
177 finish:
178 pa_operation_done(o);
179 pa_operation_unref(o);
180 }
181
182 pa_operation *pa_ext_device_manager_read(
183 pa_context *c,
184 pa_ext_device_manager_read_cb_t cb,
185 void *userdata) {
186
187 uint32_t tag;
188 pa_operation *o;
189 pa_tagstruct *t;
190
191 pa_assert(c);
192 pa_assert(PA_REFCNT_VALUE(c) >= 1);
193
194 PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
195 PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
196 PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED);
197
198 o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
199
200 t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag);
201 pa_tagstruct_putu32(t, PA_INVALID_INDEX);
202 pa_tagstruct_puts(t, "module-device-manager");
203 pa_tagstruct_putu32(t, SUBCOMMAND_READ);
204 pa_pstream_send_tagstruct(c->pstream, t);
205 pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, ext_device_manager_read_cb, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
206
207 return o;
208 }
209
210 pa_operation *pa_ext_device_manager_set_device_description(
211 pa_context *c,
212 const char* device,
213 const char* description,
214 pa_context_success_cb_t cb,
215 void *userdata) {
216
217 uint32_t tag;
218 pa_operation *o = NULL;
219 pa_tagstruct *t = NULL;
220
221 pa_assert(c);
222 pa_assert(PA_REFCNT_VALUE(c) >= 1);
223 pa_assert(device);
224 pa_assert(description);
225
226 PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
227 PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
228 PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED);
229
230 o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
231
232 t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag);
233 pa_tagstruct_putu32(t, PA_INVALID_INDEX);
234 pa_tagstruct_puts(t, "module-device-manager");
235 pa_tagstruct_putu32(t, SUBCOMMAND_RENAME);
236
237 pa_tagstruct_puts(t, device);
238 pa_tagstruct_puts(t, description);
239
240 pa_pstream_send_tagstruct(c->pstream, t);
241 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);
242
243 return o;
244 }
245
246 pa_operation *pa_ext_device_manager_delete(
247 pa_context *c,
248 const char *const s[],
249 pa_context_success_cb_t cb,
250 void *userdata) {
251
252 uint32_t tag;
253 pa_operation *o = NULL;
254 pa_tagstruct *t = NULL;
255 const char *const *k;
256
257 pa_assert(c);
258 pa_assert(PA_REFCNT_VALUE(c) >= 1);
259 pa_assert(s);
260
261 PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
262 PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
263 PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED);
264
265 o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
266
267 t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag);
268 pa_tagstruct_putu32(t, PA_INVALID_INDEX);
269 pa_tagstruct_puts(t, "module-device-manager");
270 pa_tagstruct_putu32(t, SUBCOMMAND_DELETE);
271
272 for (k = s; *k; k++) {
273 if (!*k || !**k)
274 goto fail;
275
276 pa_tagstruct_puts(t, *k);
277 }
278
279 pa_pstream_send_tagstruct(c->pstream, t);
280 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);
281
282 return o;
283
284 fail:
285 if (o) {
286 pa_operation_cancel(o);
287 pa_operation_unref(o);
288 }
289
290 if (t)
291 pa_tagstruct_free(t);
292
293 pa_context_set_error(c, PA_ERR_INVALID);
294 return NULL;
295 }
296
297 pa_operation *pa_ext_device_manager_enable_role_device_priority_routing(
298 pa_context *c,
299 int enable,
300 pa_context_success_cb_t cb,
301 void *userdata) {
302
303 uint32_t tag;
304 pa_operation *o = NULL;
305 pa_tagstruct *t = NULL;
306
307 pa_assert(c);
308 pa_assert(PA_REFCNT_VALUE(c) >= 1);
309
310 PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
311 PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
312 PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED);
313
314 o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
315
316 t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag);
317 pa_tagstruct_putu32(t, PA_INVALID_INDEX);
318 pa_tagstruct_puts(t, "module-device-manager");
319 pa_tagstruct_putu32(t, SUBCOMMAND_ROLE_DEVICE_PRIORITY_ROUTING);
320 pa_tagstruct_put_boolean(t, !!enable);
321
322 pa_pstream_send_tagstruct(c->pstream, t);
323 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);
324
325 return o;
326 }
327
328 pa_operation *pa_ext_device_manager_reorder_devices_for_role(
329 pa_context *c,
330 const char* role,
331 const char** devices,
332 pa_context_success_cb_t cb,
333 void *userdata) {
334
335 uint32_t tag, i;
336 pa_operation *o = NULL;
337 pa_tagstruct *t = NULL;
338
339 pa_assert(c);
340 pa_assert(PA_REFCNT_VALUE(c) >= 1);
341
342 PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
343 PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
344 PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED);
345
346 pa_assert(role);
347 pa_assert(devices);
348
349 o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
350
351 t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag);
352 pa_tagstruct_putu32(t, PA_INVALID_INDEX);
353 pa_tagstruct_puts(t, "module-device-manager");
354 pa_tagstruct_putu32(t, SUBCOMMAND_REORDER);
355 pa_tagstruct_puts(t, role);
356
357 i = 0; while (devices[i]) i++;
358 pa_tagstruct_putu32(t, i);
359
360 i = 0;
361 while (devices[i])
362 pa_tagstruct_puts(t, devices[i++]);
363
364 pa_pstream_send_tagstruct(c->pstream, t);
365 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);
366
367 return o;
368 }
369
370 pa_operation *pa_ext_device_manager_subscribe(
371 pa_context *c,
372 int enable,
373 pa_context_success_cb_t cb,
374 void *userdata) {
375
376 uint32_t tag;
377 pa_operation *o;
378 pa_tagstruct *t;
379
380 pa_assert(c);
381 pa_assert(PA_REFCNT_VALUE(c) >= 1);
382
383 PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
384 PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
385 PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED);
386
387 o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
388
389 t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag);
390 pa_tagstruct_putu32(t, PA_INVALID_INDEX);
391 pa_tagstruct_puts(t, "module-device-manager");
392 pa_tagstruct_putu32(t, SUBCOMMAND_SUBSCRIBE);
393 pa_tagstruct_put_boolean(t, enable);
394 pa_pstream_send_tagstruct(c->pstream, t);
395 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);
396
397 return o;
398 }
399
400 void pa_ext_device_manager_set_subscribe_cb(
401 pa_context *c,
402 pa_ext_device_manager_subscribe_cb_t cb,
403 void *userdata) {
404
405 pa_assert(c);
406 pa_assert(PA_REFCNT_VALUE(c) >= 1);
407
408 if (pa_detect_fork())
409 return;
410
411 c->ext_device_manager.callback = cb;
412 c->ext_device_manager.userdata = userdata;
413 }
414
415 void pa_ext_device_manager_command(pa_context *c, uint32_t tag, pa_tagstruct *t) {
416 uint32_t subcommand;
417
418 pa_assert(c);
419 pa_assert(PA_REFCNT_VALUE(c) >= 1);
420 pa_assert(t);
421
422 if (pa_tagstruct_getu32(t, &subcommand) < 0 ||
423 !pa_tagstruct_eof(t)) {
424
425 pa_context_fail(c, PA_ERR_PROTOCOL);
426 return;
427 }
428
429 if (subcommand != SUBCOMMAND_EVENT) {
430 pa_context_fail(c, PA_ERR_PROTOCOL);
431 return;
432 }
433
434 if (c->ext_device_manager.callback)
435 c->ext_device_manager.callback(c, c->ext_device_manager.userdata);
436 }