scripting: add zone support 86/8986/1
authorJanos Kovacs <jankovac503@gmail.com>
Fri, 16 Aug 2013 09:56:51 +0000 (12:56 +0300)
committerJaska Uimonen <jaska.uimonen@helsinki.fi>
Tue, 20 Aug 2013 08:19:12 +0000 (11:19 +0300)
murphy/Makefile.am
murphy/module-murphy-ivi.c
murphy/murphy-ivi.lua
murphy/node.c
murphy/scripting.c
murphy/userdata.h
murphy/zone.c [new file with mode: 0644]
murphy/zone.h [new file with mode: 0644]

index 01ead95..de2b159 100644 (file)
@@ -16,6 +16,7 @@ modlibexec_LTLIBRARIES = module-murphy-ivi.la
 module_murphy_ivi_la_SOURCES = \
                        module-murphy-ivi.c \
                        tracker.c \
+                       zone.c \
                        node.c \
                        discover.c \
                        constrain.c \
index c3c9420..4b54753 100644 (file)
@@ -47,6 +47,7 @@
 #include "module-murphy-ivi-symdef.h"
 #include "userdata.h"
 #include "node.h"
+#include "zone.h"
 #include "tracker.h"
 #include "discover.h"
 #include "router.h"
@@ -200,6 +201,7 @@ int pa__init(pa_module *m) {
     u->core      = m->core;
     u->module    = m;
     u->nullsink  = pa_utils_create_null_sink(u, nsnam);
+    u->zoneset   = pa_zoneset_init(u);
     u->nodeset   = pa_nodeset_init(u);
     u->audiomgr  = pa_audiomgr_init(u);
 #ifdef WITH_DBUS
@@ -275,6 +277,7 @@ void pa__done(pa_module *m) {
         pa_mir_volume_done(u);
         pa_mir_config_done(u);
         pa_nodeset_done(u);
+        pa_zoneset_done(u);
         pa_scripting_done(u);
         pa_utils_destroy_null_sink(u);
 
index adf6e5e..39cef79 100644 (file)
@@ -1,3 +1,8 @@
+zone { name = "driver" }
+zone { name = "passanger1" }
+zone { name = "passanger2" }
+zone { name = "passanger3" }
+zone { name = "passanger4" }
 
 routing_group {
     name = "default",
index ad14f91..54437d7 100644 (file)
@@ -174,7 +174,7 @@ pa_nodeset_map *pa_nodeset_get_map_by_role(struct userdata *u,
     pa_assert(u);
     pa_assert_se((ns = u->nodeset));
 
-    if (role)
+    if (role && ns->roles)
         map = pa_hashmap_get(ns->roles, role);
     else
         map = NULL;
index 6167a83..ba03165 100644 (file)
@@ -37,6 +37,7 @@
 #include <murphy/resource/protocol.h>
 
 #include "scripting.h"
+#include "zone.h"
 #include "node.h"
 #include "router.h"
 #include "volume.h"
@@ -45,6 +46,7 @@
 
 #define IMPORT_CLASS       MRP_LUA_CLASS(mdb, import)
 #define NODE_CLASS         MRP_LUA_CLASS(node, instance)
+#define ZONE_CLASS         MRP_LUA_CLASS_SIMPLE(zone)
 #define RESOURCE_CLASS     MRP_LUA_CLASS_SIMPLE(audio_resource)
 #define RTGROUP_CLASS      MRP_LUA_CLASS_SIMPLE(routing_group)
 #define APPLICATION_CLASS  MRP_LUA_CLASS_SIMPLE(application_class)
@@ -101,6 +103,13 @@ typedef struct {
     mrp_attr_t          def;
 } attribute_t;
 
+
+struct scripting_zone {
+    struct userdata    *userdata;
+    const char         *name;
+    uint32_t            index;
+};
+
 struct scripting_resource {
     struct userdata    *userdata;
     resource_name_t    *name;
@@ -241,6 +250,11 @@ static int  node_setfield(lua_State *);
 static int  node_tostring(lua_State *);
 static void node_destroy(void *);
 
+static int  zone_create(lua_State *);
+static int  zone_getfield(lua_State *);
+static int  zone_setfield(lua_State *);
+static void zone_destroy(void *);
+
 static int  resource_create(lua_State *);
 static int  resource_getfield(lua_State *);
 static int  resource_setfield(lua_State *);
@@ -375,6 +389,20 @@ MRP_LUA_CLASS_DEF (
 );
 
 MRP_LUA_CLASS_DEF_SIMPLE (
+   zone,                         /* class name */
+   scripting_zone,               /* userdata type */
+   zone_destroy,                 /* userdata destructor */
+   MRP_LUA_METHOD_LIST (         /* methods */
+      MRP_LUA_METHOD_CONSTRUCTOR  (zone_create)
+   ),
+   MRP_LUA_METHOD_LIST (         /* overrides */
+      MRP_LUA_OVERRIDE_CALL       (zone_create)
+      MRP_LUA_OVERRIDE_GETFIELD   (zone_getfield)
+      MRP_LUA_OVERRIDE_SETFIELD   (zone_setfield)
+   )
+);
+
+MRP_LUA_CLASS_DEF_SIMPLE (
    audio_resource,               /* class name */
    scripting_resource,           /* userdata type */
    resource_destroy,             /* userdata destructor */
@@ -452,6 +480,7 @@ pa_scripting *pa_scripting_init(struct userdata *u)
         mrp_create_funcbridge_class(L);
         mrp_lua_create_object_class(L, IMPORT_CLASS);
         mrp_lua_create_object_class(L, NODE_CLASS);
+        mrp_lua_create_object_class(L, ZONE_CLASS);
         mrp_lua_create_object_class(L, RESOURCE_CLASS);
         mrp_lua_create_object_class(L, RTGROUP_CLASS);
         mrp_lua_create_object_class(L, APPLICATION_CLASS);
@@ -503,6 +532,7 @@ pa_bool_t pa_scripting_dofile(struct userdata *u, const char *file)
         success =TRUE;
         scripting->configured = TRUE;
         setup_murphy_interface(u);
+        pa_zoneset_update_module_property(u);
     }
 
     return success;
@@ -1118,6 +1148,104 @@ static void node_destroy(void *data)
     MRP_LUA_LEAVE_NOARG;
 }
 
+
+static int zone_create(lua_State *L)
+{
+    static uint32_t index;
+
+    struct userdata *u;
+    size_t fldnamlen;
+    const char *fldnam;
+    scripting_zone *zone;
+    const char *name = NULL;
+    attribute_t *attributes = NULL;
+
+    MRP_LUA_ENTER;
+
+    lua_getglobal(L, USERDATA);
+    if (!lua_islightuserdata(L, -1) || !(u = lua_touserdata(L, -1)))
+        luaL_error(L, "missing or invalid global '" USERDATA "'");
+    lua_pop(L, 1);
+
+
+    MRP_LUA_FOREACH_FIELD(L, 2, fldnam, fldnamlen) {
+
+        switch (field_name_to_type(fldnam, fldnamlen)) {
+        case NAME:         name = luaL_checkstring(L, -1);           break;
+        case ATTRIBUTES:   attributes = attributes_check(L, -1);     break;
+        default:           luaL_error(L, "bad field '%s'", fldnam);  break;
+        }
+
+    } /* MRP_LUA_FOREACH_FIELD */
+
+    if (!name)
+        luaL_error(L, "missing or invalid name field");
+
+    if (pa_zoneset_add_zone(u, name, index+1))
+        luaL_error(L, "attempt to define zone '%s' multiple times", name);
+
+    zone = (scripting_zone *)mrp_lua_create_object(L, ZONE_CLASS,
+                                                   "definition",0);
+
+    zone->userdata = u;
+    zone->name = pa_xstrdup(name);
+    zone->index = ++index;
+
+
+    MRP_LUA_LEAVE(1);
+}
+
+static int zone_getfield(lua_State *L)
+{
+    scripting_zone *zone;
+    field_t fld;
+
+    MRP_LUA_ENTER;
+
+    fld = field_check(L, 2, NULL);
+    lua_pop(L, 1);
+
+    if (!(zone = (scripting_zone *)mrp_lua_check_object(L, ZONE_CLASS, 1)))
+        lua_pushnil(L);
+    else {
+        switch (fld) {
+        case NAME:           lua_pushstring(L, zone->name);         break;
+#if 0
+        case ATTRIBUTES:     lua_pushinteger(L, rtgs->type);       break;
+#endif
+        default:             lua_pushnil(L);                       break;
+        }
+    }
+
+    MRP_LUA_LEAVE(1);
+}
+
+static int zone_setfield(lua_State *L)
+{
+    const char *f;
+
+    MRP_LUA_ENTER;
+
+    f = luaL_checkstring(L, 2);
+    luaL_error(L, "attempt to set '%s' field of read-only zone", f);
+    
+    MRP_LUA_LEAVE(0);
+}
+
+static void zone_destroy(void *data)
+{
+    scripting_zone *zone = (scripting_zone *)data;
+
+    MRP_LUA_ENTER;
+
+    pa_xfree((void *)zone->name);
+    
+    zone->name = NULL;
+
+    MRP_LUA_LEAVE_NOARG;
+}
+
+
 static int resource_create(lua_State *L)
 {
     struct userdata *u;
index efd18e0..731e9d9 100644 (file)
@@ -32,6 +32,7 @@
 
 #define DIM(a) (sizeof(a)/sizeof((a)[0]))
 
+#define PA_PROP_ZONES                  "zones"
 #define PA_PROP_ZONE_NAME              "zone.name"
 #define PA_PROP_ROUTING_CLASS_NAME     "routing.class.name"
 #define PA_PROP_ROUTING_CLASS_ID       "routing.class.id"
@@ -65,6 +66,7 @@ typedef struct pa_fader                 pa_fader;
 typedef struct pa_scripting             pa_scripting;
 typedef struct pa_mir_volume            pa_mir_volume;
 typedef struct pa_mir_config            pa_mir_config;
+typedef struct pa_zoneset               pa_zoneset;
 typedef struct pa_nodeset               pa_nodeset;
 typedef struct pa_nodeset_resdef        pa_nodeset_resdef;
 typedef struct pa_nodeset_map           pa_nodeset_map;
@@ -84,6 +86,7 @@ typedef enum   mir_location             mir_location;
 typedef enum   mir_node_type            mir_node_type;
 typedef enum   mir_privacy              mir_privacy; 
 typedef struct mir_node                 mir_node;
+typedef struct mir_zone                 mir_zone;
 typedef struct mir_rtgroup              mir_rtgroup;
 typedef struct mir_rtentry              mir_rtentry;
 typedef struct mir_connection           mir_connection;
@@ -94,6 +97,7 @@ typedef struct mir_volume_suppress_arg  mir_volume_suppress_arg;
 
 typedef struct scripting_import         scripting_import;
 typedef struct scripting_node           scripting_node;
+typedef struct scripting_zone           scripting_zone;
 typedef struct scripting_resource       scripting_resource;
 typedef struct scripting_rtgroup        scripting_rtgroup;
 typedef struct scripting_apclass        scripting_apclass;
@@ -144,6 +148,7 @@ struct userdata {
     pa_core       *core;
     pa_module     *module;
     pa_null_sink  *nullsink;
+    pa_zoneset    *zoneset;
     pa_nodeset    *nodeset;
     pa_audiomgr   *audiomgr;
     pa_routerif   *routerif;
diff --git a/murphy/zone.c b/murphy/zone.c
new file mode 100644 (file)
index 0000000..1903cc5
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * module-murphy-ivi -- PulseAudio module for providing audio routing support
+ * Copyright (c) 2012, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU Lesser General Public License,
+ * version 2.1, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston,
+ * MA 02110-1301 USA.
+ *
+ */
+#include <stdio.h>
+
+#include <pulsecore/pulsecore-config.h>
+
+#include <pulse/proplist.h>
+#include <pulsecore/idxset.h>
+#include <pulsecore/hashmap.h>
+#include <pulsecore/module.h>
+
+#include "zone.h"
+
+
+struct pa_zoneset {
+    pa_hashmap     *zones;
+};
+
+
+static void free_zone_cb(void *);
+
+
+pa_zoneset *pa_zoneset_init(struct userdata *u)
+{
+    pa_zoneset *zs;
+
+    pa_assert(u);
+
+    zs = pa_xnew0(pa_zoneset, 1);
+    zs->zones = pa_hashmap_new(pa_idxset_string_hash_func,
+                               pa_idxset_string_compare_func);
+
+    return zs;
+}
+
+
+void pa_zoneset_done(struct userdata *u)
+{
+    pa_zoneset *zs;
+    int i;
+
+    if (u && (zs = u->zoneset)) {
+        pa_hashmap_free(zs->zones, free_zone_cb);
+
+        free(zs);
+    }    
+}
+
+int pa_zoneset_add_zone(struct userdata *u, const char *name, uint32_t index)
+{
+    pa_zoneset *zs;
+    mir_zone *zone;
+
+    pa_assert(u);
+    pa_assert(name);
+    pa_assert_se((zs = u->zoneset));
+
+    zone = pa_xnew0(mir_zone, 1);
+    zone->name = pa_xstrdup(name);
+    zone->index = index;
+
+    return pa_hashmap_put(zs->zones, zone->name, zone);
+}
+
+mir_zone *pa_zoneset_get_zone(struct userdata *u, const char *name)
+{
+    pa_zoneset *zs;
+    mir_zone *zone;
+
+    pa_assert(u);
+    pa_assert_se((zs = u->zoneset));
+
+    if (name && zs->zones)
+        zone = pa_hashmap_get(zs->zones, name);
+    else
+        zone = NULL;
+
+    return zone;
+}
+
+
+void pa_zoneset_update_module_property(struct userdata *u)
+{
+    pa_module *module;
+    pa_zoneset *zs;
+    mir_zone *zone;
+    void *state;
+    char buf[4096];
+    char *p, *e;
+
+    pa_assert(u);
+    pa_assert_se((module = u->module));
+    pa_assert_se((zs = u->zoneset));
+    pa_assert(zs->zones);
+
+    e = (p = buf) + sizeof(buf);
+
+    buf[1] = 0;
+    
+    PA_HASHMAP_FOREACH(zone, zs->zones, state) {
+        if (p >= e) break;
+        p += snprintf(p, e-p, " '%s'", zone->name);
+    }
+
+    pa_proplist_sets(module->proplist, PA_PROP_ZONES, buf+1); /* skip ' '@begining */
+}
+
+static void free_zone_cb(void *void_zone)
+{
+    mir_zone  *zone = (mir_zone *)void_zone;
+
+    pa_xfree((void *)zone->name);
+
+    pa_xfree(zone);
+}
+
+
+                                  
+
+
+
+/*
+ * Local Variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ *
+ */
diff --git a/murphy/zone.h b/murphy/zone.h
new file mode 100644 (file)
index 0000000..84497e7
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * module-murphy-ivi -- PulseAudio module for providing audio routing support
+ * Copyright (c) 2012, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU Lesser General Public License,
+ * version 2.1, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston,
+ * MA 02110-1301 USA.
+ *
+ */
+#ifndef foomirzonefoo
+#define foomirzonefoo
+
+#include <sys/types.h>
+
+#include "userdata.h"
+
+struct mir_zone {
+    const char *name;
+    uint32_t    index;
+};
+
+pa_zoneset *pa_zoneset_init(struct userdata *);
+void pa_zoneset_done(struct userdata *);
+
+int pa_zoneset_add_zone(struct userdata *, const char *, uint32_t);
+mir_zone *pa_zoneset_get_zone(struct userdata *, const char *);
+
+void pa_zoneset_update_module_property(struct userdata *);
+
+#endif  /* foomirzonefoo */
+
+
+/*
+ * Local Variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ *
+ */