1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
/* Copyright (C) 2013 BMW Group
* Author: Manfred Bathelt (manfred.bathelt@bmw.de)
* Author: Juergen Gehring (juergen.gehring@bmw.de)
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#if !defined (COMMONAPI_INTERNAL_COMPILATION)
#error "Only <CommonAPI/CommonAPI.h> can be included directly, this file may disappear or change contents."
#endif
#ifndef COMMONAPI_DBUS_DBUS_EVENT_H_
#define COMMONAPI_DBUS_DBUS_EVENT_H_
#include "DBusProxyConnection.h"
#include "DBusMessage.h"
#include "DBusSerializableArguments.h"
#include "DBusHelper.h"
#include <CommonAPI/Event.h>
namespace CommonAPI {
namespace DBus {
class DBusProxyBase;
template <typename _EventType, typename _DBusProxy = DBusProxyBase>
class DBusEvent: public _EventType, public DBusProxyConnection::DBusSignalHandler {
public:
typedef typename _EventType::ArgumentsTuple ArgumentsTuple;
typedef typename _EventType::CancellableListener CancellableListener;
DBusEvent(_DBusProxy& dbusProxy, const char* eventName, const char* eventSignature):
dbusProxy_(dbusProxy),
eventName_(eventName),
eventSignature_(eventSignature) {
interfaceName_ = dbusProxy.getInterfaceName().c_str();
objectPath_ = dbusProxy_.getDBusObjectPath().c_str();
assert(eventName_);
assert(eventSignature_);
assert(objectPath_);
assert(interfaceName_);
}
DBusEvent(_DBusProxy& dbusProxy, const char* eventName, const char* eventSignature, const char* objPath, const char* interfaceName) :
dbusProxy_(dbusProxy),
eventName_(eventName),
eventSignature_(eventSignature),
objectPath_(objPath),
interfaceName_(interfaceName) {
assert(eventName);
assert(eventSignature);
assert(objPath);
assert(interfaceName);
}
virtual ~DBusEvent() {
if (this->hasListeners())
dbusProxy_.removeSignalMemberHandler(subscription_, this);
}
virtual SubscriptionStatus onSignalDBusMessage(const DBusMessage& dbusMessage) {
return unpackArgumentsAndHandleSignalDBusMessage(dbusMessage, ArgumentsTuple());
}
protected:
virtual void onFirstListenerAdded(const CancellableListener&) {
subscription_ = dbusProxy_.addSignalMemberHandler(objectPath_,
interfaceName_,
eventName_,
eventSignature_,
this);
}
virtual void onLastListenerRemoved(const CancellableListener&) {
dbusProxy_.removeSignalMemberHandler(subscription_, this);
}
template<typename ... _Arguments>
inline SubscriptionStatus unpackArgumentsAndHandleSignalDBusMessage(const DBusMessage& dbusMessage,
std::tuple<_Arguments...> argTuple) {
return handleSignalDBusMessage(dbusMessage, std::move(argTuple), typename make_sequence<sizeof...(_Arguments)>::type());
}
template<typename ... _Arguments, int ... _ArgIndices>
inline SubscriptionStatus handleSignalDBusMessage(const DBusMessage& dbusMessage,
std::tuple<_Arguments...> argTuple,
index_sequence<_ArgIndices...>) {
DBusInputStream dbusInputStream(dbusMessage);
const bool success = DBusSerializableArguments<_Arguments...>::deserialize(
dbusInputStream,
std::get<_ArgIndices>(argTuple)...);
// Continue subscription if deserialization failed
return success ? this->notifyListeners(std::get<_ArgIndices>(argTuple)...) : SubscriptionStatus::RETAIN;
}
_DBusProxy& dbusProxy_;
const char* eventName_;
const char* eventSignature_;
const char* objectPath_;
const char* interfaceName_;
DBusProxyConnection::DBusSignalHandlerToken subscription_;
};
} // namespace DBus
} // namespace CommonAPI
#endif // COMMONAPI_DBUS_DBUS_EVENT_H_
|