Revert "pacat: Don't use any buffer attr if we don't set any latency/process time...
[pulseaudio-mirror.git] / src / pulse / ext-device-manager.c
blob57cb57c879848934e9eca6222b8341229e1c1c5e
1 /***
2 This file is part of PulseAudio.
4 Copyright 2008 Lennart Poettering
5 Copyright 2009 Colin Guthrie
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.
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.
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 ***/
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
27 #include <pulse/context.h>
28 #include <pulse/gccmacro.h>
29 #include <pulse/xmalloc.h>
31 #include <pulsecore/macro.h>
32 #include <pulsecore/pstream-util.h>
34 #include "internal.h"
35 #include "operation.h"
36 #include "fork-detect.h"
38 #include "ext-device-manager.h"
40 enum {
41 SUBCOMMAND_TEST,
42 SUBCOMMAND_READ,
43 SUBCOMMAND_RENAME,
44 SUBCOMMAND_DELETE,
45 SUBCOMMAND_ROLE_DEVICE_PRIORITY_ROUTING,
46 SUBCOMMAND_REORDER,
47 SUBCOMMAND_SUBSCRIBE,
48 SUBCOMMAND_EVENT
51 static void ext_device_manager_test_cb(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
52 pa_operation *o = userdata;
53 uint32_t version = PA_INVALID_INDEX;
55 pa_assert(pd);
56 pa_assert(o);
57 pa_assert(PA_REFCNT_VALUE(o) >= 1);
59 if (!o->context)
60 goto finish;
62 if (command != PA_COMMAND_REPLY) {
63 if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
64 goto finish;
66 } else if (pa_tagstruct_getu32(t, &version) < 0 ||
67 !pa_tagstruct_eof(t)) {
69 pa_context_fail(o->context, PA_ERR_PROTOCOL);
70 goto finish;
73 if (o->callback) {
74 pa_ext_device_manager_test_cb_t cb = (pa_ext_device_manager_test_cb_t) o->callback;
75 cb(o->context, version, o->userdata);
78 finish:
79 pa_operation_done(o);
80 pa_operation_unref(o);
83 pa_operation *pa_ext_device_manager_test(
84 pa_context *c,
85 pa_ext_device_manager_test_cb_t cb,
86 void *userdata) {
88 uint32_t tag;
89 pa_operation *o;
90 pa_tagstruct *t;
92 pa_assert(c);
93 pa_assert(PA_REFCNT_VALUE(c) >= 1);
95 PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
96 PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
97 PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED);
99 o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
101 t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag);
102 pa_tagstruct_putu32(t, PA_INVALID_INDEX);
103 pa_tagstruct_puts(t, "module-device-manager");
104 pa_tagstruct_putu32(t, SUBCOMMAND_TEST);
105 pa_pstream_send_tagstruct(c->pstream, t);
106 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);
108 return o;
111 static void ext_device_manager_read_cb(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
112 pa_operation *o = userdata;
113 int eol = 1;
115 pa_assert(pd);
116 pa_assert(o);
117 pa_assert(PA_REFCNT_VALUE(o) >= 1);
119 if (!o->context)
120 goto finish;
122 if (command != PA_COMMAND_REPLY) {
123 if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
124 goto finish;
126 eol = -1;
127 } else {
129 while (!pa_tagstruct_eof(t)) {
130 pa_ext_device_manager_info i;
132 memset(&i, 0, sizeof(i));
134 if (pa_tagstruct_gets(t, &i.name) < 0 ||
135 pa_tagstruct_gets(t, &i.description) < 0 ||
136 pa_tagstruct_gets(t, &i.icon) < 0 ||
137 pa_tagstruct_getu32(t, &i.index) < 0 ||
138 pa_tagstruct_getu32(t, &i.n_role_priorities) < 0) {
140 pa_context_fail(o->context, PA_ERR_PROTOCOL);
141 goto finish;
144 if (i.n_role_priorities > 0) {
145 uint32_t j;
146 i.role_priorities = pa_xnew0(pa_ext_device_manager_role_priority_info, i.n_role_priorities+1);
148 for (j = 0; j < i.n_role_priorities; j++) {
150 if (pa_tagstruct_gets(t, &i.role_priorities[j].role) < 0 ||
151 pa_tagstruct_getu32(t, &i.role_priorities[j].priority) < 0) {
153 pa_context_fail(o->context, PA_ERR_PROTOCOL);
154 pa_xfree(i.role_priorities);
155 goto finish;
159 /* Terminate with an extra NULL entry, just to make sure */
160 i.role_priorities[j].role = NULL;
161 i.role_priorities[j].priority = 0;
164 if (o->callback) {
165 pa_ext_device_manager_read_cb_t cb = (pa_ext_device_manager_read_cb_t) o->callback;
166 cb(o->context, &i, 0, o->userdata);
169 pa_xfree(i.role_priorities);
173 if (o->callback) {
174 pa_ext_device_manager_read_cb_t cb = (pa_ext_device_manager_read_cb_t) o->callback;
175 cb(o->context, NULL, eol, o->userdata);
178 finish:
179 pa_operation_done(o);
180 pa_operation_unref(o);
183 pa_operation *pa_ext_device_manager_read(
184 pa_context *c,
185 pa_ext_device_manager_read_cb_t cb,
186 void *userdata) {
188 uint32_t tag;
189 pa_operation *o;
190 pa_tagstruct *t;
192 pa_assert(c);
193 pa_assert(PA_REFCNT_VALUE(c) >= 1);
195 PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
196 PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
197 PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED);
199 o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
201 t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag);
202 pa_tagstruct_putu32(t, PA_INVALID_INDEX);
203 pa_tagstruct_puts(t, "module-device-manager");
204 pa_tagstruct_putu32(t, SUBCOMMAND_READ);
205 pa_pstream_send_tagstruct(c->pstream, t);
206 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);
208 return o;
211 pa_operation *pa_ext_device_manager_set_device_description(
212 pa_context *c,
213 const char* device,
214 const char* description,
215 pa_context_success_cb_t cb,
216 void *userdata) {
218 uint32_t tag;
219 pa_operation *o = NULL;
220 pa_tagstruct *t = NULL;
222 pa_assert(c);
223 pa_assert(PA_REFCNT_VALUE(c) >= 1);
224 pa_assert(device);
225 pa_assert(description);
227 PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
228 PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
229 PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED);
231 o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
233 t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag);
234 pa_tagstruct_putu32(t, PA_INVALID_INDEX);
235 pa_tagstruct_puts(t, "module-device-manager");
236 pa_tagstruct_putu32(t, SUBCOMMAND_RENAME);
238 pa_tagstruct_puts(t, device);
239 pa_tagstruct_puts(t, description);
241 pa_pstream_send_tagstruct(c->pstream, t);
242 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);
244 return o;
247 pa_operation *pa_ext_device_manager_delete(
248 pa_context *c,
249 const char *const s[],
250 pa_context_success_cb_t cb,
251 void *userdata) {
253 uint32_t tag;
254 pa_operation *o = NULL;
255 pa_tagstruct *t = NULL;
256 const char *const *k;
258 pa_assert(c);
259 pa_assert(PA_REFCNT_VALUE(c) >= 1);
260 pa_assert(s);
262 PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
263 PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
264 PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED);
266 o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
268 t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag);
269 pa_tagstruct_putu32(t, PA_INVALID_INDEX);
270 pa_tagstruct_puts(t, "module-device-manager");
271 pa_tagstruct_putu32(t, SUBCOMMAND_DELETE);
273 for (k = s; *k; k++) {
274 if (!*k || !**k)
275 goto fail;
277 pa_tagstruct_puts(t, *k);
280 pa_pstream_send_tagstruct(c->pstream, t);
281 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);
283 return o;
285 fail:
286 if (o) {
287 pa_operation_cancel(o);
288 pa_operation_unref(o);
291 if (t)
292 pa_tagstruct_free(t);
294 pa_context_set_error(c, PA_ERR_INVALID);
295 return NULL;
298 pa_operation *pa_ext_device_manager_enable_role_device_priority_routing(
299 pa_context *c,
300 int enable,
301 pa_context_success_cb_t cb,
302 void *userdata) {
304 uint32_t tag;
305 pa_operation *o = NULL;
306 pa_tagstruct *t = NULL;
308 pa_assert(c);
309 pa_assert(PA_REFCNT_VALUE(c) >= 1);
311 PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
312 PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
313 PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED);
315 o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
317 t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag);
318 pa_tagstruct_putu32(t, PA_INVALID_INDEX);
319 pa_tagstruct_puts(t, "module-device-manager");
320 pa_tagstruct_putu32(t, SUBCOMMAND_ROLE_DEVICE_PRIORITY_ROUTING);
321 pa_tagstruct_put_boolean(t, !!enable);
323 pa_pstream_send_tagstruct(c->pstream, t);
324 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);
326 return o;
329 pa_operation *pa_ext_device_manager_reorder_devices_for_role(
330 pa_context *c,
331 const char* role,
332 const char** devices,
333 pa_context_success_cb_t cb,
334 void *userdata) {
336 uint32_t tag, i;
337 pa_operation *o = NULL;
338 pa_tagstruct *t = NULL;
340 pa_assert(c);
341 pa_assert(PA_REFCNT_VALUE(c) >= 1);
343 PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
344 PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
345 PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED);
347 pa_assert(role);
348 pa_assert(devices);
350 o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
352 t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag);
353 pa_tagstruct_putu32(t, PA_INVALID_INDEX);
354 pa_tagstruct_puts(t, "module-device-manager");
355 pa_tagstruct_putu32(t, SUBCOMMAND_REORDER);
356 pa_tagstruct_puts(t, role);
358 i = 0; while (devices[i]) i++;
359 pa_tagstruct_putu32(t, i);
361 i = 0;
362 while (devices[i])
363 pa_tagstruct_puts(t, devices[i++]);
365 pa_pstream_send_tagstruct(c->pstream, t);
366 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);
368 return o;
371 pa_operation *pa_ext_device_manager_subscribe(
372 pa_context *c,
373 int enable,
374 pa_context_success_cb_t cb,
375 void *userdata) {
377 uint32_t tag;
378 pa_operation *o;
379 pa_tagstruct *t;
381 pa_assert(c);
382 pa_assert(PA_REFCNT_VALUE(c) >= 1);
384 PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
385 PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
386 PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED);
388 o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
390 t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag);
391 pa_tagstruct_putu32(t, PA_INVALID_INDEX);
392 pa_tagstruct_puts(t, "module-device-manager");
393 pa_tagstruct_putu32(t, SUBCOMMAND_SUBSCRIBE);
394 pa_tagstruct_put_boolean(t, enable);
395 pa_pstream_send_tagstruct(c->pstream, t);
396 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);
398 return o;
401 void pa_ext_device_manager_set_subscribe_cb(
402 pa_context *c,
403 pa_ext_device_manager_subscribe_cb_t cb,
404 void *userdata) {
406 pa_assert(c);
407 pa_assert(PA_REFCNT_VALUE(c) >= 1);
409 if (pa_detect_fork())
410 return;
412 c->ext_device_manager.callback = cb;
413 c->ext_device_manager.userdata = userdata;
416 void pa_ext_device_manager_command(pa_context *c, uint32_t tag, pa_tagstruct *t) {
417 uint32_t subcommand;
419 pa_assert(c);
420 pa_assert(PA_REFCNT_VALUE(c) >= 1);
421 pa_assert(t);
423 if (pa_tagstruct_getu32(t, &subcommand) < 0 ||
424 !pa_tagstruct_eof(t)) {
426 pa_context_fail(c, PA_ERR_PROTOCOL);
427 return;
430 if (subcommand != SUBCOMMAND_EVENT) {
431 pa_context_fail(c, PA_ERR_PROTOCOL);
432 return;
435 if (c->ext_device_manager.callback)
436 c->ext_device_manager.callback(c, c->ext_device_manager.userdata);