[libamb] - added value quality, removed deprecated GetFoo call, made updateFrequency...
[profile/ivi/automotive-message-broker.git] / plugins / common / dbussignaller.h
1 #ifndef _DBUSSIGNALLER_H_
2 #define _DBUSSIGNALLER_H_
3
4 #include <gio/gio.h>
5
6 #include <vector>
7 #include <string>
8 #include <memory>
9 #include <unordered_map>
10
11 #include "debugout.h"
12 #include "varianttype.h"
13 #include "superptr.hpp"
14 #include "listplusplus.h"
15
16 class DBusSignal
17 {
18 public:
19         DBusSignal():connection(nullptr), property(nullptr){}
20         DBusSignal(GDBusConnection* conn, const std::string & objPath, const std::string & iface, const std::string & sigName, VariantType* var)
21                 : connection(conn), objectPath(objPath), interface(iface), signalName(sigName), property(var)
22         {
23
24         }
25
26         ~DBusSignal()
27         {
28
29         }
30
31         bool operator == (const DBusSignal &other) const
32         {
33                 return connection == other.connection &&
34                                 objectPath == other.objectPath &&
35                                 interface == other.interface &&
36                                 signalName == other.signalName &&
37                                 property == other.property;
38         }
39
40         GDBusConnection* connection;
41         std::string objectPath;
42         std::string interface;
43         std::string signalName;
44         VariantType* property;
45 };
46
47 class DBusSignaller
48 {
49 public:
50
51         static DBusSignaller* factory(int timeout)
52         {
53                 if(!singleton)
54                         return singleton = new DBusSignaller(timeout);
55                 return singleton;
56         }
57
58         void fireSignal(GDBusConnection* conn, const std::string & objPath, const std::string & iface,
59                                         const std::string & sigName, VariantType* prop)
60         {
61                 DBusSignal * signal = new DBusSignal(conn, objPath, iface, sigName, prop);
62
63                 if(queue.find(objPath) != queue.end())
64                 {
65                         bool isFound = false;
66                         for(auto i : queue[objPath])
67                         {
68                                 if(*i == *signal)
69                                 {
70                                         isFound = true;
71                                         break;
72                                 }
73                         }
74
75                         if(!isFound)
76                                 queue[objPath].push_back(signal);
77                 }
78                 else
79                 {
80                         queue[objPath].push_back(signal);
81                 }
82         }
83
84 private:
85
86         DBusSignaller() { }
87
88         DBusSignaller(int timeout)
89         {
90                 g_timeout_add(timeout,[](gpointer userData)
91                 {
92                         std::unordered_map<std::string, std::vector<DBusSignal*>> *q = static_cast<std::unordered_map<std::string, std::vector<DBusSignal*>>*>(userData);
93                         std::unordered_map<std::string, std::vector<DBusSignal*>> queue = *q;
94
95                         for(auto itr : queue)
96                         {
97                                 std::string objectPath;
98                                 GDBusConnection* connection;
99                                 std::string interfaceName;
100                                 std::string signalName;
101
102                                 std::unordered_map<std::string, GVariant*> variantMap;
103
104                                 for(auto s : itr.second)
105                                 {
106                                         std::unique_ptr<DBusSignal> signal(s);
107                                         objectPath = signal->objectPath;
108                                         connection = signal->connection;
109                                         interfaceName = signal->interface;
110                                         signalName = signal->signalName;
111
112                                         VariantType* property = signal->property;
113
114                                         auto val = g_variant_ref(property->toVariant());
115                                         std::string sequenceName = property->name() + "Sequence";
116
117                                         variantMap[property->name()] = val;
118                                         variantMap[sequenceName] = g_variant_new("i", property->sequence());
119                                         variantMap["Time"] = g_variant_new("d", property->timestamp());
120                                         variantMap["Zone"] = g_variant_new("i", property->zoneFilter());
121                                 }
122
123                                 GVariantBuilder builder;
124                                 g_variant_builder_init(&builder, G_VARIANT_TYPE_DICTIONARY);
125
126                                 for(auto sv : variantMap)
127                                 {
128                                         /// Send PropertiesChanged signal
129                                         auto key = sv.first;
130                                         auto value = sv.second;
131
132                                         g_variant_builder_add(&builder, "{sv}", key.c_str(), value);
133                                 }
134
135                                 GError* error = nullptr;
136
137                                 g_dbus_connection_emit_signal(connection, NULL, objectPath.c_str(),
138                                                                                           "org.freedesktop.DBus.Properties",
139                                                                                           signalName.c_str(),
140                                                                                           g_variant_new("(sa{sv}as)", interfaceName.c_str(), &builder, NULL),
141                                                                                           &error);
142
143                                 auto errorPtr = amb::make_super(error);
144
145                                 if(errorPtr)
146                                 {
147                                         DebugOut(DebugOut::Error)<<errorPtr->message<<std::endl;
148                                 }
149                         }
150
151                         q->clear();
152
153                         return 1;
154
155                 },&queue);
156         }
157
158         std::unordered_map<std::string, std::vector<DBusSignal*>> queue;
159
160         static DBusSignaller * singleton;
161 };
162
163 #endif