DALi Version 1.9.35
[platform/core/uifw/dali-adaptor.git] / dali / internal / accessibility / bridge / dbus.h
1 #ifndef DALI_INTERNAL_ACCESSIBILITY_BRIDGE_DBUS_H
2 #define DALI_INTERNAL_ACCESSIBILITY_BRIDGE_DBUS_H
3
4 /*
5  * Copyright 2020  Samsung Electronics Co., Ltd
6  *
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
10  *
11  *  http://www.apache.org/licenses/LICENSE-2.0
12
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.
18  */
19
20 // EXTERNAL INCLUDES
21 #include <array>
22 #include <atomic>
23 #include <cassert>
24 #include <cstdint>
25 #include <cstring>
26 #include <functional>
27 #include <map>
28 #include <memory>
29 #include <sstream>
30 #include <string>
31 #include <string_view>
32 #include <thread>
33 #include <tuple>
34 #include <type_traits>
35 #include <unordered_map>
36 #include <vector>
37
38 // INTERNAL INCLUDES
39 #include <dali/public-api/common/dali-common.h>
40 #include <dali/devel-api/adaptor-framework/accessibility.h>
41
42 #define ATSPI_PREFIX_PATH "/org/a11y/atspi/accessible/"
43 #define ATSPI_NULL_PATH "/org/a11y/atspi/null"
44
45 struct _Eina_Value;
46
47 struct ObjectPath
48 {
49   std::string value;
50 };
51
52 struct DALI_ADAPTOR_API DBusWrapper
53 {
54   virtual ~DBusWrapper() = default;
55
56   enum class ConnectionType
57   {
58     SYSTEM,
59     SESSION
60   };
61
62 #define DEFINE_TYPE(name, eldbus_name, unref_call) \
63     struct name { virtual ~name() = default; }; \
64     using name ## Ptr = std::shared_ptr<name>; \
65     using name ## WeakPtr = std::weak_ptr<name>; \
66
67   DEFINE_TYPE(Connection, Eldbus_Connection, )
68     DEFINE_TYPE(MessageIter, Eldbus_Message_Iter, eldbus_message_iter_container_close(Value))
69     DEFINE_TYPE(Message, Eldbus_Message, eldbus_message_unref(Value))
70     DEFINE_TYPE(Proxy, Eldbus_Proxy, eldbus_proxy_unref(Value))
71     DEFINE_TYPE(Object, Eldbus_Object, eldbus_object_unref(Value))
72     DEFINE_TYPE(Pending, Eldbus_Pending, )
73     DEFINE_TYPE(EventPropertyChanged, Eldbus_Proxy_Event_Property_Changed, )
74
75 #undef DEFINE_TYPE
76     virtual ConnectionPtr eldbus_address_connection_get_impl(const std::string& addr) = 0;
77
78 #define eldbus_message_iter_arguments_append_impl_basic_impl(type_set, type_get, sig) \
79   virtual void eldbus_message_iter_arguments_append_impl(const MessageIterPtr &it, type_set src) = 0; \
80   virtual bool eldbus_message_iter_get_and_next_impl(const MessageIterPtr &it, type_get &dst) = 0;
81 #define eldbus_message_iter_arguments_append_impl_basic(type, sig) \
82   eldbus_message_iter_arguments_append_impl_basic_impl(type, type, sig)
83
84   eldbus_message_iter_arguments_append_impl_basic(uint8_t, y)
85     eldbus_message_iter_arguments_append_impl_basic(uint16_t, q)
86     eldbus_message_iter_arguments_append_impl_basic(uint32_t, u)
87     eldbus_message_iter_arguments_append_impl_basic(uint64_t, t)
88     eldbus_message_iter_arguments_append_impl_basic(int16_t, n)
89     eldbus_message_iter_arguments_append_impl_basic(int32_t, i)
90     eldbus_message_iter_arguments_append_impl_basic(int64_t, x)
91     eldbus_message_iter_arguments_append_impl_basic(double, d)
92     eldbus_message_iter_arguments_append_impl_basic(bool, b)
93     eldbus_message_iter_arguments_append_impl_basic_impl(const std::string&, std::string, s)
94     eldbus_message_iter_arguments_append_impl_basic_impl(const ObjectPath&, ObjectPath, o)
95
96 #undef eldbus_message_iter_arguments_append_impl_basic
97 #undef eldbus_message_iter_arguments_append_impl_basic_impl
98
99     virtual MessageIterPtr eldbus_message_iter_container_new_impl(const MessageIterPtr& it, int type, const std::string& sig) = 0;
100   virtual MessageIterPtr eldbus_message_iter_get_and_next_by_type_impl(const MessageIterPtr& it, int type) = 0;
101   virtual MessageIterPtr eldbus_message_iter_get_impl(const MessagePtr& it, bool write) = 0;
102   virtual MessagePtr eldbus_proxy_method_call_new_impl(const ProxyPtr& proxy, const std::string& funcName) = 0;
103   virtual MessagePtr eldbus_proxy_send_and_block_impl(const ProxyPtr& proxy, const MessagePtr& msg) = 0;
104   virtual bool eldbus_message_error_get_impl(const MessagePtr& msg, std::string& name, std::string& text) = 0;
105   virtual std::string eldbus_message_signature_get_impl(const MessagePtr& msg) = 0;
106
107   using SendCallback = std::function<void(const MessagePtr & msg)>;
108   virtual PendingPtr eldbus_proxy_send_impl(const ProxyPtr& proxy, const MessagePtr& msg, const SendCallback& callback) = 0;
109   virtual std::string eldbus_proxy_interface_get_impl(const ProxyPtr&) = 0;
110   virtual void eldbus_proxy_signal_handler_add_impl(const ProxyPtr& proxy, const std::string& member, const std::function<void(const MessagePtr&)>& cb) = 0;
111   virtual std::string eldbus_message_iter_signature_get_impl(const MessageIterPtr& iter) = 0;
112   virtual MessagePtr eldbus_message_method_return_new_impl(const MessagePtr& msg) = 0;
113   virtual MessagePtr eldbus_message_error_new_impl(const MessagePtr& msg, const std::string& err, const std::string& txt) = 0;
114   virtual PendingPtr eldbus_connection_send_impl(const ConnectionPtr& conn, const MessagePtr& msg) = 0;
115   virtual MessagePtr eldbus_message_signal_new_impl(const std::string& path, const std::string& iface, const std::string& name) = 0;
116   virtual MessagePtr eldbus_message_ref_impl(const MessagePtr& msg) = 0;
117   virtual ConnectionPtr eldbus_connection_get_impl(ConnectionType type) = 0;
118   virtual std::string eldbus_connection_unique_name_get_impl(const ConnectionPtr& conn) = 0;
119   virtual ObjectPtr eldbus_object_get_impl(const ConnectionPtr& conn, const std::string& bus, const std::string& path) = 0;
120   virtual ProxyPtr eldbus_proxy_get_impl(const ObjectPtr& obj, const std::string& interface) = 0;
121   virtual ProxyPtr eldbus_proxy_copy_impl(const ProxyPtr& ptr) = 0;
122
123   class StringStorage
124   {
125   public:
126     struct char_ptr_deleter
127     {
128       void operator()(char* p)
129       {
130         free(p);
131       }
132     };
133     std::vector< std::unique_ptr< char, char_ptr_deleter > > storage;
134
135     const char* add(const char* txt)
136     {
137       auto ptr = strdup(txt);
138       storage.push_back(std::unique_ptr< char, char_ptr_deleter >(ptr));
139       return storage.back().get();
140     }
141     const char* add(const std::string& txt)
142     {
143       return add(txt.c_str());
144     }
145   };
146
147   struct CallId
148   {
149     static std::atomic< unsigned int > LastId;
150     unsigned int id = ++LastId;
151   };
152   struct MethodInfo
153   {
154     CallId id;
155     std::string memberName;
156     std::vector< std::pair<std::string, std::string> > in, out; // _Eldbus_Arg_Info
157     std::function< DBusWrapper::MessagePtr(const DBusWrapper::MessagePtr & msg) > callback;
158   };
159   struct SignalInfo
160   {
161     CallId id;
162     std::string memberName;
163     std::vector< std::pair<std::string, std::string> > args;
164     unsigned int uniqueId;
165   };
166   struct PropertyInfo
167   {
168     CallId setterId, getterId;
169     std::string memberName, typeSignature;
170     std::function< std::string(const DBusWrapper::MessagePtr & src, const DBusWrapper::MessageIterPtr & dst) > getCallback, setCallback;
171   };
172   struct SignalId
173   {
174     CallId id;
175
176     SignalId() = default;
177     SignalId(CallId id) : id(id) {}
178   };
179   virtual void add_interface_impl(bool fallback, const std::string& pathName,
180     const ConnectionPtr& connection,
181     std::vector<std::function<void()>>& destructors,
182     const std::string& interfaceName,
183     std::vector< MethodInfo >& dscrMethods,
184     std::vector< PropertyInfo >& dscrProperties,
185     std::vector< SignalInfo >& dscrSignals) = 0;
186   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;
187   static DBusWrapper* Installed();
188   static void Install(std::unique_ptr<DBusWrapper>);
189
190   StringStorage Strings;
191 };
192
193 namespace detail {
194   enum class MethodType {
195     Method, Getter, Setter
196   };
197 }
198
199 namespace std {
200   template <> struct hash<std::tuple<std::string, std::string, std::string>> {
201     size_t operator () (const std::tuple<std::string, std::string, std::string>& a) const {
202       auto a1 = std::hash<std::string>()(std::get<0>(a));
203       auto a2 = std::hash<std::string>()(std::get<1>(a));
204       auto a3 = std::hash<std::string>()(std::get<2>(a));
205       size_t v = a1;
206       v = (v * 11400714819323198485llu) + a2;
207       v = (v * 11400714819323198485llu) + a3;
208       return v;
209     }
210   };
211   template <> struct hash<std::tuple<std::string, std::string, std::string, detail::MethodType>> {
212     size_t operator () (const std::tuple<std::string, std::string, std::string, detail::MethodType>& a) const {
213       auto a1 = std::hash<std::string>()(std::get<0>(a));
214       auto a2 = std::hash<std::string>()(std::get<1>(a));
215       auto a3 = std::hash<std::string>()(std::get<2>(a));
216       auto a4 = static_cast<size_t>(std::get<3>(a));
217       size_t v = a1;
218       v = (v * 11400714819323198485llu) + a2;
219       v = (v * 11400714819323198485llu) + a3;
220       v = (v * 11400714819323198485llu) + a4;
221       return v;
222     }
223   };
224   template <> struct hash<std::tuple<std::string, std::string, unsigned int>> {
225     size_t operator () (const std::tuple<std::string, std::string, unsigned int>& a) const {
226       auto a1 = std::hash<std::string>()(std::get<0>(a));
227       auto a2 = std::hash<std::string>()(std::get<1>(a));
228       auto a3 = std::get<2>(a);
229       size_t v = a1;
230       v = (v * 11400714819323198485llu) + a2;
231       v = (v * 11400714819323198485llu) + a3;
232       return v;
233     }
234   };
235 }
236
237 namespace detail {
238   template <typename T> struct DBusSigImpl { enum { value = 0, end = 0 }; };
239   template <typename T> struct DBusSig { enum { value = DBusSigImpl<typename std::decay<T>::type>::value, end = DBusSigImpl<typename std::decay<T>::type>::end }; };
240   template <typename T, typename Q, size_t I, size_t S> struct IndexFromTypeTupleImpl {
241     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 };
242   };
243   template <typename T, typename Q, size_t S> struct IndexFromTypeTupleImpl<T, Q, S, S> { enum { value = S }; };
244   template <typename T, typename Q> struct IndexFromTypeTuple {
245     enum { value = IndexFromTypeTupleImpl<T, typename std::decay<Q>::type, 0, std::tuple_size<T>::value>::value };
246   };
247   template <typename T, typename = void> struct Encoder;
248   template <size_t I, size_t S, typename ... ARGS> struct EncoderTuple;
249 }
250
251 namespace detail {
252   template <> struct DBusSigImpl<uint8_t> { enum { value = 'y', end = 0 }; };
253   template <> struct DBusSigImpl<uint16_t> { enum { value = 'q', end = 0 }; };
254   template <> struct DBusSigImpl<uint32_t> { enum { value = 'u', end = 0 }; };
255   template <> struct DBusSigImpl<uint64_t> { enum { value = 't', end = 0 }; };
256   template <> struct DBusSigImpl<int16_t> { enum { value = 'n', end = 0 }; };
257   template <> struct DBusSigImpl<int32_t> { enum { value = 'i', end = 0 }; };
258   template <> struct DBusSigImpl<int64_t> { enum { value = 'x', end = 0 }; };
259   template <> struct DBusSigImpl<double> { enum { value = 'd', end = 0 }; };
260   template <> struct DBusSigImpl<bool> { enum { value = 'b', end = 0 }; };
261   template <> struct DBusSigImpl<std::string> { enum { value = 's', end = 0 }; };
262   template <> struct DBusSigImpl<ObjectPath> { enum { value = 'o', end = 0 }; };
263 }
264
265
266 #define DBUS_DEBUG( ... )                                \
267   do                                                     \
268   {                                                      \
269     DBus::debugPrint( __FILE__, __LINE__, __VA_ARGS__ ); \
270   } while( 0 )
271
272 #define DBUS_W DBusWrapper::Installed()
273
274 /**
275  * @brief Template based, single file, wrapper library around eldbus for DBUS based communication.
276  *
277  * Main motivation was missing asynchronous calls in AT-SPI library and difficulties,
278  * when using eldbus from C++.
279  *
280  * The library:
281  * - takes care of marshalling arguments to and from DBUS calls.
282  * - allows synchronous and asynchronous calls.
283  * - allows synchronous and asynchronous listeners on signals.
284  * - manages all involved objects' lifetimes.
285  * - errors are passed as optional-alike objects, no exceptions are used.
286  * - allows setting additional debug-print function for more details about
287  *   what's going on
288  *
289  * DBUS's method signatures (and expected return values) are specified as template argument,
290  * using functor syntax. For example:
291  * \code{.cpp}
292  * auto dbus = DBusClient{ ... };
293  * auto v = dbus.method<std::tuple<int, float>(float, float, std::string)>("foo").call(1.0f, 2.0f, "qwe");
294  * \endcode
295  * means (synchronous) call on dbus object, which takes three arguments (thus making call signature \b dds)
296  * of types float, float and string (float will be automatically converted to double).
297  * Expected return value is std::tuple<int, float>, which gives signature <B>(id)</B> - std::tuple acts
298  * as struct container. Returned value v will be of type ValueOrError<std::tuple<int, float>>.\n
299  * Slightly different (asynchronous) example:
300  * \code{.cpp}
301  * auto dbus = DBusClient{ ... };
302  * std::function<void(ValueOrError<int, float>)> callback;
303  * dbus.method<ValueOrError<int, float>(float, float, std::string)>("foo").asyncCall(callback, 1.0f, 2.0f, "qwe");
304  * \endcode
305  * Now the call takes the same arguments and has the same signature. But expected values are different -
306  * now the signature is simply \b id. ValueOrError acts in this case as placeholder for list of values,
307  * which DBUS allows as return data. The call itself is asynchronous - instead of expecting reply
308  * you need to pass a callback, which will be called either with received data and error message.
309  *
310  * Library is not thread-safe, the same object shouldn't be called from different threads without
311  * synchronization. There's no guarantee, that callbacks will be executed on the same thread.
312  */
313 namespace DBus
314 {
315
316   class DBusServer;
317   class DBusClient;
318   class DBusInterfaceDescription;
319
320   /**
321    * @brief Formats debug message and calls debug printer (if any) with it
322    */
323   void debugPrint(const char* file, size_t line, const char* format, ...);
324
325   /**
326    * @brief Sets debug printer callback, which will be called with debug messages
327    *
328    * Callback will be called in various moments of DBus activity. First value passed to callback
329    * is pointer to text, second it's length. Text is ended with 0 (not counted towards it's size),
330    * user can safely printf it.
331    */
332   void setDebugPrinter(std::function< void(const char*, size_t) >);
333
334   struct Error
335   {
336     std::string message;
337
338     Error() = default;
339     Error(std::string msg) : message(std::move(msg))
340     {
341       assert(!message.empty());
342     }
343   };
344
345   struct Success
346   {
347   };
348
349
350   /**
351    * @brief Value representing data, that came from DBUS or error message
352    *
353    * Object of this class either helds series of values (of types ARGS...)
354    * or error message. This object will be true in boolean context, if has data
355    * and false, if an error occured.
356    * It's valid to create ValueOrError object with empty argument list or void:
357    * \code{.cpp}
358    * ValueOrError<> v1;
359    * ValueOrError<void> v2;
360    * \endcode
361    * Both mean the same - ValueOrError containing no real data and being a marker,
362    * wherever operation successed or failed and containing possible error message.
363    */
364   template < typename... ARGS >
365   class ValueOrError
366   {
367   public:
368     /**
369      * @brief Empty constructor. Valid only, if all ARGS types are default constructible.
370      */
371     ValueOrError() = default;
372
373     /**
374      * @brief Value constructor.
375      *
376      * This will be initialized as success with passed in values.
377      */
378     ValueOrError(ARGS... t) : value(std::move(t)...) {}
379
380     /**
381      * @brief Alternative Value constructor.
382      *
383      * This will be initialized as success with passed in values.
384      */
385     ValueOrError(std::tuple< ARGS... > t) : value(std::move(t)) {}
386
387     /**
388      * @brief Error constructor. This will be initialized as failure with given error message.
389      */
390     ValueOrError(Error e) : error(std::move(e))
391     {
392       assert(!error.message.empty());
393     }
394
395     /**
396      * @brief bool operator.
397      *
398      * Returns true, if operation was successful (getValues member is callable), or false
399      * when operation failed (getError is callable).
400      */
401     explicit operator bool() const
402     {
403       return error.message.empty();
404     }
405
406     /**
407      * @brief Returns error message object.
408      *
409      * Returns object containing error message associated with the failed operation.
410      * Only callable, if operation actually failed, otherwise will assert.
411      */
412     const Error& getError() const
413     {
414       return error;
415     }
416
417     /**
418      * @brief Returns modifiable tuple of held data.
419      *
420      * Returns reference to the internal tuple containing held data.
421      * User can modify (or move) data safely.
422      * Only callable, if operation actually successed, otherwise will assert.
423      */
424     std::tuple< ARGS... >& getValues()
425     {
426       assert(*this);
427       return value;
428     }
429
430     /**
431      * @brief Returns const tuple of held data.
432      *
433      * Returns const reference to the internal tuple containing held data.
434      * Only callable, if operation actually successed, otherwise will assert.
435      */
436     const std::tuple< ARGS... >& getValues() const
437     {
438       assert(*this);
439       return value;
440     }
441
442   protected:
443     std::tuple< ARGS... > value;
444     Error error;
445
446   };
447
448
449   template <>
450   class ValueOrError<>
451   {
452   public:
453     ValueOrError() = default;
454     ValueOrError(std::tuple<> t) {}
455     ValueOrError(Error e) : error(std::move(e))
456     {
457       assert(!error.message.empty());
458     }
459
460     explicit operator bool() const
461     {
462       return error.message.empty();
463     }
464     const Error& getError() const
465     {
466       return error;
467     }
468     std::tuple<>& getValues()
469     {
470       assert(*this);
471       static std::tuple<> t;
472       return t;
473     }
474     std::tuple<> getValues() const
475     {
476       assert(*this);
477       return {};
478     }
479
480   protected:
481     Error error;
482   };
483
484   template <>
485   class ValueOrError< void >
486   {
487   public:
488     ValueOrError() = default;
489     ValueOrError(Success) {}
490     ValueOrError(Error e) : error(std::move(e))
491     {
492       assert(!error.message.empty());
493     }
494
495     explicit operator bool() const
496     {
497       return error.message.empty();
498     }
499     const Error& getError() const
500     {
501       return error;
502     }
503     std::tuple<>& getValues()
504     {
505       assert(*this);
506       static std::tuple<> t;
507       return t;
508     }
509     std::tuple<> getValues() const
510     {
511       assert(*this);
512       return {};
513     }
514
515   protected:
516     Error error;
517   };
518
519   using ObjectPath = ObjectPath;
520
521
522   /**
523    * @brief Class used to marshall DBUS's variant type
524    *
525    * Minimalistic class, that allows user to specify DBUS variant type
526    * as argument or return value. You need to pass real type hidden under variant as
527    * template type \b A. At this point library doesn't allow to expected one of few classes
528    * as return data in variant. So for example user can't specify method call, which on return
529    * expects DBUS variant holding either string or int.
530    */
531   template < typename A >
532   struct EldbusVariant
533   {
534     A value;
535   };
536
537   /**
538    * @brief Namespace for private, internal functions and classes
539    */
540   namespace detail
541   {
542     inline namespace strings {
543       template <std::size_t N>
544       using char_array = std::array<char, N>;
545
546       constexpr char *xcopy_n(const char *src, size_t n, char *dst)
547       {
548         for (std::size_t i = 0; i < n; ++i)
549           dst[i] = src[i];
550
551         return dst + n;
552       }
553
554       template <std::size_t N>
555       constexpr std::size_t xlen(const char (&)[N])
556       {
557         return N - 1;
558       }
559
560       template <std::size_t N>
561       constexpr std::size_t xlen(const char_array<N> &)
562       {
563         return N - 1;
564       }
565
566       template <typename... Args>
567       constexpr auto concat(const Args &... args)
568       {
569           char_array<(1U + ... + xlen(args))> arr{};
570           char *ptr = arr.data();
571
572           if constexpr (!arr.empty())
573               ((ptr = xcopy_n(std::data(args), xlen(args), ptr)), ...);
574
575           return arr;
576       }
577
578       template<std::size_t... Digits>
579       struct to_chars {
580           static constexpr const char value[] = {('0' + static_cast<char>(Digits))..., '\0'};
581
582           static_assert((true && ... && (Digits < 10)));
583       };
584
585       template<std::size_t Remainder, std::size_t... Digits>
586       struct to_chars_helper : to_chars_helper<Remainder / 10, Remainder % 10, Digits...> {};
587
588       template<std::size_t... Digits>
589       struct to_chars_helper<0, Digits...> : to_chars<Digits...> {};
590
591       template<std::size_t N>
592       using to_string = to_chars_helper<N / 10, N % 10>;
593     }
594
595     template < typename T, typename = void >
596     struct signature;
597     template < typename... ARGS >
598     struct signature< std::tuple< ARGS... > >;
599     template < typename A, typename B >
600     struct signature< std::pair< A, B > >;
601     template < typename A >
602     struct signature< std::vector< A > >;
603     template < typename A, size_t N >
604     struct signature< std::array< A, N > >;
605     template < typename A, typename B >
606     struct signature< std::unordered_map< A, B > >;
607     template < typename A, typename B >
608     struct signature< std::map< A, B > >;
609
610     template <typename T>
611     struct signature_helper
612     {
613       /**
614        * @brief Returns name of type marshalled, for informative purposes
615        */
616       static constexpr std::string_view name()
617       {
618         return {T::name_v.data()};
619       }
620
621       /**
622        * @brief Returns DBUS' signature of type marshalled
623        */
624       static constexpr std::string_view sig()
625       {
626         return {T::sig_v.data()};
627       }
628     };
629
630     /**
631      * @brief Signature class for marshalling uint8 type.
632      */
633     template <>
634     struct signature< uint8_t > : signature_helper<signature<uint8_t>>
635     {
636       static constexpr auto name_v = concat("uint8_t");
637       static constexpr auto sig_v = concat("y");
638
639       /**
640        * @brief Marshals value v as marshalled type into message
641        */
642       static void set(const DBusWrapper::MessageIterPtr& iter, uint8_t v)
643       {
644         DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
645       }
646
647       /**
648        * @brief Marshals value from marshalled type into variable v
649        */
650       static bool get(const DBusWrapper::MessageIterPtr& iter, uint8_t& v)
651       {
652         return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
653       }
654     };
655
656     /**
657      * @brief Signature class for marshalling uint16 type.
658      */
659     template <>
660     struct signature< uint16_t > : signature_helper<signature<uint16_t>>
661     {
662       static constexpr auto name_v = concat("uint16_t");
663       static constexpr auto sig_v = concat("q");
664
665       /**
666        * @brief Marshals value v as marshalled type into message
667        */
668       static void set(const DBusWrapper::MessageIterPtr& iter, uint16_t v)
669       {
670         DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
671       }
672
673       /**
674        * @brief Marshals value from marshalled type into variable v
675        */
676       static bool get(const DBusWrapper::MessageIterPtr& iter, uint16_t& v)
677       {
678         return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
679       }
680     };
681
682     /**
683      * @brief Signature class for marshalling uint32 type.
684      */
685     template <>
686     struct signature< uint32_t > : signature_helper<signature<uint32_t>>
687     {
688       static constexpr auto name_v = concat("uint32_t");
689       static constexpr auto sig_v = concat("u");
690
691       /**
692        * @brief Marshals value v as marshalled type into message
693        */
694       static void set(const DBusWrapper::MessageIterPtr& iter, uint32_t v)
695       {
696         DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
697       }
698
699       /**
700        * @brief Marshals value from marshalled type into variable v
701        */
702       static bool get(const DBusWrapper::MessageIterPtr& iter, uint32_t& v)
703       {
704         return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
705       }
706     };
707
708     /**
709      * @brief Signature class for marshalling uint64 type.
710      */
711     template <>
712     struct signature< uint64_t > : signature_helper<signature<uint64_t>>
713     {
714       static constexpr auto name_v = concat("uint64_t");
715       static constexpr auto sig_v = concat("t");
716
717       /**
718        * @brief Marshals value v as marshalled type into message
719        */
720       static void set(const DBusWrapper::MessageIterPtr& iter, uint64_t v)
721       {
722         DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
723       }
724
725       /**
726        * @brief Marshals value from marshalled type into variable v
727        */
728       static bool get(const DBusWrapper::MessageIterPtr& iter, uint64_t& v)
729       {
730         return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
731       }
732     };
733
734     /**
735      * @brief Signature class for marshalling int16 type.
736      */
737     template <>
738     struct signature< int16_t > : signature_helper<signature<int16_t>>
739     {
740       static constexpr auto name_v = concat("int16_t");
741       static constexpr auto sig_v = concat("n");
742
743       /**
744        * @brief Marshals value v as marshalled type into message
745        */
746       static void set(const DBusWrapper::MessageIterPtr& iter, int16_t v)
747       {
748         DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
749       }
750
751       /**
752        * @brief Marshals value from marshalled type into variable v
753        */
754       static bool get(const DBusWrapper::MessageIterPtr& iter, int16_t& v)
755       {
756         return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
757       }
758     };
759
760     /**
761      * @brief Signature class for marshalling int32 type.
762      */
763     template <>
764     struct signature< int32_t > : signature_helper<signature<int32_t>>
765     {
766       static constexpr auto name_v = concat("int32_t");
767       static constexpr auto sig_v = concat("i");
768
769       /**
770        * @brief Marshals value v as marshalled type into message
771        */
772       static void set(const DBusWrapper::MessageIterPtr& iter, int32_t v)
773       {
774         DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
775       }
776
777       /**
778        * @brief Marshals value from marshalled type into variable v
779        */
780       static bool get(const DBusWrapper::MessageIterPtr& iter, int32_t& v)
781       {
782         return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
783       }
784     };
785
786     /**
787      * @brief Signature class for marshalling int64 type.
788      */
789     template <>
790     struct signature< int64_t > : signature_helper<signature<int64_t>>
791     {
792       static constexpr auto name_v = concat("int64_t");
793       static constexpr auto sig_v = concat("x");
794
795       /**
796        * @brief Marshals value v as marshalled type into message
797        */
798       static void set(const DBusWrapper::MessageIterPtr& iter, int64_t v)
799       {
800         DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
801       }
802
803       /**
804        * @brief Marshals value from marshalled type into variable v
805        */
806       static bool get(const DBusWrapper::MessageIterPtr& iter, int64_t& v)
807       {
808         return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
809       }
810     };
811
812     /**
813      * @brief Signature class for marshalling double type.
814      */
815     template <>
816     struct signature< double > : signature_helper<signature<double>>
817     {
818       static constexpr auto name_v = concat("double");
819       static constexpr auto sig_v = concat("d");
820
821       /**
822        * @brief Marshals value v as marshalled type into message
823        */
824       static void set(const DBusWrapper::MessageIterPtr& iter, double v)
825       {
826         DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
827       }
828
829       /**
830        * @brief Marshals value from marshalled type into variable v
831        */
832       static bool get(const DBusWrapper::MessageIterPtr& iter, double& v)
833       {
834         return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
835       }
836
837       /**
838        * @brief Marshals value from marshalled type into variable v
839        */
840       static bool get(const DBusWrapper::MessageIterPtr& iter, float& v2)
841       {
842         double v = 0;
843         auto r = DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
844         v2 = static_cast<float>(v);
845         return r;
846       }
847     };
848
849     /**
850      * @brief Signature class for marshalling float type.
851      */
852     template <>
853     struct signature< float > : signature_helper<signature<float>>
854     {
855       static constexpr auto name_v = concat("float");
856       static constexpr auto sig_v = concat("d");
857
858       /**
859        * @brief Marshals value v as marshalled type into message
860        */
861       static void set(const DBusWrapper::MessageIterPtr& iter, float v)
862       {
863         DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
864       }
865
866       /**
867        * @brief Marshals value from marshalled type into variable v
868        */
869       static bool get(const DBusWrapper::MessageIterPtr& iter, double& v)
870       {
871         return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
872       }
873
874       /**
875        * @brief Marshals value from marshalled type into variable v
876        */
877       static bool get(const DBusWrapper::MessageIterPtr& iter, float& v2)
878       {
879         double v = 0;
880         auto r = DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
881         v2 = static_cast<float>(v);
882         return r;
883       }
884     };
885
886     /**
887      * @brief Signature class for marshalling boolean type.
888      */
889     template <>
890     struct signature< bool > : signature_helper<signature<bool>>
891     {
892       static constexpr auto name_v = concat("bool");
893       static constexpr auto sig_v = concat("b");
894
895       /**
896        * @brief Marshals value v as marshalled type into message
897        */
898       static void set(const DBusWrapper::MessageIterPtr& iter, bool v)
899       {
900         DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
901       }
902
903       /**
904        * @brief Marshals value from marshalled type into variable v
905        */
906       static bool get(const DBusWrapper::MessageIterPtr& iter, bool& v)
907       {
908         return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
909       }
910     };
911
912     template < typename T >
913     struct signature<T, typename std::enable_if_t<std::is_enum_v<T>, void>> : signature_helper<signature<T>>
914     {
915       static constexpr auto name_v = concat("enum");
916       static constexpr auto sig_v = signature<typename std::underlying_type<T>::type>::sig_v;
917
918       /**
919        * @brief Marshals value v as marshalled type into message
920        */
921       static void set(const DBusWrapper::MessageIterPtr& iter, T v)
922       {
923         signature<typename std::underlying_type<T>::type>::set(iter, static_cast<int64_t>(v));
924       }
925
926       /**
927        * @brief Marshals value from marshalled type into variable v
928        */
929       static bool get(const DBusWrapper::MessageIterPtr& iter, T& v)
930       {
931         typename std::underlying_type<T>::type q = 0;
932         if (!signature<typename std::underlying_type<T>::type>::get(iter, q))
933           return false;
934
935         v = static_cast<T>(q);
936         return true;
937       }
938     };
939
940     /**
941      * @brief Signature class for marshalling string type.
942      *
943      * Both (const) char * and std::string types are accepted as value to send.
944      * Only std::string is accepted as value to receive.
945      */
946     template <>
947     struct signature< std::string > : signature_helper<signature<std::string>>
948     {
949       static constexpr auto name_v = concat("string");
950       static constexpr auto sig_v = concat("s");
951
952       /**
953        * @brief Marshals value v as marshalled type into message
954        */
955       static void set(const DBusWrapper::MessageIterPtr& iter, const std::string& v)
956       {
957         DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
958       }
959
960       /**
961        * @brief Marshals value from marshalled type into variable v
962        */
963       static bool get(const DBusWrapper::MessageIterPtr& iter, std::string& v)
964       {
965         return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
966       }
967     };
968
969     template <>
970     struct signature< ObjectPath > : signature_helper<signature<ObjectPath>>
971     {
972       static constexpr auto name_v = concat("path");
973       static constexpr auto sig_v = concat("o");
974
975       /**
976        * @brief Marshals value v as marshalled type into message
977        */
978       static void set(const DBusWrapper::MessageIterPtr& iter, const std::string& v)
979       {
980         DBUS_W->eldbus_message_iter_arguments_append_impl(iter, ObjectPath{ v });
981       }
982
983       /**
984        * @brief Marshals value v as marshalled type into message
985        */
986       static void set(const DBusWrapper::MessageIterPtr& iter, const ObjectPath& v)
987       {
988         DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
989       }
990
991       /**
992        * @brief Marshals value v as marshalled type into message
993        */
994       static void set(const DBusWrapper::MessageIterPtr& iter, const char* v)
995       {
996         DBUS_W->eldbus_message_iter_arguments_append_impl(iter, ObjectPath{ v });
997       }
998
999       /**
1000        * @brief Marshals value from marshalled type into variable v
1001        */
1002       static bool get(const DBusWrapper::MessageIterPtr& iter, ObjectPath& v)
1003       {
1004         return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
1005       }
1006
1007       /**
1008        * @brief Marshals value from marshalled type into variable v
1009        */
1010       static bool get(const DBusWrapper::MessageIterPtr& iter, std::string& v)
1011       {
1012         ObjectPath q;
1013         if (!DBUS_W->eldbus_message_iter_get_and_next_impl(iter, q)) return false;
1014         v = std::move(q.value);
1015         return true;
1016       }
1017     };
1018
1019     /**
1020      * @brief Signature class for marshalling (const) char * type.
1021      *
1022      * Both (const) char * and std::string types are accepted as value to send.
1023      * You can't use (const) char * variable type to receive value.
1024      */
1025     template <>
1026     struct signature< char* > : signature_helper<signature<char *>>
1027     {
1028       static constexpr auto name_v = concat("string");
1029       static constexpr auto sig_v = concat("s");
1030
1031       /**
1032        * @brief Marshals value v as marshalled type into message
1033        */
1034       static void set(const DBusWrapper::MessageIterPtr& iter, const std::string& v)
1035       {
1036         DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
1037       }
1038
1039       /**
1040        * @brief Marshals value v as marshalled type into message
1041        */
1042       static void set(const DBusWrapper::MessageIterPtr& iter, const char* v)
1043       {
1044         DBUS_W->eldbus_message_iter_arguments_append_impl(iter, std::string{ v });
1045       }
1046     };
1047
1048     template < size_t INDEX, typename A, typename... ARGS >
1049     struct signature_tuple_element_type_helper
1050     {
1051       using type = typename signature_tuple_element_type_helper< INDEX - 1, ARGS... >::type;
1052     };
1053
1054     template < typename A, typename... ARGS >
1055     struct signature_tuple_element_type_helper< 0, A, ARGS... >
1056     {
1057       using type = A;
1058     };
1059
1060     /**
1061      * @brief Helper class to marshall tuples
1062      *
1063      * This class marshals all elements of the tuple value starting at the index INDEX
1064      * and incrementing. This class recursively calls itself with increasing INDEX value
1065      * until INDEX is equal to SIZE, where recursive calling ends.
1066      */
1067     template < size_t INDEX, size_t SIZE, typename... ARGS >
1068     struct signature_tuple_helper : signature_helper<signature_tuple_helper<INDEX, SIZE, ARGS...>>
1069     {
1070       using current_type = typename signature_tuple_element_type_helper< INDEX, ARGS... >::type;
1071
1072       static constexpr auto name_v = concat(signature<current_type>::name_v, ", ", signature_tuple_helper<INDEX + 1, SIZE, ARGS...>::name_v);
1073       static constexpr auto sig_v = concat(signature<current_type>::sig_v, signature_tuple_helper<INDEX + 1, SIZE, ARGS...>::sig_v);
1074
1075       /**
1076        * @brief Marshals value v as marshalled type into message
1077        */
1078       static void set(const DBusWrapper::MessageIterPtr& iter, const std::tuple< ARGS... >& args)
1079       {
1080         signature< current_type >::set(iter, std::get< INDEX >(args));
1081         signature_tuple_helper< INDEX + 1, SIZE, ARGS... >::set(iter, args);
1082       }
1083
1084       /**
1085        * @brief Marshals value from marshalled type into variable v
1086        */
1087       static bool get(const DBusWrapper::MessageIterPtr& iter, std::tuple< ARGS... >& args)
1088       {
1089         return signature< current_type >::get(iter, std::get< INDEX >(args)) &&
1090           signature_tuple_helper< INDEX + 1, SIZE, ARGS... >::get(iter, args);
1091       }
1092     };
1093
1094     /**
1095      * @brief Helper class to marshall tuples
1096      *
1097      * This class marks end of the tuple marshalling. Members of this class are called
1098      * when INDEX value is equal to SIZE.
1099      */
1100     template < size_t SIZE, typename... ARGS >
1101     struct signature_tuple_helper< SIZE, SIZE, ARGS... > : signature_helper<signature_tuple_helper<SIZE, SIZE, ARGS...>>
1102     {
1103       static constexpr auto name_v = concat("");
1104       static constexpr auto sig_v = concat("");
1105
1106       /**
1107        * @brief Marshals value v as marshalled type into message
1108        */
1109       static void set(const DBusWrapper::MessageIterPtr& iter, const std::tuple< ARGS... >& args)
1110       {
1111       }
1112
1113       /**
1114        * @brief Marshals value from marshalled type into variable v
1115        */
1116       static bool get(const DBusWrapper::MessageIterPtr& iter, std::tuple< ARGS... >& args)
1117       {
1118         return true;
1119       }
1120     };
1121
1122     /**
1123      * @brief Signature class for marshalling tuple of values
1124      *
1125      * This class marshalls tuple of values. This represents
1126      * DBUS struct typle, encoded with character 'r'
1127      */
1128     template < typename... ARGS >
1129     struct signature< std::tuple< ARGS... > > : signature_helper<signature<std::tuple<ARGS...>>>
1130     {
1131       static constexpr auto name_v = concat("tuple<", signature_tuple_helper<0, sizeof...(ARGS), ARGS...>::name_v, ">");
1132       static constexpr auto sig_v = concat("(", signature_tuple_helper<0, sizeof...(ARGS), ARGS...>::sig_v, ")");
1133
1134       /**
1135        * @brief Marshals value v as marshalled type into message
1136        */
1137       static void set(const DBusWrapper::MessageIterPtr& iter, const std::tuple< ARGS... >& args)
1138       {
1139         auto entry = DBUS_W->eldbus_message_iter_container_new_impl(iter, 'r', "");
1140         signature_tuple_helper< 0, sizeof...(ARGS), ARGS... >::set(entry, args);
1141       }
1142
1143       /**
1144        * @brief Marshals value from marshalled type into variable v
1145        */
1146       static bool get(const DBusWrapper::MessageIterPtr& iter, std::tuple< ARGS... >& args)
1147       {
1148         auto entry = DBUS_W->eldbus_message_iter_get_and_next_by_type_impl(iter, 'r');
1149         if (!entry) return false;
1150         return signature_tuple_helper< 0, sizeof...(ARGS), ARGS... >::get(entry, args);
1151       }
1152     };
1153
1154     /**
1155      * @brief Signature class for marshalling ValueOrError template type
1156      *
1157      * ValueOrError template type is used to marshall list of values passed to
1158      * DBUS (or received from) at the "top" level. For example ss(s) is represented as
1159      * \code{.cpp} ValueOrError<std::string, std::string, std::tuple<std::string>> \endcode
1160      * While (ss(s)) is represented as
1161      * \code{.cpp} std::tuple<std::string, std::string, std::tuple<std::string>> \endcode
1162      * or
1163      * \code{.cpp} ValueOrError<std::tuple<std::string, std::string, std::tuple<std::string>>> \endcode
1164      */
1165     template < typename... ARGS >
1166     struct signature< ValueOrError< ARGS... > > : signature_helper<signature<ValueOrError<ARGS...>>>
1167     {
1168       static constexpr auto name_v = concat("ValueOrError<", signature_tuple_helper<0, sizeof...(ARGS), ARGS...>::name_v, ">");
1169       static constexpr auto sig_v = signature_tuple_helper<0, sizeof...(ARGS), ARGS...>::sig_v;
1170
1171       /**
1172        * @brief Marshals value v as marshalled type into message
1173        */
1174       static void set(const DBusWrapper::MessageIterPtr& iter, const ValueOrError< ARGS... >& args)
1175       {
1176         signature_tuple_helper< 0, sizeof...(ARGS), ARGS... >::set(iter, args.getValues());
1177       }
1178
1179       /**
1180        * @brief Marshals value from marshalled type into variable v
1181        */
1182       static bool get(const DBusWrapper::MessageIterPtr& iter, ValueOrError< ARGS... >& args)
1183       {
1184         return signature_tuple_helper< 0, sizeof...(ARGS), ARGS... >::get(iter, args.getValues());
1185       }
1186     };
1187
1188     /**
1189      * @brief Signature class for marshalling ValueOrError<void> type
1190      */
1191     template <>
1192     struct signature< ValueOrError< void > > : signature_helper<signature<ValueOrError<void>>>
1193     {
1194       static constexpr auto name_v = concat("ValueOrError<void>");
1195       static constexpr auto sig_v = concat("");
1196
1197       /**
1198        * @brief Marshals value v as marshalled type into message
1199        */
1200       static void set(const DBusWrapper::MessageIterPtr& iter, const ValueOrError< void >& args)
1201       {
1202       }
1203
1204       /**
1205        * @brief Marshals value from marshalled type into variable v
1206        */
1207       static bool get(const DBusWrapper::MessageIterPtr& iter, ValueOrError< void >& args)
1208       {
1209         return true;
1210       }
1211     };
1212
1213     /**
1214      * @brief Signature class for marshalling ValueOrError<> type
1215      */
1216     template <>
1217     struct signature< ValueOrError<> > : signature_helper<signature<ValueOrError<>>>
1218     {
1219       static constexpr auto name_v = concat("ValueOrError<>");
1220       static constexpr auto sig_v = concat("");
1221
1222       /**
1223        * @brief Marshals value v as marshalled type into message
1224        */
1225       static void set(const DBusWrapper::MessageIterPtr& iter, const ValueOrError<>& args)
1226       {
1227       }
1228
1229       /**
1230        * @brief Marshals value from marshalled type into variable v
1231        */
1232       static bool get(const DBusWrapper::MessageIterPtr& iter, ValueOrError<>& args)
1233       {
1234         return true;
1235       }
1236     };
1237
1238     /**
1239      * @brief Signature class for marshalling pair of types
1240      */
1241     template < typename A, typename B >
1242     struct signature< std::pair< A, B > > : signature_helper<signature<std::pair<A, B>>>
1243     {
1244       static constexpr auto name_v = concat("pair<", signature_tuple_helper<0, 2, A, B>::name_v, ">");
1245       static constexpr auto sig_v = concat("(", signature_tuple_helper<0, 2, A, B>::sig_v, ")");
1246
1247       /**
1248        * @brief Marshals value v as marshalled type into message
1249        */
1250       static void set(const DBusWrapper::MessageIterPtr& iter, const std::pair< A, B >& ab, bool dictionary = false)
1251       {
1252         auto entry = DBUS_W->eldbus_message_iter_container_new_impl(iter, dictionary ? 'e' : 'r', "");
1253         signature_tuple_helper< 0, 2, A, B >::set(entry, ab);
1254       }
1255
1256       /**
1257        * @brief Marshals value from marshalled type into variable v
1258        */
1259       static bool get(const DBusWrapper::MessageIterPtr& iter, std::pair< A, B >& ab)
1260       {
1261         auto entry = DBUS_W->eldbus_message_iter_get_and_next_by_type_impl(iter, 'r');
1262         if (!entry) {
1263           entry = DBUS_W->eldbus_message_iter_get_and_next_by_type_impl(iter, '{');
1264           if (!entry) return false;
1265         }
1266
1267         std::tuple< A, B > ab_tmp;
1268         auto z = signature_tuple_helper< 0, 2, A, B >::get(entry, ab_tmp);
1269         if (z)
1270         {
1271           ab.first = std::move(std::get< 0 >(ab_tmp));
1272           ab.second = std::move(std::get< 1 >(ab_tmp));
1273         }
1274         return z;
1275       }
1276     };
1277
1278     /**
1279      * @brief Signature class for marshalling std::vector template type
1280      *
1281      * This marshals container's content as DBUS a ascii character type code.
1282      */
1283     template < typename A >
1284     struct signature< std::vector< A > > : signature_helper<signature<std::vector<A>>>
1285     {
1286       static constexpr auto name_v = concat("vector<", signature<A>::name_v, ">");
1287       static constexpr auto sig_v = concat("a", signature<A>::sig_v);
1288
1289       /**
1290        * @brief Marshals value v as marshalled type into message
1291        */
1292       static void set(const DBusWrapper::MessageIterPtr& iter, const std::vector< A >& v)
1293       {
1294         auto lst = DBUS_W->eldbus_message_iter_container_new_impl(iter, 'a', std::string{signature< A >::sig()});
1295         assert(lst);
1296         for (auto& a : v)
1297         {
1298           signature< A >::set(lst, a);
1299         }
1300       }
1301
1302       /**
1303        * @brief Marshals value from marshalled type into variable v
1304        */
1305       static bool get(const DBusWrapper::MessageIterPtr& iter, std::vector< A >& v)
1306       {
1307         auto s = DBUS_W->eldbus_message_iter_get_and_next_by_type_impl(iter, 'a');
1308         if (!s) return false;
1309         v.clear();
1310         A a;
1311         while (signature< A >::get(s, a))
1312           v.push_back(std::move(a));
1313
1314         return true;
1315       }
1316     };
1317
1318     /**
1319      * @brief Signature class for marshalling std::array template type
1320      *
1321      * This marshals container's content as DBUS a ascii character type code.
1322      */
1323     template < typename A, size_t N >
1324     struct signature< std::array< A, N > > : signature_helper<signature<std::array<A, N>>>
1325     {
1326       static constexpr auto name_v = concat("array<", signature<A>::name_v, ", ", to_string<N>::value, ">");
1327       static constexpr auto sig_v = concat("a", signature<A>::sig_v);
1328
1329       /**
1330        * @brief Marshals value v as marshalled type into message
1331        */
1332       static void set(const DBusWrapper::MessageIterPtr& iter, const std::array< A, N >& v)
1333       {
1334         auto lst = DBUS_W->eldbus_message_iter_container_new_impl(iter, 'a', std::string{signature< A >::sig()});
1335         assert(lst);
1336         for (auto& a : v)
1337         {
1338           signature< A >::set(lst, a);
1339         }
1340       }
1341
1342       /**
1343        * @brief Marshals value from marshalled type into variable v
1344        */
1345       static bool get(const DBusWrapper::MessageIterPtr& iter, std::array< A, N >& v)
1346       {
1347         auto s = DBUS_W->eldbus_message_iter_get_and_next_by_type_impl(iter, 'a');
1348         if (!s)
1349           return false;
1350         for (auto& a : v)
1351         {
1352           if (!signature< A >::get(s, a))
1353             return false;
1354         }
1355         return true;
1356       }
1357     };
1358
1359     /**
1360      * @brief Signature class for marshalling EldbusVariant type
1361      *
1362      * This marshals variant's content as DBUS v ascii character type code.
1363      */
1364     template < typename A >
1365     struct signature< EldbusVariant< A > > : signature_helper<signature<EldbusVariant<A>>>
1366     {
1367       static constexpr auto name_v = concat("variant<", signature<A>::name_v, ">");
1368       static constexpr auto sig_v = concat("v");
1369
1370       /**
1371        * @brief Marshals value v as marshalled type into message
1372        */
1373       static void set(const DBusWrapper::MessageIterPtr& iter, const EldbusVariant< A >& v)
1374       {
1375         set(iter, v.value);
1376       }
1377
1378       /**
1379        * @brief Marshals value v as marshalled type into message
1380        */
1381       static void set(const DBusWrapper::MessageIterPtr& iter, const A& v)
1382       {
1383         auto var = DBUS_W->eldbus_message_iter_container_new_impl(iter, 'v', std::string{signature< A >::sig()});
1384         signature< A >::set(var, v);
1385       }
1386
1387       /**
1388        * @brief Marshals value from marshalled type into variable v
1389        */
1390       static bool get(const DBusWrapper::MessageIterPtr& iter, EldbusVariant< A >& v)
1391       {
1392         auto s = DBUS_W->eldbus_message_iter_get_and_next_by_type_impl(iter, 'v');
1393         if (!s)
1394           return false;
1395         return signature< A >::get(s, v.value);
1396       }
1397     };
1398
1399     /**
1400      * @brief Signature class for marshalling std::unordered_map template type
1401      *
1402      * This marshals container's content as DBUS {} ascii character type code.
1403      * Note, that library doesnt check, if the key is basic type, as DBUS
1404      * specification mandates.
1405      * User can always exchange std::unordered_map for std::map and the reverse.
1406      * User can receive such values as std::vector of std::pair<key, value> values.
1407      * Order of such values is unspecified.
1408      */
1409     template < typename A, typename B >
1410     struct signature< std::unordered_map< A, B > > : signature_helper<signature<std::unordered_map<A, B>>>
1411     {
1412       static constexpr auto name_v = concat("unordered_map<", signature<A>::name_v, ", ", signature<B>::name_v, ">");
1413       static constexpr auto sig_v = concat("a{", signature_tuple_helper<0, 2, A, B>::sig_v, "}");
1414
1415       /**
1416        * @brief Marshals value v as marshalled type into message
1417        */
1418       static void set(const DBusWrapper::MessageIterPtr& iter, const std::unordered_map< A, B >& v)
1419       {
1420         auto sig = "{" + std::string{signature_tuple_helper< 0, 2, A, B >::sig()} + "}";
1421         auto lst = DBUS_W->eldbus_message_iter_container_new_impl(iter, 'a', sig);
1422         assert(lst);
1423         for (auto& a : v)
1424         {
1425           signature< std::pair< A, B > >::set(lst, a, true);
1426         }
1427       }
1428
1429       /**
1430        * @brief Marshals value from marshalled type into variable v
1431        */
1432       static bool get(const DBusWrapper::MessageIterPtr& iter, std::unordered_map< A, B >& v)
1433       {
1434         auto s = DBUS_W->eldbus_message_iter_get_and_next_by_type_impl(iter, 'a');
1435         v.clear();
1436         if (!s)
1437           return false;
1438         std::pair< A, B > a;
1439         while (signature< std::pair< A, B > >::get(s, a))
1440           v.insert(std::move(a));
1441         return true;
1442       }
1443     };
1444
1445     /**
1446      * @brief Signature class for marshalling std::unordered_map template type
1447      *
1448      * This marshals container's content as DBUS {} ascii character type code.
1449      * Note, that library doesnt check, if the key is basic type, as DBUS
1450      * specification mandates.
1451      * User can always exchange std::unordered_map for std::map and the reverse.
1452      * User can receive such values as std::vector of std::pair<key, value> values.
1453      * Order of such values is unspecified.
1454      */
1455     template < typename A, typename B >
1456     struct signature< std::map< A, B > > : signature_helper<signature<std::map<A, B>>>
1457     {
1458       static constexpr auto name_v = concat("map<", signature<A>::name_v, ", ", signature<B>::name_v, ">");
1459       static constexpr auto sig_v = concat("a{", signature_tuple_helper<0, 2, A, B>::sig_v, "}");
1460
1461       /**
1462        * @brief Marshals value v as marshalled type into message
1463        */
1464       static void set(const DBusWrapper::MessageIterPtr& iter, const std::map< A, B >& v)
1465       {
1466         auto sig = "{" + std::string{signature_tuple_helper< 0, 2, A, B >::sig()} + "}";
1467         auto lst = DBUS_W->eldbus_message_iter_container_new_impl(iter, 'a', sig);
1468         assert(lst);
1469         for (auto& a : v)
1470         {
1471           signature< std::pair< A, B > >::set(lst, a, true);
1472         }
1473       }
1474
1475       /**
1476        * @brief Marshals value from marshalled type into variable v
1477        */
1478       static bool get(const DBusWrapper::MessageIterPtr& iter, std::map< A, B >& v)
1479       {
1480         auto s = DBUS_W->eldbus_message_iter_get_and_next_by_type_impl(iter, 'a');
1481         if (!s)
1482           return false;
1483         std::pair< A, B > a;
1484         while (signature< std::pair< A, B > >::get(s, a))
1485           v.insert(std::move(a));
1486         return true;
1487       }
1488     };
1489
1490     /**
1491      * @brief Signature helper class for marshalling const reference types
1492      */
1493     template < typename A >
1494     struct signature< const A& > : signature_helper<signature<const A &>>
1495     {
1496       static constexpr auto name_v = concat("const ", signature<A>::name_v, "&");
1497       static constexpr auto sig_v = signature<A>::sig_v;
1498
1499       /**
1500        * @brief Marshals value v as marshalled type into message
1501        */
1502       static void set(const DBusWrapper::MessageIterPtr& iter, const A& v)
1503       {
1504         signature< A >::set(iter, v);
1505       }
1506
1507       /**
1508        * @brief Marshals value from marshalled type into variable v
1509        */
1510       static void get(const DBusWrapper::MessageIterPtr& iter, A& v)
1511       {
1512         signature< A >::get(iter, v);
1513       }
1514     };
1515
1516     /**
1517      * @brief Signature helper class for marshalling reference types
1518      */
1519     template < typename A >
1520     struct signature< A& > : signature_helper<signature<A &>>
1521     {
1522       static constexpr auto name_v = concat(signature<A>::name_v, "&");
1523       static constexpr auto sig_v = signature<A>::sig_v;
1524
1525       /**
1526        * @brief Marshals value v as marshalled type into message
1527        */
1528       static void set(const DBusWrapper::MessageIterPtr& iter, const A& v)
1529       {
1530         signature< A >::set(iter, v);
1531       }
1532
1533       /**
1534        * @brief Marshals value from marshalled type into variable v
1535        */
1536       static void get(const DBusWrapper::MessageIterPtr& iter, A& v)
1537       {
1538         signature< A >::get(iter, v);
1539       }
1540     };
1541
1542     /**
1543      * @brief Signature helper class for marshalling const types
1544      */
1545     template < typename A >
1546     struct signature< const A > : signature_helper<signature<const A>>
1547     {
1548       static constexpr auto name_v = concat("const ", signature<A>::name_v);
1549       static constexpr auto sig_v = signature<A>::sig_v;
1550
1551       /**
1552        * @brief Marshals value v as marshalled type into message
1553        */
1554       static void set(const DBusWrapper::MessageIterPtr& iter, const A& v)
1555       {
1556         signature< A >::set(iter, v);
1557       }
1558
1559       /**
1560        * @brief Marshals value from marshalled type into variable v
1561        */
1562       static void get(const DBusWrapper::MessageIterPtr& iter, A& v)
1563       {
1564         signature< A >::get(iter, v);
1565       }
1566     };
1567
1568     using CallId = DBusWrapper::CallId;
1569
1570     template < typename ValueType >
1571     ValueType unpackValues(CallId callId, const DBusWrapper::MessagePtr& msg)
1572     {
1573       static const std::string sig{signature< ValueType >::sig().data()};
1574
1575       auto iter = DBUS_W->eldbus_message_iter_get_impl(msg, false);
1576       ValueType r;
1577
1578       if (iter)
1579       {
1580         if (!signature< ValueType >::get(iter, r))
1581         {
1582           DBUS_DEBUG("ValueType is %s", signature< ValueType >::name().data());
1583           r = Error{ "call " + std::to_string(callId.id) + ": failed to unpack values, got signature '" +
1584                 DBUS_W->eldbus_message_signature_get_impl(msg) + "', expected '" + sig + "'" };
1585         }
1586       }
1587       else
1588       {
1589         r = Error{ "call " + std::to_string(callId.id) + ": failed to get iterator" };
1590       }
1591       return r;
1592     }
1593
1594     inline void packValues_helper(const DBusWrapper::MessageIterPtr&) {}
1595
1596     template < typename A, typename... ARGS >
1597     void packValues_helper(const DBusWrapper::MessageIterPtr& iter, A&& a, ARGS&&... r)
1598     {
1599       signature< A >::set(iter, std::forward< A >(a));
1600       packValues_helper(iter, std::forward< ARGS >(r)...);
1601     }
1602
1603     template < typename... ARGS >
1604     void packValues(CallId callId, const DBusWrapper::MessagePtr& msg, ARGS&&... r)
1605     {
1606       auto iter = DBUS_W->eldbus_message_iter_get_impl(msg, true);
1607       packValues_helper(iter, std::forward< ARGS >(r)...);
1608     }
1609
1610     struct ConnectionState
1611     {
1612       DBusWrapper::ConnectionPtr connection;
1613       DBusWrapper::ObjectPtr object;
1614       DBusWrapper::ProxyPtr proxy, propertiesProxy;
1615     };
1616
1617     template < typename RETTYPE, typename... ARGS >
1618     RETTYPE call(CallId callId, const ConnectionState& connectionState, bool property, const std::string& funcName, const ARGS&... args)
1619     {
1620       const auto& proxy = property ? connectionState.propertiesProxy : connectionState.proxy;
1621       if (!proxy)
1622       {
1623         DBUS_DEBUG("call %d: not initialized", callId.id);
1624         return Error{ "not initialized" };
1625       }
1626
1627       DBUS_DEBUG("call %d: calling '%s'", callId.id, funcName.c_str());
1628       auto msg = DBUS_W->eldbus_proxy_method_call_new_impl(proxy, funcName);
1629       if (!msg)
1630       {
1631         DBUS_DEBUG("call %d: failed", callId.id);
1632         return Error{ "failed to create message" };
1633       }
1634
1635       detail::packValues(callId, msg, args...);
1636       auto reply = DBUS_W->eldbus_proxy_send_and_block_impl(proxy, msg);
1637       DBUS_DEBUG("call %d: calling '%s' done", callId.id, funcName.c_str());
1638       if (!reply)
1639       {
1640         DBUS_DEBUG("call %d: failed", callId.id);
1641         return Error{ "eldbus returned null as reply" };
1642       }
1643       std::string errname, errmsg;
1644       if (DBUS_W->eldbus_message_error_get_impl(reply, errname, errmsg))
1645       {
1646         DBUS_DEBUG("call %d: %s: %s", callId.id, errname.c_str(), errmsg.c_str());
1647         return Error{ errname + ": " + errmsg };
1648       }
1649       DBUS_DEBUG("call %d: got reply with signature '%s'", callId.id,
1650         DBUS_W->eldbus_message_signature_get_impl(reply).c_str());
1651       return detail::unpackValues< RETTYPE >(callId, reply);
1652     }
1653
1654     template < typename RETTYPE, typename... ARGS >
1655     void asyncCall(CallId callId, const ConnectionState& connectionState,
1656       bool property, const std::string& funcName,
1657       std::function< void(RETTYPE) > callback, const ARGS&... args)
1658     {
1659       const auto& proxy = property ? connectionState.propertiesProxy : connectionState.proxy;
1660       if (!proxy)
1661       {
1662         DBUS_DEBUG("call %d: not initialized", callId.id);
1663         callback(Error{ "not initialized" });
1664         return;
1665       }
1666
1667       auto msg = DBUS_W->eldbus_proxy_method_call_new_impl(proxy, funcName);
1668       if (!msg)
1669       {
1670         DBUS_DEBUG("call %d: failed", callId.id);
1671         callback(Error{ "failed to create message" });
1672         return;
1673       }
1674
1675       detail::packValues(callId, msg, args...);
1676       auto pending = DBUS_W->eldbus_proxy_send_impl(proxy, msg, [callback, callId, proxy](const DBusWrapper::MessagePtr& reply) {
1677         DBUS_DEBUG("call %d: calling done", callId.id);
1678         if (!reply)
1679         {
1680           DBUS_DEBUG("call %d: failed", callId.id);
1681           callback(Error{ "eldbus returned null as reply" });
1682         }
1683         else
1684         {
1685           std::string errname, errmsg;
1686           if (DBUS_W->eldbus_message_error_get_impl(reply, errname, errmsg))
1687           {
1688             DBUS_DEBUG("call %d: %s: %s", callId.id, errname.c_str(), errmsg.c_str());
1689             callback(Error{ errname + ": " + errmsg });
1690           }
1691           else
1692           {
1693             DBUS_DEBUG("call %d: got reply with signature '%s'", callId.id,
1694               DBUS_W->eldbus_message_signature_get_impl(reply).c_str());
1695             callback(detail::unpackValues< RETTYPE >(callId, reply));
1696           }
1697         }
1698         }
1699       );
1700       if (pending)
1701       {
1702         DBUS_DEBUG("call %d: call sent", callId.id);
1703       }
1704       else
1705       {
1706         DBUS_DEBUG("call %d: failed to send call", callId.id);
1707         callback(Error{ "failed to send call" });
1708       }
1709     }
1710
1711     inline void displayDebugCallInfo(CallId callId, const std::string& funcName, const std::string& info, const std::string& interfaceName)
1712     {
1713       DBUS_DEBUG("call %d: %s iname = %s fname = %s", callId.id, info.c_str(), interfaceName.c_str(), funcName.c_str());
1714     }
1715
1716     inline void displayDebugCallInfoSignal(CallId callId, const std::string& funcName, const std::string& info, const std::string& interfaceName)
1717     {
1718       DBUS_DEBUG("call %d: %s signal iname = %s fname = %s", callId.id, info.c_str(), interfaceName.c_str(), funcName.c_str());
1719     }
1720
1721     inline void displayDebugCallInfoProperty(CallId callId, const std::string& funcName, std::string info, const std::string& interfaceName,
1722       const std::string& propertyName)
1723     {
1724       DBUS_DEBUG("call %d: %s iname = %s pname = %s", callId.id, info.c_str(), interfaceName.c_str(), propertyName.c_str());
1725     }
1726
1727     using StringStorage = DBusWrapper::StringStorage;
1728
1729     template < typename A, typename... ARGS >
1730     struct EldbusArgGenerator_Helper
1731     {
1732       static void add(std::vector< std::pair<std::string, std::string> >& r)
1733       {
1734         auto s = r.size();
1735         auto sig = std::string{signature< A >::sig()};
1736         assert(!sig.empty());
1737         auto name = "p" + std::to_string(s + 1);
1738         r.push_back({ std::move(sig), std::move(name) });
1739         EldbusArgGenerator_Helper<ARGS...>::add(r);
1740       }
1741     };
1742
1743     template <>
1744     struct EldbusArgGenerator_Helper< void >
1745     {
1746       static void add(std::vector< std::pair<std::string, std::string> >&)
1747       {
1748       }
1749     };
1750
1751     template <>
1752     struct EldbusArgGenerator_Helper< ValueOrError< void >, void >
1753     {
1754       static void add(std::vector< std::pair<std::string, std::string> >&)
1755       {
1756       }
1757     };
1758     template <>
1759     struct EldbusArgGenerator_Helper< ValueOrError<>, void >
1760     {
1761       static void add(std::vector< std::pair<std::string, std::string> >&)
1762       {
1763       }
1764     };
1765
1766     template < typename... ARGS >
1767     struct EldbusArgGenerator_Helper< std::tuple< ARGS... > >
1768     {
1769       static void add(std::vector< std::pair<std::string, std::string> >& r)
1770       {
1771         EldbusArgGenerator_Helper< ARGS..., void >::add(r);
1772       }
1773     };
1774
1775     template < typename RetType >
1776     struct dbus_interface_return_type_traits
1777     {
1778       using type = ValueOrError< RetType >;
1779     };
1780
1781     template < typename... ARGS >
1782     struct dbus_interface_return_type_traits< ValueOrError< ARGS... > >
1783     {
1784       using type = ValueOrError< ARGS... >;
1785     };
1786
1787     template < typename T >
1788     struct dbus_interface_traits;
1789     template < typename RetType, typename... ARGS >
1790     struct dbus_interface_traits< RetType(ARGS...) >
1791     {
1792       using Ret = typename dbus_interface_return_type_traits< RetType >::type;
1793       using SyncCB = std::function< Ret(ARGS...) >;
1794       using AsyncCB = std::function< void(std::function< void(Ret) >, ARGS...) >;
1795       using VEArgs = ValueOrError< ARGS... >;
1796     };
1797
1798     template < typename T >
1799     struct EldbusArgGenerator_Args;
1800     template < typename RetType, typename... ARGS >
1801     struct EldbusArgGenerator_Args< RetType(ARGS...) >
1802     {
1803       static std::string name()
1804       {
1805         return std::string{signature_tuple_helper< 0, sizeof...(ARGS), ARGS... >::name()};
1806       }
1807       static std::vector< std::pair<std::string, std::string> > get()
1808       {
1809         std::vector< std::pair<std::string, std::string> > tmp;
1810         EldbusArgGenerator_Helper< ARGS..., void >::add(tmp);
1811         return tmp;
1812       }
1813     };
1814
1815     template < typename T >
1816     struct EldbusArgGenerator_ReturnType;
1817     template < typename RetType, typename... ARGS >
1818     struct EldbusArgGenerator_ReturnType< RetType(ARGS...) >
1819     {
1820       static std::string name()
1821       {
1822         return std::string{signature< RetType >::name()};
1823       }
1824       static std::vector< std::pair<std::string, std::string> > get()
1825       {
1826         std::vector< std::pair<std::string, std::string> > tmp;
1827         EldbusArgGenerator_Helper< RetType, void >::add(tmp);
1828         return tmp;
1829       }
1830     };
1831
1832     template < typename T >
1833     struct EldbusArgGenerator_ReturnType;
1834     template < typename... ARGS >
1835     struct EldbusArgGenerator_ReturnType< void(ARGS...) >
1836     {
1837       static std::string name()
1838       {
1839         return "";
1840       }
1841       static std::vector< std::pair<std::string, std::string> > get()
1842       {
1843         return {};
1844       }
1845     };
1846
1847   }
1848
1849   using ConnectionType = DBusWrapper::ConnectionType;
1850
1851   /**
1852    * @brief Class representing client's end of DBUS connection
1853    *
1854    * Allows calling (synchronous and asynchronous) methods on selected interface
1855    * Allows (synchronous and asynchronous) setting / getting properties.
1856    * Allows registering signals.
1857    */
1858   class DBusClient
1859   {
1860     struct ConnectionInfo
1861     {
1862       std::string interfaceName, busName, pathName;
1863     };
1864   public:
1865     /**
1866      * @brief Default constructor, creates non-connected object.
1867      */
1868     DBusClient() = default;
1869
1870     /**
1871      * @brief Connects to dbus choosen by tp, using given arguments
1872      *
1873      * @param bus_name name of the bus to connect to
1874      * @param path_name object's path
1875      * @param interface_name interface name
1876      */
1877     DBusClient(std::string busName_, std::string pathName_, std::string interfaceName_,
1878       ConnectionType tp);
1879
1880     /**
1881      * @brief Connects to dbus using connection conn
1882      *
1883      * @param bus_name name of the bus to connect to
1884      * @param path_name object's path
1885      * @param interface_name interface name
1886      * @param conn connection object from getDBusConnectionByType call
1887      */
1888     DBusClient(std::string busName_, std::string pathName_, std::string interfaceName_,
1889       const DBusWrapper::ConnectionPtr& conn = {});
1890
1891     /**
1892      * @brief Destructor object.
1893      *
1894      * All signals added will be disconnected.
1895      * All asynchronous calls will be cancelled, their callback's will be called
1896      * with failure message.
1897      */
1898     ~DBusClient() = default;
1899     DBusClient(const DBusClient&) = delete;
1900     DBusClient(DBusClient&&) = default;
1901
1902     DBusClient& operator=(DBusClient&&) = default;
1903     DBusClient& operator=(const DBusClient&) = delete;
1904
1905     /**
1906      * @brief bool operator
1907      *
1908      * Returns true, if object is connected to DBUS
1909      */
1910     explicit operator bool() const
1911     {
1912       return bool(connectionState->proxy);
1913     }
1914
1915     /**
1916      * @brief Helper class for calling a method
1917      *
1918      * Template type T defines both arguments sent to the method
1919      * and expected values. Receiving different values will be reported as
1920      * error. For example:
1921      * \code{.cpp} Method<int(float, float)> \endcode
1922      * defines method, which takes two arguments (two floats) and return
1923      * single value of type int.
1924      */
1925     template < typename T >
1926     struct Method
1927     {
1928       using RetType = typename detail::dbus_interface_traits< T >::Ret;
1929       const detail::ConnectionState& connectionState;
1930       std::string funcName;
1931       std::string info;
1932       std::shared_ptr< ConnectionInfo > connectionInfo;
1933
1934       /**
1935        * @brief Executes synchronous call on DBUS's method
1936        *
1937        * The function returns ValueOrError<...> object, which
1938        * contains either received values or error message.
1939        *
1940        * @param args arguments to pass to the method
1941        */
1942       template < typename... ARGS >
1943       RetType call(const ARGS&... args)
1944       {
1945         detail::CallId callId;
1946         detail::displayDebugCallInfo(callId, funcName, info, connectionInfo->interfaceName);
1947         return detail::call< RetType >(callId, connectionState, false, funcName, args...);
1948       }
1949
1950       /**
1951        * @brief Executes asynchronous call on DBUS's method
1952        *
1953        * The function calls callback with either received values or error message.
1954        *
1955        * @param callback callback functor, which will be called with return value(s) or error message
1956        * @param args arguments to pass to the method
1957        */
1958       template < typename... ARGS >
1959       void asyncCall(std::function< void(RetType) > callback, const ARGS&... args)
1960       {
1961         detail::CallId callId;
1962         detail::displayDebugCallInfo(callId, funcName, info, connectionInfo->interfaceName);
1963         detail::asyncCall< RetType >(callId, connectionState, false, funcName, std::move(callback), args...);
1964       }
1965     };
1966
1967     /**
1968      * @brief Helper class for calling a property
1969      *
1970      * Template type T defines type of the value hidden under property.
1971      * Note, that library automatically wraps both sent and received value into
1972      * DBUS's wrapper type.
1973      */
1974     template < typename T >
1975     struct Property
1976     {
1977       using RetType = typename detail::dbus_interface_return_type_traits< T >::type;
1978       using VariantRetType = typename detail::dbus_interface_return_type_traits< EldbusVariant< T > >::type;
1979       const detail::ConnectionState& connectionState;
1980       std::string propName;
1981       std::string info;
1982       std::shared_ptr< ConnectionInfo > connectionInfo;
1983
1984       /**
1985        * @brief executes synchronous get on property
1986        *
1987        * The function returns ValueOrError<...> object, which
1988        * contains either received values or error message.
1989        */
1990       RetType get()
1991       {
1992         detail::CallId callId;
1993         detail::displayDebugCallInfoProperty(callId, "Get", info, connectionInfo->interfaceName, propName);
1994         auto z = detail::call< VariantRetType >(callId, connectionState, true, "Get", connectionInfo->interfaceName, propName);
1995         if (!z)
1996           return z.getError();
1997         return { std::get< 0 >(z.getValues()).value };
1998       }
1999
2000       /**
2001        * @brief executes asynchronous get on property
2002        *
2003        * The function calls callback with either received values or error message.
2004        *
2005        * @param callback callback functor, which will be called with return value(s) or error message
2006        */
2007       void asyncGet(std::function< void(RetType) > callback)
2008       {
2009         detail::CallId callId;
2010         detail::displayDebugCallInfoProperty(callId, "Get", info, connectionInfo->interfaceName, propName);
2011         auto cc = [callback](VariantRetType reply) {
2012           if (reply)
2013             callback(std::move(std::get< 0 >(reply.getValues()).value));
2014           else
2015             callback(reply.getError());
2016         };
2017         detail::asyncCall< VariantRetType >(callId, connectionState, true, "Get", std::move(cc), connectionInfo->interfaceName, propName);
2018       }
2019
2020       /**
2021        * @brief executes synchronous set on property
2022        *
2023        * The function returns ValueOrError<void> object, with
2024        * possible error message.
2025        */
2026       ValueOrError< void > set(const T& r)
2027       {
2028         detail::CallId callId;
2029         detail::displayDebugCallInfoProperty(callId, "Set", info, connectionInfo->interfaceName, propName);
2030         EldbusVariant< T > variantValue{ std::move(r) };
2031         return detail::call< ValueOrError< void > >(callId, connectionState, true, "Set", connectionInfo->interfaceName, propName, variantValue);
2032       }
2033
2034       /**
2035        * @brief executes asynchronous get on property
2036        *
2037        * The function calls callback with either received values or error message.
2038        *
2039        * @param callback callback functor, which will be called with return value(s) or error message
2040        */
2041       void asyncSet(std::function< void(ValueOrError< void >) > callback, const T& r)
2042       {
2043         detail::CallId callId;
2044         detail::displayDebugCallInfoProperty(callId, "Set", info, connectionInfo->interfaceName, propName);
2045         EldbusVariant< T > variantValue{ std::move(r) };
2046         detail::asyncCall< ValueOrError< void > >(callId, connectionState, true, "Set", std::move(callback), connectionInfo->interfaceName, propName, variantValue);
2047       }
2048     };
2049
2050     /**
2051      * @brief Constructs Property<...> object for calling properties
2052      *
2053      * The function constructs and returns proxy object for calling property.
2054      *
2055      * @param propName property name to set and / or query
2056      */
2057     template < typename PropertyType >
2058     Property< PropertyType > property(std::string propName)
2059     {
2060       return Property< PropertyType >{*connectionState, std::move(propName), info, connectionInfo};
2061     }
2062
2063     /**
2064      * @brief Constructs Method<...> object for calling methods
2065      *
2066      * The function constructs and returns proxy object for calling method.
2067      *
2068      * @param funcName function name to call
2069      */
2070     template < typename MethodType >
2071     Method< MethodType > method(std::string funcName)
2072     {
2073       return Method< MethodType >{*connectionState, std::move(funcName), info, connectionInfo};
2074     }
2075
2076     /**
2077      * @brief Registers notification callback, when property has changed
2078      *
2079      * The callback will be called with new value, when property's value has changed.
2080      * Note, that template type V must match expected type, otherwise undefined behavior will occur,
2081      * there's no check for this.
2082      */
2083     template < typename V >
2084     void addPropertyChangedEvent(std::string propertyName, std::function< void(V) > callback)
2085     {
2086       detail::CallId callId;
2087       detail::displayDebugCallInfoSignal(callId, propertyName, info, connectionInfo->interfaceName);
2088       DBUS_DEBUG("call %d: adding property", callId.id);
2089       auto& cI = this->connectionInfo;
2090       DBUS_W->add_property_changed_event_listener_impl(connectionState->proxy, cI->interfaceName, propertyName,
2091         [callback](const _Eina_Value* newValue) {
2092           V val = 0;
2093           if (!getFromEinaValue(newValue, &val))
2094           {
2095             DBUS_DEBUG("unable to get property's value");
2096             return;
2097           }
2098           callback(val);
2099         });
2100     }
2101
2102     /**
2103      * @brief Registers callback on the DBUS' signal
2104      *
2105      * The function registers callback signalName. When signal comes, callback will be called.
2106      * Callback object will exists as long as signal is registered. You can unregister signal
2107      * by destroying DBusClient object.
2108      *
2109      * @param signalName name of the signal to register
2110      * @param callback callback to call
2111      */
2112     template < typename SignalType >
2113     void addSignal(std::string signalName, std::function< SignalType > callback)
2114     {
2115       detail::CallId callId;
2116       detail::displayDebugCallInfoSignal(callId, signalName, info, connectionInfo->interfaceName);
2117       DBUS_W->eldbus_proxy_signal_handler_add_impl(connectionState->proxy, signalName,
2118         [callId, callback, signalName](const DBusWrapper::MessagePtr& msg) -> void {
2119           std::string errname, aux;
2120           if (DBUS_W->eldbus_message_error_get_impl(msg, errname, aux))
2121           {
2122             DBUS_DEBUG("call %d: Eldbus error: %s %s", callId.id, errname.c_str(), aux.c_str());
2123             return;
2124           }
2125           DBUS_DEBUG("call %d: received signal with signature '%s'", callId.id, DBUS_W->eldbus_message_signature_get_impl(msg).c_str());
2126           using ParamsType = typename detail::dbus_interface_traits< SignalType >::VEArgs;
2127           auto params = detail::unpackValues< ParamsType >(callId, msg);
2128           if (!params)
2129           {
2130             DBUS_DEBUG("call %d: failed: %s", callId.id, params.getError().message.c_str());
2131             return;
2132           }
2133           try
2134           {
2135             std::apply(callback, params.getValues());
2136           }
2137           catch (const Dali::DaliException &e)
2138           {
2139             DBUS_DEBUG("unhandled exception");
2140             assert(0);
2141           }
2142         });
2143     }
2144
2145   private:
2146     std::unique_ptr<detail::ConnectionState> connectionState{ new detail::ConnectionState };
2147     std::string info;
2148     std::shared_ptr< ConnectionInfo > connectionInfo;
2149
2150     static bool getFromEinaValue(const _Eina_Value* v, void* dst);
2151   };
2152
2153   /**
2154    * @brief Helper class describing DBUS's server interface
2155    *
2156    */
2157   class DBusInterfaceDescription
2158   {
2159     friend class DBusServer;
2160
2161   public:
2162     using MethodInfo = DBusWrapper::MethodInfo;
2163     using SignalInfo = DBusWrapper::SignalInfo;
2164     using PropertyInfo = DBusWrapper::PropertyInfo;
2165     using SignalId = DBusWrapper::SignalId;
2166
2167     /**
2168      * @brief Creates empty interface description with given name
2169      *
2170      * @param interfaceName name of the interface
2171      */
2172     DBusInterfaceDescription(std::string interfaceName);
2173
2174     /**
2175      * @brief adds new, synchronous method to the interface
2176      *
2177      * When method memberName is called on DBUS, callback functor will be called
2178      * with values received from DBUS. callback won't be called, if method was
2179      * called with invalid signature. Value returned from functor (or error message)
2180      * will be marshalled back to the caller.
2181      *
2182      * Template type T defines both arguments sent to the method
2183      * and expected values. Receiving different values will be reported as
2184      * error. For example:
2185      * \code{.cpp} Method<int(float, float)> \endcode
2186      * defines method, which takes two arguments (two floats) and return
2187      * single value of type int.
2188      *
2189      * @param memberName name of the method
2190      * @param callback functor, which will be called
2191      */
2192     template < typename T >
2193     void addMethod(const std::string& memberName, typename detail::dbus_interface_traits< T >::SyncCB callback)
2194     {
2195       detail::CallId callId;
2196       MethodInfo mi;
2197       methods.push_back(std::move(mi));
2198       auto& z = methods.back();
2199       z.in = detail::EldbusArgGenerator_Args< T >::get();
2200       z.out = detail::EldbusArgGenerator_ReturnType< T >::get();
2201       z.memberName = memberName;
2202       DBUS_DEBUG("call %d: method %s, in %s, out %s", callId.id, memberName.c_str(),
2203         detail::EldbusArgGenerator_Args< T >::name().c_str(),
2204         detail::EldbusArgGenerator_ReturnType< T >::name().c_str());
2205       z.callback = construct< T >(callId, callback);
2206       z.id = callId;
2207     }
2208
2209     /**
2210      * @brief adds new, synchronous property to the interface
2211      *
2212      * When property memberName is called on DBUS, respective callback functor will be called
2213      * with values received from DBUS. callback won't be called, if method was
2214      * called with invalid signature. Value returned from functor (or error message)
2215      * will be marshalled back to the caller.
2216      *
2217      * Template type T defines type of the value hidden under property.
2218      * Note, that library automatically wraps both sent and received value into
2219      * DBUS's wrapper type.
2220      *
2221      * @param memberName name of the method
2222      * @param getter functor, which will be called when property is being read
2223      * @param setter functor, which will be called when property is being set
2224      */
2225     template < typename T >
2226     void addProperty(const std::string& memberName, std::function< ValueOrError< T >() > getter, std::function< ValueOrError< void >(T) > setter)
2227     {
2228       properties.push_back({});
2229       auto& z = properties.back();
2230       z.memberName = memberName;
2231       z.typeSignature = detail::signature< T >::sig();
2232       if (getter)
2233       {
2234         detail::CallId getterId;
2235         z.getterId = getterId;
2236         DBUS_DEBUG("call %d: property %s (get) type %s", getterId.id, memberName.c_str(), detail::signature< T >::name().data());
2237         z.getCallback = [=](const DBusWrapper::MessagePtr& src, const DBusWrapper::MessageIterPtr& dst) -> std::string {
2238           try
2239           {
2240             auto v = std::apply(getter, std::tuple<>{});
2241             if (v)
2242             {
2243               detail::signature< T >::set(dst, std::get< 0 >(v.getValues()));
2244               DBUS_DEBUG("call %d: success", getterId.id);
2245               return "";
2246             }
2247             DBUS_DEBUG("call %d: failed: %s", getterId.id, v.getError().message.c_str());
2248             return v.getError().message;
2249           }
2250           catch (std::exception & e)
2251           {
2252             return std::string("unhandled exception (") + e.what() + ")";
2253           }
2254           catch (const Dali::DaliException &e)
2255           {
2256             return std::string("unhandled exception (") + e.condition + ")";
2257           }
2258         };
2259       }
2260       if (setter)
2261       {
2262         detail::CallId setterId;
2263         z.setterId = setterId;
2264         DBUS_DEBUG("call %d: property %s (set) type %s", setterId.id, memberName.c_str(), detail::signature< T >::name().data());
2265         z.setCallback = [=](const DBusWrapper::MessagePtr& src, const DBusWrapper::MessageIterPtr& src_iter) -> std::string {
2266           std::tuple< T > value;
2267           auto src_signature = DBUS_W->eldbus_message_iter_signature_get_impl(src_iter);
2268           if (detail::signature< T >::get(src_iter, std::get< 0 >(value)))
2269           {
2270             try
2271             {
2272               auto v = std::apply(setter, std::move(value));
2273               if (v)
2274               {
2275                 DBUS_DEBUG("call %d: success", setterId.id);
2276                 return "";
2277               }
2278               DBUS_DEBUG("call %d: failed: %s", setterId.id, v.getError().message.c_str());
2279               return v.getError().message;
2280             }
2281             catch (std::exception & e)
2282             {
2283               return std::string("unhandled exception (") + e.what() + ")";
2284             }
2285             catch (const Dali::DaliException &e)
2286             {
2287               return std::string("unhandled exception (") + e.condition + ")";
2288             }
2289           }
2290           DBUS_DEBUG("call %d: failed to unpack values, got signature '%s', expected '%s'", setterId.id,
2291             src_signature.c_str(), detail::signature< T >::sig().data());
2292           return "call " + std::to_string(setterId.id) + ": failed to unpack values, got signature '" +
2293             src_signature + "', expected '" + std::string{detail::signature< T >::sig()} + "'";
2294         };
2295       }
2296     }
2297
2298     /**
2299      * @brief adds new signal to the interface
2300      *
2301      * Template types ARGS defines values, which will be emited with the signal
2302      *
2303      * @param memberName name of the method
2304      */
2305     template < typename... ARGS >
2306     SignalId addSignal(const std::string& memberName)
2307     {
2308       detail::CallId callId;
2309       signals.push_back({});
2310       auto& z = signals.back();
2311       z.memberName = memberName;
2312       z.args = detail::EldbusArgGenerator_Args< void(ARGS...) >::get(DBUS_W->Strings);
2313       z.id = callId;
2314       DBUS_DEBUG("call %d: signal %s", callId.id, memberName.c_str());
2315       return SignalId{ callId };
2316     }
2317
2318   private:
2319     std::vector< MethodInfo > methods;
2320     std::vector< PropertyInfo > properties;
2321     std::vector< SignalInfo > signals;
2322     std::string interfaceName;
2323
2324     template < typename T >
2325     std::function< DBusWrapper::MessagePtr(const DBusWrapper::MessagePtr & msg) > construct(detail::CallId callId,
2326       typename detail::dbus_interface_traits< T >::SyncCB callback)
2327     {
2328       using VEArgs = typename detail::dbus_interface_traits< T >::VEArgs;
2329       return [=](const DBusWrapper::MessagePtr& msg) -> DBusWrapper::MessagePtr {
2330         DBUS_DEBUG("call %d: entering", callId.id);
2331         DBusWrapper::MessagePtr ret = {};
2332         auto args = detail::unpackValues< VEArgs >(callId, msg);
2333         if (args)
2334         {
2335           try
2336           {
2337             auto v = std::apply(callback, std::move(args.getValues()));
2338             if (v)
2339             {
2340               DBUS_DEBUG("call %d: success", callId.id);
2341               ret = DBUS_W->eldbus_message_method_return_new_impl(msg);
2342               detail::packValues(callId, ret, v);
2343             }
2344             else
2345             {
2346               DBUS_DEBUG("call %d: failed: %s", callId.id, v.getError().message.c_str());
2347               ret = DBUS_W->eldbus_message_error_new_impl(msg, "org.freedesktop.DBus.Error.Failed", v.getError().message);
2348             }
2349           }
2350           catch (std::exception & e)
2351           {
2352             auto txt = std::string("unhandled exception (") + e.what() + ")";
2353             DBUS_DEBUG("call %d: failed: %s", callId.id, txt.c_str());
2354             ret = DBUS_W->eldbus_message_error_new_impl(msg, "org.freedesktop.DBus.Error.Failed", txt);
2355           }
2356           catch (const Dali::DaliException &e)
2357           {
2358             auto txt = std::string("unhandled exception (") + e.condition + ")";
2359             DBUS_DEBUG("call %d: failed: %s", callId.id, txt.c_str());
2360             ret = DBUS_W->eldbus_message_error_new_impl(msg, "org.freedesktop.DBus.Error.Failed", txt);
2361           }
2362         }
2363         else
2364         {
2365           std::ostringstream err;
2366           err << "expected signature '" << detail::signature< VEArgs >::sig() << "', got '" << DBUS_W->eldbus_message_signature_get_impl(msg) << "'";
2367           auto str = err.str();
2368           DBUS_DEBUG("call %d: failed: %s", callId.id, str.c_str());
2369           ret = DBUS_W->eldbus_message_error_new_impl(msg, "org.freedesktop.DBus.Error.InvalidArgs", str);
2370         }
2371         return ret;
2372       };
2373     }
2374   };
2375
2376   /**
2377    * @brief Class representing server's end of DBUS connection
2378    *
2379    * Allows listening (synchronously and asynchronously) on methods on selected interface
2380    * Allows listening (synchronously and asynchronously) on setting / getting properties.
2381    * Allows emiting signals.
2382    */
2383   class DBusServer
2384   {
2385   public:
2386     /**
2387      * @brief Constructs non-connected dbus server.
2388      */
2389     DBusServer() = default;
2390
2391     /**
2392      * @brief Constructs dbus server on either system or user dbus connection.
2393      */
2394     DBusServer(ConnectionType tp);
2395
2396     /**
2397      * @brief Constructs dbus server on connection from getDBusConnectionByType
2398      */
2399     DBusServer(const DBusWrapper::ConnectionPtr& conn);
2400
2401     /**
2402      * @brief Destructor
2403      *
2404      * Destructor will properly destroy everything. Destructor will cancel
2405      * pending replies.
2406      */
2407     ~DBusServer() = default;
2408
2409     DBusServer(const DBusServer&) = delete;
2410     DBusServer(DBusServer&&) = default;
2411
2412     DBusServer& operator=(DBusServer&&) = default;
2413     DBusServer& operator=(const DBusServer&) = delete;
2414
2415     /**
2416      * @brief Registers interface on given path name
2417      *
2418      * @param pathName path object to register interface on.
2419      * @param dscr
2420      * @param fallback
2421      */
2422     void addInterface(const std::string& pathName, DBusInterfaceDescription& dscr, bool fallback = false);
2423
2424     /**
2425      * @brief Gets bus name of the current connection (must be connected)
2426      */
2427     std::string getBusName() const;
2428
2429     /**
2430      * @brief Returns connection object for this dbus server object
2431      *
2432      * @return connection object
2433      */
2434     DBusWrapper::ConnectionPtr getConnection();
2435
2436     /**
2437      * @brief Emits signal
2438      *
2439      * Emits signal based only on data passed to the function
2440      *
2441      * @param signal identifier of the signal
2442      * @param args values to emit
2443      */
2444     template < typename... ARGS >
2445     void emit2(const std::string& path, const std::string& interfaceName,
2446       const std::string& signalName, const ARGS&... args)
2447     {
2448       auto msg = DBUS_W->eldbus_message_signal_new_impl(path, interfaceName, signalName);
2449       detail::CallId id;
2450       detail::packValues(id, msg, args...);
2451       DBUS_W->eldbus_connection_send_impl(connection, msg);
2452     }
2453
2454     /**
2455      * @brief Returns current object path, when handling call to property / method
2456      *
2457      * User can call this function from inside callback used to handle property / method calls.
2458      * It will retrieve object's path used in the call. Note, that in asynchronous handling
2459      * of those calls user need to retrieve and store the current object / current connection
2460      * as the value will change at the moment user's callback handling will exit. For example:
2461      * \code{.cpp}
2462      * DBusInterfaceDescription interface{"name"};
2463      * auto handler_later = [](std::function<void(void)> done_cb) {
2464      *   // process something later on
2465      *   DBusServer::getCurrentObjectPath(); // this will return empty string
2466      * };
2467      * interface.addAsyncMethod<void()>("m", [=](std::function<void(void)> done_cb) {
2468      *   DBusServer::getCurrentObjectPath(); // this will current object's path
2469      *
2470      *   // do some processing later on and call done_cb, when it's done
2471      *   register_to_call_sometime_later_on(std::move(done_cb));
2472      * };
2473      * \endcode
2474      */
2475     static std::string getCurrentObjectPath() { return currentObjectPath; }
2476
2477     /**
2478      * @brief Returns current connection object, when handling call to property / method
2479      *
2480      * User can call this function from inside callback used to handle property / method calls.
2481      * It will retrieve object's path used in the call. Note, that in asynchronous handling
2482      * of those calls user need to retrieve and store the current object / current connection
2483      * as the value will change at the moment user's callback handling will exit. For example:
2484      * \code{.cpp}
2485      * DBusInterfaceDescription interface{"name"};
2486      * auto handler_later = [](std::function<void(void)> done_cb) {
2487      *   // process something later on
2488      *   DBusServer::getCurrentObjectPath(); // this will return empty string
2489      * };
2490      * interface.addAsyncMethod<void()>("m", [=](std::function<void(void)> done_cb) {
2491      *   DBusServer::getCurrentObjectPath(); // this will current object's path
2492      *
2493      *   // do some processing later on and call done_cb, when it's done
2494      *   register_to_call_sometime_later_on(std::move(done_cb));
2495      * };
2496      * \endcode
2497      */
2498     static const DBusWrapper::ConnectionPtr& getCurrentConnection() { return currentConnection; }
2499
2500     /// \cond
2501     class CurrentObjectSetter
2502     {
2503     public:
2504       CurrentObjectSetter(DBusWrapper::ConnectionPtr con, std::string path)
2505       {
2506         currentObjectPath = std::move(path);
2507         currentConnection = std::move(con);
2508       }
2509       ~CurrentObjectSetter()
2510       {
2511         currentObjectPath = "";
2512         currentConnection = {};
2513       }
2514       CurrentObjectSetter(const CurrentObjectSetter&) = delete;
2515       CurrentObjectSetter(CurrentObjectSetter&&) = delete;
2516       void operator=(const CurrentObjectSetter&) = delete;
2517       void operator=(CurrentObjectSetter&&) = delete;
2518     };
2519
2520   private:
2521     DBusWrapper::ConnectionPtr connection;
2522     struct DestructorObject {
2523       std::vector<std::function<void()>> destructors;
2524       ~DestructorObject() {
2525         for (auto& a : destructors) a();
2526       }
2527     };
2528
2529     std::unique_ptr<DestructorObject> destructorObject{ new DestructorObject() };
2530     static thread_local std::string currentObjectPath;
2531     static thread_local DBusWrapper::ConnectionPtr currentConnection;
2532
2533   };
2534
2535   DBusWrapper::ConnectionPtr getDBusConnectionByType(ConnectionType tp);
2536   DBusWrapper::ConnectionPtr getDBusConnectionByName(const std::string& name);
2537   std::string getConnectionName(const DBusWrapper::ConnectionPtr&);
2538 }
2539
2540 namespace std
2541 {
2542   template < size_t INDEX, typename... ARGS >
2543   inline auto get(DBus::ValueOrError< ARGS... >& v) -> decltype(std::get< INDEX >(v.getValues()))&
2544   {
2545     return std::get< INDEX >(v.getValues());
2546   }
2547
2548   template < size_t INDEX, typename... ARGS >
2549   inline auto get(const DBus::ValueOrError< ARGS... >& v) -> decltype(std::get< INDEX >(v.getValues()))
2550   {
2551     return std::get< INDEX >(v.getValues());
2552   }
2553 }
2554
2555 #endif // DALI_INTERNAL_ACCESSIBILITY_BRIDGE_DBUS_H