finer granularity of amname generation + audio manager registration filtering
[profile/ivi/pulseaudio-module-murphy-ivi.git] / murphy / dbusif.c
1 /*
2  * module-murphy-ivi -- PulseAudio module for providing audio routing support
3  * Copyright (c) 2012, Intel Corporation.
4  *
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.
8  *
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.
13  *
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,
17  * MA 02110-1301 USA.
18  *
19  */
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24
25 #include <pulsecore/pulsecore-config.h>
26 #include <pulsecore/dbus-shared.h>
27
28 #include "userdata.h"
29 #include "dbusif.h"
30 #include "audiomgr.h"
31
32 #define ADMIN_DBUS_MANAGER          "org.freedesktop.DBus"
33 #define ADMIN_DBUS_PATH             "/org/freedesktop/DBus"
34 #define ADMIN_DBUS_INTERFACE        "org.freedesktop.DBus"
35
36 #define ADMIN_NAME_OWNER_CHANGED    "NameOwnerChanged"
37
38 #define AUDIOMGR_DBUS_INTERFACE     "org.genivi.audiomanager"
39 #define AUDIOMGR_DBUS_PATH          "/org/genivi/audiomanager"
40
41 #define AUDIOMGR_DBUS_ROUTE_NAME    "RoutingInterface"
42 #define AUDIOMGR_DBUS_ROUTE_PATH    "RoutingInterface"
43
44 #define AUDIOMGR_DBUS_CONTROL_NAME    "ControlInterface"
45 #define AUDIOMGR_DBUS_CONTROL_PATH    "ControlInterface"
46
47 #define PULSE_DBUS_INTERFACE        "org.genivi.pulse"
48 #define PULSE_DBUS_PATH             "/org/genivi/pulse"
49 #define PULSE_DBUS_NAME             "org.genivi.pulse"
50
51 #define STRUCT_OFFSET(s,m) ((char *)&(((s *)0)->m) - (char *)0)
52
53 typedef void (*pending_cb_t)(struct userdata *, const char *,
54                              DBusMessage *, void *);
55 typedef bool (*method_t)(struct userdata *, DBusMessage *);
56
57 struct pending {
58     PA_LLIST_FIELDS(struct pending);
59     struct userdata  *u;
60     const char       *method;
61     DBusPendingCall  *call;
62     pending_cb_t      cb;
63     void             *data;
64 };
65
66 struct pa_routerif {
67     pa_dbus_connection *conn;
68     char               *ampath;   /* audio manager path */
69     char               *amnam;    /* audio manager name */
70     char               *amrpath;  /* audio manager routing path */
71     char               *amrnam;   /* audio manager routing name */
72     char               *amcpath;  /* audio manager control path */
73     char               *amcnam;   /* audio manager control name */
74     char               *admarule; /* match rule to catch audiomgr name change*/
75     int                 amisup;   /* is the audio manager up */
76     PA_LLIST_HEAD(struct pending, pendlist);
77 };
78
79 struct actdsc {                 /* action descriptor */
80     const char         *name;
81     int               (*parser)(struct userdata *u, DBusMessageIter *iter);
82 };
83
84 struct argdsc {                 /* argument descriptor for actions */
85     const char         *name;
86     int                 offs;
87     int                 type;
88 };
89
90 struct argrt {                  /* audio_route arguments */
91     char               *type;
92     char               *device;
93     char               *mode;
94     char               *hwid;
95 };
96
97 struct argvol {                 /* volume_limit arguments */
98     char               *group;
99     int32_t             limit;
100 };
101
102 struct argcork {                /* audio_cork arguments */
103     char               *group;
104     char               *cork;
105 };
106
107 struct argmute {
108     char               *device;
109     char               *mute;
110 };
111
112 struct argctx {                 /* context arguments */
113     char               *variable;
114     char               *value;
115 };
116
117 static void free_routerif(pa_routerif *,struct userdata *);
118
119 static bool send_message_with_reply(struct userdata *, 
120                                          DBusConnection *, DBusMessage *,
121                                          pending_cb_t, void *);
122
123 static DBusHandlerResult filter(DBusConnection *, DBusMessage *, void *);
124 static void handle_admin_message(struct userdata *, DBusMessage *);
125 static bool register_to_controlif(struct userdata *);
126 static DBusHandlerResult audiomgr_method_handler(DBusConnection *,
127                                                  DBusMessage *, void *);
128 static void audiomgr_register_domain_cb(struct userdata *, const char *,
129                                         DBusMessage *, void *);
130 static bool register_to_audiomgr(struct userdata *);
131 static bool unregister_from_audiomgr(struct userdata *);
132 static void audiomgr_register_node_cb(struct userdata *, const char *,
133                                       DBusMessage *, void *);
134 static void audiomgr_unregister_node_cb(struct userdata *, const char *,
135                                         DBusMessage *, void *);
136 static bool build_sound_properties(DBusMessageIter *,
137                                         struct am_nodereg_data *);
138 static bool build_connection_formats(DBusMessageIter *,
139                                           struct am_nodereg_data *);
140 static bool routerif_connect(struct userdata *, DBusMessage *);
141 static bool routerif_disconnect(struct userdata *, DBusMessage *);
142
143 static const char *method_str(am_method);
144
145 pa_routerif *pa_routerif_init(struct userdata *u,
146                               const char      *dbustype,
147                               const char      *ampath,
148                               const char      *amnam)
149 {
150     static const DBusObjectPathVTable  vtable = {
151         .message_function = audiomgr_method_handler,
152     };
153
154     pa_module      *m = u->module;
155     pa_routerif    *routerif = NULL;
156     DBusBusType     type;
157     DBusConnection *dbusconn;
158     DBusError       error;
159     unsigned int    flags;
160     char            nambuf[128];
161     char            pathbuf[128];
162     char            ctlnambuf[128];
163     char            ctlpathbuf[128];
164     char           *amrnam;
165     char           *amrpath;
166     char           *amcnam;
167     char           *amcpath;
168     char            admarule[512];
169     int             result;
170     
171     if (!dbustype || !strcasecmp(dbustype, "session")) {
172         dbustype = "session";
173         type = DBUS_BUS_SESSION;
174     }
175     else if (!strcasecmp(dbustype, "system")) {
176         dbustype = "system";
177         type = DBUS_BUS_SYSTEM;
178     }
179     else {
180         pa_log("invalid dbus type '%s'", dbustype);
181         return NULL;
182     }
183     
184     routerif = pa_xnew0(pa_routerif, 1);
185     PA_LLIST_HEAD_INIT(struct pending, routerif->pendlist);
186
187     dbus_error_init(&error);
188     routerif->conn = pa_dbus_bus_get(m->core, type, &error);
189
190     if (routerif->conn == NULL || dbus_error_is_set(&error)) {
191         pa_log("%s: failed to get %s Bus: %s: %s",
192                __FILE__, dbustype, error.name, error.message);
193         goto fail;
194     }
195
196     dbusconn = pa_dbus_connection_get(routerif->conn);
197
198     flags  = DBUS_NAME_FLAG_REPLACE_EXISTING | DBUS_NAME_FLAG_DO_NOT_QUEUE;
199     result = dbus_bus_request_name(dbusconn, PULSE_DBUS_NAME, flags,&error);
200
201     if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER &&
202         result != DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER    ) {
203         pa_log("%s: D-Bus name request failed: %s: %s",
204                __FILE__, error.name, error.message);
205         goto fail;
206     }
207     
208     pa_log_info("%s: now owner of '%s' D-Bus name on %s bus",
209                 __FILE__, PULSE_DBUS_NAME, dbustype);
210  
211     if (!dbus_connection_add_filter(dbusconn, filter,u, NULL)) {
212         pa_log("%s: failed to add filter function", __FILE__);
213         goto fail;
214     }
215
216     if (ampath && *ampath) {
217         char *slash = ampath[strlen(ampath)-1] == '/' ? "" : "/";
218         snprintf(pathbuf, sizeof(pathbuf), "%s%s" AUDIOMGR_DBUS_ROUTE_PATH,
219                  ampath, slash);
220         amrpath = pathbuf;
221         snprintf(ctlpathbuf, sizeof(ctlpathbuf), "%s%s" AUDIOMGR_DBUS_CONTROL_PATH,
222                  ampath, slash);
223         amcpath = ctlpathbuf;
224     }
225     else {
226         ampath  = AUDIOMGR_DBUS_PATH;
227         amrpath = AUDIOMGR_DBUS_PATH "/" AUDIOMGR_DBUS_ROUTE_PATH;
228         amcpath = AUDIOMGR_DBUS_PATH "/" AUDIOMGR_DBUS_CONTROL_PATH;
229     }
230
231     if (amnam && *amnam){
232         char *dot = amnam[strlen(amnam)-1] == '.' ? "" : ".";
233         snprintf(nambuf, sizeof(nambuf), "%s%s" AUDIOMGR_DBUS_ROUTE_NAME,
234                  amnam, dot);
235         amrnam = nambuf;
236         snprintf(ctlnambuf, sizeof(ctlnambuf), "%s%s" AUDIOMGR_DBUS_CONTROL_NAME,
237                  amnam, dot);
238         amcnam = ctlnambuf;
239     }
240     else {
241         amnam  = AUDIOMGR_DBUS_INTERFACE;
242         amrnam = AUDIOMGR_DBUS_INTERFACE "." AUDIOMGR_DBUS_ROUTE_NAME;
243         amcnam = AUDIOMGR_DBUS_INTERFACE "." AUDIOMGR_DBUS_CONTROL_NAME;
244     }
245
246     snprintf(admarule, sizeof(admarule), "type='signal',sender='%s',path='%s',"
247              "interface='%s',member='%s',arg0='%s'", ADMIN_DBUS_MANAGER,
248              ADMIN_DBUS_PATH, ADMIN_DBUS_INTERFACE, ADMIN_NAME_OWNER_CHANGED,
249              amnam);
250     dbus_bus_add_match(dbusconn, admarule, &error);
251
252     if (dbus_error_is_set(&error)) {
253         pa_log("%s: unable to subscribe name change signals on %s: %s: %s",
254                __FILE__, ADMIN_DBUS_INTERFACE, error.name, error.message);
255         goto fail;
256     }
257
258     dbus_connection_register_object_path(dbusconn, PULSE_DBUS_PATH, &vtable,u);
259
260     routerif->ampath   = pa_xstrdup(ampath);
261     routerif->amnam    = pa_xstrdup(amnam);
262     routerif->amrpath  = pa_xstrdup(amrpath);
263     routerif->amrnam   = pa_xstrdup(amrnam);
264     routerif->amcpath  = pa_xstrdup(amcpath);
265     routerif->amcnam   = pa_xstrdup(amcnam);
266     routerif->admarule = pa_xstrdup(admarule);
267
268     u->routerif = routerif; /* Argh.. */
269
270     register_to_controlif(u);
271     register_to_audiomgr(u);
272
273     return routerif;
274
275  fail:
276     free_routerif(routerif, u);
277     dbus_error_free(&error);
278     return NULL;
279 }
280
281 static void free_routerif(pa_routerif *routerif, struct userdata *u)
282 {
283     DBusConnection  *dbusconn;
284     struct pending  *p, *n;
285
286     if (routerif) {
287
288         if (routerif->conn) {
289             dbusconn = pa_dbus_connection_get(routerif->conn);
290
291             PA_LLIST_FOREACH_SAFE(p,n, routerif->pendlist) {
292                 PA_LLIST_REMOVE(struct pending, routerif->pendlist, p);
293                 dbus_pending_call_set_notify(p->call, NULL,NULL, NULL);
294                 dbus_pending_call_unref(p->call);
295             }
296
297             if (u) {
298                 dbus_connection_remove_filter(dbusconn, filter,u);
299             }
300
301             dbus_bus_remove_match(dbusconn, routerif->admarule, NULL);
302
303             pa_dbus_connection_unref(routerif->conn);
304         }
305
306         pa_xfree(routerif->ampath);
307         pa_xfree(routerif->amnam);
308         pa_xfree(routerif->amrpath);
309         pa_xfree(routerif->amrnam);
310         pa_xfree(routerif->amcpath);
311         pa_xfree(routerif->amcnam);
312         pa_xfree(routerif->admarule);
313
314         pa_xfree(routerif);
315     }
316 }
317
318 void pa_routerif_done(struct userdata *u)
319 {
320     if (u && u->routerif) {
321         free_routerif(u->routerif, u);
322         u->routerif = NULL;
323     }
324 }
325
326 static DBusHandlerResult filter(DBusConnection *conn, DBusMessage *msg,
327                                 void *arg)
328 {
329     struct userdata  *u = arg;
330
331     if (dbus_message_is_signal(msg, ADMIN_DBUS_INTERFACE,
332                                ADMIN_NAME_OWNER_CHANGED))
333     {
334         handle_admin_message(u, msg);
335         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
336     }
337
338     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
339 }
340
341
342 static void handle_admin_message(struct userdata *u, DBusMessage *msg)
343 {
344     pa_routerif *routerif;
345     char        *name;
346     char        *before;
347     char        *after;
348     int          success;
349
350     pa_assert(u);
351     pa_assert_se((routerif = u->routerif));
352
353     success = dbus_message_get_args(msg, NULL,
354                                     DBUS_TYPE_STRING, &name,
355                                     DBUS_TYPE_STRING, &before,
356                                     DBUS_TYPE_STRING, &after,
357                                     DBUS_TYPE_INVALID);
358
359     if (!success || !name) {
360         pa_log("Received malformed '%s' message", ADMIN_NAME_OWNER_CHANGED);
361         return;
362     }
363
364     if (!strcmp(name, routerif->amnam)) {
365         if (after && strcmp(after, "")) {
366             pa_log_debug("audio manager is up");
367
368             if (!routerif->amisup) {
369                 register_to_audiomgr(u);
370             }
371         }
372
373         if (name && before && (!after || !strcmp(after, ""))) {
374             pa_log_info("audio manager is gone");
375
376             if (routerif->amisup)
377                 unregister_from_audiomgr(u);
378
379             routerif->amisup = 0;
380         } 
381     }
382 }
383
384 static void reply_cb(DBusPendingCall *pend, void *data)
385 {
386     struct pending  *pdata = (struct pending *)data;
387     struct userdata *u;
388     pa_routerif     *routerif;
389     DBusMessage     *reply;
390
391     pa_assert(pdata);
392     pa_assert(pdata->call == pend);
393     pa_assert_se((u = pdata->u));
394     pa_assert_se((routerif = u->routerif));
395
396     PA_LLIST_REMOVE(struct pending, routerif->pendlist, pdata);
397
398     if ((reply = dbus_pending_call_steal_reply(pend)) == NULL) {
399         pa_log("%s: Murphy pending call '%s' failed: invalid argument",
400                __FILE__, pdata->method);
401     }
402     else {
403         pdata->cb(u, pdata->method, reply, pdata->data);
404         dbus_message_unref(reply);
405     }
406
407     pa_xfree((void *)pdata->method);
408     pa_xfree((void *)pdata);
409 }
410
411 static bool send_message_with_reply(struct userdata *u,
412                                          DBusConnection  *conn,
413                                          DBusMessage     *msg,
414                                          pending_cb_t     cb,
415                                          void            *data)
416 {
417     pa_routerif     *routerif;
418     struct pending  *pdata = NULL;
419     const char      *method;
420     DBusPendingCall *pend;
421
422     pa_assert(u);
423     pa_assert(conn);
424     pa_assert(msg);
425     pa_assert(cb);
426     pa_assert_se((routerif = u->routerif));
427
428     if ((method = dbus_message_get_member(msg)) == NULL)
429         goto failed;
430
431     pdata = pa_xnew0(struct pending, 1);
432     pdata->u      = u;
433     pdata->method = pa_xstrdup(method);
434     pdata->cb     = cb;
435     pdata->data   = data;
436
437     PA_LLIST_PREPEND(struct pending, routerif->pendlist, pdata);
438
439     if (!dbus_connection_send_with_reply(conn, msg, &pend, -1)) {
440         pa_log("%s: Failed to %s", __FILE__, method);
441         goto failed;
442     }
443
444     pdata->call = pend;
445
446     if (!dbus_pending_call_set_notify(pend, reply_cb,pdata, NULL)) {
447         pa_log("%s: Can't set notification for %s", __FILE__, method);
448         goto failed;
449     }
450
451
452     return true;
453
454  failed:
455     if (pdata) {
456         PA_LLIST_REMOVE(struct pending, routerif->pendlist, pdata);
457         pa_xfree((void *)pdata->method);
458         pa_xfree((void *)pdata);
459     }
460     return false;
461 }
462
463 static bool register_to_controlif(struct userdata *u)
464 {
465     return true;
466 }
467
468 /**************************************************************************
469  *
470  * Audio Manager interfaces
471  *
472  */
473 static DBusHandlerResult audiomgr_method_handler(DBusConnection *conn,
474                                                  DBusMessage    *msg,
475                                                  void           *arg)
476 {
477     struct dispatch {
478         const char *name;
479         method_t    method;
480     };
481
482     static struct dispatch dispatch_tbl[] = {
483         { AUDIOMGR_CONNECT   , routerif_connect    },
484         { AUDIOMGR_DISCONNECT, routerif_disconnect },
485         {        NULL,                 NULL        }
486     };
487
488     struct userdata         *u = (struct userdata *)arg;
489     struct dispatch         *d;
490     const char              *name;
491     method_t                 method;
492     //uint32_t                 serial;
493     dbus_int16_t             errcod;
494     DBusMessage             *reply;
495     bool                success;
496
497     pa_assert(conn);
498     pa_assert(msg);
499     pa_assert(u);
500
501     if (dbus_message_get_type(msg) == DBUS_MESSAGE_TYPE_METHOD_CALL) {
502
503         name = dbus_message_get_member(msg);
504         // serial = dbus_message_get_serial(msg);
505
506         pa_assert(name);
507
508         for (method = NULL, d = dispatch_tbl;  d->name;    d++) {
509             if (!strcmp(name, d->name)) {
510                 method = d->method;
511                 break;
512             }
513         }
514
515         errcod = method ? E_OK : E_NOT_POSSIBLE; 
516         reply  = dbus_message_new_method_return(msg);
517
518         // dbus_message_set_reply_serial(reply, serial);
519                 
520         success = dbus_message_append_args(reply,
521                                            DBUS_TYPE_INT16, &errcod,
522                                            DBUS_TYPE_INVALID);
523         
524         if (!success || !dbus_connection_send(conn, reply, NULL))
525             pa_log("%s: failed to reply '%s'", __FILE__, name);
526         else
527             pa_log_debug("'%s' replied (%d)", name, errcod);
528
529         dbus_message_unref(reply);
530
531         if (method)
532             d->method(u, msg);
533         else
534             pa_log_info("%s: unsupported '%s' method ignored", __FILE__, name);
535                 
536         return DBUS_HANDLER_RESULT_HANDLED;
537     }
538
539     pa_log_debug("got some unexpected type of D-Bus message");
540
541     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
542 }
543
544
545 static bool register_to_audiomgr(struct userdata *u)
546 {
547     pa_audiomgr_register_domain(u);
548     return true;
549 }
550
551 static bool unregister_from_audiomgr(struct userdata *u)
552 {
553     pa_audiomgr_unregister_domain(u, false);
554     return true;
555 }
556
557 static void audiomgr_register_domain_cb(struct userdata *u,
558                                         const char      *method,
559                                         DBusMessage     *reply,
560                                         void            *data)
561 {
562     const char        *error_descr;
563     dbus_uint16_t      domain_id;
564     dbus_uint16_t      status;
565     int                success;
566
567     if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
568         success = dbus_message_get_args(reply, NULL,
569                                         DBUS_TYPE_STRING, &error_descr,
570                                         DBUS_TYPE_INVALID);
571
572         if (!success)
573             error_descr = dbus_message_get_error_name(reply);
574
575         pa_log_info("%s: AudioManager domain registration failed: %s",
576                     __FILE__, error_descr);
577     }
578     else {
579         success = dbus_message_get_args(reply, NULL,
580                                         DBUS_TYPE_UINT16, &domain_id,
581                                         DBUS_TYPE_UINT16, &status,
582                                         DBUS_TYPE_INVALID);
583
584         if (!success) {
585             pa_log("got broken message from AudioManager.Registration failed");
586         }
587         else {
588             pa_log_info("AudioManager replied to registration: "
589                         "domainID %u, status %u", domain_id, status);
590
591             if (u->routerif) {
592                 u->routerif->amisup = 1;
593                 pa_audiomgr_domain_registered(u, domain_id, status, data);
594             }
595         }
596     }
597 }
598
599 bool pa_routerif_register_domain(struct userdata   *u,
600                                  am_domainreg_data *dr)
601 {
602     pa_routerif    *routerif;
603     DBusConnection *conn;
604     DBusMessage    *msg;
605     DBusMessageIter iter;
606     DBusMessageIter sub_iter;
607     const char     *dbus_name;
608     const char     *dbus_path;
609     const char     *dbus_if;
610     int             success;
611
612     pa_assert(u);
613     pa_assert(dr);
614     pa_assert_se((routerif = u->routerif));
615     pa_assert_se((conn = pa_dbus_connection_get(routerif->conn)));
616
617     pa_log_info("%s: registering to AudioManager: name='%s' path='%s' if='%s'"
618                 , __FILE__, routerif->amnam, routerif->amrpath, routerif->amrnam);
619
620     msg = dbus_message_new_method_call(routerif->amnam,
621                                        routerif->amrpath,
622                                        routerif->amrnam,
623                                        AUDIOMGR_REGISTER_DOMAIN);
624     if (msg == NULL) {
625         pa_log("%s: Failed to create D-Bus message to '%s'",
626                __FILE__, AUDIOMGR_REGISTER_DOMAIN);
627         success = false;
628         goto getout;
629     }
630
631     dbus_name = PULSE_DBUS_NAME;
632     dbus_path = PULSE_DBUS_PATH;
633     dbus_if   = PULSE_DBUS_INTERFACE;
634
635     dbus_message_iter_init_append(msg, &iter);
636     success = dbus_message_iter_open_container(&iter, DBUS_TYPE_STRUCT, NULL, &sub_iter);
637
638     success = success && dbus_message_iter_append_basic(&sub_iter, DBUS_TYPE_UINT16,  &dr->domain_id);
639     success = success && dbus_message_iter_append_basic(&sub_iter, DBUS_TYPE_STRING,  &dr->name);
640     success = success && dbus_message_iter_append_basic(&sub_iter, DBUS_TYPE_STRING,  &dr->bus_name);
641     success = success && dbus_message_iter_append_basic(&sub_iter, DBUS_TYPE_STRING,  &dr->node_name);
642     success = success && dbus_message_iter_append_basic(&sub_iter, DBUS_TYPE_BOOLEAN, &dr->early);
643     success = success && dbus_message_iter_append_basic(&sub_iter, DBUS_TYPE_BOOLEAN, &dr->complete);
644     success = success && dbus_message_iter_append_basic(&sub_iter, DBUS_TYPE_UINT16 , &dr->state);
645
646     success = success && dbus_message_iter_close_container(&iter, &sub_iter);
647
648     success = success && dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING , &dbus_name);
649     success = success && dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING , &dbus_path);
650     success = success && dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING , &dbus_if);
651
652     if (!success) {
653         pa_log("%s: Failed to build D-Bus message to register", __FILE__);
654         goto getout;
655     }
656
657     success = send_message_with_reply(u, conn, msg,
658                                       audiomgr_register_domain_cb, dr);
659     if (!success) {
660         pa_log("%s: Failed to register", __FILE__);
661         goto getout;
662     }
663
664  getout:
665     dbus_message_unref(msg);
666     return success;
667 }
668
669 bool pa_routerif_domain_complete(struct userdata *u, uint16_t domain)
670 {
671     dbus_int32_t    id32 = domain;
672     pa_routerif    *routerif;
673     DBusConnection *conn;
674     DBusMessage    *msg;
675     bool       success;
676
677     pa_assert(u);
678     pa_assert_se((routerif = u->routerif));
679     pa_assert_se((conn = pa_dbus_connection_get(routerif->conn)));
680     
681
682     pa_log_debug("%s: domain %u AudioManager %s", __FUNCTION__,
683                  domain, AUDIOMGR_DOMAIN_COMPLETE);
684
685     msg = dbus_message_new_method_call(routerif->amnam,
686                                        routerif->amrpath,
687                                        routerif->amrnam,
688                                        AUDIOMGR_DOMAIN_COMPLETE);
689     if (msg == NULL) {
690         pa_log("%s: Failed to create D-Bus message for '%s'",
691                __FILE__, AUDIOMGR_DOMAIN_COMPLETE);
692         success = false;
693         goto getout;
694     }
695
696     success = dbus_message_append_args(msg,
697                                        DBUS_TYPE_UINT16,  &id32,
698                                        DBUS_TYPE_INVALID);
699     if (!success) {
700         pa_log("%s: Failed to build D-Bus message for '%s'",
701                __FILE__, AUDIOMGR_DOMAIN_COMPLETE);
702         goto getout;
703     }
704
705     if (!dbus_connection_send(conn, msg, NULL)) {
706         pa_log("%s: Failed to send '%s'", __FILE__, AUDIOMGR_DOMAIN_COMPLETE);
707         goto getout;
708     }
709
710     dbus_connection_flush(conn);
711
712  getout:
713     dbus_message_unref(msg);
714     return success;
715 }
716
717 bool pa_routerif_unregister_domain(struct userdata *u, uint16_t domain)
718 {
719     pa_routerif    *routerif;
720     DBusConnection *conn;
721     DBusMessage    *msg;
722     bool       success;
723
724     pa_assert(u);
725     pa_assert_se((routerif = u->routerif));
726     pa_assert_se((conn = pa_dbus_connection_get(routerif->conn)));
727
728     pa_log_info("%s: deregistreing domain %u from AudioManager",
729                 __FILE__, domain);
730
731     msg = dbus_message_new_method_call(routerif->amnam,
732                                        routerif->amrpath,
733                                        routerif->amrnam,
734                                        AUDIOMGR_DEREGISTER_DOMAIN);
735     if (msg == NULL) {
736         pa_log("%s: Failed to create D-Bus message for '%s'",
737                __FILE__, AUDIOMGR_DEREGISTER_DOMAIN);
738         success = false;
739         goto getout;
740     }
741
742     dbus_message_set_no_reply(msg, true);
743
744     success = dbus_message_append_args(msg,
745                                        DBUS_TYPE_UINT16,  &domain,
746                                        DBUS_TYPE_INVALID);
747     if (!success) {
748         pa_log("%s: Failed to build D-Bus message for '%s'",
749                __FILE__, AUDIOMGR_DEREGISTER_DOMAIN);
750         goto getout;
751     }
752
753     if (!dbus_connection_send(conn, msg, NULL)) {
754         pa_log("%s: Failed to send '%s'", __FILE__,AUDIOMGR_DEREGISTER_DOMAIN);
755         goto getout;
756     }
757
758     dbus_connection_flush(conn);
759
760  getout:
761     dbus_message_unref(msg);
762     return success;
763 }
764
765
766 static void audiomgr_register_node_cb(struct userdata *u,
767                                       const char      *method,
768                                       DBusMessage     *reply,
769                                       void            *data)
770 {
771     const char      *error_descr;
772     dbus_uint16_t    object_id;
773     dbus_uint16_t    status;
774     int              success;
775     const char      *objtype;
776
777     pa_assert(u);
778     pa_assert(method);
779     pa_assert(reply);
780     pa_assert(data);
781
782     if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
783         success = dbus_message_get_args(reply, NULL,
784                                         DBUS_TYPE_STRING, &error_descr,
785                                         DBUS_TYPE_INVALID);
786
787         if (!success)
788             error_descr = dbus_message_get_error_name(reply);
789
790         pa_log_info("%s: AudioManager registration failed: %s",
791                     __FILE__, error_descr);
792     }
793     else {
794         success = dbus_message_get_args(reply, NULL,
795                                         DBUS_TYPE_UINT16, &object_id,
796                                         DBUS_TYPE_UINT16, &status,
797                                         DBUS_TYPE_INVALID);
798
799         if (!success) {
800             pa_log("got broken message from AudioManager.Registration failed");
801         }
802         else {
803             if (!strncasecmp("register", method, 8))
804                 objtype = method + 8;
805             else
806                 objtype = method;
807
808             pa_log_info("AudioManager replied to registration: %sID: %u",
809                         objtype, object_id);
810
811             pa_audiomgr_node_registered(u, object_id, status, data);
812         }
813     }
814 }
815
816 static bool build_sound_properties(DBusMessageIter *mit,
817                                         struct am_nodereg_data *rd)
818 {
819     static int16_t zero;
820
821     DBusMessageIter ait, sit;
822     int i;
823
824 #define CONT_OPEN(p,t,s,c) dbus_message_iter_open_container(p, t, s, c)
825 #define CONT_APPEND(i,t,v) dbus_message_iter_append_basic(i, t, v)
826 #define CONT_CLOSE(p,c)    dbus_message_iter_close_container(p, c)
827
828     if (!CONT_OPEN(mit, DBUS_TYPE_ARRAY, "(nn)", &ait))
829         return false;
830
831     for (i = 1;  i < 3;  i++) {
832         if (! CONT_OPEN   (&ait, DBUS_TYPE_STRUCT, NULL, &sit) ||
833             ! CONT_APPEND (&sit, DBUS_TYPE_INT16,  &i        ) ||
834             ! CONT_APPEND (&sit, DBUS_TYPE_INT16,  &zero     ) ||
835             ! CONT_CLOSE  (&ait,                         &sit)   )
836         {
837             return false;
838         }
839     }
840
841     if (!CONT_CLOSE(mit, &ait))
842         return false;
843
844 #undef CONT_CLOSE
845 #undef CONT_APPEND
846 #undef CONT_OPEN
847
848     return true;
849 }
850
851 static bool build_connection_formats(DBusMessageIter *mit,
852                                           struct am_nodereg_data *rd)
853 {
854     DBusMessageIter ait;
855     int i;
856
857 #define CONT_OPEN(t,s)   dbus_message_iter_open_container(mit, t, s, &ait)
858 #define CONT_APPEND(t,v) dbus_message_iter_append_basic(&ait, t, v)
859 #define CONT_CLOSE       dbus_message_iter_close_container(mit, &ait)
860
861     if (!CONT_OPEN(DBUS_TYPE_ARRAY, "n")) 
862         return false;
863
864     for (i = 1;  i < 2;  i++) {
865         if (!CONT_APPEND(DBUS_TYPE_INT16,  &i))
866             return false;
867     }
868
869     if (!CONT_CLOSE)
870         return false;
871
872 #undef CONT_CLOSE
873 #undef CONT_APPEND
874 #undef CONT_OPEN
875
876     return true;
877 }
878
879 bool pa_routerif_register_node(struct userdata *u,
880                                     am_method m,
881                                     am_nodereg_data *rd)
882 {
883     const char      *method = method_str(m);
884     pa_routerif     *routerif;
885     DBusConnection  *conn;
886     DBusMessage     *msg;
887     DBusMessageIter  mit;
888     DBusMessageIter  cit;
889     DBusMessageIter  dit;
890     bool        success = false;
891
892     pa_assert(u);
893     pa_assert(rd);
894     pa_assert_se((routerif = u->routerif));
895     pa_assert_se((conn = pa_dbus_connection_get(routerif->conn)));
896
897     pa_log_debug("%s: %s '%s' to AudioManager", __FUNCTION__, method,rd->name);
898
899     msg = dbus_message_new_method_call(routerif->amnam, routerif->amrpath,
900                                        routerif->amrnam, method);
901     
902     if (msg == NULL) {
903         pa_log("%s: Failed to create D-BUS message to '%s'", __FILE__, method);
904         goto getout;
905     }
906
907 #define MSG_APPEND(t,v)  dbus_message_iter_append_basic(&mit, t, v)
908 #define CONT_OPEN(t,s)   dbus_message_iter_open_container(&mit, t, s, &cit)
909 #define CONT_APPEND(t,v) dbus_message_iter_append_basic(&cit, t, v)
910 #define CONT_CLOSE       dbus_message_iter_close_container(&mit, &cit)
911
912 #define CONT_OPEN_1(t,s)   dbus_message_iter_open_container(&cit, t, s, &dit)
913 #define CONT_APPEND_1(t,v) dbus_message_iter_append_basic(&dit, t, v)
914 #define CONT_CLOSE_1       dbus_message_iter_close_container(&cit, &dit)
915
916     dbus_message_iter_init_append(msg, &mit);
917
918     if ((!strcmp(method, AUDIOMGR_REGISTER_SINK) &&
919          (! CONT_OPEN   ( DBUS_TYPE_STRUCT ,  NULL            ) ||
920           ! CONT_APPEND  ( DBUS_TYPE_UINT16 , &rd->id          ) ||
921           ! CONT_APPEND  ( DBUS_TYPE_STRING , &rd->name        ) ||
922           ! CONT_APPEND  ( DBUS_TYPE_UINT16 , &rd->domain      ) ||
923           ! CONT_APPEND  ( DBUS_TYPE_UINT16 , &rd->class       ) ||
924           ! CONT_APPEND  ( DBUS_TYPE_INT16  , &rd->volume      ) ||
925           ! CONT_APPEND  ( DBUS_TYPE_BOOLEAN, &rd->visible     ) ||
926           ! CONT_OPEN_1   ( DBUS_TYPE_STRUCT ,  NULL            ) ||
927           ! CONT_APPEND_1 ( DBUS_TYPE_INT16  , &rd->avail.status) ||
928           ! CONT_APPEND_1 ( DBUS_TYPE_INT16  , &rd->avail.reason) ||
929           ! CONT_CLOSE_1                                          ||
930           ! CONT_APPEND  ( DBUS_TYPE_INT16  , &rd->mute        ) ||
931           ! CONT_APPEND  ( DBUS_TYPE_INT16  , &rd->mainvol     ) ||
932           ! build_sound_properties(&cit, rd)                    ||
933           ! build_connection_formats(&cit, rd)                  ||
934           ! build_sound_properties(&cit, rd)                    ||  
935           ! CONT_CLOSE                                          )) ||
936         (!strcmp(method, AUDIOMGR_REGISTER_SOURCE) &&
937          (! CONT_OPEN   ( DBUS_TYPE_STRUCT ,  NULL            ) ||
938           ! CONT_APPEND  ( DBUS_TYPE_UINT16 , &rd->id          ) ||
939           ! CONT_APPEND  ( DBUS_TYPE_UINT16 , &rd->domain      ) ||
940           ! CONT_APPEND  ( DBUS_TYPE_STRING , &rd->name        ) ||
941           ! CONT_APPEND  ( DBUS_TYPE_UINT16 , &rd->class       ) ||
942           ! CONT_APPEND  ( DBUS_TYPE_UINT16 , &rd->state       ) ||
943           ! CONT_APPEND  ( DBUS_TYPE_INT16  , &rd->volume      ) ||
944           ! CONT_APPEND  ( DBUS_TYPE_BOOLEAN, &rd->visible     ) ||
945           ! CONT_OPEN_1   ( DBUS_TYPE_STRUCT ,  NULL            ) ||
946           ! CONT_APPEND_1 ( DBUS_TYPE_INT16  , &rd->avail.status) ||
947           ! CONT_APPEND_1 ( DBUS_TYPE_INT16  , &rd->avail.reason) ||
948           ! CONT_CLOSE_1                                          ||
949           ! CONT_APPEND  ( DBUS_TYPE_UINT16 , &rd->interrupt   ) ||
950           ! build_sound_properties(&cit, rd)                    ||
951           ! build_connection_formats(&cit, rd)                  ||
952           ! build_sound_properties(&cit, rd)                    ||  
953           ! CONT_CLOSE                                          )))
954     {        
955         pa_log("%s: failed to build message for AudioManager '%s'",
956                __FILE__, method);
957         goto getout;
958     }
959
960 #undef CONT_CLOSE
961 #undef CONT_APPEND
962 #undef CONT_OPEN
963 #undef MSG_APPEND
964
965 #undef CONT_CLOSE_1
966 #undef CONT_APPEND_1
967 #undef CONT_OPEN_1
968
969     success = send_message_with_reply(u, conn, msg,
970                                       audiomgr_register_node_cb, rd);
971     if (!success) {
972         pa_log("%s: Failed to %s", __FILE__, method);
973         goto getout;
974     }
975     
976  getout:
977     dbus_message_unref(msg);
978     return success;
979 }
980
981 static void audiomgr_unregister_node_cb(struct userdata *u,
982                                         const char      *method,
983                                         DBusMessage     *reply,
984                                         void            *data)
985 {
986     const char      *error_descr;
987     dbus_uint16_t    status;
988     int              success;
989     const char      *objtype;
990
991     pa_assert(u);
992     pa_assert(method);
993     pa_assert(reply);
994     pa_assert(data);
995
996     if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
997         success = dbus_message_get_args(reply, NULL,
998                                         DBUS_TYPE_STRING, &error_descr,
999                                         DBUS_TYPE_INVALID);
1000
1001         if (!success)
1002             error_descr = dbus_message_get_error_name(reply);
1003
1004         pa_log_info("%s: AudioManager deregistration failed: %s",
1005                     __FILE__, error_descr);
1006     }
1007     else {
1008         success = dbus_message_get_args(reply, NULL,
1009                                         DBUS_TYPE_UINT16, &status,
1010                                         DBUS_TYPE_INVALID);
1011
1012         if (!success) {
1013             pa_log("got broken message from AudioManager. "
1014                    "Deregistration failed");
1015         }
1016         else {
1017             if (!strncasecmp("deregister", method, 10))
1018                 objtype = method + 10;
1019             else
1020                 objtype = method;
1021
1022             pa_log_info("AudioManager replied to %s deregistration: %u",
1023                         objtype, status);
1024
1025             pa_audiomgr_node_unregistered(u, data);
1026         }
1027     }
1028 }
1029
1030 bool pa_routerif_unregister_node(struct userdata *u,
1031                                       am_method m,
1032                                       am_nodeunreg_data *ud)
1033 {
1034     const char     *method = method_str(m);
1035     pa_routerif    *routerif;
1036     DBusConnection *conn;
1037     DBusMessage    *msg;
1038     bool       success = false;
1039
1040     pa_assert(u);
1041     pa_assert(ud);
1042     pa_assert_se((routerif = u->routerif));
1043     pa_assert_se((conn = pa_dbus_connection_get(routerif->conn)));
1044
1045     pa_log_debug("%s: %s '%s' to AudioManager", __FUNCTION__, method,ud->name);
1046
1047     msg = dbus_message_new_method_call(routerif->amnam, routerif->amrpath,
1048                                        routerif->amrnam, method);
1049     
1050     if (msg == NULL) {
1051         pa_log("%s: Failed to create D-Bus message for '%s'", __FILE__,method);
1052         goto getout;
1053     }
1054
1055     success = dbus_message_append_args(msg,
1056                                        DBUS_TYPE_INT16, &ud->id,
1057                                        DBUS_TYPE_INVALID);
1058
1059     success = send_message_with_reply(u, conn, msg,
1060                                       audiomgr_unregister_node_cb,ud);
1061     if (!success) {
1062         pa_log("%s: Failed to %s", __FILE__, method);
1063         goto getout;
1064     }
1065     
1066  getout:
1067     dbus_message_unref(msg);
1068     return success;
1069 }
1070
1071 bool pa_routerif_register_implicit_connection(struct userdata *u,
1072                                               am_connect_data *cd)
1073 {
1074     static const char    *method = AUDIOMGR_IMPLICIT_CONNECTION;
1075
1076     pa_routerif     *routerif;
1077     DBusConnection  *conn;
1078     DBusMessage     *msg;
1079     bool             success = false;
1080
1081     pa_assert(u);
1082     pa_assert(cd);
1083     pa_assert_se((routerif = u->routerif));
1084     pa_assert_se((conn = pa_dbus_connection_get(routerif->conn)));
1085
1086     pa_log_debug("%s: register implicit connection", __FUNCTION__);
1087
1088     msg = dbus_message_new_method_call(routerif->amnam, routerif->amcpath,
1089                                        routerif->amcnam, method);
1090     if (msg == NULL) {
1091         pa_log("%s: Failed to create D-Bus message for '%s'", __FILE__,method);
1092         goto getout;
1093     }
1094
1095     dbus_message_set_no_reply(msg, true);
1096
1097     success = dbus_message_append_args(msg,
1098                                        DBUS_TYPE_INT16 , &cd->format,
1099                                        DBUS_TYPE_UINT16, &cd->source,
1100                                        DBUS_TYPE_UINT16, &cd->sink,
1101                                        DBUS_TYPE_INVALID);
1102     if (!success) {
1103         pa_log("%s: failed to build message for %s", __FILE__, method);
1104         goto getout;
1105     }
1106
1107     success = dbus_connection_send(conn, msg, NULL);
1108
1109     if (!success) {
1110         pa_log("%s: Failed to %s", __FILE__, method);
1111         goto getout;
1112     }
1113
1114  getout:
1115     dbus_message_unref(msg);
1116     return success;
1117 }
1118
1119 bool pa_routerif_register_implicit_connections(struct userdata *u,
1120                                                int              nconn,
1121                                                am_connect_data *conns)
1122 {
1123 #if 0
1124     static const char    *method = AUDIOMGR_IMPLICIT_CONNECTIONS;
1125     static dbus_uint16_t  zero;
1126
1127     pa_routerif     *routerif;
1128     DBusConnection  *conn;
1129     DBusMessage     *msg;
1130     DBusMessageIter  mit;
1131     DBusMessageIter  ait;
1132     DBusMessageIter  sit;
1133     am_connect_data *cd;
1134     int              i;
1135     bool             success = false;
1136
1137     pa_assert(u);
1138     pa_assert(nconn > 0);
1139     pa_assert(conns);
1140     pa_assert_se((routerif = u->routerif));
1141     pa_assert_se((conn = pa_dbus_connection_get(routerif->conn)));
1142
1143     pa_log_debug("%s: register %d implicit connections", __FUNCTION__, nconn);
1144
1145     msg = dbus_message_new_method_call(routerif->amnam, routerif->amrpath,
1146                                        routerif->amrnam, method);
1147     if (msg == NULL) {
1148         pa_log("%s: Failed to create D-Bus message for '%s'", __FILE__,method);
1149         goto getout;
1150     }
1151
1152     dbus_message_set_no_reply(msg, true);
1153     dbus_message_iter_init_append(msg, &mit);
1154
1155 #define CONT_OPEN(p,t,s,c) dbus_message_iter_open_container(p, t, s, c)
1156 #define CONT_APPEND(i,t,v) dbus_message_iter_append_basic(i, t, v)
1157 #define CONT_CLOSE(p,c)    dbus_message_iter_close_container(p, c)
1158
1159     if (!CONT_OPEN(&mit, DBUS_TYPE_ARRAY, "(qqqqn)", &ait)) {
1160         pa_log("%s: failed to open array iterator for %s", __FILE__, method);
1161         goto getout;
1162     }
1163
1164     for (i = 0;   i < nconn;   i++) {
1165         cd = conns + i;
1166         
1167         if (! CONT_OPEN   (&ait, DBUS_TYPE_STRUCT, NULL, &sit     ) ||
1168             ! CONT_APPEND (&sit, DBUS_TYPE_UINT16, &cd->connection) ||
1169             ! CONT_APPEND (&sit, DBUS_TYPE_UINT16, &cd->source    ) ||
1170             ! CONT_APPEND (&sit, DBUS_TYPE_UINT16, &cd->sink      ) ||
1171             ! CONT_APPEND (&sit, DBUS_TYPE_UINT16, &zero          ) ||
1172             ! CONT_APPEND (&sit, DBUS_TYPE_INT16 , &cd->format    ) ||
1173             ! CONT_CLOSE  (&ait,                          &sit    )   )
1174         {
1175             pa_log("%s: failed to build conn struct for %s", __FILE__, method);
1176             goto getout;
1177         }
1178     }
1179
1180     if (!CONT_CLOSE(&mit, &ait)) {
1181         pa_log("%s: failed to close array iterator for %s", __FILE__, method);
1182         goto getout;
1183     } 
1184
1185 #undef CONT_CLOSE
1186 #undef CONT_APPEND
1187 #undef CONT_OPEN
1188
1189
1190     success = dbus_connection_send(conn, msg, NULL);
1191
1192     if (!success) {
1193         pa_log("%s: Failed to %s", __FILE__, method);
1194         goto getout;
1195     }
1196
1197  getout:
1198     dbus_message_unref(msg);
1199     return success;
1200 #endif
1201     return true;
1202 }
1203
1204 static bool routerif_connect(struct userdata *u, DBusMessage *msg)
1205 {
1206     struct am_connect_data ac;
1207     int                    success;
1208
1209     pa_assert(u);
1210     pa_assert(msg);
1211
1212     memset(&ac, 0, sizeof(ac));
1213
1214     success = dbus_message_get_args(msg, NULL,
1215                                     DBUS_TYPE_UINT16, &ac.handle,
1216                                     DBUS_TYPE_UINT16, &ac.connection,
1217                                     DBUS_TYPE_UINT16, &ac.source,
1218                                     DBUS_TYPE_UINT16, &ac.sink,
1219                                     DBUS_TYPE_INT16 , &ac.format,
1220                                     DBUS_TYPE_INVALID);
1221     if (!success) {
1222         pa_log("%s: got broken connect message from AudioManager. "
1223                "Ignoring it", __FILE__);
1224         return false;
1225     }
1226
1227     pa_log_debug("AudioManager connect(%u|%u|%u|%u|%d)",
1228                  ac.handle, ac.connection, ac.source, ac.sink, ac.format);
1229
1230     pa_audiomgr_connect(u, &ac);
1231
1232     return true;
1233 }
1234
1235 static bool routerif_disconnect(struct userdata *u, DBusMessage *msg)
1236 {
1237     struct am_connect_data ac;
1238     int                    success;
1239
1240     pa_assert(u);
1241     pa_assert(msg);
1242
1243     memset(&ac, 0, sizeof(ac));
1244
1245     success = dbus_message_get_args(msg, NULL,
1246                                     DBUS_TYPE_UINT16, &ac.handle,
1247                                     DBUS_TYPE_UINT16, &ac.connection,
1248                                     DBUS_TYPE_INVALID);
1249     if (!success) {
1250         pa_log("%s: got broken disconnect message from AudioManager. "
1251                "Ignoring it",  __FILE__);
1252         return false;
1253     }
1254
1255     pa_log_debug("AudioManager disconnect(%u|%u)", ac.handle, ac.connection);
1256
1257     pa_audiomgr_disconnect(u, &ac);
1258
1259     return true;
1260 }
1261
1262 bool pa_routerif_acknowledge(struct userdata *u, am_method m,
1263                                   struct am_ack_data *ad)
1264 {
1265     const char     *method = method_str(m);
1266     pa_routerif    *routerif;
1267     DBusConnection *conn;
1268     DBusMessage    *msg;
1269     bool       success;
1270
1271     pa_assert(u);
1272     pa_assert(method);
1273     pa_assert_se((routerif = u->routerif));
1274     pa_assert_se((conn = pa_dbus_connection_get(routerif->conn)));
1275
1276     pa_log_debug("%s: sending %s", __FILE__, method);
1277
1278     msg = dbus_message_new_method_call(routerif->amnam,
1279                                        routerif->amrpath,
1280                                        routerif->amrnam,
1281                                        method);
1282     if (msg == NULL) {
1283         pa_log("%s: Failed to create D-Bus message for '%s'",
1284                __FILE__, method);
1285         success = false;
1286         goto getout;
1287     }
1288
1289     success = dbus_message_append_args(msg,
1290                                        DBUS_TYPE_UINT16,  &ad->handle,
1291                                        DBUS_TYPE_UINT16,  &ad->param1,
1292                                        DBUS_TYPE_UINT16,  &ad->error,
1293                                        DBUS_TYPE_INVALID);
1294     if (!success) {
1295         pa_log("%s: Failed to build D-Bus message message '%s'",
1296                __FILE__, method);
1297         goto getout;
1298     }
1299
1300     if (!dbus_connection_send(conn, msg, NULL)) {
1301         pa_log("%s: Failed to send D-Bus message '%s'", __FILE__, method);
1302         goto getout;
1303     }
1304
1305  getout:
1306     dbus_message_unref(msg);
1307     return success;
1308 }
1309
1310
1311 static const char *method_str(am_method m)
1312 {
1313     switch (m) {
1314     case audiomgr_register_domain:      return AUDIOMGR_REGISTER_DOMAIN;
1315     case audiomgr_domain_complete:      return AUDIOMGR_DOMAIN_COMPLETE;
1316     case audiomgr_deregister_domain:    return AUDIOMGR_DEREGISTER_DOMAIN;
1317     case audiomgr_register_source:      return AUDIOMGR_REGISTER_SOURCE;
1318     case audiomgr_deregister_source:    return AUDIOMGR_DEREGISTER_SOURCE;
1319     case audiomgr_register_sink:        return AUDIOMGR_REGISTER_SINK;
1320     case audiomgr_deregister_sink:      return AUDIOMGR_DEREGISTER_SINK;
1321     case audiomgr_implicit_connection:  return AUDIOMGR_IMPLICIT_CONNECTION;
1322     case audiomgr_implicit_connections: return AUDIOMGR_IMPLICIT_CONNECTIONS;
1323     case audiomgr_connect:              return AUDIOMGR_CONNECT;
1324     case audiomgr_connect_ack:          return AUDIOMGR_CONNECT_ACK;   
1325     case audiomgr_disconnect:           return AUDIOMGR_DISCONNECT;
1326     case audiomgr_disconnect_ack:       return AUDIOMGR_DISCONNECT_ACK;    
1327     case audiomgr_setsinkvol_ack:       return AUDIOMGR_SETSINKVOL_ACK;
1328     case audiomgr_setsrcvol_ack:        return AUDIOMGR_SETSRCVOL_ACK;
1329     case audiomgr_sinkvoltick_ack:      return AUDIOMGR_SINKVOLTICK_ACK;
1330     case audiomgr_srcvoltick_ack:       return AUDIOMGR_SRCVOLTICK_ACK;
1331     case audiomgr_setsinkprop_ack:      return AUDIOMGR_SETSINKPROP_ACK;
1332     default:                            return "invalid_method";
1333     }
1334 }
1335
1336 /*
1337  * Local Variables:
1338  * c-basic-offset: 4
1339  * indent-tabs-mode: nil
1340  * End:
1341  *
1342  */
1343