only export dbus properties that are supported
[profile/ivi/automotive-message-broker.git] / plugins / dbus / abstractdbusinterface.cpp
1 /*
2 Copyright (C) 2012 Intel Corporation
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17 */
18
19 #include "abstractdbusinterface.h"
20 #include "debugout.h"
21 #include <boost/algorithm/string.hpp>
22 #include <gio/gio.h>
23
24 #include "abstractproperty.h"
25
26 unordered_map<string, AbstractDBusInterface*> AbstractDBusInterface::interfaceMap;
27
28 AbstractDBusInterface::AbstractDBusInterface(string interfaceName, string objectPath,
29                                                                                          GDBusConnection* connection)
30         : mInterfaceName(interfaceName), mObjectPath(objectPath), mConnection(connection)
31 {
32         interfaceMap[interfaceName] = this;
33         startRegistration();
34 }
35
36 void AbstractDBusInterface::addProperty(AbstractProperty* property)
37 {
38         string nameToLower = property->name();
39         boost::algorithm::to_lower<string>(nameToLower);
40         
41         string access;
42
43         if(property->access() == AbstractProperty::Read)
44                 access = "read";
45         else if(property->access() == AbstractProperty::Write)
46                 access = "write";
47         else if(property->access() == AbstractProperty::ReadWrite)
48                 access = "readwrite";
49         else throw -1; //FIXME: don't throw
50
51         ///see which properties are supported:
52         introspectionXml +=     "<property type='"+ property->signature() + "' name='"+ property->name()+"' access='"+access+"' />"
53         "<signal name='" + property->name() + "' >"
54         "       <arg type='"+ property->signature() + "' name='" + nameToLower + "' direction='out' />"
55         "</signal>";
56         
57         properties[property->name()] = property;
58 }
59
60 void AbstractDBusInterface::registerObject()
61 {
62         if(!mConnection)
63         {
64                 throw std::runtime_error("forgot to call setDBusConnection on AbstractDBusInterface");
65         }
66         
67         if(introspectionXml.empty())
68         {
69                 cerr<<"no interface to export: "<<mInterfaceName<<endl;
70                 throw -1;
71         }
72
73         introspectionXml += "</interface>";
74         introspectionXml += "</node>";
75         
76         GError* error=NULL;
77
78         GDBusNodeInfo* introspection = g_dbus_node_info_new_for_xml(introspectionXml.c_str(), &error);
79         
80         if(!introspection)
81         {
82                 cerr<<"Error in "<<__FILE__<<" - "<<__FUNCTION__<<":"<<__LINE__<<endl;
83                 cerr<<error->message<<endl;
84                 cerr<<"probably bad xml:"<<endl;
85                 cerr<<introspectionXml<<endl;
86                 return;
87         }
88
89         GDBusInterfaceInfo* mInterfaceInfo = g_dbus_node_info_lookup_interface(introspection, mInterfaceName.c_str());
90         
91         const GDBusInterfaceVTable vtable = { NULL, AbstractDBusInterface::getProperty, AbstractDBusInterface::setProperty };
92         
93         regId = g_dbus_connection_register_object(mConnection, mObjectPath.c_str(), mInterfaceInfo, &vtable, NULL, NULL, &error);
94         
95         if(error) throw -1;
96         
97         g_assert(regId > 0);
98 }
99
100 void AbstractDBusInterface::unregisterObject()
101 {
102         g_dbus_connection_unregister_object(mConnection, regId);
103 }
104
105 void AbstractDBusInterface::updateValue(AbstractProperty *property)
106 {
107         if(mConnection == nullptr)
108         {
109                 return;
110         }
111
112         GError *error = NULL;
113         g_dbus_connection_emit_signal(mConnection, NULL, mObjectPath.c_str(), mInterfaceName.c_str(), property->name().c_str(), g_variant_new("(v)",property->toGVariant()), &error);
114
115         if(error)
116         {
117                 throw -1;
118         }
119 }
120
121 void AbstractDBusInterface::startRegistration()
122 {
123         unregisterObject();
124         introspectionXml ="<node>" ;
125         introspectionXml += "<interface name='"+ mInterfaceName + "' >";
126 }
127
128 GVariant* AbstractDBusInterface::getProperty(GDBusConnection* connection, const gchar* sender, const gchar* objectPath, const gchar* interfaceName, const gchar* propertyName, GError** error, gpointer userData)
129 {
130         *error = NULL;
131         if(interfaceMap.count(interfaceName))
132         {
133                 GVariant* value = interfaceMap[interfaceName]->getProperty(propertyName);
134                 return value;
135         }
136         debugOut("No interface for" + string(interfaceName));
137         return nullptr;
138 }
139
140 gboolean AbstractDBusInterface::setProperty(GDBusConnection* connection, const gchar* sender, const gchar* objectPath, const gchar* interfaceName, const gchar* propertyName, GVariant* value, GError** error, gpointer userData)
141 {
142         if(interfaceMap.count(interfaceName))
143         {
144                 interfaceMap[interfaceName]->setProperty(propertyName, value);
145                 return true;
146         }
147
148         return false;
149 }
150
151 void AbstractDBusInterface::setProperty(string propertyName, GVariant *value)
152 {
153         if(properties.count(propertyName))
154         {
155                 properties[propertyName]->fromGVariant(value);
156         }
157         else
158         {
159                 throw -1;
160         }
161 }
162
163 GVariant *AbstractDBusInterface::getProperty(string propertyName)
164 {
165         if(properties.count(propertyName))
166                 return properties[propertyName]->toGVariant();
167         else
168                 throw -1;
169 }
170