2 * module-murphy-ivi -- PulseAudio module for providing audio routing support
3 * Copyright (c) 2012, Intel Corporation.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU Lesser General Public License,
7 * version 2.1, as published by the Free Software Foundation.
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.
12 * See the GNU Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this program; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston,
20 #include <pulsecore/pulsecore-config.h>
21 #include <pulsecore/module.h>
24 #include <murphy/common/macros.h>
25 #include <murphy/common/mainloop.h>
26 #include <murphy/pulse/pulse-glue.h>
38 mrp_domctl_table_t *tables;
40 mrp_domctl_watch_t *watches;
41 pa_murphyif_watch_cb watchcb;
47 static void connect_notify(mrp_domctl_t *, int, int, const char *, void *);
48 static void watch_notify(mrp_domctl_t *, mrp_domctl_data_t *, int, void *);
49 static void dump_data(mrp_domctl_data_t *);
54 pa_domctl *pa_murphyif_init(struct userdata *u, const char *addr)
60 if (!(ml = mrp_mainloop_pulse_get(u->core->mainloop))) {
61 pa_log_error("Failed to set up murphy mainloop.");
66 domctl = pa_xnew0(pa_domctl, 1);
67 domctl->addr = pa_xstrdup(addr ? addr : MRP_DEFAULT_DOMCTL_ADDRESS);
76 void pa_murphyif_done(struct userdata *u)
80 if (u && (domctl = u->domctl)) {
82 mrp_domctl_table_t *t;
83 mrp_domctl_watch_t *w;
86 mrp_domctl_destroy(domctl->ctl);
87 mrp_mainloop_destroy(domctl->ml);
89 if (domctl->ntable > 0 && domctl->tables) {
90 for (i = 0; i < domctl->ntable; i++) {
91 t = domctl->tables + i;
92 pa_xfree((void *)t->table);
93 pa_xfree((void *)t->mql_columns);
94 pa_xfree((void *)t->mql_index);
96 pa_xfree(domctl->tables);
99 if (domctl->nwatch > 0 && domctl->watches) {
100 for (i = 0; i < domctl->nwatch; i++) {
101 w = domctl->watches + i;
102 pa_xfree((void *)w->table);
103 pa_xfree((void *)w->mql_columns);
104 pa_xfree((void *)w->mql_where);
106 pa_xfree(domctl->watches);
109 pa_xfree((void *)domctl->addr);
115 void pa_murphyif_add_table(struct userdata *u,
121 mrp_domctl_table_t *t;
128 pa_assert_se((domctl = u->domctl));
130 idx = domctl->ntable++;
131 size = sizeof(mrp_domctl_table_t) * domctl->ntable;
132 t = (domctl->tables = pa_xrealloc(domctl->tables, size)) + idx;
134 t->table = pa_xstrdup(table);
135 t->mql_columns = pa_xstrdup(columns);
136 t->mql_index = index ? pa_xstrdup(index) : NULL;
139 void pa_murphyif_add_watch(struct userdata *u,
146 mrp_domctl_watch_t *w;
153 pa_assert(max_rows > 0 && max_rows < MQI_QUERY_RESULT_MAX);
154 pa_assert_se((domctl = u->domctl));
156 idx = domctl->nwatch++;
157 size = sizeof(mrp_domctl_watch_t) * domctl->nwatch;
158 w = (domctl->watches = pa_xrealloc(domctl->watches, size)) + idx;
160 w->table = pa_xstrdup(table);
161 w->mql_columns = pa_xstrdup(columns);
162 w->mql_where = where ? pa_xstrdup(where) : NULL;
163 w->max_rows = max_rows;
166 void pa_murphyif_setup_domainctl(struct userdata *u, pa_murphyif_watch_cb wcb)
168 static const char *name = "pulse";
174 pa_assert_se((domctl = u->domctl));
177 if (domctl->ntable || domctl->nwatch) {
178 domctl->ctl = mrp_domctl_create(name, domctl->ml,
179 domctl->tables, domctl->ntable,
180 domctl->watches, domctl->nwatch,
181 connect_notify, watch_notify, u);
183 pa_log("failed to create '%s' domain controller", name);
187 if (!mrp_domctl_connect(domctl->ctl, domctl->addr, 0)) {
188 pa_log("failed to conect to murphyd");
192 domctl->watchcb = wcb;
193 pa_log_info("'%s' domain controller sucessfully created", name);
199 static void connect_notify(mrp_domctl_t *dc, int connected, int errcode,
200 const char *errmsg, void *user_data)
203 MRP_UNUSED(user_data);
206 pa_log_info("Successfully registered to Murphy.");
209 pa_log_error("Connection to Murphy failed (%d: %s).", errcode, errmsg);
212 static void watch_notify(mrp_domctl_t *dc, mrp_domctl_data_t *tables,
213 int ntable, void *user_data)
215 struct userdata *u = (struct userdata *)user_data;
217 mrp_domctl_data_t *t;
218 mrp_domctl_watch_t *w;
224 pa_assert(ntable > 0);
226 pa_assert_se((domctl = u->domctl));
228 pa_log_info("Received change notification for %d tables.", ntable);
230 for (i = 0; i < ntable; i++) {
235 pa_assert(t->id >= 0);
236 pa_assert(t->id < domctl->nwatch);
238 w = domctl->watches + t->id;
240 domctl->watchcb(u, w->table, t->nrow, t->rows);
244 static void dump_data(mrp_domctl_data_t *table)
246 mrp_domctl_value_t *row;
252 pa_log_debug("Table #%d: %d rows x %d columns", table->id,
253 table->nrow, table->ncolumn);
255 for (i = 0; i < table->nrow; i++) {
256 row = table->rows[i];
260 for (j = 0, t = ""; j < table->ncolumn; j++, t = ", ") {
261 switch (row[j].type) {
262 case MRP_DOMCTL_STRING:
263 l = snprintf(p, n, "%s'%s'", t, row[j].str);
267 case MRP_DOMCTL_INTEGER:
268 l = snprintf(p, n, "%s%d", t, row[j].s32);
272 case MRP_DOMCTL_UNSIGNED:
273 l = snprintf(p, n, "%s%u", t, row[j].u32);
277 case MRP_DOMCTL_DOUBLE:
278 l = snprintf(p, n, "%s%f", t, row[j].dbl);
283 l = snprintf(p, n, "%s<invalid column 0x%x>",
290 pa_log_debug("row #%d: { %s }", i, buf);
298 * indent-tabs-mode: nil