1 #ifndef DALI_INTERNAL_ACCESSIBILITY_BRIDGE_DBUS_H
2 #define DALI_INTERNAL_ACCESSIBILITY_BRIDGE_DBUS_H
5 * Copyright 2019 Samsung Electronics Co., Ltd
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
32 #include <type_traits>
33 #include <unordered_map>
38 //#include <dali/public-api/adaptor-framework/accessibility.h>
39 //#include <dali/internal/accessibility/bridge/optional.h>
41 #include <dali/devel-api/adaptor-framework/accessibility.h>
43 #define ATSPI_PREFIX_PATH "/org/a11y/atspi/accessible/"
44 #define ATSPI_NULL_PATH "/org/a11y/atspi/null"
48 #define bart_assert(x) do{}while(0)
60 virtual ~DBusWrapper() = default;
62 enum class ConnectionType
68 #define DEFINE_TYPE(name, eldbus_name, unref_call) \
69 struct name { virtual ~name() = default; }; \
70 using name ## Ptr = std::shared_ptr<name>; \
71 using name ## WeakPtr = std::weak_ptr<name>; \
73 DEFINE_TYPE(Connection, Eldbus_Connection, )
74 DEFINE_TYPE(MessageIter, Eldbus_Message_Iter, eldbus_message_iter_container_close( Value ))
75 DEFINE_TYPE(Message, Eldbus_Message, eldbus_message_unref( Value ))
76 DEFINE_TYPE(Proxy, Eldbus_Proxy, eldbus_proxy_unref( Value ))
77 DEFINE_TYPE(Object, Eldbus_Object, eldbus_object_unref( Value ))
78 DEFINE_TYPE(Pending, Eldbus_Pending, )
79 DEFINE_TYPE(EventPropertyChanged, Eldbus_Proxy_Event_Property_Changed, )
82 virtual ConnectionPtr eldbus_address_connection_get_impl(const std::string &addr) = 0;
84 #define eldbus_message_iter_arguments_append_impl_basic_impl(type_set, type_get, sig) \
85 virtual void eldbus_message_iter_arguments_append_impl(const MessageIterPtr &it, type_set src) = 0; \
86 virtual bool eldbus_message_iter_get_and_next_impl(const MessageIterPtr &it, type_get &dst) = 0;
87 #define eldbus_message_iter_arguments_append_impl_basic(type, sig) \
88 eldbus_message_iter_arguments_append_impl_basic_impl(type, type, sig)
90 eldbus_message_iter_arguments_append_impl_basic(uint8_t, y)
91 eldbus_message_iter_arguments_append_impl_basic(uint16_t, q)
92 eldbus_message_iter_arguments_append_impl_basic(uint32_t, u)
93 eldbus_message_iter_arguments_append_impl_basic(uint64_t, t)
94 eldbus_message_iter_arguments_append_impl_basic(int16_t, n)
95 eldbus_message_iter_arguments_append_impl_basic(int32_t, i)
96 eldbus_message_iter_arguments_append_impl_basic(int64_t, x)
97 eldbus_message_iter_arguments_append_impl_basic(double, d)
98 eldbus_message_iter_arguments_append_impl_basic(bool, b)
99 eldbus_message_iter_arguments_append_impl_basic_impl(const std::string &, std::string, s)
100 eldbus_message_iter_arguments_append_impl_basic_impl(const ObjectPath &, ObjectPath, o)
102 #undef eldbus_message_iter_arguments_append_impl_basic
103 #undef eldbus_message_iter_arguments_append_impl_basic_impl
105 virtual MessageIterPtr eldbus_message_iter_container_new_impl(const MessageIterPtr &it, int type, const std::string &sig) = 0;
106 virtual MessageIterPtr eldbus_message_iter_get_and_next_by_type_impl(const MessageIterPtr &it, int type) = 0;
107 virtual MessageIterPtr eldbus_message_iter_get_impl(const MessagePtr &it, bool write) = 0;
108 virtual MessagePtr eldbus_proxy_method_call_new_impl(const ProxyPtr &proxy, const std::string &funcName) = 0;
109 virtual MessagePtr eldbus_proxy_send_and_block_impl(const ProxyPtr &proxy, const MessagePtr &msg) = 0;
110 virtual bool eldbus_message_error_get_impl(const MessagePtr &msg, std::string &name, std::string &text) = 0;
111 virtual std::string eldbus_message_signature_get_impl(const MessagePtr &msg) = 0;
113 using SendCallback = std::function<void(const MessagePtr &msg)>;
114 virtual PendingPtr eldbus_proxy_send_impl(const ProxyPtr &proxy, const MessagePtr &msg, const SendCallback &callback) = 0;
115 virtual std::string eldbus_proxy_interface_get_impl(const ProxyPtr &) = 0;
116 virtual void eldbus_proxy_signal_handler_add_impl(const ProxyPtr &proxy, const std::string &member, const std::function<void(const MessagePtr &)> &cb) = 0;
117 virtual std::string eldbus_message_iter_signature_get_impl(const MessageIterPtr &iter) = 0;
118 virtual MessagePtr eldbus_message_method_return_new_impl( const MessagePtr &msg) = 0;
119 virtual MessagePtr eldbus_message_error_new_impl( const MessagePtr &msg, const std::string &err, const std::string &txt ) = 0;
120 virtual PendingPtr eldbus_connection_send_impl(const ConnectionPtr &conn, const MessagePtr &msg) = 0;
121 virtual MessagePtr eldbus_message_signal_new_impl(const std::string &path, const std::string &iface, const std::string &name) = 0;
122 virtual MessagePtr eldbus_message_ref_impl(const MessagePtr &msg) = 0;
123 virtual ConnectionPtr eldbus_connection_get_impl(ConnectionType type) = 0;
124 virtual std::string eldbus_connection_unique_name_get_impl(const ConnectionPtr &conn) = 0;
125 virtual ObjectPtr eldbus_object_get_impl( const ConnectionPtr &conn, const std::string &bus, const std::string &path ) = 0;
126 virtual ProxyPtr eldbus_proxy_get_impl( const ObjectPtr &obj, const std::string &interface ) = 0;
127 virtual ProxyPtr eldbus_proxy_copy_impl( const ProxyPtr &ptr) = 0;
128 virtual void eldbus_name_request_impl(const ConnectionPtr&, const std::string&) {} // no-op
129 virtual void eldbus_name_release_impl(const ConnectionPtr&, const std::string&) {} // no-op
134 struct char_ptr_deleter
136 void operator()( char* p )
141 std::vector< std::unique_ptr< char, char_ptr_deleter > > storage;
143 const char* add( const char* txt )
145 auto ptr = strdup( txt );
146 storage.push_back( std::unique_ptr< char, char_ptr_deleter >( ptr ) );
147 return storage.back().get();
149 const char* add( const std::string& txt )
151 return add( txt.c_str() );
157 static std::atomic< unsigned int > LastId;
158 unsigned int id = ++LastId;
163 std::string memberName;
164 std::vector< std::pair<std::string, std::string> > in, out; // _Eldbus_Arg_Info
165 std::function< DBusWrapper::MessagePtr( const DBusWrapper::MessagePtr &msg ) > callback;
170 std::string memberName;
171 std::vector< std::pair<std::string, std::string> > args;
172 unsigned int uniqueId;
176 CallId setterId, getterId;
177 std::string memberName, typeSignature;
178 std::function< std::string( const DBusWrapper::MessagePtr &src, const DBusWrapper::MessageIterPtr &dst ) > getCallback, setCallback;
184 SignalId() = default;
185 SignalId( CallId id ) : id( id ) {}
187 virtual void add_interface_impl( bool fallback, const std::string& pathName,
188 const ConnectionPtr &connection,
189 std::vector<std::function<void()>> &destructors,
190 const std::string& interfaceName,
191 std::vector< MethodInfo >& dscrMethods,
192 std::vector< PropertyInfo >& dscrProperties,
193 std::vector< SignalInfo >& dscrSignals ) = 0;
194 virtual void add_property_changed_event_listener_impl( const ProxyPtr &proxy, const std::string &interface, const std::string &name, std::function< void( const _Eina_Value * ) > cb) = 0;
195 static DBusWrapper *Installed();
196 static void Install(std::unique_ptr<DBusWrapper>);
198 StringStorage Strings;
202 enum class MethodType {
203 Method, Getter, Setter
208 template <> struct hash<std::tuple<std::string, std::string, std::string>> {
209 size_t operator () (const std::tuple<std::string, std::string, std::string> &a) const {
210 auto a1 = std::hash<std::string>()(std::get<0>(a));
211 auto a2 = std::hash<std::string>()(std::get<1>(a));
212 auto a3 = std::hash<std::string>()(std::get<2>(a));
214 v = (v * 11400714819323198485llu) + a2;
215 v = (v * 11400714819323198485llu) + a3;
219 template <> struct hash<std::tuple<std::string, std::string, std::string, detail::MethodType>> {
220 size_t operator () (const std::tuple<std::string, std::string, std::string, detail::MethodType> &a) const {
221 auto a1 = std::hash<std::string>()(std::get<0>(a));
222 auto a2 = std::hash<std::string>()(std::get<1>(a));
223 auto a3 = std::hash<std::string>()(std::get<2>(a));
224 auto a4 = static_cast<size_t>(std::get<3>(a));
226 v = (v * 11400714819323198485llu) + a2;
227 v = (v * 11400714819323198485llu) + a3;
228 v = (v * 11400714819323198485llu) + a4;
232 template <> struct hash<std::tuple<std::string, std::string, unsigned int>> {
233 size_t operator () (const std::tuple<std::string, std::string, unsigned int> &a) const {
234 auto a1 = std::hash<std::string>()(std::get<0>(a));
235 auto a2 = std::hash<std::string>()(std::get<1>(a));
236 auto a3 = std::get<2>(a);
238 v = (v * 11400714819323198485llu) + a2;
239 v = (v * 11400714819323198485llu) + a3;
245 template <typename T> struct DBusSigImpl { enum { value = 0, end = 0 }; };
246 template <typename T> struct DBusSig { enum { value = DBusSigImpl<typename std::decay<T>::type>::value, end = DBusSigImpl<typename std::decay<T>::type>::end }; };
247 template <typename T, typename Q, size_t I, size_t S> struct IndexFromTypeTupleImpl {
248 enum { value = std::is_same<typename std::decay<typename std::tuple_element<I, T>::type>::type, Q>::value ? I : IndexFromTypeTupleImpl<T, Q, I + 1, S>::value };
250 template <typename T, typename Q, size_t S> struct IndexFromTypeTupleImpl<T, Q, S, S> { enum { value = S }; };
251 template <typename T, typename Q> struct IndexFromTypeTuple {
252 enum { value = IndexFromTypeTupleImpl<T, typename std::decay<Q>::type, 0, std::tuple_size<T>::value>::value };
254 template <typename T, typename = void> struct Encoder;
255 template <size_t I, size_t S, typename ... ARGS> struct EncoderTuple;
257 struct TestDBusWrapper : public DBusWrapper
259 using MethodType = detail::MethodType;
260 ConnectionPtr connection;
261 std::unordered_map<std::tuple<std::string, std::string, std::string, MethodType>, std::function<MessagePtr(const MessagePtr&)>> testMethods;
262 std::unordered_map<std::tuple<std::string, std::string, std::string, MethodType>, std::function<MessagePtr(const MessagePtr&)>> daliMethods;
263 std::unordered_map<std::tuple<std::string, std::string, unsigned int>, std::string> daliSignalsMap;
264 std::unordered_map<std::tuple<std::string, std::string, std::string>, std::function<void(const MessagePtr&)>> daliSignals;
265 std::unordered_map<std::tuple<std::string, std::string, std::string>, std::function<void(const _Eina_Value *)>> propertyChangeListeners;
267 std::vector<std::function<void()>> asyncCalls;
269 template <typename T> struct Variant {
272 Variant(T t) : value(std::move(t)) { }
274 template <typename ... ARGS> void Encode(const MessagePtr &m, const std::tuple<ARGS...> &args) {
275 auto iter = eldbus_message_iter_get_impl(m, true);
276 detail::EncoderTuple<0, sizeof...(ARGS), ARGS...>::encode(*this, iter, args);
278 template <typename ... ARGS> void Decode(const MessagePtr &m, std::tuple<ARGS...> &args) {
279 auto iter = eldbus_message_iter_get_impl(m, false);
280 detail::EncoderTuple<0, sizeof...(ARGS), ARGS...>::decode(*this, args, iter);
282 MessagePtr newMessage(const std::string &path, const std::string &interface, const std::string &name, bool reply);
283 MessagePtr newReplyMessage(const MessagePtr &m);
285 template <typename ... ARGS> void fromTestEmitSignal(std::string path, const std::string &interface, const std::string &name, const std::tuple<ARGS...> &args) {
286 if (path.empty()) throw error{};
287 if (path[0] != '/') path = "/org/a11y/atspi/accessible/" + path;
288 auto msg = newMessage(path, interface, name, false);
290 auto it = daliSignals.find(std::tuple<std::string, std::string, std::string>{ path, interface, name });
291 if (it == daliSignals.end()) throw error{};
294 static std::shared_ptr<_Eina_Value> createEinaValue(bool);
295 template <typename T> void fromTestChangeProperty(std::string path, const std::string &interface, const std::string &name, T new_value) {
296 auto v = createEinaValue(new_value);
297 if (path.empty()) throw error{};
298 if (path[0] != '/') path = "/org/a11y/atspi/accessible/" + path;
299 auto it = propertyChangeListeners.find(std::tuple<std::string, std::string, std::string>{ path, interface, name });
300 if (it == propertyChangeListeners.end()) throw error{};
303 template <typename ... ARGS1, typename ... ARGS2> std::tuple<ARGS1...> fromTestCall(const std::string &path, const std::string &interface, const std::string &name, const std::tuple<ARGS2...> &args) {
304 auto msg = newMessage(path, interface, name, false);
306 auto res = call(daliMethods, "daliMethods", msg, MethodType::Method);
308 if (eldbus_message_error_get_impl(res, a, b)) throw error{} << "call to " << path << " " << interface << " " << name << " failed: " << a << ": " << b;
309 std::tuple<ARGS1...> tmp;
313 template <typename T> T fromTestGet(const std::string &path, const std::string &interface, const std::string &name) {
314 auto msg = newMessage(path, interface, name, false);
315 auto res = call(daliMethods, "daliMethods", msg, MethodType::Getter);
317 if (eldbus_message_error_get_impl(res, a, b)) throw error{} << "call to " << path << " " << interface << " " << name << " failed: " << a << ": " << b;
320 return std::move(std::get<0>(tmp));
322 template <typename ... ARGS1, typename T> std::tuple<ARGS1...> fromTestSet(const std::string &path, const std::string &interface, const std::string &name, const T &arg) {
323 auto msg = newMessage(path, interface, name, false);
324 Encode(msg, TestDBusWrapper::Variant<T>{ arg });
325 auto res = call(daliMethods, "daliMethods", msg, MethodType::Setter);
327 if (eldbus_message_error_get_impl(res, a, b)) throw error{} << "call to " << path << " " << interface << " " << name << " failed: " << a << ": " << b;
328 std::tuple<ARGS1...> tmp;
336 class error : public std::exception {
337 std::shared_ptr<std::ostringstream> temp = std::make_shared<std::ostringstream>();
338 mutable std::string text;
342 template <typename T> error &operator << (T &&t) {
343 *temp << std::forward<T>(t);
346 const char *what() const noexcept override {
351 #define DEFINE_TYPE(name) struct name ## Impl; static name ## Impl *get(const name ## Ptr &);
352 DEFINE_TYPE(Connection)
356 DEFINE_TYPE(MessageIter)
360 using ElementList = std::list<Element>;
361 using ElementMap = std::map<std::string, std::string>;
362 using ElementTuple = std::tuple<
363 uint8_t, uint16_t, uint32_t, uint64_t, int16_t, int32_t, int64_t, double, bool, std::string, ObjectPath,
369 char signature_ = 0, end_ = 0, index_ = 0;
370 template <typename T> void set(T &&t, char signature = detail::DBusSig<T>::value) {
371 signature_ = signature;
372 end_ = detail::DBusSig<T>::end;
373 index_ = static_cast<char>(detail::IndexFromTypeTuple<ElementTuple, T>::value);
374 get<T>() = std::forward<T>(t);
377 template <typename T> Element(T &&t, typename std::enable_if<detail::DBusSig<T>::value != 0>::type* = nullptr) { set(std::forward<T>(t)); }
378 Element(ElementList t, int signature) { set(std::move(t), static_cast<char>(signature)); }
380 char signature() const { return signature_; }
381 char end() const { return end_; }
382 char index() const { return index_; }
383 bool isContainer() const { return index_ == detail::IndexFromTypeTuple<ElementTuple, ElementList>::value; }
384 template <typename T, typename = typename std::enable_if<detail::DBusSig<T>::value != 0>::type>
385 bool is() const { return index_ == detail::IndexFromTypeTuple<ElementTuple, T>::value; }
386 template <typename T, typename = typename std::enable_if<detail::DBusSig<T>::value != 0>::type>
387 const T &get() const { if (!is<T>()) throw error{}; return std::get<detail::IndexFromTypeTuple<ElementTuple, T>::value>(data); }
388 template <typename T, typename = typename std::enable_if<detail::DBusSig<T>::value != 0>::type>
389 T &get() { if (!is<T>()) throw error{}; return std::get<detail::IndexFromTypeTuple<ElementTuple, T>::value>(data); }
392 ConnectionPtr eldbus_address_connection_get_impl(const std::string &addr) override;
394 #define eldbus_message_iter_arguments_append_impl_basic_impl(type_set, type_get, sig) \
395 void eldbus_message_iter_arguments_append_impl(const MessageIterPtr &it, type_set src) override; \
396 bool eldbus_message_iter_get_and_next_impl(const MessageIterPtr &it, type_get &dst) override;
397 #define eldbus_message_iter_arguments_append_impl_basic(type, sig) \
398 eldbus_message_iter_arguments_append_impl_basic_impl(type, type, sig)
400 eldbus_message_iter_arguments_append_impl_basic(uint8_t, y)
401 eldbus_message_iter_arguments_append_impl_basic(uint16_t, q)
402 eldbus_message_iter_arguments_append_impl_basic(uint32_t, u)
403 eldbus_message_iter_arguments_append_impl_basic(uint64_t, t)
404 eldbus_message_iter_arguments_append_impl_basic(int16_t, n)
405 eldbus_message_iter_arguments_append_impl_basic(int32_t, i)
406 eldbus_message_iter_arguments_append_impl_basic(int64_t, x)
407 eldbus_message_iter_arguments_append_impl_basic(double, d)
408 eldbus_message_iter_arguments_append_impl_basic(bool, b)
409 eldbus_message_iter_arguments_append_impl_basic_impl(const std::string &, std::string, s)
410 eldbus_message_iter_arguments_append_impl_basic_impl(const ObjectPath &, ObjectPath, o)
412 #undef eldbus_message_iter_arguments_append_impl_basic
413 #undef eldbus_message_iter_arguments_append_impl_basic_impl
415 MessageIterPtr eldbus_message_iter_container_new_impl(const MessageIterPtr &it, int type, const std::string &sig) override;
416 MessageIterPtr eldbus_message_iter_get_and_next_by_type_impl(const MessageIterPtr &it, int type) override;
417 MessageIterPtr eldbus_message_iter_get_impl(const MessagePtr &it, bool write) override;
418 MessagePtr eldbus_proxy_method_call_new_impl(const ProxyPtr &proxy, const std::string &funcName) override;
419 MessagePtr eldbus_proxy_send_and_block_impl(const ProxyPtr &proxy, const MessagePtr &msg) override;
420 bool eldbus_message_error_get_impl(const MessagePtr &msg, std::string &name, std::string &text) override;
421 std::string eldbus_message_signature_get_impl(const MessagePtr &msg) override;
422 PendingPtr eldbus_proxy_send_impl(const ProxyPtr &proxy, const MessagePtr &msg, const SendCallback &callback) override;
423 std::string eldbus_proxy_interface_get_impl(const ProxyPtr &) override;
424 void eldbus_proxy_signal_handler_add_impl(const ProxyPtr &proxy, const std::string &member, const std::function<void(const MessagePtr &)> &cb) override;
425 std::string eldbus_message_iter_signature_get_impl(const MessageIterPtr &iter) override;
426 MessagePtr eldbus_message_method_return_new_impl( const MessagePtr &msg) override;
427 MessagePtr eldbus_message_error_new_impl( const MessagePtr &msg, const std::string &err, const std::string &txt ) override;
428 PendingPtr eldbus_connection_send_impl(const ConnectionPtr &conn, const MessagePtr &msg) override;
429 MessagePtr eldbus_message_signal_new_impl(const std::string &path, const std::string &iface, const std::string &name) override;
430 MessagePtr eldbus_message_ref_impl(const MessagePtr &msg) override;
431 ConnectionPtr eldbus_connection_get_impl(ConnectionType type) override;
432 std::string eldbus_connection_unique_name_get_impl(const ConnectionPtr &conn) override;
433 ObjectPtr eldbus_object_get_impl( const ConnectionPtr &conn, const std::string &bus, const std::string &path ) override;
434 ProxyPtr eldbus_proxy_get_impl( const ObjectPtr &obj, const std::string &interface ) override;
435 ProxyPtr eldbus_proxy_copy_impl( const ProxyPtr &ptr) override;
436 void add_property_changed_event_listener_impl( const ProxyPtr &proxy, const std::string &interface, const std::string &name, std::function< void( const _Eina_Value * ) > cb) override;
437 void add_interface_impl( bool fallback, const std::string& pathName,
438 const ConnectionPtr &connection,
439 std::vector<std::function<void()>> &destructors,
440 const std::string& interfaceName,
441 std::vector< MethodInfo >& dscrMethods,
442 std::vector< PropertyInfo >& dscrProperties,
443 std::vector< SignalInfo >& dscrSignals ) override;
444 static bool completed(const MessageIterPtr &iter);
446 MessagePtr call(std::unordered_map<std::tuple<std::string, std::string, std::string, MethodType>, std::function<MessagePtr(const MessagePtr&)>> &mp, const std::string &name, const MessagePtr &msg, MethodType type);
450 template <> struct DBusSigImpl<uint8_t> { enum { value = 'y', end = 0 }; };
451 template <> struct DBusSigImpl<uint16_t> { enum { value = 'q', end = 0 }; };
452 template <> struct DBusSigImpl<uint32_t> { enum { value = 'u', end = 0 }; };
453 template <> struct DBusSigImpl<uint64_t> { enum { value = 't', end = 0 }; };
454 template <> struct DBusSigImpl<int16_t> { enum { value = 'n', end = 0 }; };
455 template <> struct DBusSigImpl<int32_t> { enum { value = 'i', end = 0 }; };
456 template <> struct DBusSigImpl<int64_t> { enum { value = 'x', end = 0 }; };
457 template <> struct DBusSigImpl<double> { enum { value = 'd', end = 0 }; };
458 template <> struct DBusSigImpl<bool> { enum { value = 'b', end = 0 }; };
459 template <> struct DBusSigImpl<std::string> { enum { value = 's', end = 0 }; };
460 template <> struct DBusSigImpl<ObjectPath> { enum { value = 'o', end = 0 }; };
461 template <> struct DBusSigImpl<TestDBusWrapper::ElementList> { enum { value = '(', end = ')' }; };
462 template <> struct DBusSigImpl<TestDBusWrapper::ElementMap> { enum { value = '{', end = '}' }; };
464 template <typename T> struct Encoder<T, decltype(TestDBusWrapper().eldbus_message_iter_arguments_append_impl(TestDBusWrapper::MessageIterPtr(), T()))> {
465 static void encode(TestDBusWrapper &w, const TestDBusWrapper::MessageIterPtr &tgt, const T &src) {
466 w.eldbus_message_iter_arguments_append_impl(tgt, src);
468 static void decode(TestDBusWrapper &w, T &tgt, const TestDBusWrapper::MessageIterPtr &src) {
469 if (!w.eldbus_message_iter_get_and_next_impl(src, tgt)) throw TestDBusWrapper::error{};
472 template <typename T> struct Encoder<T, typename std::enable_if<std::is_enum<T>::value>::type> {
473 static void encode(TestDBusWrapper &w, const TestDBusWrapper::MessageIterPtr &tgt, const T &src) {
474 Encoder<typename std::underlying_type<T>::type>::encode(w, tgt, static_cast<typename std::underlying_type<T>::type>(src));
476 static void decode(TestDBusWrapper &w, T &tgt, const TestDBusWrapper::MessageIterPtr &src) {
477 typename std::underlying_type<T>::type v = 0;
478 Encoder<typename std::underlying_type<T>::type>::decode(w, v, src);
479 tgt = static_cast<T>(v);
482 template <typename T> struct Encoder<const T> {
483 static void encode(TestDBusWrapper &w, const TestDBusWrapper::MessageIterPtr &tgt, const T &src) {
484 Encoder<T>::encode(w, tgt, src);
486 static void decode(TestDBusWrapper &w, T &tgt, const TestDBusWrapper::MessageIterPtr &src) {
487 Encoder<T>::decode(w, tgt, src);
490 template <typename T> struct Encoder<const T &> {
491 static void encode(TestDBusWrapper &w, const TestDBusWrapper::MessageIterPtr &tgt, const T &src) {
492 Encoder<T>::encode(w, tgt, src);
494 static void decode(TestDBusWrapper &w, T &tgt, const TestDBusWrapper::MessageIterPtr &src) {
495 Encoder<T>::decode(w, tgt, src);
498 template <typename T> struct Encoder<T &> {
499 static void encode(TestDBusWrapper &w, const TestDBusWrapper::MessageIterPtr &tgt, const T &src) {
500 Encoder<T>::encode(w, tgt, src);
502 static void decode(TestDBusWrapper &w, T &tgt, const TestDBusWrapper::MessageIterPtr &src) {
503 Encoder<T>::decode(w, tgt, src);
506 template <size_t I, size_t S, typename ... ARGS> struct EncoderTuple {
507 static void encode(TestDBusWrapper &w, const TestDBusWrapper::MessageIterPtr &tgt, const std::tuple<ARGS...> &src) {
508 Encoder<typename std::tuple_element<I, std::tuple<ARGS...>>::type>::encode(w, tgt, std::get<I>(src));
509 EncoderTuple<I + 1, S, ARGS...>::encode(w, tgt, src);
511 static void decode(TestDBusWrapper &w, std::tuple<ARGS...> &tgt, const TestDBusWrapper::MessageIterPtr &src) {
512 Encoder<typename std::tuple_element<I, std::tuple<ARGS...>>::type>::decode(w, std::get<I>(tgt), src);
513 EncoderTuple<I + 1, S, ARGS...>::decode(w, tgt, src);
516 template <size_t S, typename ... ARGS> struct EncoderTuple<S, S, ARGS...> {
517 static void encode(TestDBusWrapper &w, const TestDBusWrapper::MessageIterPtr &tgt, const std::tuple<ARGS...> &src) { }
518 static void decode(TestDBusWrapper &w, std::tuple<ARGS...> &tgt, const TestDBusWrapper::MessageIterPtr &src) { }
520 template <typename ...ARGS> struct Encoder<std::tuple<ARGS...>> {
521 static void encode(TestDBusWrapper &w, const TestDBusWrapper::MessageIterPtr &tgt, const std::tuple<ARGS...> &src) {
522 auto var = w.eldbus_message_iter_container_new_impl( tgt, 'r', "");
523 EncoderTuple<0, sizeof...(ARGS), ARGS...>::encode(w, var, src);
525 static void decode(TestDBusWrapper &w, std::tuple<ARGS...> &tgt, const TestDBusWrapper::MessageIterPtr &src) {
526 auto s = w.eldbus_message_iter_get_and_next_by_type_impl( src, 'r' );
527 if( !s ) throw TestDBusWrapper::error{};
528 EncoderTuple<0, sizeof...(ARGS), ARGS...>::decode(w, tgt, s);
531 template <typename A, typename B> struct Encoder<std::pair<A, B>> {
532 static void encode(TestDBusWrapper &w, const TestDBusWrapper::MessageIterPtr &tgt, const std::pair<A, B> &src, char type = 'r') {
533 auto var = w.eldbus_message_iter_container_new_impl( tgt, type, "");
534 Encoder<A>::encode(w, var, src.first);
535 Encoder<B>::encode(w, var, src.second);
537 static void decode(TestDBusWrapper &w, std::pair<A, B> &tgt, const TestDBusWrapper::MessageIterPtr &src, char type = 'r') {
538 auto s = w.eldbus_message_iter_get_and_next_by_type_impl( src, type );
539 if( !s ) throw TestDBusWrapper::error{};
540 Encoder<A>::decode(w, tgt.first, s);
541 Encoder<B>::decode(w, tgt.second, s);
544 template <typename T> struct Encoder<TestDBusWrapper::Variant<T>> {
545 static void encode(TestDBusWrapper &w, const TestDBusWrapper::MessageIterPtr &tgt, const TestDBusWrapper::Variant<T> &src) {
546 //w.eldbus_message_iter_arguments_append_impl(tgt, src);
547 auto var = w.eldbus_message_iter_container_new_impl( tgt, 'v', "");
548 Encoder<T>::encode(w, var, src.value);
550 static void decode(TestDBusWrapper &w, TestDBusWrapper::Variant<T> &tgt, const TestDBusWrapper::MessageIterPtr &src) {
551 auto s = w.eldbus_message_iter_get_and_next_by_type_impl( src, 'v' );
552 if( !s ) throw TestDBusWrapper::error{};
553 Encoder<T>::decode(w, tgt.value, s);
556 template <typename T> struct Encoder<std::vector<T>> {
557 static void encode(TestDBusWrapper &w, const TestDBusWrapper::MessageIterPtr &tgt, const std::vector<T> &src) {
558 auto var = w.eldbus_message_iter_container_new_impl( tgt, 'a', "");
560 Encoder<T>::encode(w, var, q);
562 static void decode(TestDBusWrapper &w, std::vector<T> &tgt, const TestDBusWrapper::MessageIterPtr &src) {
563 auto s = w.eldbus_message_iter_get_and_next_by_type_impl( src, 'a' );
564 if( !s ) throw TestDBusWrapper::error{};
565 while(!TestDBusWrapper::completed(s)) {
567 Encoder<T>::decode(w, tgt.back(), s);
571 template <typename K, typename V> struct Encoder<std::unordered_map<K,V>> {
572 static void encode(TestDBusWrapper &w, const TestDBusWrapper::MessageIterPtr &tgt, const std::unordered_map<K,V> &src) {
573 auto var = w.eldbus_message_iter_container_new_impl( tgt, 'a', "");
575 Encoder<typename std::unordered_map<K,V>::value_type>::encode(w, var, q, 'e');
578 static void decode(TestDBusWrapper &w, std::unordered_map<K,V> &tgt, const TestDBusWrapper::MessageIterPtr &src) {
579 auto s = w.eldbus_message_iter_get_and_next_by_type_impl( src, 'a' );
580 if( !s ) throw TestDBusWrapper::error{};
581 while(!TestDBusWrapper::completed(s)) {
583 Encoder<std::pair<K,V>>::decode(w, tmp, s, 'e');
584 tgt.insert(std::move(tmp));
588 template <typename T, size_t I> struct Encoder<std::array<T, I>> {
589 static void encode(TestDBusWrapper &w, const TestDBusWrapper::MessageIterPtr &tgt, const std::array<T, I> &src) {
590 auto var = w.eldbus_message_iter_container_new_impl( tgt, 'a', "");
592 Encoder<T>::encode(w, var, q);
594 static void decode(TestDBusWrapper &w, std::array<T, I> &tgt, const TestDBusWrapper::MessageIterPtr &src) {
595 auto s = w.eldbus_message_iter_get_and_next_by_type_impl( src, 'a' );
596 if( !s ) throw TestDBusWrapper::error{};
598 while(!TestDBusWrapper::completed(s)) {
599 if(i >= tgt.size()) throw TestDBusWrapper::error{};
600 Encoder<T>::decode(w, tgt[i], s);
603 if( i!=tgt.size()) throw TestDBusWrapper::error{};
606 template <> struct Encoder<Dali::Accessibility::Address> {
607 static void encode(TestDBusWrapper &w, const TestDBusWrapper::MessageIterPtr &tgt, const Dali::Accessibility::Address &src) {
608 Encoder<std::tuple<std::string, ObjectPath>>::encode(w, tgt,std::tuple<std::string, ObjectPath> {
609 src.GetBus(), ObjectPath{ "/org/a11y/atspi/accessible/" + src.GetPath() } }
612 static void decode(TestDBusWrapper &w, Dali::Accessibility::Address &tgt, const TestDBusWrapper::MessageIterPtr &src) {
613 std::tuple<std::string, ObjectPath> tmp;
614 Encoder<std::tuple<std::string, ObjectPath>>::decode(w, tmp, src);
615 static const size_t prefixSize = std::string{ "/org/a11y/atspi/accessible/" }.size();
616 tgt = { std::move(std::get<0>(tmp)), std::get<1>(tmp).value.substr(prefixSize) };
619 template <> struct Encoder<const char*> {
620 static void encode(TestDBusWrapper &w, const TestDBusWrapper::MessageIterPtr &tgt, const char *src) {
621 Encoder<std::string>::encode(w, tgt, src);
627 #define DBUS_DEBUG( ... ) \
630 DBus::debugPrint( __FILE__, __LINE__, __VA_ARGS__ ); \
633 #define DBUS_W DBusWrapper::Installed()
636 * @brief Template based, single file, wrapper library around eldbus for DBUS based communication.
638 * Main motivation was missing asynchronous calls in AT-SPI library and difficulties,
639 * when using eldbus from C++.
642 * - takes care of marshalling arguments to and from DBUS calls.
643 * - allows synchronous and asynchronous calls.
644 * - allows synchronous and asynchronous listeners on signals.
645 * - manages all involved objects' lifetimes.
646 * - errors are passed as optional-alike objects, no exceptions are used.
647 * - allows setting additional debug-print function for more details about
650 * DBUS's method signatures (and expected return values) are specified as template argument,
651 * using functor syntax. For example:
653 * auto dbus = DBusClient{ ... };
654 * auto v = dbus.method<std::tuple<int, float>(float, float, std::string)>("foo").call(1.0f, 2.0f, "qwe");
656 * means (synchronous) call on dbus object, which takes three arguments (thus making call signature \b dds)
657 * of types float, float and string (float will be automatically converted to double).
658 * Expected return value is std::tuple<int, float>, which gives signature <B>(id)</B> - std::tuple acts
659 * as struct container. Returned value v will be of type ValueOrError<std::tuple<int, float>>.\n
660 * Slightly different (asynchronous) example:
662 * auto dbus = DBusClient{ ... };
663 * std::function<void(ValueOrError<int, float>)> callback;
664 * dbus.method<ValueOrError<int, float>(float, float, std::string)>("foo").asyncCall(callback, 1.0f, 2.0f, "qwe");
666 * Now the call takes the same arguments and has the same signature. But expected values are different -
667 * now the signature is simply \b id. ValueOrError acts in this case as placeholder for list of values,
668 * which DBUS allows as return data. The call itself is asynchronous - instead of expecting reply
669 * you need to pass a callback, which will be called either with received data and error message.
671 * Library is not thread-safe, the same object shouldn't be called from different threads without
672 * synchronization. There's no guarantee, that callbacks will be executed on the same thread.
679 class DBusInterfaceDescription;
682 * @brief Formats debug message and calls debug printer (if any) with it
684 void debugPrint( const char* file, size_t line, const char* format, ... );
687 * @brief Sets debug printer callback, which will be called with debug messages
689 * Callback will be called in various moments of DBus activity. First value passed to callback
690 * is pointer to text, second it's length. Text is ended with 0 (not counted towards it's size),
691 * user can safely printf it.
693 void setDebugPrinter( std::function< void( const char*, size_t ) > );
700 Error( std::string msg ) : message( std::move( msg ) )
702 bart_assert( !message.empty() );
712 * @brief Value representing data, that came from DBUS or error message
714 * Object of this class either helds series of values (of types ARGS...)
715 * or error message. This object will be true in boolean context, if has data
716 * and false, if an error occured.
717 * It's valid to create ValueOrError object with empty argument list or void:
720 * ValueOrError<void> v2;
722 * Both mean the same - ValueOrError containing no real data and being a marker,
723 * wherever operation successed or failed and containing possible error message.
725 template < typename... ARGS >
730 * @brief Empty constructor. Valid only, if all ARGS types are default constructible.
732 ValueOrError() = default;
735 * @brief Value constructor.
737 * This will be initialized as success with passed in values.
739 ValueOrError( ARGS... t ) : value( std::move( t )... ) {}
742 * @brief Alternative Value constructor.
744 * This will be initialized as success with passed in values.
746 ValueOrError( std::tuple< ARGS... > t ) : value( std::move( t ) ) {}
749 * @brief Error constructor. This will be initialized as failure with given error message.
751 ValueOrError( Error e ) : error( std::move( e ) )
753 bart_assert( !error.message.empty() );
757 * @brief bool operator.
759 * Returns true, if operation was successful (getValues member is callable), or false
760 * when operation failed (getError is callable).
762 explicit operator bool() const
764 return error.message.empty();
768 * @brief Returns error message object.
770 * Returns object containing error message associated with the failed operation.
771 * Only callable, if operation actually failed, otherwise will bart_assert.
773 const Error& getError() const
779 * @brief Returns modifiable tuple of held data.
781 * Returns reference to the internal tuple containing held data.
782 * User can modify (or move) data safely.
783 * Only callable, if operation actually successed, otherwise will bart_assert.
785 std::tuple< ARGS... >& getValues()
787 bart_assert( *this );
792 * @brief Returns const tuple of held data.
794 * Returns const reference to the internal tuple containing held data.
795 * Only callable, if operation actually successed, otherwise will bart_assert.
797 const std::tuple< ARGS... >& getValues() const
799 bart_assert( *this );
805 std::tuple< ARGS... > value;
815 ValueOrError() = default;
816 ValueOrError( std::tuple<> t ) {}
817 ValueOrError( Error e ) : error( std::move( e ) )
819 bart_assert( !error.message.empty() );
822 explicit operator bool() const
824 return error.message.empty();
826 const Error& getError() const
830 std::tuple<>& getValues()
832 bart_assert( *this );
833 static std::tuple<> t;
836 std::tuple<> getValues() const
838 bart_assert( *this );
847 class ValueOrError< void >
850 ValueOrError() = default;
851 ValueOrError( Success ) {}
852 ValueOrError( Error e ) : error( std::move( e ) )
854 bart_assert( !error.message.empty() );
857 explicit operator bool() const
859 return error.message.empty();
861 const Error& getError() const
865 std::tuple<>& getValues()
867 bart_assert( *this );
868 static std::tuple<> t;
871 std::tuple<> getValues() const
873 bart_assert( *this );
881 using ObjectPath = ObjectPath;
886 * @brief Class used to marshall DBUS's variant type
888 * Minimalistic class, that allows user to specify DBUS variant type
889 * as argument or return value. You need to pass real type hidden under variant as
890 * template type \b A. At this point library doesn't allow to expected one of few classes
891 * as return data in variant. So for example user can't specify method call, which on return
892 * expects DBUS variant holding either string or int.
894 template < typename A >
901 * @brief Namespace for private, internal functions and classes
906 template < typename T, typename = void >
908 template < typename... ARGS >
909 struct signature< std::tuple< ARGS... > >;
910 template < typename A, typename B >
911 struct signature< std::pair< A, B > >;
912 template < typename A >
913 struct signature< std::vector< A > >;
914 template < typename A, size_t N >
915 struct signature< std::array< A, N > >;
916 template < typename A, typename B >
917 struct signature< std::unordered_map< A, B > >;
918 template < typename A, typename B >
919 struct signature< std::map< A, B > >;
923 * @brief Signature class for marshalling uint8 type.
926 struct signature< uint8_t >
929 * @brief Returns name of type marshalled, for informative purposes
931 static std::string name()
937 * @brief Returns DBUS' signature of type marshalled
939 static std::string sig()
945 * @brief Marshals value v as marshalled type into message
947 static void set( const DBusWrapper::MessageIterPtr &iter, uint8_t v )
949 DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
953 * @brief Marshals value from marshalled type into variable v
955 static bool get( const DBusWrapper::MessageIterPtr &iter, uint8_t& v )
957 return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
962 * @brief Signature class for marshalling uint16 type.
965 struct signature< uint16_t >
968 * @brief Returns name of type marshalled, for informative purposes
970 static std::string name()
976 * @brief Returns DBUS' signature of type marshalled
978 static std::string sig()
984 * @brief Marshals value v as marshalled type into message
986 static void set( const DBusWrapper::MessageIterPtr &iter, uint16_t v )
988 DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
992 * @brief Marshals value from marshalled type into variable v
994 static bool get( const DBusWrapper::MessageIterPtr &iter, uint16_t& v )
996 return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
1001 * @brief Signature class for marshalling uint32 type.
1004 struct signature< uint32_t >
1007 * @brief Returns name of type marshalled, for informative purposes
1009 static std::string name()
1015 * @brief Returns DBUS' signature of type marshalled
1017 static std::string sig()
1023 * @brief Marshals value v as marshalled type into message
1025 static void set( const DBusWrapper::MessageIterPtr &iter, uint32_t v )
1027 DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
1031 * @brief Marshals value from marshalled type into variable v
1033 static bool get( const DBusWrapper::MessageIterPtr &iter, uint32_t& v )
1035 return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
1040 * @brief Signature class for marshalling uint64 type.
1043 struct signature< uint64_t >
1046 * @brief Returns name of type marshalled, for informative purposes
1048 static std::string name()
1054 * @brief Returns DBUS' signature of type marshalled
1056 static std::string sig()
1062 * @brief Marshals value v as marshalled type into message
1064 static void set( const DBusWrapper::MessageIterPtr &iter, uint64_t v )
1066 DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
1070 * @brief Marshals value from marshalled type into variable v
1072 static bool get( const DBusWrapper::MessageIterPtr &iter, uint64_t& v )
1074 return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
1079 * @brief Signature class for marshalling int16 type.
1082 struct signature< int16_t >
1085 * @brief Returns name of type marshalled, for informative purposes
1087 static std::string name()
1093 * @brief Returns DBUS' signature of type marshalled
1095 static std::string sig()
1101 * @brief Marshals value v as marshalled type into message
1103 static void set( const DBusWrapper::MessageIterPtr &iter, int16_t v )
1105 DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
1109 * @brief Marshals value from marshalled type into variable v
1111 static bool get( const DBusWrapper::MessageIterPtr &iter, int16_t& v )
1113 return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
1118 * @brief Signature class for marshalling int32 type.
1121 struct signature< int32_t >
1124 * @brief Returns name of type marshalled, for informative purposes
1126 static std::string name()
1132 * @brief Returns DBUS' signature of type marshalled
1134 static std::string sig()
1140 * @brief Marshals value v as marshalled type into message
1142 static void set( const DBusWrapper::MessageIterPtr &iter, int32_t v )
1144 DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
1148 * @brief Marshals value from marshalled type into variable v
1150 static bool get( const DBusWrapper::MessageIterPtr &iter, int32_t& v )
1152 return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
1157 * @brief Signature class for marshalling int64 type.
1160 struct signature< int64_t >
1163 * @brief Returns name of type marshalled, for informative purposes
1165 static std::string name()
1171 * @brief Returns DBUS' signature of type marshalled
1173 static std::string sig()
1179 * @brief Marshals value v as marshalled type into message
1181 static void set( const DBusWrapper::MessageIterPtr &iter, int64_t v )
1183 DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
1187 * @brief Marshals value from marshalled type into variable v
1189 static bool get( const DBusWrapper::MessageIterPtr &iter, int64_t& v )
1191 return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
1196 * @brief Signature class for marshalling double type.
1199 struct signature< double >
1202 * @brief Returns name of type marshalled, for informative purposes
1204 static std::string name()
1210 * @brief Returns DBUS' signature of type marshalled
1212 static std::string sig()
1218 * @brief Marshals value v as marshalled type into message
1220 static void set( const DBusWrapper::MessageIterPtr &iter, double v )
1222 DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
1226 * @brief Marshals value from marshalled type into variable v
1228 static bool get( const DBusWrapper::MessageIterPtr &iter, double& v )
1230 return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
1234 * @brief Marshals value from marshalled type into variable v
1236 static bool get( const DBusWrapper::MessageIterPtr &iter, float& v2 )
1239 auto r = DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
1240 v2 = static_cast< float >( v );
1246 * @brief Signature class for marshalling float type.
1249 struct signature< float >
1252 * @brief Returns name of type marshalled, for informative purposes
1254 static std::string name()
1260 * @brief Returns DBUS' signature of type marshalled
1262 static std::string sig()
1268 * @brief Marshals value v as marshalled type into message
1270 static void set( const DBusWrapper::MessageIterPtr &iter, float v )
1272 DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
1276 * @brief Marshals value from marshalled type into variable v
1278 static bool get( const DBusWrapper::MessageIterPtr &iter, double& v )
1280 return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
1284 * @brief Marshals value from marshalled type into variable v
1286 static bool get( const DBusWrapper::MessageIterPtr &iter, float& v2 )
1289 auto r = DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
1290 v2 = static_cast< float >( v );
1296 * @brief Signature class for marshalling boolean type.
1299 struct signature< bool >
1302 * @brief Returns name of type marshalled, for informative purposes
1304 static std::string name()
1310 * @brief Returns DBUS' signature of type marshalled
1312 static std::string sig()
1318 * @brief Marshals value v as marshalled type into message
1320 static void set( const DBusWrapper::MessageIterPtr &iter, bool v )
1322 DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
1326 * @brief Marshals value from marshalled type into variable v
1328 static bool get( const DBusWrapper::MessageIterPtr &iter, bool& v )
1330 return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
1334 template < typename T >
1335 struct signature< T, typename std::enable_if< std::is_enum< T >::value, void >::type >
1338 * @brief Returns name of type marshalled, for informative purposes
1340 static std::string name()
1346 * @brief Returns DBUS' signature of type marshalled
1348 static std::string sig()
1350 return signature<typename std::underlying_type<T>::type>::sig();
1354 * @brief Marshals value v as marshalled type into message
1356 static void set( const DBusWrapper::MessageIterPtr &iter, T v )
1358 signature<typename std::underlying_type<T>::type>::set(iter, static_cast< int64_t >( v ));
1362 * @brief Marshals value from marshalled type into variable v
1364 static bool get( const DBusWrapper::MessageIterPtr &iter, T& v )
1366 typename std::underlying_type<T>::type q = 0;
1367 if (!signature<typename std::underlying_type<T>::type>::get(iter, q))
1370 v = static_cast< T >( q );
1376 * @brief Signature class for marshalling string type.
1378 * Both (const) char * and std::string types are accepted as value to send.
1379 * Only std::string is accepted as value to receive.
1382 struct signature< std::string >
1385 * @brief Returns name of type marshalled, for informative purposes
1387 static std::string name()
1393 * @brief Returns DBUS' signature of type marshalled
1395 static std::string sig()
1401 * @brief Marshals value v as marshalled type into message
1403 static void set( const DBusWrapper::MessageIterPtr &iter, const std::string& v )
1405 DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
1409 // * @brief Marshals value v as marshalled type into message
1411 // static void set( const DBusWrapper::MessageIterPtr &iter, const char* v )
1413 // DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
1417 * @brief Marshals value from marshalled type into variable v
1419 static bool get( const DBusWrapper::MessageIterPtr &iter, std::string& v )
1421 return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
1426 struct signature< ObjectPath >
1429 * @brief Returns name of type marshalled, for informative purposes
1431 static std::string name()
1437 * @brief Returns DBUS' signature of type marshalled
1439 static std::string sig()
1445 * @brief Marshals value v as marshalled type into message
1447 static void set( const DBusWrapper::MessageIterPtr &iter, const std::string& v )
1449 DBUS_W->eldbus_message_iter_arguments_append_impl(iter, ObjectPath{ v });
1453 * @brief Marshals value v as marshalled type into message
1455 static void set( const DBusWrapper::MessageIterPtr &iter, const ObjectPath& v )
1457 DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
1461 * @brief Marshals value v as marshalled type into message
1463 static void set( const DBusWrapper::MessageIterPtr &iter, const char* v )
1465 DBUS_W->eldbus_message_iter_arguments_append_impl(iter, ObjectPath{ v });
1469 * @brief Marshals value from marshalled type into variable v
1471 static bool get( const DBusWrapper::MessageIterPtr &iter, ObjectPath& v )
1473 return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
1477 * @brief Marshals value from marshalled type into variable v
1479 static bool get( const DBusWrapper::MessageIterPtr &iter, std::string& v )
1482 if (!DBUS_W->eldbus_message_iter_get_and_next_impl(iter, q)) return false;
1483 v = std::move(q.value);
1489 * @brief Signature class for marshalling (const) char * type.
1491 * Both (const) char * and std::string types are accepted as value to send.
1492 * You can't use (const) char * variable type to receive value.
1495 struct signature< char* >
1498 * @brief Returns name of type marshalled, for informative purposes
1500 static std::string name()
1506 * @brief Returns DBUS' signature of type marshalled
1508 static std::string sig()
1514 * @brief Marshals value v as marshalled type into message
1516 static void set( const DBusWrapper::MessageIterPtr &iter, const std::string& v )
1518 DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
1522 * @brief Marshals value v as marshalled type into message
1524 static void set( const DBusWrapper::MessageIterPtr &iter, const char* v )
1526 DBUS_W->eldbus_message_iter_arguments_append_impl(iter, std::string{ v });
1531 template < size_t INDEX, typename A, typename... ARGS >
1532 struct signature_tuple_element_type_helper
1534 using type = typename signature_tuple_element_type_helper< INDEX - 1, ARGS... >::type;
1537 template < typename A, typename... ARGS >
1538 struct signature_tuple_element_type_helper< 0, A, ARGS... >
1545 * @brief Helper class to marshall tuples
1547 * This class marshals all elements of the tuple value starting at the index INDEX
1548 * and incrementing. This class recursively calls itself with increasing INDEX value
1549 * until INDEX is equal to SIZE, where recursive calling ends.
1551 template < size_t INDEX, size_t SIZE, typename... ARGS >
1552 struct signature_tuple_helper
1554 using current_type = typename signature_tuple_element_type_helper< INDEX, ARGS... >::type;
1557 * @brief Returns name of type marshalled, for informative purposes
1559 static std::string name()
1561 if( INDEX + 1 >= SIZE )
1562 return signature< current_type >::name();
1563 return signature< current_type >::name() + ", " + signature_tuple_helper< INDEX + 1, SIZE, ARGS... >::name();
1567 * @brief Returns DBUS' signature of type marshalled
1569 static std::string sig()
1571 return signature< current_type >::sig() + signature_tuple_helper< INDEX + 1, SIZE, ARGS... >::sig();
1575 * @brief Marshals value v as marshalled type into message
1577 static void set( const DBusWrapper::MessageIterPtr &iter, const std::tuple< ARGS... >& args )
1579 signature< current_type >::set( iter, std::get< INDEX >( args ) );
1580 signature_tuple_helper< INDEX + 1, SIZE, ARGS... >::set( iter, args );
1584 * @brief Marshals value from marshalled type into variable v
1586 static bool get( const DBusWrapper::MessageIterPtr &iter, std::tuple< ARGS... >& args )
1588 return signature< current_type >::get( iter, std::get< INDEX >( args ) ) &&
1589 signature_tuple_helper< INDEX + 1, SIZE, ARGS... >::get( iter, args );
1594 * @brief Helper class to marshall tuples
1596 * This class marks end of the tuple marshalling. Members of this class are called
1597 * when INDEX value is equal to SIZE.
1599 template < size_t SIZE, typename... ARGS >
1600 struct signature_tuple_helper< SIZE, SIZE, ARGS... >
1603 * @brief Returns name of type marshalled, for informative purposes
1605 static std::string name()
1611 * @brief Returns DBUS' signature of type marshalled
1613 static std::string sig()
1619 * @brief Marshals value v as marshalled type into message
1621 static void set( const DBusWrapper::MessageIterPtr &iter, const std::tuple< ARGS... >& args )
1626 * @brief Marshals value from marshalled type into variable v
1628 static bool get( const DBusWrapper::MessageIterPtr &iter, std::tuple< ARGS... >& args )
1635 * @brief Signature class for marshalling tuple of values
1637 * This class marshalls tuple of values. This represents
1638 * DBUS struct typle, encoded with character 'r'
1640 template < typename... ARGS >
1641 struct signature< std::tuple< ARGS... > >
1644 * @brief Returns name of type marshalled, for informative purposes
1646 static std::string name()
1648 return "tuple<" + signature_tuple_helper< 0, sizeof...( ARGS ), ARGS... >::name() + ">";
1652 * @brief Returns DBUS' signature of type marshalled
1654 static std::string sig()
1656 return "(" + signature_tuple_helper< 0, sizeof...( ARGS ), ARGS... >::sig() + ")";
1660 * @brief Marshals value v as marshalled type into message
1662 static void set( const DBusWrapper::MessageIterPtr &iter, const std::tuple< ARGS... >& args )
1664 auto entry = DBUS_W->eldbus_message_iter_container_new_impl( iter, 'r', "");
1665 signature_tuple_helper< 0, sizeof...( ARGS ), ARGS... >::set( entry, args );
1669 * @brief Marshals value from marshalled type into variable v
1671 static bool get( const DBusWrapper::MessageIterPtr &iter, std::tuple< ARGS... >& args )
1673 auto entry = DBUS_W->eldbus_message_iter_get_and_next_by_type_impl( iter, 'r' );
1674 if (!entry) return false;
1675 return signature_tuple_helper< 0, sizeof...( ARGS ), ARGS... >::get( entry, args );
1680 * @brief Signature class for marshalling ValueOrError template type
1682 * ValueOrError template type is used to marshall list of values passed to
1683 * DBUS (or received from) at the "top" level. For example ss(s) is represented as
1684 * \code{.cpp} ValueOrError<std::string, std::string, std::tuple<std::string>> \endcode
1685 * While (ss(s)) is represented as
1686 * \code{.cpp} std::tuple<std::string, std::string, std::tuple<std::string>> \endcode
1688 * \code{.cpp} ValueOrError<std::tuple<std::string, std::string, std::tuple<std::string>>> \endcode
1690 template < typename... ARGS >
1691 struct signature< ValueOrError< ARGS... > >
1694 * @brief Returns name of type marshalled, for informative purposes
1696 static std::string name()
1698 return "ValueOrError<" + signature_tuple_helper< 0, sizeof...( ARGS ), ARGS... >::name() + ">";
1702 * @brief Returns DBUS' signature of type marshalled
1704 static std::string sig()
1706 return signature_tuple_helper< 0, sizeof...( ARGS ), ARGS... >::sig();
1710 * @brief Marshals value v as marshalled type into message
1712 static void set( const DBusWrapper::MessageIterPtr &iter, const ValueOrError< ARGS... >& args )
1714 signature_tuple_helper< 0, sizeof...( ARGS ), ARGS... >::set( iter, args.getValues() );
1718 * @brief Marshals value from marshalled type into variable v
1720 static bool get( const DBusWrapper::MessageIterPtr &iter, ValueOrError< ARGS... >& args )
1722 return signature_tuple_helper< 0, sizeof...( ARGS ), ARGS... >::get( iter, args.getValues() );
1727 * @brief Signature class for marshalling ValueOrError<void> type
1730 struct signature< ValueOrError< void > >
1733 * @brief Returns name of type marshalled, for informative purposes
1735 static std::string name()
1737 return "ValueOrError<void>";
1741 * @brief Returns DBUS' signature of type marshalled
1743 static std::string sig()
1749 * @brief Marshals value v as marshalled type into message
1751 static void set( const DBusWrapper::MessageIterPtr &iter, const ValueOrError< void >& args )
1756 * @brief Marshals value from marshalled type into variable v
1758 static bool get( const DBusWrapper::MessageIterPtr &iter, ValueOrError< void >& args )
1765 * @brief Signature class for marshalling ValueOrError<> type
1768 struct signature< ValueOrError<> >
1771 * @brief Returns name of type marshalled, for informative purposes
1773 static std::string name()
1775 return "ValueOrError<>";
1779 * @brief Returns DBUS' signature of type marshalled
1781 static std::string sig()
1787 * @brief Marshals value v as marshalled type into message
1789 static void set( const DBusWrapper::MessageIterPtr &iter, const ValueOrError<>& args )
1794 * @brief Marshals value from marshalled type into variable v
1796 static bool get( const DBusWrapper::MessageIterPtr &iter, ValueOrError<>& args )
1803 * @brief Signature class for marshalling pair of types
1805 template < typename A, typename B >
1806 struct signature< std::pair< A, B > >
1809 * @brief Returns name of type marshalled, for informative purposes
1811 static std::string name()
1813 return "pair<" + signature_tuple_helper< 0, 2, A, B >::name() + ">";
1817 * @brief Returns DBUS' signature of type marshalled
1819 static std::string sig()
1821 return "(" + signature_tuple_helper< 0, 2, A, B >::sig() + ")";
1825 * @brief Marshals value v as marshalled type into message
1827 static void set( const DBusWrapper::MessageIterPtr &iter, const std::pair< A, B >& ab, bool dictionary = false )
1829 auto entry = DBUS_W->eldbus_message_iter_container_new_impl( iter, dictionary ? 'e' : 'r', "");
1830 signature_tuple_helper< 0, 2, A, B >::set( entry, ab );
1834 * @brief Marshals value from marshalled type into variable v
1836 static bool get( const DBusWrapper::MessageIterPtr &iter, std::pair< A, B >& ab )
1838 auto entry = DBUS_W->eldbus_message_iter_get_and_next_by_type_impl( iter, 'r' );
1840 entry = DBUS_W->eldbus_message_iter_get_and_next_by_type_impl( iter, '{' );
1841 if (!entry) return false;
1844 std::tuple< A, B > ab_tmp;
1845 auto z = signature_tuple_helper< 0, 2, A, B >::get( entry, ab_tmp );
1848 ab.first = std::move( std::get< 0 >( ab_tmp ) );
1849 ab.second = std::move( std::get< 1 >( ab_tmp ) );
1856 * @brief Signature class for marshalling std::vector template type
1858 * This marshals container's content as DBUS a ascii character type code.
1860 template < typename A >
1861 struct signature< std::vector< A > >
1864 * @brief Returns name of type marshalled, for informative purposes
1866 static std::string name()
1868 return "vector<" + signature< A >::name() + ">";
1872 * @brief Returns DBUS' signature of type marshalled
1874 static std::string sig()
1876 return "a" + signature< A >::sig();
1880 * @brief Marshals value v as marshalled type into message
1882 static void set( const DBusWrapper::MessageIterPtr &iter, const std::vector< A >& v )
1884 auto lst = DBUS_W->eldbus_message_iter_container_new_impl( iter, 'a', signature< A >::sig());
1888 signature< A >::set( lst, a );
1893 * @brief Marshals value from marshalled type into variable v
1895 static bool get( const DBusWrapper::MessageIterPtr &iter, std::vector< A >& v )
1897 auto s = DBUS_W->eldbus_message_iter_get_and_next_by_type_impl( iter, 'a' );
1898 if (!s) return false;
1901 while( signature< A >::get( s, a ) )
1902 v.push_back( std::move( a ) );
1909 * @brief Signature class for marshalling std::array template type
1911 * This marshals container's content as DBUS a ascii character type code.
1913 template < typename A, size_t N >
1914 struct signature< std::array< A, N > >
1917 * @brief Returns name of type marshalled, for informative purposes
1919 static std::string name()
1921 return "array<" + signature< A >::name() + ", " + std::to_string( N ) + ">";
1925 * @brief Returns DBUS' signature of type marshalled
1927 static std::string sig()
1929 return "a" + signature< A >::sig();
1933 * @brief Marshals value v as marshalled type into message
1935 static void set( const DBusWrapper::MessageIterPtr &iter, const std::array< A, N >& v )
1937 auto lst = DBUS_W->eldbus_message_iter_container_new_impl( iter, 'a', signature< A >::sig());
1941 signature< A >::set( lst, a );
1946 * @brief Marshals value from marshalled type into variable v
1948 static bool get( const DBusWrapper::MessageIterPtr &iter, std::array< A, N >& v )
1950 auto s = DBUS_W->eldbus_message_iter_get_and_next_by_type_impl( iter, 'a' );
1955 if( !signature< A >::get( s, a ) )
1963 * @brief Signature class for marshalling EldbusVariant type
1965 * This marshals variant's content as DBUS v ascii character type code.
1967 template < typename A >
1968 struct signature< EldbusVariant< A > >
1971 * @brief Returns name of type marshalled, for informative purposes
1973 static std::string name()
1975 return "variant<" + signature< A >::name() + ">";
1979 * @brief Returns DBUS' signature of type marshalled
1981 static std::string sig()
1987 * @brief Marshals value v as marshalled type into message
1989 static void set( const DBusWrapper::MessageIterPtr &iter, const EldbusVariant< A >& v )
1991 set( iter, v.value );
1995 * @brief Marshals value v as marshalled type into message
1997 static void set( const DBusWrapper::MessageIterPtr &iter, const A& v )
1999 auto var = DBUS_W->eldbus_message_iter_container_new_impl( iter, 'v', signature< A >::sig());
2000 signature< A >::set( var, v );
2004 * @brief Marshals value from marshalled type into variable v
2006 static bool get( const DBusWrapper::MessageIterPtr &iter, EldbusVariant< A >& v )
2008 auto s = DBUS_W->eldbus_message_iter_get_and_next_by_type_impl( iter, 'v' );
2011 return signature< A >::get( s, v.value );
2016 * @brief Signature class for marshalling std::unordered_map template type
2018 * This marshals container's content as DBUS {} ascii character type code.
2019 * Note, that library doesnt check, if the key is basic type, as DBUS
2020 * specification mandates.
2021 * User can always exchange std::unordered_map for std::map and the reverse.
2022 * User can receive such values as std::vector of std::pair<key, value> values.
2023 * Order of such values is unspecified.
2025 template < typename A, typename B >
2026 struct signature< std::unordered_map< A, B > >
2029 * @brief Returns name of type marshalled, for informative purposes
2031 static std::string name()
2033 return "unordered_map<" + signature< A >::name() + ", " + signature< B >::name() + ">";
2037 * @brief Returns DBUS' signature of type marshalled
2039 static std::string sig()
2041 return "a{" + signature_tuple_helper< 0, 2, A, B >::sig() + "}";
2045 * @brief Marshals value v as marshalled type into message
2047 static void set( const DBusWrapper::MessageIterPtr &iter, const std::unordered_map< A, B >& v )
2049 auto sig = "{" + signature_tuple_helper< 0, 2, A, B >::sig() + "}";
2050 auto lst = DBUS_W->eldbus_message_iter_container_new_impl( iter, 'a', sig);
2054 signature< std::pair< A, B > >::set( lst, a, true );
2059 * @brief Marshals value from marshalled type into variable v
2061 static bool get( const DBusWrapper::MessageIterPtr &iter, std::unordered_map< A, B >& v )
2063 auto s = DBUS_W->eldbus_message_iter_get_and_next_by_type_impl( iter, 'a' );
2067 std::pair< A, B > a;
2068 while( signature< std::pair< A, B > >::get( s, a ) )
2069 v.insert( std::move( a ) );
2075 * @brief Signature class for marshalling std::unordered_map template type
2077 * This marshals container's content as DBUS {} ascii character type code.
2078 * Note, that library doesnt check, if the key is basic type, as DBUS
2079 * specification mandates.
2080 * User can always exchange std::unordered_map for std::map and the reverse.
2081 * User can receive such values as std::vector of std::pair<key, value> values.
2082 * Order of such values is unspecified.
2084 template < typename A, typename B >
2085 struct signature< std::map< A, B > >
2088 * @brief Returns name of type marshalled, for informative purposes
2090 static std::string name()
2092 return "map<" + signature< A >::name() + ", " + signature< B >::name() + ">";
2096 * @brief Returns DBUS' signature of type marshalled
2098 static std::string sig()
2100 return "a{" + signature_tuple_helper< 0, 2, A, B >::sig() + "}";
2104 * @brief Marshals value v as marshalled type into message
2106 static void set( const DBusWrapper::MessageIterPtr &iter, const std::map< A, B >& v )
2108 auto sig = "{" + signature_tuple_helper< 0, 2, A, B >::sig() + "}";
2109 auto lst = DBUS_W->eldbus_message_iter_container_new_impl( iter, 'a', sig);
2113 signature< std::pair< A, B > >::set( lst, a, true );
2118 * @brief Marshals value from marshalled type into variable v
2120 static bool get( const DBusWrapper::MessageIterPtr &iter, std::map< A, B >& v )
2122 auto s = DBUS_W->eldbus_message_iter_get_and_next_by_type_impl( iter, 'a' );
2125 std::pair< A, B > a;
2126 while( signature< std::pair< A, B > >::get( s, a ) )
2127 v.insert( std::move( a ) );
2133 * @brief Signature helper class for marshalling const reference types
2135 template < typename A >
2136 struct signature< const A& >
2139 * @brief Returns name of type marshalled, for informative purposes
2141 static std::string name()
2143 return "const " + signature< A >::name() + "&";
2147 * @brief Returns DBUS' signature of type marshalled
2149 static std::string sig()
2151 return signature< A >::sig();
2155 * @brief Marshals value v as marshalled type into message
2157 static void set( const DBusWrapper::MessageIterPtr &iter, const A& v )
2159 signature< A >::set( iter, v );
2163 * @brief Marshals value from marshalled type into variable v
2165 static void get( const DBusWrapper::MessageIterPtr &iter, A& v )
2167 signature< A >::get( iter, v );
2172 * @brief Signature helper class for marshalling reference types
2174 template < typename A >
2175 struct signature< A& >
2178 * @brief Returns name of type marshalled, for informative purposes
2180 static std::string name()
2182 return signature< A >::name() + "&";
2186 * @brief Returns DBUS' signature of type marshalled
2188 static std::string sig()
2190 return signature< A >::sig();
2194 * @brief Marshals value v as marshalled type into message
2196 static void set( const DBusWrapper::MessageIterPtr &iter, const A& v )
2198 signature< A >::set( iter, v );
2202 * @brief Marshals value from marshalled type into variable v
2204 static void get( const DBusWrapper::MessageIterPtr &iter, A& v )
2206 signature< A >::get( iter, v );
2211 * @brief Signature helper class for marshalling const types
2213 template < typename A >
2214 struct signature< const A >
2217 * @brief Returns name of type marshalled, for informative purposes
2219 static std::string name()
2221 return "const " + signature< A >::name();
2225 * @brief Returns DBUS' signature of type marshalled
2227 static std::string sig()
2229 return signature< A >::sig();
2233 * @brief Marshals value v as marshalled type into message
2235 static void set( const DBusWrapper::MessageIterPtr &iter, const A& v )
2237 signature< A >::set( iter, v );
2241 * @brief Marshals value from marshalled type into variable v
2243 static void get( const DBusWrapper::MessageIterPtr &iter, A& v )
2245 signature< A >::get( iter, v );
2250 using CallId = DBusWrapper::CallId;
2252 template < typename ValueType >
2253 ValueType unpackValues( CallId callId, const DBusWrapper::MessagePtr &msg )
2255 auto iter = DBUS_W->eldbus_message_iter_get_impl( msg, false );
2260 if( !signature< ValueType >::get( iter, r ) )
2262 DBUS_DEBUG( "ValueType is %s", signature< ValueType >::name().c_str() );
2263 r = Error{"call " + std::to_string( callId.id ) + ": failed to unpack values, got signature '" +
2264 DBUS_W->eldbus_message_signature_get_impl( msg ) + "', expected '" + signature< ValueType >::sig() + "'"};
2269 r = Error{"call " + std::to_string( callId.id ) + ": failed to get iterator"};
2274 inline void packValues_helper( const DBusWrapper::MessageIterPtr& ) {}
2276 template < typename A, typename... ARGS >
2277 void packValues_helper( const DBusWrapper::MessageIterPtr &iter, A&& a, ARGS&&... r )
2279 signature< A >::set( iter, std::forward< A >( a ) );
2280 packValues_helper( iter, std::forward< ARGS >( r )... );
2283 template < typename... ARGS >
2284 void packValues( CallId callId, const DBusWrapper::MessagePtr &msg, ARGS&&... r )
2286 auto iter = DBUS_W->eldbus_message_iter_get_impl( msg, true );
2287 packValues_helper( iter, std::forward< ARGS >( r )... );
2290 template < typename >
2292 template < typename R, typename... ARGS >
2293 struct ReturnType< R( ARGS... ) >
2298 template < typename R, typename... ARGS >
2299 struct ReturnType< std::function< R( ARGS... ) > >
2309 template < int N, int... S >
2310 struct sequence_gen : sequence_gen< N - 1, N - 1, S... >
2314 template < int... S >
2315 struct sequence_gen< 0, S... >
2317 typedef sequence< S... > type;
2320 template < typename C, typename... ARGS >
2323 const std::function< C >& c;
2324 const std::tuple< ARGS... >& args;
2326 template < int... S >
2327 auto apply_2( sequence< S... > ) const -> decltype( c( std::get< S >( args )... ) )
2329 return c( std::get< S >( args )... );
2331 auto apply_1() const -> decltype( apply_2( typename sequence_gen< sizeof...( ARGS ) >::type() ) )
2333 return apply_2( typename sequence_gen< sizeof...( ARGS ) >::type() );
2337 template < typename C, typename A, typename... ARGS >
2338 struct apply_helper_2
2340 const std::function< C >& c;
2342 const std::tuple< ARGS... >& args;
2344 template < int... S >
2345 auto apply_2( sequence< S... > ) const -> decltype( c( a, std::get< S >( args )... ) )
2347 return c( a, std::get< S >( args )... );
2349 auto apply_1() const -> decltype( apply_2( typename sequence_gen< sizeof...( ARGS ) >::type() ) )
2351 return apply_2( typename sequence_gen< sizeof...( ARGS ) >::type() );
2355 template < typename C, typename... ARGS >
2356 auto apply( const std::function< C >& c, const std::tuple< ARGS... >& args ) -> typename ReturnType< C >::type
2358 apply_helper< C, ARGS... > ah{c, args};
2359 return ah.apply_1();
2362 template < typename C, typename D, typename... ARGS >
2363 auto apply( const std::function< C >& c, const D& d, const std::tuple< ARGS... >& args ) -> typename ReturnType< C >::type
2365 apply_helper_2< C, D, ARGS... > ah{c, d, args};
2366 return ah.apply_1();
2369 struct ConnectionState
2371 DBusWrapper::ConnectionPtr connection;
2372 DBusWrapper::ObjectPtr object;
2373 DBusWrapper::ProxyPtr proxy, propertiesProxy;
2376 template < typename RETTYPE, typename... ARGS >
2377 RETTYPE call( CallId callId, const ConnectionState& connectionState, bool property, const std::string& funcName, const ARGS&... args )
2379 const auto &proxy = property ? connectionState.propertiesProxy : connectionState.proxy;
2382 DBUS_DEBUG( "call %d: not initialized", callId.id );
2383 return Error{"not initialized"};
2386 DBUS_DEBUG( "call %d: calling '%s'", callId.id, funcName.c_str() );
2387 auto msg = DBUS_W->eldbus_proxy_method_call_new_impl(proxy, funcName);
2390 DBUS_DEBUG( "call %d: failed", callId.id );
2391 return Error{"failed to create message"};
2394 detail::packValues( callId, msg, args... );
2395 auto reply = DBUS_W->eldbus_proxy_send_and_block_impl( proxy, msg );
2396 DBUS_DEBUG( "call %d: calling '%s' done", callId.id, funcName.c_str() );
2399 DBUS_DEBUG( "call %d: failed", callId.id );
2400 return Error{"eldbus returned null as reply"};
2402 std::string errname, errmsg;
2403 if( DBUS_W->eldbus_message_error_get_impl( reply, errname, errmsg ) )
2405 DBUS_DEBUG( "call %d: %s: %s", callId.id, errname.c_str(), errmsg.c_str() );
2406 return Error{errname + ": " + errmsg};
2408 DBUS_DEBUG( "call %d: got reply with signature '%s'", callId.id,
2409 DBUS_W->eldbus_message_signature_get_impl( reply ).c_str() );
2410 return detail::unpackValues< RETTYPE >( callId, reply );
2413 template < typename RETTYPE, typename... ARGS >
2414 void asyncCall( CallId callId, const ConnectionState &connectionState,
2415 bool property, const std::string& funcName,
2416 std::function< void( RETTYPE ) > callback, const ARGS&... args )
2418 const auto &proxy = property ? connectionState.propertiesProxy : connectionState.proxy;
2421 DBUS_DEBUG( "call %d: not initialized", callId.id );
2422 callback( Error{"not initialized"} );
2426 auto msg = DBUS_W->eldbus_proxy_method_call_new_impl( proxy, funcName );
2429 DBUS_DEBUG( "call %d: failed", callId.id );
2430 callback( Error{"failed to create message"} );
2434 detail::packValues( callId, msg, args... );
2435 auto pending = DBUS_W->eldbus_proxy_send_impl( proxy, msg, [callback, callId, proxy]( const DBusWrapper::MessagePtr &reply ) {
2436 DBUS_DEBUG( "call %d: calling done", callId.id );
2439 DBUS_DEBUG( "call %d: failed", callId.id );
2440 callback( Error{"eldbus returned null as reply"} );
2444 std::string errname, errmsg;
2445 if( DBUS_W->eldbus_message_error_get_impl( reply, errname, errmsg ) )
2447 DBUS_DEBUG( "call %d: %s: %s", callId.id, errname.c_str(), errmsg.c_str() );
2448 callback( Error{errname + ": " + errmsg} );
2452 DBUS_DEBUG( "call %d: got reply with signature '%s'", callId.id,
2453 DBUS_W->eldbus_message_signature_get_impl( reply ).c_str() );
2454 callback( detail::unpackValues< RETTYPE >( callId, reply ) );
2461 DBUS_DEBUG( "call %d: call sent", callId.id );
2465 DBUS_DEBUG( "call %d: failed to send call", callId.id );
2466 callback( Error{"failed to send call"} );
2470 inline void displayDebugCallInfo( CallId callId, const std::string& funcName, const std::string& info, const std::string& interfaceName )
2472 DBUS_DEBUG( "call %d: %s iname = %s fname = %s", callId.id, info.c_str(), interfaceName.c_str(), funcName.c_str() );
2475 inline void displayDebugCallInfoSignal( CallId callId, const std::string& funcName, const std::string& info, const std::string& interfaceName )
2477 DBUS_DEBUG( "call %d: %s signal iname = %s fname = %s", callId.id, info.c_str(), interfaceName.c_str(), funcName.c_str() );
2480 inline void displayDebugCallInfoProperty( CallId callId, const std::string& funcName, std::string info, const std::string& interfaceName,
2481 const std::string& propertyName )
2483 DBUS_DEBUG( "call %d: %s iname = %s pname = %s", callId.id, info.c_str(), interfaceName.c_str(), propertyName.c_str() );
2486 using StringStorage = DBusWrapper::StringStorage;
2488 template < typename A, typename... ARGS >
2489 struct EldbusArgGenerator_Helper
2491 static void add( std::vector< std::pair<std::string, std::string> >& r )
2494 auto sig = signature< A >::sig();
2495 bart_assert( !sig.empty() );
2496 auto name = "p" + std::to_string( s + 1 );
2497 r.push_back({ std::move(sig), std::move(name) });
2498 EldbusArgGenerator_Helper<ARGS...>::add( r );
2503 struct EldbusArgGenerator_Helper< void >
2505 static void add( std::vector< std::pair<std::string, std::string> >& )
2511 struct EldbusArgGenerator_Helper< ValueOrError< void >, void >
2513 static void add( std::vector< std::pair<std::string, std::string> >& )
2518 struct EldbusArgGenerator_Helper< ValueOrError<>, void >
2520 static void add( std::vector< std::pair<std::string, std::string> >& )
2525 template < typename... ARGS >
2526 struct EldbusArgGenerator_Helper< std::tuple< ARGS... > >
2528 static void add( std::vector< std::pair<std::string, std::string> >& r )
2530 EldbusArgGenerator_Helper< ARGS..., void >::add( r );
2534 template < typename RetType >
2535 struct dbus_interface_return_type_traits
2537 using type = ValueOrError< RetType >;
2540 template < typename... ARGS >
2541 struct dbus_interface_return_type_traits< ValueOrError< ARGS... > >
2543 using type = ValueOrError< ARGS... >;
2546 template < typename T >
2547 struct dbus_interface_traits;
2548 template < typename RetType, typename... ARGS >
2549 struct dbus_interface_traits< RetType( ARGS... ) >
2551 using Ret = typename dbus_interface_return_type_traits< RetType >::type;
2552 using SyncCB = std::function< Ret( ARGS... ) >;
2553 using AsyncCB = std::function< void( std::function< void( Ret ) >, ARGS... ) >;
2554 using VEArgs = ValueOrError< ARGS... >;
2557 template < typename T >
2558 struct EldbusArgGenerator_Args;
2559 template < typename RetType, typename... ARGS >
2560 struct EldbusArgGenerator_Args< RetType( ARGS... ) >
2562 static std::string name()
2564 return signature_tuple_helper< 0, sizeof...( ARGS ), ARGS... >::name();
2566 static std::vector< std::pair<std::string, std::string> > get()
2568 std::vector< std::pair<std::string, std::string> > tmp;
2569 EldbusArgGenerator_Helper< ARGS..., void >::add( tmp );
2574 template < typename T >
2575 struct EldbusArgGenerator_ReturnType;
2576 template < typename RetType, typename... ARGS >
2577 struct EldbusArgGenerator_ReturnType< RetType( ARGS... ) >
2579 static std::string name()
2581 return signature< RetType >::name();
2583 static std::vector< std::pair<std::string, std::string> > get( )
2585 std::vector< std::pair<std::string, std::string> > tmp;
2586 EldbusArgGenerator_Helper< RetType, void >::add( tmp );
2591 template < typename T >
2592 struct EldbusArgGenerator_ReturnType;
2593 template < typename... ARGS >
2594 struct EldbusArgGenerator_ReturnType< void( ARGS... ) >
2596 static std::string name()
2600 static std::vector< std::pair<std::string, std::string> > get( )
2608 using ConnectionType = DBusWrapper::ConnectionType;
2611 * @brief Class representing client's end of DBUS connection
2613 * Allows calling (synchronous and asynchronos) methods on selected interface
2614 * Allows (synchronous and asynchronos) setting / getting properties.
2615 * Allows registering signals.
2620 struct ConnectionInfo
2622 std::string interfaceName, busName, pathName;
2627 * @brief Default constructor, creates non-connected object.
2629 DBusClient() = default;
2632 * @brief Connects to dbus choosen by tp, using given arguments
2634 * @param bus_name name of the bus to connect to
2635 * @param path_name object's path
2636 * @param interface_name interface name
2638 DBusClient( std::string busName_, std::string pathName_, std::string interfaceName_,
2639 ConnectionType tp );
2642 * @brief Connects to dbus using connection conn
2644 * @param bus_name name of the bus to connect to
2645 * @param path_name object's path
2646 * @param interface_name interface name
2647 * @param conn connection object from getDBusConnectionByType call
2649 DBusClient( std::string busName_, std::string pathName_, std::string interfaceName_,
2650 const DBusWrapper::ConnectionPtr &conn = {} );
2653 * @brief Destructor object.
2655 * All signals added will be disconnected.
2656 * All asynchronous calls will be cancelled, their callback's will be called
2657 * with failure message.
2659 ~DBusClient() = default;
2660 DBusClient( const DBusClient& ) = delete;
2661 DBusClient( DBusClient&& ) = default;
2663 DBusClient& operator=( DBusClient&& ) = default;
2664 DBusClient& operator=( const DBusClient& ) = delete;
2667 * @brief bool operator
2669 * Returns true, if object is connected to DBUS
2671 explicit operator bool() const
2673 return bool( connectionState->proxy );
2677 * @brief Helper class for calling a method
2679 * Template type T defines both arguments sent to the method
2680 * and expected values. Receiving different values will be reported as
2681 * error. For example:
2682 * \code{.cpp} Method<int(float, float)> \endcode
2683 * defines method, which takes two arguments (two floats) and return
2684 * single value of type int.
2686 template < typename T >
2690 using RetType = typename detail::dbus_interface_traits< T >::Ret;
2691 const detail::ConnectionState &connectionState;
2692 std::string funcName;
2694 std::shared_ptr< ConnectionInfo > connectionInfo;
2698 * @brief Executes synchronous call on DBUS's method
2700 * The function returns ValueOrError<...> object, which
2701 * contains either received values or error message.
2703 * @param args arguments to pass to the method
2705 template < typename... ARGS >
2706 RetType call( const ARGS&... args )
2708 detail::CallId callId;
2709 detail::displayDebugCallInfo( callId, funcName, info, connectionInfo->interfaceName );
2710 return detail::call< RetType >( callId, connectionState, false, funcName, args... );
2714 * @brief Executes asynchronous call on DBUS's method
2716 * The function calls callback with either received values or error message.
2718 * @param callback callback functor, which will be called with return value(s) or error message
2719 * @param args arguments to pass to the method
2721 template < typename... ARGS >
2722 void asyncCall( std::function< void( RetType ) > callback, const ARGS&... args )
2724 detail::CallId callId;
2725 detail::displayDebugCallInfo( callId, funcName, info, connectionInfo->interfaceName );
2726 detail::asyncCall< RetType >( callId, connectionState, false, funcName, std::move( callback ), args... );
2731 * @brief Helper class for calling a property
2733 * Template type T defines type of the value hidden under property.
2734 * Note, that library automatically wraps both sent and received value into
2735 * DBUS's wrapper type.
2737 template < typename T >
2741 using RetType = typename detail::dbus_interface_return_type_traits< T >::type;
2742 using VariantRetType = typename detail::dbus_interface_return_type_traits< EldbusVariant< T > >::type;
2743 const detail::ConnectionState &connectionState;
2744 std::string propName;
2746 std::shared_ptr< ConnectionInfo > connectionInfo;
2750 * @brief executes synchronous get on property
2752 * The function returns ValueOrError<...> object, which
2753 * contains either received values or error message.
2757 detail::CallId callId;
2758 detail::displayDebugCallInfoProperty( callId, "Get", info, connectionInfo->interfaceName, propName );
2759 auto z = detail::call< VariantRetType >( callId, connectionState, true, "Get", connectionInfo->interfaceName, propName );
2761 return z.getError();
2762 return {std::get< 0 >( z.getValues() ).value};
2766 * @brief executes asynchronous get on property
2768 * The function calls callback with either received values or error message.
2770 * @param callback callback functor, which will be called with return value(s) or error message
2772 void asyncGet( std::function< void( RetType ) > callback )
2774 detail::CallId callId;
2775 detail::displayDebugCallInfoProperty( callId, "Get", info, connectionInfo->interfaceName, propName );
2776 auto cc = [callback]( VariantRetType reply ) {
2778 callback( std::move( std::get< 0 >( reply.getValues() ).value ) );
2780 callback( reply.getError() );
2782 detail::asyncCall< VariantRetType >( callId, connectionState, true, "Get", std::move( cc ), connectionInfo->interfaceName, propName );
2786 * @brief executes synchronous set on property
2788 * The function returns ValueOrError<void> object, with
2789 * possible error message.
2791 ValueOrError< void > set( const T& r )
2793 detail::CallId callId;
2794 detail::displayDebugCallInfoProperty( callId, "Set", info, connectionInfo->interfaceName, propName );
2795 EldbusVariant< T > variantValue{std::move( r )};
2796 return detail::call< ValueOrError< void > >( callId, connectionState, true, "Set", connectionInfo->interfaceName, propName, variantValue );
2800 * @brief executes asynchronous get on property
2802 * The function calls callback with either received values or error message.
2804 * @param callback callback functor, which will be called with return value(s) or error message
2806 void asyncSet( std::function< void( ValueOrError< void > ) > callback, const T& r )
2808 detail::CallId callId;
2809 detail::displayDebugCallInfoProperty( callId, "Set", info, connectionInfo->interfaceName, propName );
2810 EldbusVariant< T > variantValue{std::move( r )};
2811 detail::asyncCall< ValueOrError< void > >( callId, connectionState, true, "Set", std::move( callback ), connectionInfo->interfaceName, propName, variantValue );
2816 * @brief Constructs Property<...> object for calling properties
2818 * The function constructs and returns proxy object for calling property.
2820 * @param propName property name to set and / or query
2822 template < typename PropertyType >
2823 Property< PropertyType > property( std::string propName )
2825 return Property< PropertyType >{*connectionState, std::move( propName ), info, connectionInfo};
2829 * @brief Constructs Method<...> object for calling methods
2831 * The function constructs and returns proxy object for calling method.
2833 * @param funcName function name to call
2835 template < typename MethodType >
2836 Method< MethodType > method( std::string funcName )
2838 return Method< MethodType >{*connectionState, std::move( funcName ), info, connectionInfo};
2842 * @brief Registers notification callback, when property has changed
2844 * The callback will be called with new value, when property's value has changed.
2845 * Note, that template type V must match expected type, otherwise undefined behavior will occur,
2846 * there's no check for this.
2848 template < typename V >
2849 void addPropertyChangedEvent( std::string propertyName, std::function< void( V ) > callback )
2851 detail::CallId callId;
2852 detail::displayDebugCallInfoSignal( callId, propertyName, info, connectionInfo->interfaceName );
2853 DBUS_DEBUG( "call %d: adding property", callId.id );
2854 auto &cI = this->connectionInfo;
2855 DBUS_W->add_property_changed_event_listener_impl(connectionState->proxy, cI->interfaceName, propertyName,
2856 [callback]( const _Eina_Value *newValue ) {
2858 if( !getFromEinaValue( newValue, &val ) )
2860 DBUS_DEBUG( "unable to get property's value" );
2868 * @brief Registers callback on the DBUS' signal
2870 * The function registers callback signalName. When signal comes, callback will be called.
2871 * Callback object will exists as long as signal is registered. You can unregister signal
2872 * by destroying DBusClient object.
2874 * @param signalName name of the signal to register
2875 * @param callback callback to call
2877 template < typename SignalType >
2878 void addSignal( std::string signalName, std::function< SignalType > callback )
2880 detail::CallId callId;
2881 detail::displayDebugCallInfoSignal( callId, signalName, info, connectionInfo->interfaceName );
2882 DBUS_W->eldbus_proxy_signal_handler_add_impl( connectionState->proxy, signalName,
2883 [callId, callback, signalName]( const DBusWrapper::MessagePtr &msg ) -> void {
2884 std::string errname, aux;
2885 if( DBUS_W->eldbus_message_error_get_impl( msg, errname, aux ) )
2887 DBUS_DEBUG( "call %d: Eldbus error: %s %s", callId.id, errname.c_str(), aux.c_str() );
2890 DBUS_DEBUG( "call %d: received signal with signature '%s'", callId.id, DBUS_W->eldbus_message_signature_get_impl( msg ).c_str() );
2891 using ParamsType = typename detail::dbus_interface_traits< SignalType >::VEArgs;
2892 auto params = detail::unpackValues< ParamsType >( callId, msg );
2895 DBUS_DEBUG( "call %d: failed: %s", callId.id, params.getError().message.c_str() );
2900 detail::apply( callback, params.getValues() );
2904 DBUS_DEBUG( "unhandled exception" );
2912 std::unique_ptr<detail::ConnectionState> connectionState{ new detail::ConnectionState };
2914 std::shared_ptr< ConnectionInfo > connectionInfo;
2916 static bool getFromEinaValue(const _Eina_Value *v, void *dst);