summaryrefslogtreecommitdiff
path: root/src/CommonAPI/DBus/DBusEvent.h
blob: 4bd235d6448f8b743acbe78b367b2e740855aae5 (plain)
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
/* 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_);
	}

	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_);
	}

	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* interfaceName_;
	const char* objectPath_;
	DBusProxyConnection::DBusSignalHandlerToken subscription_;
};

} // namespace DBus
} // namespace CommonAPI

#endif // COMMONAPI_DBUS_DBUS_EVENT_H_