1 #ifndef DALI_INTERNAL_ACCESSIBILITY_BRIDGE_DBUS_H
2 #define DALI_INTERNAL_ACCESSIBILITY_BRIDGE_DBUS_H
5 * Copyright 2020 Samsung Electronics Co., Ltd
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
31 #include <string_view>
34 #include <type_traits>
35 #include <unordered_map>
39 #include <dali/devel-api/adaptor-framework/accessibility.h>
40 #include <dali/public-api/common/dali-common.h>
42 #define ATSPI_PREFIX_PATH "/org/a11y/atspi/accessible/"
43 #define ATSPI_NULL_PATH "/org/a11y/atspi/null"
52 struct DALI_ADAPTOR_API DBusWrapper
54 virtual ~DBusWrapper() = default;
56 enum class ConnectionType
62 #define DEFINE_TYPE(name, eldbus_name, unref_call) \
65 virtual ~name() = default; \
67 using name##Ptr = std::shared_ptr<name>; \
68 using name##WeakPtr = std::weak_ptr<name>;
70 DEFINE_TYPE(Connection, Eldbus_Connection, )
71 DEFINE_TYPE(MessageIter, Eldbus_Message_Iter, eldbus_message_iter_container_close(Value))
72 DEFINE_TYPE(Message, Eldbus_Message, eldbus_message_unref(Value))
73 DEFINE_TYPE(Proxy, Eldbus_Proxy, eldbus_proxy_unref(Value))
74 DEFINE_TYPE(Object, Eldbus_Object, eldbus_object_unref(Value))
75 DEFINE_TYPE(Pending, Eldbus_Pending, )
76 DEFINE_TYPE(EventPropertyChanged, Eldbus_Proxy_Event_Property_Changed, )
79 virtual ConnectionPtr eldbus_address_connection_get_impl(const std::string& addr) = 0;
81 #define eldbus_message_iter_arguments_append_impl_basic_impl(type_set, type_get, sig) \
82 virtual void eldbus_message_iter_arguments_append_impl(const MessageIterPtr& it, type_set src) = 0; \
83 virtual bool eldbus_message_iter_get_and_next_impl(const MessageIterPtr& it, type_get& dst) = 0;
84 #define eldbus_message_iter_arguments_append_impl_basic(type, sig) \
85 eldbus_message_iter_arguments_append_impl_basic_impl(type, type, sig)
88 eldbus_message_iter_arguments_append_impl_basic(uint8_t, y)
89 eldbus_message_iter_arguments_append_impl_basic(uint16_t, q)
90 eldbus_message_iter_arguments_append_impl_basic(uint32_t, u)
91 eldbus_message_iter_arguments_append_impl_basic(uint64_t, t)
92 eldbus_message_iter_arguments_append_impl_basic(int16_t, n)
93 eldbus_message_iter_arguments_append_impl_basic(int32_t, i)
94 eldbus_message_iter_arguments_append_impl_basic(int64_t, x)
95 eldbus_message_iter_arguments_append_impl_basic(double, d)
96 eldbus_message_iter_arguments_append_impl_basic(bool, b)
97 eldbus_message_iter_arguments_append_impl_basic_impl(const std::string&, std::string, s)
98 eldbus_message_iter_arguments_append_impl_basic_impl(const ObjectPath&, ObjectPath, o)
100 #undef eldbus_message_iter_arguments_append_impl_basic
101 #undef eldbus_message_iter_arguments_append_impl_basic_impl
103 virtual MessageIterPtr eldbus_message_iter_container_new_impl(const MessageIterPtr& it, int type, const std::string& sig) = 0;
104 virtual MessageIterPtr eldbus_message_iter_get_and_next_by_type_impl(const MessageIterPtr& it, int type) = 0;
105 virtual MessageIterPtr eldbus_message_iter_get_impl(const MessagePtr& it, bool write) = 0;
106 virtual MessagePtr eldbus_proxy_method_call_new_impl(const ProxyPtr& proxy, const std::string& funcName) = 0;
107 virtual MessagePtr eldbus_proxy_send_and_block_impl(const ProxyPtr& proxy, const MessagePtr& msg) = 0;
108 virtual bool eldbus_message_error_get_impl(const MessagePtr& msg, std::string& name, std::string& text) = 0;
109 virtual std::string eldbus_message_signature_get_impl(const MessagePtr& msg) = 0;
112 using SendCallback = std::function<void(const MessagePtr& msg)>;
114 virtual PendingPtr eldbus_proxy_send_impl(const ProxyPtr& proxy, const MessagePtr& msg, const SendCallback& callback) = 0;
115 virtual std::string eldbus_proxy_interface_get_impl(const ProxyPtr&) = 0;
116 virtual void eldbus_proxy_signal_handler_add_impl(const ProxyPtr& proxy, const std::string& member, const std::function<void(const MessagePtr&)>& cb) = 0;
117 virtual std::string eldbus_message_iter_signature_get_impl(const MessageIterPtr& iter) = 0;
118 virtual MessagePtr eldbus_message_method_return_new_impl(const MessagePtr& msg) = 0;
119 virtual MessagePtr eldbus_message_error_new_impl(const MessagePtr& msg, const std::string& err, const std::string& txt) = 0;
120 virtual PendingPtr eldbus_connection_send_impl(const ConnectionPtr& conn, const MessagePtr& msg) = 0;
121 virtual MessagePtr eldbus_message_signal_new_impl(const std::string& path, const std::string& iface, const std::string& name) = 0;
122 virtual MessagePtr eldbus_message_ref_impl(const MessagePtr& msg) = 0;
123 virtual ConnectionPtr eldbus_connection_get_impl(ConnectionType type) = 0;
124 virtual std::string eldbus_connection_unique_name_get_impl(const ConnectionPtr& conn) = 0;
125 virtual ObjectPtr eldbus_object_get_impl(const ConnectionPtr& conn, const std::string& bus, const std::string& path) = 0;
126 virtual ProxyPtr eldbus_proxy_get_impl(const ObjectPtr& obj, const std::string& interface) = 0;
127 virtual ProxyPtr eldbus_proxy_copy_impl(const ProxyPtr& ptr) = 0;
128 virtual void eldbus_name_request_impl(const ConnectionPtr& conn, const std::string& bus) = 0;
129 virtual void eldbus_name_release_impl(const ConnectionPtr& conn, const std::string& bus) = 0;
134 struct char_ptr_deleter
136 void operator()(char* p)
141 std::vector<std::unique_ptr<char, char_ptr_deleter>> storage;
143 const char* add(const char* txt)
145 auto ptr = strdup(txt);
146 storage.push_back(std::unique_ptr<char, char_ptr_deleter>(ptr));
147 return storage.back().get();
149 const char* add(const std::string& txt)
151 return add(txt.c_str());
157 static std::atomic<unsigned int> LastId;
158 unsigned int id = ++LastId;
163 std::string memberName;
164 std::vector<std::pair<std::string, std::string>> in, out; // _Eldbus_Arg_Info
165 std::function<DBusWrapper::MessagePtr(const DBusWrapper::MessagePtr& msg)> callback;
170 std::string memberName;
171 std::vector<std::pair<std::string, std::string>> args;
172 unsigned int uniqueId;
176 CallId setterId, getterId;
177 std::string memberName, typeSignature;
178 std::function<std::string(const DBusWrapper::MessagePtr&src, const DBusWrapper::MessageIterPtr&dst)> getCallback, setCallback;
184 SignalId() = default;
190 virtual void add_interface_impl(bool fallback, const std::string& pathName, const ConnectionPtr& connection, std::vector<std::function<void()>>& destructors, const std::string& interfaceName, std::vector<MethodInfo>& dscrMethods, std::vector<PropertyInfo>& dscrProperties, std::vector<SignalInfo>& dscrSignals) = 0;
191 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;
192 static DBusWrapper* Installed();
193 static void Install(std::unique_ptr<DBusWrapper>);
195 StringStorage Strings;
200 enum class MethodType
211 struct hash<std::tuple<std::string, std::string, std::string>>
213 size_t operator()(const std::tuple<std::string, std::string, std::string>& a) const
215 auto a1 = std::hash<std::string>()(std::get<0>(a));
216 auto a2 = std::hash<std::string>()(std::get<1>(a));
217 auto a3 = std::hash<std::string>()(std::get<2>(a));
219 v = (v * 11400714819323198485llu) + a2;
220 v = (v * 11400714819323198485llu) + a3;
225 struct hash<std::tuple<std::string, std::string, std::string, detail::MethodType>>
227 size_t operator()(const std::tuple<std::string, std::string, std::string, detail::MethodType>& a) const
229 auto a1 = std::hash<std::string>()(std::get<0>(a));
230 auto a2 = std::hash<std::string>()(std::get<1>(a));
231 auto a3 = std::hash<std::string>()(std::get<2>(a));
232 auto a4 = static_cast<size_t>(std::get<3>(a));
234 v = (v * 11400714819323198485llu) + a2;
235 v = (v * 11400714819323198485llu) + a3;
236 v = (v * 11400714819323198485llu) + a4;
241 struct hash<std::tuple<std::string, std::string, unsigned int>>
243 size_t operator()(const std::tuple<std::string, std::string, unsigned int>& a) const
245 auto a1 = std::hash<std::string>()(std::get<0>(a));
246 auto a2 = std::hash<std::string>()(std::get<1>(a));
247 auto a3 = std::get<2>(a);
249 v = (v * 11400714819323198485llu) + a2;
250 v = (v * 11400714819323198485llu) + a3;
272 value = DBusSigImpl<typename std::decay<T>::type>::value,
273 end = DBusSigImpl<typename std::decay<T>::type>::end
276 template<typename T, typename Q, size_t I, size_t S>
277 struct IndexFromTypeTupleImpl
281 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
284 template<typename T, typename Q, size_t S>
285 struct IndexFromTypeTupleImpl<T, Q, S, S>
292 template<typename T, typename Q>
293 struct IndexFromTypeTuple
297 value = IndexFromTypeTupleImpl<T, typename std::decay<Q>::type, 0, std::tuple_size<T>::value>::value
300 template<typename T, typename = void>
302 template<size_t I, size_t S, typename... ARGS>
304 } // namespace detail
309 struct DBusSigImpl<uint8_t>
318 struct DBusSigImpl<uint16_t>
327 struct DBusSigImpl<uint32_t>
336 struct DBusSigImpl<uint64_t>
345 struct DBusSigImpl<int16_t>
354 struct DBusSigImpl<int32_t>
363 struct DBusSigImpl<int64_t>
372 struct DBusSigImpl<double>
381 struct DBusSigImpl<bool>
390 struct DBusSigImpl<std::string>
399 struct DBusSigImpl<ObjectPath>
407 } // namespace detail
409 #define DBUS_DEBUG(...) \
412 DBus::debugPrint(__FILE__, __LINE__, __VA_ARGS__); \
415 #define DBUS_W DBusWrapper::Installed()
418 * @brief Template based, single file, wrapper library around eldbus for DBUS based communication.
420 * Main motivation was missing asynchronous calls in AT-SPI library and difficulties,
421 * when using eldbus from C++.
424 * - takes care of marshalling arguments to and from DBUS calls.
425 * - allows synchronous and asynchronous calls.
426 * - allows synchronous and asynchronous listeners on signals.
427 * - manages all involved objects' lifetimes.
428 * - errors are passed as optional-alike objects, no exceptions are used.
429 * - allows setting additional debug-print function for more details about
432 * DBUS's method signatures (and expected return values) are specified as template argument,
433 * using functor syntax. For example:
435 * auto dbus = DBusClient{ ... };
436 * auto v = dbus.method<std::tuple<int, float>(float, float, std::string)>("foo").call(1.0f, 2.0f, "qwe");
438 * means (synchronous) call on dbus object, which takes three arguments (thus making call signature \b dds)
439 * of types float, float and string (float will be automatically converted to double).
440 * Expected return value is std::tuple<int, float>, which gives signature <B>(id)</B> - std::tuple acts
441 * as struct container. Returned value v will be of type ValueOrError<std::tuple<int, float>>.\n
442 * Slightly different (asynchronous) example:
444 * auto dbus = DBusClient{ ... };
445 * std::function<void(ValueOrError<int, float>)> callback;
446 * dbus.method<ValueOrError<int, float>(float, float, std::string)>("foo").asyncCall(callback, 1.0f, 2.0f, "qwe");
448 * Now the call takes the same arguments and has the same signature. But expected values are different -
449 * now the signature is simply \b id. ValueOrError acts in this case as placeholder for list of values,
450 * which DBUS allows as return data. The call itself is asynchronous - instead of expecting reply
451 * you need to pass a callback, which will be called either with received data and error message.
453 * Library is not thread-safe, the same object shouldn't be called from different threads without
454 * synchronization. There's no guarantee, that callbacks will be executed on the same thread.
460 class DBusInterfaceDescription;
463 * @brief Formats debug message and calls debug printer (if any) with it
465 void debugPrint(const char* file, size_t line, const char* format, ...);
468 * @brief Sets debug printer callback, which will be called with debug messages
470 * Callback will be called in various moments of DBus activity. First value passed to callback
471 * is pointer to text, second it's length. Text is ended with 0 (not counted towards it's size),
472 * user can safely printf it.
474 void setDebugPrinter(std::function<void(const char*, size_t)>);
477 * @brief Enumeration indicatng DBus error type
481 DEFAULT, ///< default
482 INVALID_REPLY ///< reply message has error
488 ErrorType errorType{ErrorType::DEFAULT};
491 Error(std::string msg, ErrorType errorType = ErrorType::DEFAULT)
492 : message(std::move(msg)),
495 assert(!message.empty());
504 * @brief Value representing data, that came from DBUS or error message
506 * Object of this class either helds series of values (of types ARGS...)
507 * or error message. This object will be true in boolean context, if has data
508 * and false, if an error occured.
509 * It's valid to create ValueOrError object with empty argument list or void:
512 * ValueOrError<void> v2;
514 * Both mean the same - ValueOrError containing no real data and being a marker,
515 * wherever operation successed or failed and containing possible error message.
517 template<typename... ARGS>
522 * @brief Empty constructor. Valid only, if all ARGS types are default constructible.
524 ValueOrError() = default;
527 * @brief Value constructor.
529 * This will be initialized as success with passed in values.
531 ValueOrError(ARGS... t)
532 : value(std::move(t)...)
537 * @brief Alternative Value constructor.
539 * This will be initialized as success with passed in values.
541 ValueOrError(std::tuple<ARGS...> t)
542 : value(std::move(t))
547 * @brief Error constructor. This will be initialized as failure with given error message.
549 ValueOrError(Error e)
550 : error(std::move(e))
552 assert(!error.message.empty());
556 * @brief bool operator.
558 * Returns true, if operation was successful (getValues member is callable), or false
559 * when operation failed (getError is callable).
561 explicit operator bool() const
563 return error.message.empty();
567 * @brief Returns error message object.
569 * Returns object containing error message associated with the failed operation.
570 * Only callable, if operation actually failed, otherwise will assert.
572 const Error& getError() const
578 * @brief Returns modifiable tuple of held data.
580 * Returns reference to the internal tuple containing held data.
581 * User can modify (or move) data safely.
582 * Only callable, if operation actually successed, otherwise will assert.
584 std::tuple<ARGS...>& getValues()
591 * @brief Returns const tuple of held data.
593 * Returns const reference to the internal tuple containing held data.
594 * Only callable, if operation actually successed, otherwise will assert.
596 const std::tuple<ARGS...>& getValues() const
603 std::tuple<ARGS...> value;
611 ValueOrError() = default;
612 ValueOrError(std::tuple<> t)
615 ValueOrError(Error e)
616 : error(std::move(e))
618 assert(!error.message.empty());
621 explicit operator bool() const
623 return error.message.empty();
625 const Error& getError() const
629 std::tuple<>& getValues()
632 static std::tuple<> t;
635 std::tuple<> getValues() const
646 class ValueOrError<void>
649 ValueOrError() = default;
650 ValueOrError(Success)
653 ValueOrError(Error e)
654 : error(std::move(e))
656 assert(!error.message.empty());
659 explicit operator bool() const
661 return error.message.empty();
663 const Error& getError() const
667 std::tuple<>& getValues()
670 static std::tuple<> t;
673 std::tuple<> getValues() const
683 using ObjectPath = ObjectPath;
686 * @brief Class used to marshall DBUS's variant type
688 * Minimalistic class, that allows user to specify DBUS variant type
689 * as argument or return value. You need to pass real type hidden under variant as
690 * template type \b A. At this point library doesn't allow to expected one of few classes
691 * as return data in variant. So for example user can't specify method call, which on return
692 * expects DBUS variant holding either string or int.
701 * @brief Namespace for private, internal functions and classes
705 inline namespace strings
707 template<std::size_t N>
708 using char_array = std::array<char, N>;
710 constexpr char* xcopy_n(const char* src, size_t n, char* dst)
712 for(std::size_t i = 0; i < n; ++i)
720 template<std::size_t L, std::size_t R>
721 constexpr char_array<L + R - 1> concat_internal(const char_array<L> lhs, const char_array<R> rhs)
723 char_array<L + R - 1> arr{};
724 char* ptr = arr.data();
726 if constexpr(!arr.empty())
728 ptr = xcopy_n(std::data(lhs), L - 1, ptr);
729 ptr = xcopy_n(std::data(rhs), R - 1, ptr);
735 template<std::size_t L>
736 constexpr char_array<L> convert_internal(const char (&str)[L])
739 char* ptr = arr.data();
741 if constexpr(!arr.empty())
743 ptr = xcopy_n(std::data(str), L, ptr);
748 template<std::size_t L, std::size_t R>
749 constexpr char_array<L + R - 1> concat(const char_array<L> lhs, const char_array<R> rhs)
751 return concat_internal(lhs, rhs);
753 template<std::size_t L, std::size_t R>
754 constexpr char_array<L + R - 1> concat(const char (&lhs)[L], const char_array<R> rhs)
756 return concat_internal(convert_internal(lhs), rhs);
758 template<std::size_t L, std::size_t R>
759 constexpr char_array<L + R - 1> concat(const char_array<L> lhs, const char (&rhs)[R])
761 return concat_internal(lhs, convert_internal(rhs));
763 template<std::size_t L, std::size_t R>
764 constexpr char_array<L + R - 1> concat(const char (&lhs)[L], const char (&rhs)[R])
766 return concat_internal(convert_internal(lhs), convert_internal(rhs));
768 template<std::size_t L>
769 constexpr char_array<L> concat(const char (&str)[L])
771 return convert_internal(str);
773 template<std::size_t L>
774 constexpr char_array<L> concat(const char_array<L> str)
779 template<std::size_t... Digits>
782 static constexpr const char value[] = {('0' + static_cast<char>(Digits))..., '\0'};
784 static_assert((true && ... && (Digits < 10)));
787 template<std::size_t Remainder, std::size_t... Digits>
788 struct to_chars_helper : to_chars_helper<Remainder / 10, Remainder % 10, Digits...>
792 template<std::size_t... Digits>
793 struct to_chars_helper<0, Digits...> : to_chars<Digits...>
797 template<std::size_t N>
798 using to_string = to_chars_helper<N / 10, N % 10>;
799 } // namespace strings
801 template<typename T, typename = void>
803 template<typename... ARGS>
804 struct signature<std::tuple<ARGS...>>;
805 template<typename A, typename B>
806 struct signature<std::pair<A, B>>;
808 struct signature<std::vector<A>>;
809 template<typename A, size_t N>
810 struct signature<std::array<A, N>>;
811 template<typename A, typename B>
812 struct signature<std::unordered_map<A, B>>;
813 template<typename A, typename B>
814 struct signature<std::map<A, B>>;
817 struct signature_helper
820 * @brief Returns name of type marshalled, for informative purposes
822 static constexpr std::string_view name()
824 return {T::name_v.data()};
828 * @brief Returns DBUS' signature of type marshalled
830 static constexpr std::string_view sig()
832 return {T::sig_v.data()};
837 * @brief Signature class for marshalling uint8 type.
840 struct signature<uint8_t> : signature_helper<signature<uint8_t>>
842 static constexpr auto name_v = concat("uint8_t");
843 static constexpr auto sig_v = concat("y");
846 * @brief Marshals value v as marshalled type into message
848 static void set(const DBusWrapper::MessageIterPtr& iter, uint8_t v)
850 DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
854 * @brief Marshals value from marshalled type into variable v
856 static bool get(const DBusWrapper::MessageIterPtr& iter, uint8_t& v)
858 return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
863 * @brief Signature class for marshalling uint16 type.
866 struct signature<uint16_t> : signature_helper<signature<uint16_t>>
868 static constexpr auto name_v = concat("uint16_t");
869 static constexpr auto sig_v = concat("q");
872 * @brief Marshals value v as marshalled type into message
874 static void set(const DBusWrapper::MessageIterPtr& iter, uint16_t v)
876 DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
880 * @brief Marshals value from marshalled type into variable v
882 static bool get(const DBusWrapper::MessageIterPtr& iter, uint16_t& v)
884 return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
889 * @brief Signature class for marshalling uint32 type.
892 struct signature<uint32_t> : signature_helper<signature<uint32_t>>
894 static constexpr auto name_v = concat("uint32_t");
895 static constexpr auto sig_v = concat("u");
898 * @brief Marshals value v as marshalled type into message
900 static void set(const DBusWrapper::MessageIterPtr& iter, uint32_t v)
902 DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
906 * @brief Marshals value from marshalled type into variable v
908 static bool get(const DBusWrapper::MessageIterPtr& iter, uint32_t& v)
910 return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
915 * @brief Signature class for marshalling uint64 type.
918 struct signature<uint64_t> : signature_helper<signature<uint64_t>>
920 static constexpr auto name_v = concat("uint64_t");
921 static constexpr auto sig_v = concat("t");
924 * @brief Marshals value v as marshalled type into message
926 static void set(const DBusWrapper::MessageIterPtr& iter, uint64_t v)
928 DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
932 * @brief Marshals value from marshalled type into variable v
934 static bool get(const DBusWrapper::MessageIterPtr& iter, uint64_t& v)
936 return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
941 * @brief Signature class for marshalling int16 type.
944 struct signature<int16_t> : signature_helper<signature<int16_t>>
946 static constexpr auto name_v = concat("int16_t");
947 static constexpr auto sig_v = concat("n");
950 * @brief Marshals value v as marshalled type into message
952 static void set(const DBusWrapper::MessageIterPtr& iter, int16_t v)
954 DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
958 * @brief Marshals value from marshalled type into variable v
960 static bool get(const DBusWrapper::MessageIterPtr& iter, int16_t& v)
962 return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
967 * @brief Signature class for marshalling int32 type.
970 struct signature<int32_t> : signature_helper<signature<int32_t>>
972 static constexpr auto name_v = concat("int32_t");
973 static constexpr auto sig_v = concat("i");
976 * @brief Marshals value v as marshalled type into message
978 static void set(const DBusWrapper::MessageIterPtr& iter, int32_t v)
980 DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
984 * @brief Marshals value from marshalled type into variable v
986 static bool get(const DBusWrapper::MessageIterPtr& iter, int32_t& v)
988 return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
993 * @brief Signature class for marshalling int64 type.
996 struct signature<int64_t> : signature_helper<signature<int64_t>>
998 static constexpr auto name_v = concat("int64_t");
999 static constexpr auto sig_v = concat("x");
1002 * @brief Marshals value v as marshalled type into message
1004 static void set(const DBusWrapper::MessageIterPtr& iter, int64_t v)
1006 DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
1010 * @brief Marshals value from marshalled type into variable v
1012 static bool get(const DBusWrapper::MessageIterPtr& iter, int64_t& v)
1014 return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
1019 * @brief Signature class for marshalling double type.
1022 struct signature<double> : signature_helper<signature<double>>
1024 static constexpr auto name_v = concat("double");
1025 static constexpr auto sig_v = concat("d");
1028 * @brief Marshals value v as marshalled type into message
1030 static void set(const DBusWrapper::MessageIterPtr& iter, double v)
1032 DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
1036 * @brief Marshals value from marshalled type into variable v
1038 static bool get(const DBusWrapper::MessageIterPtr& iter, double& v)
1040 return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
1044 * @brief Marshals value from marshalled type into variable v
1046 static bool get(const DBusWrapper::MessageIterPtr& iter, float& v2)
1049 auto r = DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
1050 v2 = static_cast<float>(v);
1056 * @brief Signature class for marshalling float type.
1059 struct signature<float> : signature_helper<signature<float>>
1061 static constexpr auto name_v = concat("float");
1062 static constexpr auto sig_v = concat("f");
1065 * @brief Marshals value v as marshalled type into message
1067 static void set(const DBusWrapper::MessageIterPtr& iter, float v)
1069 DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
1073 * @brief Marshals value from marshalled type into variable v
1075 static bool get(const DBusWrapper::MessageIterPtr& iter, double& v)
1077 return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
1081 * @brief Marshals value from marshalled type into variable v
1083 static bool get(const DBusWrapper::MessageIterPtr& iter, float& v2)
1086 auto r = DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
1087 v2 = static_cast<float>(v);
1093 * @brief Signature class for marshalling boolean type.
1096 struct signature<bool> : signature_helper<signature<bool>>
1098 static constexpr auto name_v = concat("bool");
1099 static constexpr auto sig_v = concat("b");
1102 * @brief Marshals value v as marshalled type into message
1104 static void set(const DBusWrapper::MessageIterPtr& iter, bool v)
1106 DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
1110 * @brief Marshals value from marshalled type into variable v
1112 static bool get(const DBusWrapper::MessageIterPtr& iter, bool& v)
1114 return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
1118 template<typename T>
1119 struct signature<T, typename std::enable_if_t<std::is_enum_v<T>, void>> : signature_helper<signature<T>>
1121 static constexpr auto name_v = concat("enum");
1122 static constexpr auto sig_v = signature<typename std::underlying_type<T>::type>::sig_v;
1125 * @brief Marshals value v as marshalled type into message
1127 static void set(const DBusWrapper::MessageIterPtr& iter, T v)
1129 signature<typename std::underlying_type<T>::type>::set(iter, static_cast<int64_t>(v));
1133 * @brief Marshals value from marshalled type into variable v
1135 static bool get(const DBusWrapper::MessageIterPtr& iter, T& v)
1137 typename std::underlying_type<T>::type q = 0;
1138 if(!signature<typename std::underlying_type<T>::type>::get(iter, q))
1141 v = static_cast<T>(q);
1147 * @brief Signature class for marshalling string type.
1149 * Both (const) char * and std::string types are accepted as value to send.
1150 * Only std::string is accepted as value to receive.
1153 struct signature<std::string> : signature_helper<signature<std::string>>
1155 static constexpr auto name_v = concat("string");
1156 static constexpr auto sig_v = concat("s");
1159 * @brief Marshals value v as marshalled type into message
1161 static void set(const DBusWrapper::MessageIterPtr& iter, const std::string& v)
1163 DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
1167 * @brief Marshals value from marshalled type into variable v
1169 static bool get(const DBusWrapper::MessageIterPtr& iter, std::string& v)
1171 return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
1176 struct signature<ObjectPath> : signature_helper<signature<ObjectPath>>
1178 static constexpr auto name_v = concat("path");
1179 static constexpr auto sig_v = concat("o");
1182 * @brief Marshals value v as marshalled type into message
1184 static void set(const DBusWrapper::MessageIterPtr& iter, const std::string& v)
1186 DBUS_W->eldbus_message_iter_arguments_append_impl(iter, ObjectPath{v});
1190 * @brief Marshals value v as marshalled type into message
1192 static void set(const DBusWrapper::MessageIterPtr& iter, const ObjectPath& v)
1194 DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
1198 * @brief Marshals value v as marshalled type into message
1200 static void set(const DBusWrapper::MessageIterPtr& iter, const char* v)
1202 DBUS_W->eldbus_message_iter_arguments_append_impl(iter, ObjectPath{v});
1206 * @brief Marshals value from marshalled type into variable v
1208 static bool get(const DBusWrapper::MessageIterPtr& iter, ObjectPath& v)
1210 return DBUS_W->eldbus_message_iter_get_and_next_impl(iter, v);
1214 * @brief Marshals value from marshalled type into variable v
1216 static bool get(const DBusWrapper::MessageIterPtr& iter, std::string& v)
1219 if(!DBUS_W->eldbus_message_iter_get_and_next_impl(iter, q)) return false;
1220 v = std::move(q.value);
1226 * @brief Signature class for marshalling (const) char * type.
1228 * Both (const) char * and std::string types are accepted as value to send.
1229 * You can't use (const) char * variable type to receive value.
1232 struct signature<char*> : signature_helper<signature<char*>>
1234 static constexpr auto name_v = concat("string");
1235 static constexpr auto sig_v = concat("s");
1238 * @brief Marshals value v as marshalled type into message
1240 static void set(const DBusWrapper::MessageIterPtr& iter, const std::string& v)
1242 DBUS_W->eldbus_message_iter_arguments_append_impl(iter, v);
1246 * @brief Marshals value v as marshalled type into message
1248 static void set(const DBusWrapper::MessageIterPtr& iter, const char* v)
1250 DBUS_W->eldbus_message_iter_arguments_append_impl(iter, std::string{v});
1254 template<size_t INDEX, typename A, typename... ARGS>
1255 struct signature_tuple_element_type_helper
1257 using type = typename signature_tuple_element_type_helper<INDEX - 1, ARGS...>::type;
1260 template<typename A, typename... ARGS>
1261 struct signature_tuple_element_type_helper<0, A, ARGS...>
1267 * @brief Helper class to marshall tuples
1269 * This class marshals all elements of the tuple value starting at the index INDEX
1270 * and incrementing. This class recursively calls itself with increasing INDEX value
1271 * until INDEX is equal to SIZE, where recursive calling ends.
1273 template<size_t INDEX, size_t SIZE, typename... ARGS>
1274 struct signature_tuple_helper : signature_helper<signature_tuple_helper<INDEX, SIZE, ARGS...>>
1276 using current_type = typename signature_tuple_element_type_helper<INDEX, ARGS...>::type;
1278 static constexpr auto name_v = concat(signature<current_type>::name_v, concat(", ", signature_tuple_helper<INDEX + 1, SIZE, ARGS...>::name_v));
1279 static constexpr auto sig_v = concat(signature<current_type>::sig_v, signature_tuple_helper<INDEX + 1, SIZE, ARGS...>::sig_v);
1282 * @brief Marshals value v as marshalled type into message
1284 static void set(const DBusWrapper::MessageIterPtr& iter, const std::tuple<ARGS...>& args)
1286 signature<current_type>::set(iter, std::get<INDEX>(args));
1287 signature_tuple_helper<INDEX + 1, SIZE, ARGS...>::set(iter, args);
1291 * @brief Marshals value from marshalled type into variable v
1293 static bool get(const DBusWrapper::MessageIterPtr& iter, std::tuple<ARGS...>& args)
1295 return signature<current_type>::get(iter, std::get<INDEX>(args)) &&
1296 signature_tuple_helper<INDEX + 1, SIZE, ARGS...>::get(iter, args);
1301 * @brief Helper class to marshall tuples
1303 * This class marks end of the tuple marshalling. Members of this class are called
1304 * when INDEX value is equal to SIZE.
1306 template<size_t SIZE, typename... ARGS>
1307 struct signature_tuple_helper<SIZE, SIZE, ARGS...> : signature_helper<signature_tuple_helper<SIZE, SIZE, ARGS...>>
1309 static constexpr auto name_v = concat("");
1310 static constexpr auto sig_v = concat("");
1313 * @brief Marshals value v as marshalled type into message
1315 static void set(const DBusWrapper::MessageIterPtr& iter, const std::tuple<ARGS...>& args)
1320 * @brief Marshals value from marshalled type into variable v
1322 static bool get(const DBusWrapper::MessageIterPtr& iter, std::tuple<ARGS...>& args)
1329 * @brief Signature class for marshalling tuple of values
1331 * This class marshalls tuple of values. This represents
1332 * DBUS struct typle, encoded with character 'r'
1334 template<typename... ARGS>
1335 struct signature<std::tuple<ARGS...>> : signature_helper<signature<std::tuple<ARGS...>>>
1337 static constexpr auto name_v = concat("tuple<", concat(signature_tuple_helper<0, sizeof...(ARGS), ARGS...>::name_v, ">"));
1338 static constexpr auto sig_v = concat("(", concat(signature_tuple_helper<0, sizeof...(ARGS), ARGS...>::sig_v, ")"));
1341 * @brief Marshals value v as marshalled type into message
1343 static void set(const DBusWrapper::MessageIterPtr& iter, const std::tuple<ARGS...>& args)
1345 auto entry = DBUS_W->eldbus_message_iter_container_new_impl(iter, 'r', "");
1346 signature_tuple_helper<0, sizeof...(ARGS), ARGS...>::set(entry, args);
1350 * @brief Marshals value from marshalled type into variable v
1352 static bool get(const DBusWrapper::MessageIterPtr& iter, std::tuple<ARGS...>& args)
1354 auto entry = DBUS_W->eldbus_message_iter_get_and_next_by_type_impl(iter, 'r');
1355 if(!entry) return false;
1356 return signature_tuple_helper<0, sizeof...(ARGS), ARGS...>::get(entry, args);
1361 * @brief Signature class for marshalling ValueOrError template type
1363 * ValueOrError template type is used to marshall list of values passed to
1364 * DBUS (or received from) at the "top" level. For example ss(s) is represented as
1365 * \code{.cpp} ValueOrError<std::string, std::string, std::tuple<std::string>> \endcode
1366 * While (ss(s)) is represented as
1367 * \code{.cpp} std::tuple<std::string, std::string, std::tuple<std::string>> \endcode
1369 * \code{.cpp} ValueOrError<std::tuple<std::string, std::string, std::tuple<std::string>>> \endcode
1371 template<typename... ARGS>
1372 struct signature<ValueOrError<ARGS...>> : signature_helper<signature<ValueOrError<ARGS...>>>
1374 static constexpr auto name_v = concat("ValueOrError<", concat(signature_tuple_helper<0, sizeof...(ARGS), ARGS...>::name_v, ">"));
1375 static constexpr auto sig_v = signature_tuple_helper<0, sizeof...(ARGS), ARGS...>::sig_v;
1378 * @brief Marshals value v as marshalled type into message
1380 static void set(const DBusWrapper::MessageIterPtr& iter, const ValueOrError<ARGS...>& args)
1382 signature_tuple_helper<0, sizeof...(ARGS), ARGS...>::set(iter, args.getValues());
1386 * @brief Marshals value from marshalled type into variable v
1388 static bool get(const DBusWrapper::MessageIterPtr& iter, ValueOrError<ARGS...>& args)
1390 return signature_tuple_helper<0, sizeof...(ARGS), ARGS...>::get(iter, args.getValues());
1395 * @brief Signature class for marshalling ValueOrError<void> type
1398 struct signature<ValueOrError<void>> : signature_helper<signature<ValueOrError<void>>>
1400 static constexpr auto name_v = concat("ValueOrError<void>");
1401 static constexpr auto sig_v = concat("");
1404 * @brief Marshals value v as marshalled type into message
1406 static void set(const DBusWrapper::MessageIterPtr& iter, const ValueOrError<void>& args)
1411 * @brief Marshals value from marshalled type into variable v
1413 static bool get(const DBusWrapper::MessageIterPtr& iter, ValueOrError<void>& args)
1420 * @brief Signature class for marshalling ValueOrError<> type
1423 struct signature<ValueOrError<>> : signature_helper<signature<ValueOrError<>>>
1425 static constexpr auto name_v = concat("ValueOrError<>");
1426 static constexpr auto sig_v = concat("");
1429 * @brief Marshals value v as marshalled type into message
1431 static void set(const DBusWrapper::MessageIterPtr& iter, const ValueOrError<>& args)
1436 * @brief Marshals value from marshalled type into variable v
1438 static bool get(const DBusWrapper::MessageIterPtr& iter, ValueOrError<>& args)
1445 * @brief Signature class for marshalling pair of types
1447 template<typename A, typename B>
1448 struct signature<std::pair<A, B>> : signature_helper<signature<std::pair<A, B>>>
1450 static constexpr auto name_v = concat("pair<", concat(signature_tuple_helper<0, 2, A, B>::name_v, ">"));
1451 static constexpr auto sig_v = concat("(", concat(signature_tuple_helper<0, 2, A, B>::sig_v, ")"));
1454 * @brief Marshals value v as marshalled type into message
1456 static void set(const DBusWrapper::MessageIterPtr& iter, const std::pair<A, B>& ab, bool dictionary = false)
1458 auto entry = DBUS_W->eldbus_message_iter_container_new_impl(iter, dictionary ? 'e' : 'r', "");
1459 signature_tuple_helper<0, 2, A, B>::set(entry, ab);
1463 * @brief Marshals value from marshalled type into variable v
1465 static bool get(const DBusWrapper::MessageIterPtr& iter, std::pair<A, B>& ab)
1467 auto entry = DBUS_W->eldbus_message_iter_get_and_next_by_type_impl(iter, 'r');
1470 entry = DBUS_W->eldbus_message_iter_get_and_next_by_type_impl(iter, '{');
1471 if(!entry) return false;
1474 std::tuple<A, B> ab_tmp;
1475 auto z = signature_tuple_helper<0, 2, A, B>::get(entry, ab_tmp);
1478 ab.first = std::move(std::get<0>(ab_tmp));
1479 ab.second = std::move(std::get<1>(ab_tmp));
1486 * @brief Signature class for marshalling std::vector template type
1488 * This marshals container's content as DBUS a ascii character type code.
1490 template<typename A>
1491 struct signature<std::vector<A>> : signature_helper<signature<std::vector<A>>>
1493 static constexpr auto name_v = concat("vector<", concat(signature<A>::name_v, ">"));
1494 static constexpr auto sig_v = concat("a", signature<A>::sig_v);
1497 * @brief Marshals value v as marshalled type into message
1499 static void set(const DBusWrapper::MessageIterPtr& iter, const std::vector<A>& v)
1501 auto lst = DBUS_W->eldbus_message_iter_container_new_impl(iter, 'a', std::string{signature<A>::sig()});
1505 signature<A>::set(lst, a);
1510 * @brief Marshals value from marshalled type into variable v
1512 static bool get(const DBusWrapper::MessageIterPtr& iter, std::vector<A>& v)
1514 auto s = DBUS_W->eldbus_message_iter_get_and_next_by_type_impl(iter, 'a');
1515 if(!s) return false;
1518 while(signature<A>::get(s, a))
1519 v.push_back(std::move(a));
1526 * @brief Signature class for marshalling std::array template type
1528 * This marshals container's content as DBUS a ascii character type code.
1530 template<typename A, size_t N>
1531 struct signature<std::array<A, N>> : signature_helper<signature<std::array<A, N>>>
1533 static constexpr auto name_v = concat("array<", concat(signature<A>::name_v, concat(", ", concat(to_string<N>::value, ">"))));
1534 static constexpr auto sig_v = concat("a", signature<A>::sig_v);
1537 * @brief Marshals value v as marshalled type into message
1539 static void set(const DBusWrapper::MessageIterPtr& iter, const std::array<A, N>& v)
1541 auto lst = DBUS_W->eldbus_message_iter_container_new_impl(iter, 'a', std::string{signature<A>::sig()});
1545 signature<A>::set(lst, a);
1550 * @brief Marshals value from marshalled type into variable v
1552 static bool get(const DBusWrapper::MessageIterPtr& iter, std::array<A, N>& v)
1554 auto s = DBUS_W->eldbus_message_iter_get_and_next_by_type_impl(iter, 'a');
1559 if(!signature<A>::get(s, a))
1567 * @brief Signature class for marshalling EldbusVariant type
1569 * This marshals variant's content as DBUS v ascii character type code.
1571 template<typename A>
1572 struct signature<EldbusVariant<A>> : signature_helper<signature<EldbusVariant<A>>>
1574 static constexpr auto name_v = concat("variant<", concat(signature<A>::name_v, ">"));
1575 static constexpr auto sig_v = concat("v");
1578 * @brief Marshals value v as marshalled type into message
1580 static void set(const DBusWrapper::MessageIterPtr& iter, const EldbusVariant<A>& v)
1586 * @brief Marshals value v as marshalled type into message
1588 static void set(const DBusWrapper::MessageIterPtr& iter, const A& v)
1590 auto var = DBUS_W->eldbus_message_iter_container_new_impl(iter, 'v', std::string{signature<A>::sig()});
1591 signature<A>::set(var, v);
1595 * @brief Marshals value from marshalled type into variable v
1597 static bool get(const DBusWrapper::MessageIterPtr& iter, EldbusVariant<A>& v)
1599 auto s = DBUS_W->eldbus_message_iter_get_and_next_by_type_impl(iter, 'v');
1602 return signature<A>::get(s, v.value);
1607 * @brief Signature class for marshalling std::unordered_map template type
1609 * This marshals container's content as DBUS {} ascii character type code.
1610 * Note, that library doesnt check, if the key is basic type, as DBUS
1611 * specification mandates.
1612 * User can always exchange std::unordered_map for std::map and the reverse.
1613 * User can receive such values as std::vector of std::pair<key, value> values.
1614 * Order of such values is unspecified.
1616 template<typename A, typename B>
1617 struct signature<std::unordered_map<A, B>> : signature_helper<signature<std::unordered_map<A, B>>>
1619 static constexpr auto name_v = concat("unordered_map<", concat(signature<A>::name_v, concat(", ", concat(signature<B>::name_v, ">"))));
1620 static constexpr auto sig_v = concat("a{", concat(signature_tuple_helper<0, 2, A, B>::sig_v, "}"));
1623 * @brief Marshals value v as marshalled type into message
1625 static void set(const DBusWrapper::MessageIterPtr& iter, const std::unordered_map<A, B>& v)
1627 auto sig = "{" + std::string{signature_tuple_helper<0, 2, A, B>::sig()} + "}";
1628 auto lst = DBUS_W->eldbus_message_iter_container_new_impl(iter, 'a', sig);
1632 signature<std::pair<A, B>>::set(lst, a, true);
1637 * @brief Marshals value from marshalled type into variable v
1639 static bool get(const DBusWrapper::MessageIterPtr& iter, std::unordered_map<A, B>& v)
1641 auto s = DBUS_W->eldbus_message_iter_get_and_next_by_type_impl(iter, 'a');
1646 while(signature<std::pair<A, B>>::get(s, a))
1647 v.insert(std::move(a));
1653 * @brief Signature class for marshalling std::unordered_map template type
1655 * This marshals container's content as DBUS {} ascii character type code.
1656 * Note, that library doesnt check, if the key is basic type, as DBUS
1657 * specification mandates.
1658 * User can always exchange std::unordered_map for std::map and the reverse.
1659 * User can receive such values as std::vector of std::pair<key, value> values.
1660 * Order of such values is unspecified.
1662 template<typename A, typename B>
1663 struct signature<std::map<A, B>> : signature_helper<signature<std::map<A, B>>>
1665 static constexpr auto name_v = concat("map<", concat(signature<A>::name_v, concat(", ", concat(signature<B>::name_v, ">"))));
1666 static constexpr auto sig_v = concat("a{", concat(signature_tuple_helper<0, 2, A, B>::sig_v, "}"));
1669 * @brief Marshals value v as marshalled type into message
1671 static void set(const DBusWrapper::MessageIterPtr& iter, const std::map<A, B>& v)
1673 auto sig = "{" + std::string{signature_tuple_helper<0, 2, A, B>::sig()} + "}";
1674 auto lst = DBUS_W->eldbus_message_iter_container_new_impl(iter, 'a', sig);
1678 signature<std::pair<A, B>>::set(lst, a, true);
1683 * @brief Marshals value from marshalled type into variable v
1685 static bool get(const DBusWrapper::MessageIterPtr& iter, std::map<A, B>& v)
1687 auto s = DBUS_W->eldbus_message_iter_get_and_next_by_type_impl(iter, 'a');
1691 while(signature<std::pair<A, B>>::get(s, a))
1692 v.insert(std::move(a));
1698 * @brief Signature helper class for marshalling const reference types
1700 template<typename A>
1701 struct signature<const A&> : signature_helper<signature<const A&>>
1703 static constexpr auto name_v = concat("const ", concat(signature<A>::name_v, "&"));
1704 static constexpr auto sig_v = signature<A>::sig_v;
1707 * @brief Marshals value v as marshalled type into message
1709 static void set(const DBusWrapper::MessageIterPtr& iter, const A& v)
1711 signature<A>::set(iter, v);
1715 * @brief Marshals value from marshalled type into variable v
1717 static void get(const DBusWrapper::MessageIterPtr& iter, A& v)
1719 signature<A>::get(iter, v);
1724 * @brief Signature helper class for marshalling reference types
1726 template<typename A>
1727 struct signature<A&> : signature_helper<signature<A&>>
1729 static constexpr auto name_v = concat(signature<A>::name_v, "&");
1730 static constexpr auto sig_v = signature<A>::sig_v;
1733 * @brief Marshals value v as marshalled type into message
1735 static void set(const DBusWrapper::MessageIterPtr& iter, const A& v)
1737 signature<A>::set(iter, v);
1741 * @brief Marshals value from marshalled type into variable v
1743 static void get(const DBusWrapper::MessageIterPtr& iter, A& v)
1745 signature<A>::get(iter, v);
1750 * @brief Signature helper class for marshalling const types
1752 template<typename A>
1753 struct signature<const A> : signature_helper<signature<const A>>
1755 static constexpr auto name_v = concat("const ", signature<A>::name_v);
1756 static constexpr auto sig_v = signature<A>::sig_v;
1759 * @brief Marshals value v as marshalled type into message
1761 static void set(const DBusWrapper::MessageIterPtr& iter, const A& v)
1763 signature<A>::set(iter, v);
1767 * @brief Marshals value from marshalled type into variable v
1769 static void get(const DBusWrapper::MessageIterPtr& iter, A& v)
1771 signature<A>::get(iter, v);
1775 using CallId = DBusWrapper::CallId;
1777 template<typename ValueType>
1778 ValueType unpackValues(CallId callId, const DBusWrapper::MessagePtr& msg)
1780 static const std::string sig{signature<ValueType>::sig().data()};
1782 auto iter = DBUS_W->eldbus_message_iter_get_impl(msg, false);
1787 if(!signature<ValueType>::get(iter, r))
1789 DBUS_DEBUG("ValueType is %s", signature<ValueType>::name().data());
1790 r = Error{"call " + std::to_string(callId.id) + ": failed to unpack values, got signature '" +
1791 DBUS_W->eldbus_message_signature_get_impl(msg) + "', expected '" + sig + "'"};
1796 r = Error{"call " + std::to_string(callId.id) + ": failed to get iterator"};
1801 inline void packValues_helper(const DBusWrapper::MessageIterPtr&)
1805 template<typename A, typename... ARGS>
1806 void packValues_helper(const DBusWrapper::MessageIterPtr& iter, A&& a, ARGS&&... r)
1808 signature<A>::set(iter, std::forward<A>(a));
1809 packValues_helper(iter, std::forward<ARGS>(r)...);
1812 template<typename... ARGS>
1813 void packValues(CallId callId, const DBusWrapper::MessagePtr& msg, ARGS&&... r)
1815 auto iter = DBUS_W->eldbus_message_iter_get_impl(msg, true);
1816 packValues_helper(iter, std::forward<ARGS>(r)...);
1819 struct ConnectionState
1821 DBusWrapper::ConnectionPtr connection;
1822 DBusWrapper::ObjectPtr object;
1823 DBusWrapper::ProxyPtr proxy, propertiesProxy;
1826 template<typename RETTYPE, typename... ARGS>
1827 RETTYPE call(CallId callId, const ConnectionState& connectionState, bool property, const std::string& funcName, const ARGS&... args)
1829 const auto& proxy = property ? connectionState.propertiesProxy : connectionState.proxy;
1832 DBUS_DEBUG("call %d: not initialized", callId.id);
1833 return Error{"not initialized"};
1836 DBUS_DEBUG("call %d: calling '%s'", callId.id, funcName.c_str());
1837 auto msg = DBUS_W->eldbus_proxy_method_call_new_impl(proxy, funcName);
1840 DBUS_DEBUG("call %d: failed", callId.id);
1841 return Error{"failed to create message"};
1844 detail::packValues(callId, msg, args...);
1845 auto reply = DBUS_W->eldbus_proxy_send_and_block_impl(proxy, msg);
1846 DBUS_DEBUG("call %d: calling '%s' done", callId.id, funcName.c_str());
1849 DBUS_DEBUG("call %d: failed", callId.id);
1850 return Error{"eldbus returned null as reply"};
1852 std::string errname, errmsg;
1853 if(DBUS_W->eldbus_message_error_get_impl(reply, errname, errmsg))
1855 DBUS_DEBUG("call %d: %s: %s", callId.id, errname.c_str(), errmsg.c_str());
1856 return Error{errname + ": " + errmsg};
1858 DBUS_DEBUG("call %d: got reply with signature '%s'", callId.id, DBUS_W->eldbus_message_signature_get_impl(reply).c_str());
1859 return detail::unpackValues<RETTYPE>(callId, reply);
1862 template<typename RETTYPE, typename... ARGS>
1863 void asyncCall(CallId callId, const ConnectionState& connectionState, bool property, const std::string& funcName, std::function<void(RETTYPE)> callback, const ARGS&... args)
1865 const auto& proxy = property ? connectionState.propertiesProxy : connectionState.proxy;
1868 DBUS_DEBUG("call %d: not initialized", callId.id);
1869 callback(Error{"not initialized"});
1873 auto msg = DBUS_W->eldbus_proxy_method_call_new_impl(proxy, funcName);
1876 DBUS_DEBUG("call %d: failed", callId.id);
1877 callback(Error{"failed to create message"});
1881 detail::packValues(callId, msg, args...);
1882 auto pending = DBUS_W->eldbus_proxy_send_impl(proxy, msg, [callback, callId, proxy](const DBusWrapper::MessagePtr& reply) {
1883 DBUS_DEBUG("call %d: calling done", callId.id);
1886 DBUS_DEBUG("call %d: failed", callId.id);
1887 callback(Error{"eldbus returned null as reply"});
1891 std::string errname, errmsg;
1892 if(DBUS_W->eldbus_message_error_get_impl(reply, errname, errmsg))
1894 DBUS_DEBUG("call %d: %s: %s", callId.id, errname.c_str(), errmsg.c_str());
1895 callback(Error{errname + ": " + errmsg, ErrorType::INVALID_REPLY});
1899 DBUS_DEBUG("call %d: got reply with signature '%s'", callId.id, DBUS_W->eldbus_message_signature_get_impl(reply).c_str());
1900 callback(detail::unpackValues<RETTYPE>(callId, reply));
1906 DBUS_DEBUG("call %d: call sent", callId.id);
1910 DBUS_DEBUG("call %d: failed to send call", callId.id);
1911 callback(Error{"failed to send call"});
1915 inline void displayDebugCallInfo(CallId callId, const std::string& funcName, const std::string& info, const std::string& interfaceName)
1917 DBUS_DEBUG("call %d: %s iname = %s fname = %s", callId.id, info.c_str(), interfaceName.c_str(), funcName.c_str());
1920 inline void displayDebugCallInfoSignal(CallId callId, const std::string& funcName, const std::string& info, const std::string& interfaceName)
1922 DBUS_DEBUG("call %d: %s signal iname = %s fname = %s", callId.id, info.c_str(), interfaceName.c_str(), funcName.c_str());
1925 inline void displayDebugCallInfoProperty(CallId callId, const std::string& funcName, std::string info, const std::string& interfaceName, const std::string& propertyName)
1927 DBUS_DEBUG("call %d: %s iname = %s pname = %s", callId.id, info.c_str(), interfaceName.c_str(), propertyName.c_str());
1930 using StringStorage = DBusWrapper::StringStorage;
1932 template<typename A, typename... ARGS>
1933 struct EldbusArgGenerator_Helper
1935 static void add(std::vector<std::pair<std::string, std::string>>& r)
1938 auto sig = std::string{signature<A>::sig()};
1939 assert(!sig.empty());
1940 auto name = "p" + std::to_string(s + 1);
1941 r.push_back({std::move(sig), std::move(name)});
1942 EldbusArgGenerator_Helper<ARGS...>::add(r);
1947 struct EldbusArgGenerator_Helper<void>
1949 static void add(std::vector<std::pair<std::string, std::string>>&)
1955 struct EldbusArgGenerator_Helper<ValueOrError<void>, void>
1957 static void add(std::vector<std::pair<std::string, std::string>>&)
1962 struct EldbusArgGenerator_Helper<ValueOrError<>, void>
1964 static void add(std::vector<std::pair<std::string, std::string>>&)
1969 template<typename... ARGS>
1970 struct EldbusArgGenerator_Helper<std::tuple<ARGS...>>
1972 static void add(std::vector<std::pair<std::string, std::string>>& r)
1974 EldbusArgGenerator_Helper<ARGS..., void>::add(r);
1978 template<typename RetType>
1979 struct dbus_interface_return_type_traits
1981 using type = ValueOrError<RetType>;
1984 template<typename... ARGS>
1985 struct dbus_interface_return_type_traits<ValueOrError<ARGS...>>
1987 using type = ValueOrError<ARGS...>;
1990 template<typename T>
1991 struct dbus_interface_traits;
1992 template<typename RetType, typename... ARGS>
1993 struct dbus_interface_traits<RetType(ARGS...)>
1995 using Ret = typename dbus_interface_return_type_traits<RetType>::type;
1996 using SyncCB = std::function<Ret(ARGS...)>;
1997 using AsyncCB = std::function<void(std::function<void(Ret)>, ARGS...)>;
1998 using VEArgs = ValueOrError<ARGS...>;
2001 template<typename T>
2002 struct EldbusArgGenerator_Args;
2003 template<typename RetType, typename... ARGS>
2004 struct EldbusArgGenerator_Args<RetType(ARGS...)>
2006 static std::string name()
2008 return std::string{signature_tuple_helper<0, sizeof...(ARGS), ARGS...>::name()};
2010 static std::vector<std::pair<std::string, std::string>> get()
2012 std::vector<std::pair<std::string, std::string>> tmp;
2013 EldbusArgGenerator_Helper<ARGS..., void>::add(tmp);
2018 template<typename T>
2019 struct EldbusArgGenerator_ReturnType;
2020 template<typename RetType, typename... ARGS>
2021 struct EldbusArgGenerator_ReturnType<RetType(ARGS...)>
2023 static std::string name()
2025 return std::string{signature<RetType>::name()};
2027 static std::vector<std::pair<std::string, std::string>> get()
2029 std::vector<std::pair<std::string, std::string>> tmp;
2030 EldbusArgGenerator_Helper<RetType, void>::add(tmp);
2035 template<typename T>
2036 struct EldbusArgGenerator_ReturnType;
2037 template<typename... ARGS>
2038 struct EldbusArgGenerator_ReturnType<void(ARGS...)>
2040 static std::string name()
2044 static std::vector<std::pair<std::string, std::string>> get()
2050 } // namespace detail
2052 using ConnectionType = DBusWrapper::ConnectionType;
2055 * @brief Class representing client's end of DBUS connection
2057 * Allows calling (synchronous and asynchronous) methods on selected interface
2058 * Allows (synchronous and asynchronous) setting / getting properties.
2059 * Allows registering signals.
2063 struct ConnectionInfo
2065 std::string interfaceName, busName, pathName;
2070 * @brief Default constructor, creates non-connected object.
2072 DBusClient() = default;
2075 * @brief Connects to dbus choosen by tp, using given arguments
2077 * @param bus_name name of the bus to connect to
2078 * @param path_name object's path
2079 * @param interface_name interface name
2081 DBusClient(std::string busName_, std::string pathName_, std::string interfaceName_, ConnectionType tp);
2084 * @brief Connects to dbus using connection conn
2086 * @param bus_name name of the bus to connect to
2087 * @param path_name object's path
2088 * @param interface_name interface name
2089 * @param conn connection object from getDBusConnectionByType call
2091 DBusClient(std::string busName_, std::string pathName_, std::string interfaceName_, const DBusWrapper::ConnectionPtr& conn = {});
2094 * @brief Destructor object.
2096 * All signals added will be disconnected.
2097 * All asynchronous calls will be cancelled, their callback's will be called
2098 * with failure message.
2100 ~DBusClient() = default;
2101 DBusClient(const DBusClient&) = delete;
2102 DBusClient(DBusClient&&) = default;
2104 DBusClient& operator=(DBusClient&&) = default;
2105 DBusClient& operator=(const DBusClient&) = delete;
2108 * @brief bool operator
2110 * Returns true, if object is connected to DBUS
2112 explicit operator bool() const
2114 return bool(connectionState->proxy);
2118 * @brief Helper class for calling a method
2120 * Template type T defines both arguments sent to the method
2121 * and expected values. Receiving different values will be reported as
2122 * error. For example:
2123 * \code{.cpp} Method<int(float, float)> \endcode
2124 * defines method, which takes two arguments (two floats) and return
2125 * single value of type int.
2127 template<typename T>
2130 using RetType = typename detail::dbus_interface_traits<T>::Ret;
2131 const detail::ConnectionState& connectionState;
2132 std::string funcName;
2134 std::shared_ptr<ConnectionInfo> connectionInfo;
2137 * @brief Executes synchronous call on DBUS's method
2139 * The function returns ValueOrError<...> object, which
2140 * contains either received values or error message.
2142 * @param args arguments to pass to the method
2144 template<typename... ARGS>
2145 RetType call(const ARGS&... args)
2147 detail::CallId callId;
2148 detail::displayDebugCallInfo(callId, funcName, info, connectionInfo->interfaceName);
2149 return detail::call<RetType>(callId, connectionState, false, funcName, args...);
2153 * @brief Executes asynchronous call on DBUS's method
2155 * The function calls callback with either received values or error message.
2157 * @param callback callback functor, which will be called with return value(s) or error message
2158 * @param args arguments to pass to the method
2160 template<typename... ARGS>
2161 void asyncCall(std::function<void(RetType)> callback, const ARGS&... args)
2163 detail::CallId callId;
2164 detail::displayDebugCallInfo(callId, funcName, info, connectionInfo->interfaceName);
2165 detail::asyncCall<RetType>(callId, connectionState, false, funcName, std::move(callback), args...);
2170 * @brief Helper class for calling a property
2172 * Template type T defines type of the value hidden under property.
2173 * Note, that library automatically wraps both sent and received value into
2174 * DBUS's wrapper type.
2176 template<typename T>
2179 using RetType = typename detail::dbus_interface_return_type_traits<T>::type;
2180 using VariantRetType = typename detail::dbus_interface_return_type_traits<EldbusVariant<T>>::type;
2181 const detail::ConnectionState& connectionState;
2182 std::string propName;
2184 std::shared_ptr<ConnectionInfo> connectionInfo;
2187 * @brief executes synchronous get on property
2189 * The function returns ValueOrError<...> object, which
2190 * contains either received values or error message.
2194 detail::CallId callId;
2195 detail::displayDebugCallInfoProperty(callId, "Get", info, connectionInfo->interfaceName, propName);
2196 auto z = detail::call<VariantRetType>(callId, connectionState, true, "Get", connectionInfo->interfaceName, propName);
2198 return z.getError();
2199 return {std::get<0>(z.getValues()).value};
2203 * @brief executes asynchronous get on property
2205 * The function calls callback with either received values or error message.
2207 * @param callback callback functor, which will be called with return value(s) or error message
2209 void asyncGet(std::function<void(RetType)> callback)
2211 detail::CallId callId;
2212 detail::displayDebugCallInfoProperty(callId, "Get", info, connectionInfo->interfaceName, propName);
2213 auto cc = [callback](VariantRetType reply) {
2215 callback(std::move(std::get<0>(reply.getValues()).value));
2217 callback(reply.getError());
2219 detail::asyncCall<VariantRetType>(callId, connectionState, true, "Get", std::move(cc), connectionInfo->interfaceName, propName);
2223 * @brief executes synchronous set on property
2225 * The function returns ValueOrError<void> object, with
2226 * possible error message.
2228 ValueOrError<void> set(const T& r)
2230 detail::CallId callId;
2231 detail::displayDebugCallInfoProperty(callId, "Set", info, connectionInfo->interfaceName, propName);
2232 EldbusVariant<T> variantValue{std::move(r)};
2233 return detail::call<ValueOrError<void>>(callId, connectionState, true, "Set", connectionInfo->interfaceName, propName, variantValue);
2237 * @brief executes asynchronous get on property
2239 * The function calls callback with either received values or error message.
2241 * @param callback callback functor, which will be called with return value(s) or error message
2243 void asyncSet(std::function<void(ValueOrError<void>)> callback, const T& r)
2245 detail::CallId callId;
2246 detail::displayDebugCallInfoProperty(callId, "Set", info, connectionInfo->interfaceName, propName);
2247 EldbusVariant<T> variantValue{std::move(r)};
2248 detail::asyncCall<ValueOrError<void>>(callId, connectionState, true, "Set", std::move(callback), connectionInfo->interfaceName, propName, variantValue);
2253 * @brief Constructs Property<...> object for calling properties
2255 * The function constructs and returns proxy object for calling property.
2257 * @param propName property name to set and / or query
2259 template<typename PropertyType>
2260 Property<PropertyType> property(std::string propName)
2262 return Property<PropertyType>{*connectionState, std::move(propName), info, connectionInfo};
2266 * @brief Constructs Method<...> object for calling methods
2268 * The function constructs and returns proxy object for calling method.
2270 * @param funcName function name to call
2272 template<typename MethodType>
2273 Method<MethodType> method(std::string funcName)
2275 return Method<MethodType>{*connectionState, std::move(funcName), info, connectionInfo};
2279 * @brief Registers notification callback, when property has changed
2281 * The callback will be called with new value, when property's value has changed.
2282 * Note, that template type V must match expected type, otherwise undefined behavior will occur,
2283 * there's no check for this.
2285 template<typename V>
2286 void addPropertyChangedEvent(std::string propertyName, std::function<void(V)> callback)
2288 detail::CallId callId;
2289 detail::displayDebugCallInfoSignal(callId, propertyName, info, connectionInfo->interfaceName);
2290 DBUS_DEBUG("call %d: adding property", callId.id);
2291 auto& cI = this->connectionInfo;
2292 DBUS_W->add_property_changed_event_listener_impl(connectionState->proxy, cI->interfaceName, propertyName, [callback](const _Eina_Value* newValue) {
2294 if(!getFromEinaValue(newValue, &val))
2296 DBUS_DEBUG("unable to get property's value");
2304 * @brief Registers callback on the DBUS' signal
2306 * The function registers callback signalName. When signal comes, callback will be called.
2307 * Callback object will exists as long as signal is registered. You can unregister signal
2308 * by destroying DBusClient object.
2310 * @param signalName name of the signal to register
2311 * @param callback callback to call
2313 template<typename SignalType>
2314 void addSignal(std::string signalName, std::function<SignalType> callback)
2316 detail::CallId callId;
2317 detail::displayDebugCallInfoSignal(callId, signalName, info, connectionInfo->interfaceName);
2318 DBUS_W->eldbus_proxy_signal_handler_add_impl(connectionState->proxy, signalName, [callId, callback, signalName](const DBusWrapper::MessagePtr& msg) -> void {
2319 std::string errname, aux;
2320 if(DBUS_W->eldbus_message_error_get_impl(msg, errname, aux))
2322 DBUS_DEBUG("call %d: Eldbus error: %s %s", callId.id, errname.c_str(), aux.c_str());
2325 DBUS_DEBUG("call %d: received signal with signature '%s'", callId.id, DBUS_W->eldbus_message_signature_get_impl(msg).c_str());
2326 using ParamsType = typename detail::dbus_interface_traits<SignalType>::VEArgs;
2327 auto params = detail::unpackValues<ParamsType>(callId, msg);
2330 DBUS_DEBUG("call %d: failed: %s", callId.id, params.getError().message.c_str());
2335 std::apply(callback, params.getValues());
2337 catch(const Dali::DaliException& e)
2339 DBUS_DEBUG("unhandled exception");
2346 std::unique_ptr<detail::ConnectionState> connectionState{new detail::ConnectionState};
2348 std::shared_ptr<ConnectionInfo> connectionInfo;
2350 static bool getFromEinaValue(const _Eina_Value* v, void* dst);
2354 * @brief Helper class describing DBUS's server interface
2357 class DBusInterfaceDescription
2359 friend class DBusServer;
2362 using MethodInfo = DBusWrapper::MethodInfo;
2363 using SignalInfo = DBusWrapper::SignalInfo;
2364 using PropertyInfo = DBusWrapper::PropertyInfo;
2365 using SignalId = DBusWrapper::SignalId;
2368 * @brief Creates empty interface description with given name
2370 * @param interfaceName name of the interface
2372 DBusInterfaceDescription(std::string interfaceName);
2375 * @brief adds new, synchronous method to the interface
2377 * When method memberName is called on DBUS, callback functor will be called
2378 * with values received from DBUS. callback won't be called, if method was
2379 * called with invalid signature. Value returned from functor (or error message)
2380 * will be marshalled back to the caller.
2382 * Template type T defines both arguments sent to the method
2383 * and expected values. Receiving different values will be reported as
2384 * error. For example:
2385 * \code{.cpp} Method<int(float, float)> \endcode
2386 * defines method, which takes two arguments (two floats) and return
2387 * single value of type int.
2389 * @param memberName name of the method
2390 * @param callback functor, which will be called
2392 template<typename T>
2393 void addMethod(const std::string& memberName, typename detail::dbus_interface_traits<T>::SyncCB callback)
2395 detail::CallId callId;
2397 methods.push_back(std::move(mi));
2398 auto& z = methods.back();
2399 z.in = detail::EldbusArgGenerator_Args<T>::get();
2400 z.out = detail::EldbusArgGenerator_ReturnType<T>::get();
2401 z.memberName = memberName;
2402 DBUS_DEBUG("call %d: method %s, in %s, out %s", callId.id, memberName.c_str(), detail::EldbusArgGenerator_Args<T>::name().c_str(), detail::EldbusArgGenerator_ReturnType<T>::name().c_str());
2403 z.callback = construct<T>(callId, callback);
2408 * @brief adds new, synchronous property to the interface
2410 * When property memberName is called on DBUS, respective callback functor will be called
2411 * with values received from DBUS. callback won't be called, if method was
2412 * called with invalid signature. Value returned from functor (or error message)
2413 * will be marshalled back to the caller.
2415 * Template type T defines type of the value hidden under property.
2416 * Note, that library automatically wraps both sent and received value into
2417 * DBUS's wrapper type.
2419 * @param memberName name of the method
2420 * @param getter functor, which will be called when property is being read
2421 * @param setter functor, which will be called when property is being set
2423 template<typename T>
2424 void addProperty(const std::string& memberName, std::function<ValueOrError<T>()> getter, std::function<ValueOrError<void>(T)> setter)
2426 properties.push_back({});
2427 auto& z = properties.back();
2428 z.memberName = memberName;
2429 z.typeSignature = detail::signature<T>::sig();
2432 detail::CallId getterId;
2433 z.getterId = getterId;
2434 DBUS_DEBUG("call %d: property %s (get) type %s", getterId.id, memberName.c_str(), detail::signature<T>::name().data());
2435 z.getCallback = [=](const DBusWrapper::MessagePtr& src, const DBusWrapper::MessageIterPtr& dst) -> std::string {
2438 auto v = std::apply(getter, std::tuple<>{});
2441 detail::signature<T>::set(dst, std::get<0>(v.getValues()));
2442 DBUS_DEBUG("call %d: success", getterId.id);
2445 DBUS_DEBUG("call %d: failed: %s", getterId.id, v.getError().message.c_str());
2446 return v.getError().message;
2448 catch(std::exception& e)
2450 return std::string("unhandled exception (") + e.what() + ")";
2452 catch(const Dali::DaliException& e)
2454 return std::string("unhandled exception (") + e.condition + ")";
2460 detail::CallId setterId;
2461 z.setterId = setterId;
2462 DBUS_DEBUG("call %d: property %s (set) type %s", setterId.id, memberName.c_str(), detail::signature<T>::name().data());
2463 z.setCallback = [=](const DBusWrapper::MessagePtr& src, const DBusWrapper::MessageIterPtr& src_iter) -> std::string {
2464 std::tuple<T> value;
2465 auto src_signature = DBUS_W->eldbus_message_iter_signature_get_impl(src_iter);
2466 if(detail::signature<T>::get(src_iter, std::get<0>(value)))
2470 auto v = std::apply(setter, std::move(value));
2473 DBUS_DEBUG("call %d: success", setterId.id);
2476 DBUS_DEBUG("call %d: failed: %s", setterId.id, v.getError().message.c_str());
2477 return v.getError().message;
2479 catch(std::exception& e)
2481 return std::string("unhandled exception (") + e.what() + ")";
2483 catch(const Dali::DaliException& e)
2485 return std::string("unhandled exception (") + e.condition + ")";
2488 DBUS_DEBUG("call %d: failed to unpack values, got signature '%s', expected '%s'", setterId.id, src_signature.c_str(), detail::signature<T>::sig().data());
2489 return "call " + std::to_string(setterId.id) + ": failed to unpack values, got signature '" +
2490 src_signature + "', expected '" + std::string{detail::signature<T>::sig()} + "'";
2496 * @brief adds new signal to the interface
2498 * Template types ARGS defines values, which will be emited with the signal
2500 * @param memberName name of the method
2502 template<typename... ARGS>
2503 SignalId addSignal(const std::string& memberName)
2505 detail::CallId callId;
2506 signals.push_back({});
2507 auto& z = signals.back();
2508 z.memberName = memberName;
2509 z.args = detail::EldbusArgGenerator_Args<void(ARGS...)>::get(DBUS_W->Strings);
2511 DBUS_DEBUG("call %d: signal %s", callId.id, memberName.c_str());
2512 return SignalId{callId};
2516 std::vector<MethodInfo> methods;
2517 std::vector<PropertyInfo> properties;
2518 std::vector<SignalInfo> signals;
2519 std::string interfaceName;
2521 template<typename T>
2522 std::function<DBusWrapper::MessagePtr(const DBusWrapper::MessagePtr& msg)> construct(detail::CallId callId,
2523 typename detail::dbus_interface_traits<T>::SyncCB callback)
2525 using VEArgs = typename detail::dbus_interface_traits<T>::VEArgs;
2526 return [=](const DBusWrapper::MessagePtr& msg) -> DBusWrapper::MessagePtr {
2527 DBUS_DEBUG("call %d: entering", callId.id);
2528 DBusWrapper::MessagePtr ret = {};
2529 auto args = detail::unpackValues<VEArgs>(callId, msg);
2534 auto v = std::apply(callback, std::move(args.getValues()));
2537 DBUS_DEBUG("call %d: success", callId.id);
2538 ret = DBUS_W->eldbus_message_method_return_new_impl(msg);
2539 detail::packValues(callId, ret, v);
2543 DBUS_DEBUG("call %d: failed: %s", callId.id, v.getError().message.c_str());
2544 ret = DBUS_W->eldbus_message_error_new_impl(msg, "org.freedesktop.DBus.Error.Failed", v.getError().message);
2547 catch(std::exception& e)
2549 auto txt = std::string("unhandled exception (") + e.what() + ")";
2550 DBUS_DEBUG("call %d: failed: %s", callId.id, txt.c_str());
2551 ret = DBUS_W->eldbus_message_error_new_impl(msg, "org.freedesktop.DBus.Error.Failed", txt);
2553 catch(const Dali::DaliException& e)
2555 auto txt = std::string("unhandled exception (") + e.condition + ")";
2556 DBUS_DEBUG("call %d: failed: %s", callId.id, txt.c_str());
2557 ret = DBUS_W->eldbus_message_error_new_impl(msg, "org.freedesktop.DBus.Error.Failed", txt);
2562 std::ostringstream err;
2563 err << "expected signature '" << detail::signature<VEArgs>::sig() << "', got '" << DBUS_W->eldbus_message_signature_get_impl(msg) << "'";
2564 auto str = err.str();
2565 DBUS_DEBUG("call %d: failed: %s", callId.id, str.c_str());
2566 ret = DBUS_W->eldbus_message_error_new_impl(msg, "org.freedesktop.DBus.Error.InvalidArgs", str);
2574 * @brief Class representing server's end of DBUS connection
2576 * Allows listening (synchronously and asynchronously) on methods on selected interface
2577 * Allows listening (synchronously and asynchronously) on setting / getting properties.
2578 * Allows emiting signals.
2584 * @brief Constructs non-connected dbus server.
2586 DBusServer() = default;
2589 * @brief Constructs dbus server on either system or user dbus connection.
2591 DBusServer(ConnectionType tp);
2594 * @brief Constructs dbus server on connection from getDBusConnectionByType
2596 DBusServer(const DBusWrapper::ConnectionPtr& conn);
2601 * Destructor will properly destroy everything. Destructor will cancel
2604 ~DBusServer() = default;
2606 DBusServer(const DBusServer&) = delete;
2607 DBusServer(DBusServer&&) = default;
2609 DBusServer& operator=(DBusServer&&) = default;
2610 DBusServer& operator=(const DBusServer&) = delete;
2613 * @brief Registers interface on given path name
2615 * @param pathName path object to register interface on.
2619 void addInterface(const std::string& pathName, DBusInterfaceDescription& dscr, bool fallback = false);
2622 * @brief Gets bus name of the current connection (must be connected)
2624 std::string getBusName() const;
2627 * @brief Returns connection object for this dbus server object
2629 * @return connection object
2631 DBusWrapper::ConnectionPtr getConnection();
2634 * @brief Emits signal
2636 * Emits signal based only on data passed to the function
2638 * @param signal identifier of the signal
2639 * @param args values to emit
2641 template<typename... ARGS>
2642 void emit2(const std::string& path, const std::string& interfaceName, const std::string& signalName, const ARGS&... args)
2644 auto msg = DBUS_W->eldbus_message_signal_new_impl(path, interfaceName, signalName);
2646 detail::packValues(id, msg, args...);
2647 DBUS_W->eldbus_connection_send_impl(connection, msg);
2651 * @brief Returns current object path, when handling call to property / method
2653 * User can call this function from inside callback used to handle property / method calls.
2654 * It will retrieve object's path used in the call. Note, that in asynchronous handling
2655 * of those calls user need to retrieve and store the current object / current connection
2656 * as the value will change at the moment user's callback handling will exit. For example:
2658 * DBusInterfaceDescription interface{"name"};
2659 * auto handler_later = [](std::function<void(void)> done_cb) {
2660 * // process something later on
2661 * DBusServer::getCurrentObjectPath(); // this will return empty string
2663 * interface.addAsyncMethod<void()>("m", [=](std::function<void(void)> done_cb) {
2664 * DBusServer::getCurrentObjectPath(); // this will current object's path
2666 * // do some processing later on and call done_cb, when it's done
2667 * register_to_call_sometime_later_on(std::move(done_cb));
2671 static std::string getCurrentObjectPath()
2673 return currentObjectPath;
2677 * @brief Returns current connection object, when handling call to property / method
2679 * User can call this function from inside callback used to handle property / method calls.
2680 * It will retrieve object's path used in the call. Note, that in asynchronous handling
2681 * of those calls user need to retrieve and store the current object / current connection
2682 * as the value will change at the moment user's callback handling will exit. For example:
2684 * DBusInterfaceDescription interface{"name"};
2685 * auto handler_later = [](std::function<void(void)> done_cb) {
2686 * // process something later on
2687 * DBusServer::getCurrentObjectPath(); // this will return empty string
2689 * interface.addAsyncMethod<void()>("m", [=](std::function<void(void)> done_cb) {
2690 * DBusServer::getCurrentObjectPath(); // this will current object's path
2692 * // do some processing later on and call done_cb, when it's done
2693 * register_to_call_sometime_later_on(std::move(done_cb));
2697 static const DBusWrapper::ConnectionPtr& getCurrentConnection()
2699 return currentConnection;
2703 class CurrentObjectSetter
2706 CurrentObjectSetter(DBusWrapper::ConnectionPtr con, std::string path)
2708 currentObjectPath = std::move(path);
2709 currentConnection = std::move(con);
2711 ~CurrentObjectSetter()
2713 currentObjectPath = "";
2714 currentConnection = {};
2716 CurrentObjectSetter(const CurrentObjectSetter&) = delete;
2717 CurrentObjectSetter(CurrentObjectSetter&&) = delete;
2718 void operator=(const CurrentObjectSetter&) = delete;
2719 void operator=(CurrentObjectSetter&&) = delete;
2723 DBusWrapper::ConnectionPtr connection;
2724 struct DestructorObject
2726 std::vector<std::function<void()>> destructors;
2729 for(auto& a : destructors) a();
2733 std::unique_ptr<DestructorObject> destructorObject{new DestructorObject()};
2734 static thread_local std::string currentObjectPath;
2735 static thread_local DBusWrapper::ConnectionPtr currentConnection;
2738 DBusWrapper::ConnectionPtr getDBusConnectionByType(ConnectionType tp);
2739 DBusWrapper::ConnectionPtr getDBusConnectionByName(const std::string& name);
2740 std::string getConnectionName(const DBusWrapper::ConnectionPtr&);
2741 void requestBusName(const DBusWrapper::ConnectionPtr& conn, const std::string& bus);
2742 void releaseBusName(const DBusWrapper::ConnectionPtr& conn, const std::string& bus);
2747 template<size_t INDEX, typename... ARGS>
2748 inline auto get(DBus::ValueOrError<ARGS...>& v) -> decltype(std::get<INDEX>(v.getValues()))&
2750 return std::get<INDEX>(v.getValues());
2753 template<size_t INDEX, typename... ARGS>
2754 inline auto get(const DBus::ValueOrError<ARGS...>& v) -> decltype(std::get<INDEX>(v.getValues()))
2756 return std::get<INDEX>(v.getValues());
2760 #endif // DALI_INTERNAL_ACCESSIBILITY_BRIDGE_DBUS_H