// Copyright (C) 2013-2020 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // 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 can be included directly, this file may disappear or change contents." #endif #ifndef COMMONAPI_DBUS_DBUS_EVENT_HPP_ #define COMMONAPI_DBUS_DBUS_EVENT_HPP_ #include #include #include #include #include #include #include namespace CommonAPI { namespace DBus { template class DBusEvent: public Event_ { public: typedef typename Event_::Subscription Subscription; typedef typename Event_::Listener Listener; DBusEvent(DBusProxyBase &_proxy, const std::string &_name, const std::string &_signature, std::tuple _arguments) : proxy_(_proxy), signalHandler_(), name_(_name), signature_(_signature), getMethodName_(""), arguments_(_arguments) { interface_ = proxy_.getDBusAddress().getInterface(); path_ = proxy_.getDBusAddress().getObjectPath(); } DBusEvent(DBusProxyBase &_proxy, const std::string &_name, const std::string &_signature, const std::string &_path, const std::string &_interface, std::tuple _arguments) : proxy_(_proxy), signalHandler_(), name_(_name), signature_(_signature), path_(_path), interface_(_interface), getMethodName_(""), arguments_(_arguments) { } DBusEvent(DBusProxyBase &_proxy, const std::string &_name, const std::string &_signature, const std::string &_getMethodName, std::tuple _arguments) : proxy_(_proxy), signalHandler_(), name_(_name), signature_(_signature), getMethodName_(_getMethodName), arguments_(_arguments) { interface_ = proxy_.getDBusAddress().getInterface(); path_ = proxy_.getDBusAddress().getObjectPath(); } virtual ~DBusEvent() { proxy_.removeSignalStateHandler(signalHandler_, 0, true); proxy_.removeSignalMemberHandler(subscription_, signalHandler_.get()); } virtual void onError(const CommonAPI::CallStatus status) { (void)status; } virtual void onSpecificError(const CommonAPI::CallStatus status, const uint32_t tag) { this->notifySpecificError(tag, status); } virtual void setSubscriptionToken(const DBusProxyConnection::DBusSignalHandlerToken token, const uint32_t tag) { (void)token; (void)tag; } protected: class SignalHandler : public DBusProxyConnection::DBusSignalHandler, public std::enable_shared_from_this { public: SignalHandler(DBusProxyBase&_proxy, DBusEvent* _dbusEvent) : proxy_(_proxy.getWeakPtr()), dbusEvent_(_dbusEvent) { } virtual void onSignalDBusMessage(const DBusMessage &_message) { if(auto itsProxy = proxy_.lock()) { dbusEvent_->handleSignalDBusMessage(_message, typename make_sequence::type()); } } virtual void onInitialValueSignalDBusMessage(const DBusMessage&_message, const uint32_t tag) { if(auto itsProxy = proxy_.lock()) { dbusEvent_->handleSignalDBusMessage(tag, _message, typename make_sequence::type()); } } virtual void onSpecificError(const CommonAPI::CallStatus status, const uint32_t tag) { if(auto itsProxy = proxy_.lock()) { dbusEvent_->onSpecificError(status, tag); } } virtual void setSubscriptionToken(const DBusProxyConnection::DBusSignalHandlerToken token, const uint32_t tag) { if(auto itsProxy = proxy_.lock()) { dbusEvent_->setSubscriptionToken(token, tag); } } private : std::weak_ptr proxy_; DBusEvent* dbusEvent_; }; virtual void onFirstListenerAdded(const Listener &_listener) { (void)_listener; init(); subscription_ = proxy_.addSignalMemberHandler( path_, interface_, name_, signature_, getMethodName_, signalHandler_, false); } virtual void onListenerAdded(const Listener &_listener, const Subscription subscription) { (void)_listener; if ("" != getMethodName_) { proxy_.getCurrentValueForSignalListener(getMethodName_, signalHandler_, subscription); } proxy_.addSignalStateHandler(signalHandler_, subscription); } virtual void onListenerRemoved(const Listener &_listener, const Subscription _subscription) { (void)_listener; proxy_.removeSignalStateHandler(signalHandler_, _subscription); } virtual void onLastListenerRemoved(const Listener&) { proxy_.removeSignalMemberHandler(subscription_, signalHandler_.get()); std::get<0>(subscription_) = ""; std::get<1>(subscription_) = ""; std::get<2>(subscription_) = ""; std::get<3>(subscription_) = ""; } template inline void handleSignalDBusMessage(const DBusMessage &_message, index_sequence) { DBusInputStream input(_message); if (DBusSerializableArguments< Arguments_... >::deserialize(input, std::get(arguments_)...)) { this->notifyListeners(std::get(arguments_)...); } } template inline void handleSignalDBusMessage(const uint32_t tag, const DBusMessage &_message, index_sequence) { DBusInputStream input(_message); if (DBusSerializableArguments< Arguments_... >::deserialize(input, std::get(arguments_)...)) { this->notifySpecificListener(tag, std::get(arguments_)...); } } virtual void init() { if (!signalHandler_) { signalHandler_ = std::make_shared(proxy_, this); } } DBusProxyBase &proxy_; std::shared_ptr signalHandler_; std::string name_; std::string signature_; std::string path_; std::string interface_; std::string getMethodName_; DBusProxyConnection::DBusSignalHandlerToken subscription_; std::tuple arguments_; }; } // namespace DBus } // namespace CommonAPI #endif // COMMONAPI_DBUS_DBUS_EVENT_HPP_