#define DBUS_DEBUG(...) do { DBus::debugPrint(__FILE__, __LINE__, __VA_ARGS__); } while(0)
+/**
+ * @brief Template based, single file, wrapper library around eldbus for DBUS based communication.
+ *
+ * Main motivation was missing asynchronous calls in AT-SPI library and difficulties,
+ * when using eldbus from C++.
+ *
+ * The library:
+ * - takes care of marshalling arguments to and from DBUS calls.
+ * - allows synchronous and asynchronous calls.
+ * - allows synchronous and asynchronous listeners on signals.
+ * - manages all involved objects' lifetimes.
+ * - errors are passed as optional-alike objects, no exceptions are used.
+ * - allows setting additional debug-print function for more details about
+ * what's going on
+ *
+ * DBUS's method signatures (and expected return values) are specified as template argument,
+ * using functor syntax. For example:
+ * \code{.cpp}
+ * auto dbus = DBusClient{ ... };
+ * auto v = dbus.method<std::tuple<int, float>(float, float, std::string)>("foo").call(1.0f, 2.0f, "qwe");
+ * \endcode
+ * means (synchronous) call on dbus object, which takes three arguments (thus making call signature \b dds)
+ * of types float, float and string (float will be automatically converted to double).
+ * Expected return value is std::tuple<int, float>, which gives signature <B>(id)</B> - std::tuple acts
+ * as struct container. Returned value v will be of type ValueOrError<std::tuple<int, float>>.\n
+ * Slightly different (asynchronous) example:
+ * \code{.cpp}
+ * auto dbus = DBusClient{ ... };
+ * std::function<void(ValueOrError<int, float>)> callback;
+ * dbus.method<ValueOrError<int, float>(float, float, std::string)>("foo").asyncCall(callback, 1.0f, 2.0f, "qwe");
+ * \endcode
+ * Now the call takes the same arguments and has the same signature. But expected values are different -
+ * now the signature is simply \b id. ValueOrError acts in this case as placeholder for list of values,
+ * which DBUS allows as return data. The call itself is asynchronous - instead of expecting reply
+ * you need to pass a callback, which will be called either with received data and error message.
+ *
+ * Library is not thread-safe, the same object shouldn't be called from different threads without
+ * synchronization. There's no guarantee, that callbacks will be executed on the same thread.
+ */
namespace DBus
{
+ /// \cond
class DBusServer;
class DBusClient;
class DBusInterfaceDescription;
}
};
struct Success { };
-
+ /// \endcond
+
+ /**
+ * @brief Value representing data, that came from DBUS or error message
+ *
+ * Object of this class either helds series of values (of types ARGS...)
+ * or error message. This object will be true in boolean context, if has data
+ * and false, if an error occured.
+ * It's valid to create ValueOrError object with empty argument list or void:
+ * \code{.cpp}
+ * ValueOrError<> v1;
+ * ValueOrError<void> v2;
+ * \endcode
+ * Both mean the same - ValueOrError containing no real data and being a marker,
+ * wherever operation successed or failed and containing possible error message.
+ */
template <typename ... ARGS> class ValueOrError
{
public:
+ /**
+ * @brief Empty constructor. Valid only, if all ARGS types are default constructible.
+ */
ValueOrError() = default;
+
+ /**
+ * @brief Value constructor.
+ *
+ * This will be initialized as success with passed in values.
+ */
ValueOrError(ARGS ... t) : value(std::move(t)...) { }
+
+ /**
+ * @brief Alternative Value constructor.
+ *
+ * This will be initialized as success with passed in values.
+ */
ValueOrError(std::tuple<ARGS...> t) : value(std::move(t)) { }
+
+ /**
+ * @brief Error constructor. This will be initialized as failure with given error message.
+ */
ValueOrError(Error e) : error(std::move(e))
{
ASSERT(!error.message.empty());
}
+ /**
+ * @brief bool operator.
+ *
+ * Returns true, if operation was successful (getValues member is callable), or false
+ * when operation failed (getError is callable).
+ */
explicit operator bool () const
{
return error.message.empty();
}
+
+ /**
+ * @brief Returns error message object.
+ *
+ * Returns object containing error message associated with the failed operation.
+ * Only callable, if operation actually failed, otherwise will assert.
+ */
const Error &getError() const
{
return error;
}
+
+ /**
+ * @brief Returns modifiable tuple of held data.
+ *
+ * Returns reference to the internal tuple containing held data.
+ * User can modify (or move) data safely.
+ * Only callable, if operation actually successed, otherwise will assert.
+ */
std::tuple<ARGS...> &getValues()
{
ASSERT(*this);
return value;
}
+
+ /**
+ * @brief Returns const tuple of held data.
+ *
+ * Returns const reference to the internal tuple containing held data.
+ * Only callable, if operation actually successed, otherwise will assert.
+ */
const std::tuple<ARGS...> &getValues() const
{
ASSERT(*this);
return value;
}
+
protected:
+ /// \cond
std::tuple<ARGS...> value;
Error error;
+ /// \endcond
};
+ /// \cond
template <> class ValueOrError<>
{
public:
}
};
}
-
+ /// \endcond
+
+ /**
+ * @brief Class used to marshall DBUS's variant type
+ *
+ * Minimalistic class, that allows user to specify DBUS variant type
+ * as argument or return value. You need to pass real type hidden under variant as
+ * template type \b A. At this point library doesn't allow to expected one of few classes
+ * as return data in variant. So for example user can't specify method call, which on return
+ * expects DBUS variant holding either string or int.
+ */
template <typename A> struct EldbusVariant {
A value;
};
+ /// \cond
using EldbusConnectionCallbackHandle = std::shared_ptr<Eldbus_Connection>;
using EldbusMessageCallbackHandle = std::unique_ptr<Eldbus_Message, detail::caller_eldbus_message_unref>;
using EldbusObjectCallbackHandle = std::shared_ptr<Eldbus_Object>;
+ /// \endcond
+ /**
+ * @brief Namespace for private, internal functions and classes
+ *
+ */
namespace detail
{
+ /// \cond
template <typename T, typename = void> struct signature;
template <typename ... ARGS> struct signature<std::tuple<ARGS...>>;
template <typename A, typename B> struct signature<std::pair<A, B>>;
template <typename A, typename B> struct signature<std::map<A, B>>;
template <typename T> struct signature<T, typename std::enable_if<std::is_enum<T>::value, void>::type> {
+ /**
+ * @brief Returns name of type marshalled, for informative purposes
+ */
static std::string name()
{
return "enum";
}
+ /**
+ * @brief Returns DBUS' signature of type marshalled
+ */
static std::string sig()
{
// TODO: add check for failure in marshalling arguments
return "i";
}
+ /**
+ * @brief Marshals value v as marshalled type into message
+ */
static void set(Eldbus_Message_Iter *iter, T v)
{
eldbus_message_iter_arguments_append(iter, sig().c_str(), (int)v);
}
+ /**
+ * @brief Marshals value from marshalled type into variable v
+ */
static bool get(Eldbus_Message_Iter *iter, T &v)
{
int q;
return z;
}
};
+ /// \endcond
+
+ /**
+ * @brief Signature class for marshalling uint8 type.
+ */
+ template <> struct signature<uint8_t> {
+ /**
+ * @brief Returns name of type marshalled, for informative purposes
+ */
+ static std::string name()
+ {
+ return "uint8_t";
+ }
+ /**
+ * @brief Returns DBUS' signature of type marshalled
+ */
+ static std::string sig()
+ {
+ return "y";
+ }
+ /**
+ * @brief Marshals value v as marshalled type into message
+ */
+ static void set(Eldbus_Message_Iter *iter, uint8_t v)
+ {
+ eldbus_message_iter_arguments_append(iter, sig().c_str(), v);
+ }
+ /**
+ * @brief Marshals value from marshalled type into variable v
+ */
+ static bool get(Eldbus_Message_Iter *iter, uint8_t &v)
+ {
+ return eldbus_message_iter_get_and_next(iter, sig()[0], &v);
+ }
+ };
-#define SIGNATURE(T, S) \
- template <> struct signature<T> { \
- static std::string name() { return #T; } \
- static std::string sig() { return #S; } \
- static void set(Eldbus_Message_Iter *iter, T v) { \
- eldbus_message_iter_arguments_append(iter, sig().c_str(), v); \
- } \
- static bool get(Eldbus_Message_Iter *iter, T &v) { \
- return eldbus_message_iter_get_and_next(iter, sig()[0], &v); \
- } \
- };
- SIGNATURE(uint8_t, y);
- SIGNATURE(uint16_t, q);
- SIGNATURE(uint32_t, u);
- SIGNATURE(uint64_t, t);
- SIGNATURE(int16_t, n);
- SIGNATURE(int32_t, i);
- SIGNATURE(int64_t, x);
- SIGNATURE(double, d);
-#undef SIGNATURE
+ /**
+ * @brief Signature class for marshalling uint16 type.
+ */
+ template <> struct signature<uint16_t> {
+ /**
+ * @brief Returns name of type marshalled, for informative purposes
+ */
+ static std::string name()
+ {
+ return "uint16_t";
+ }
+ /**
+ * @brief Returns DBUS' signature of type marshalled
+ */
+ static std::string sig()
+ {
+ return "q";
+ }
+ /**
+ * @brief Marshals value v as marshalled type into message
+ */
+ static void set(Eldbus_Message_Iter *iter, uint16_t v)
+ {
+ eldbus_message_iter_arguments_append(iter, sig().c_str(), v);
+ }
+ /**
+ * @brief Marshals value from marshalled type into variable v
+ */
+ static bool get(Eldbus_Message_Iter *iter, uint16_t &v)
+ {
+ return eldbus_message_iter_get_and_next(iter, sig()[0], &v);
+ }
+ };
+
+ /**
+ * @brief Signature class for marshalling uint32 type.
+ */
+ template <> struct signature<uint32_t> {
+ /**
+ * @brief Returns name of type marshalled, for informative purposes
+ */
+ static std::string name()
+ {
+ return "uint32_t";
+ }
+ /**
+ * @brief Returns DBUS' signature of type marshalled
+ */
+ static std::string sig()
+ {
+ return "u";
+ }
+ /**
+ * @brief Marshals value v as marshalled type into message
+ */
+ static void set(Eldbus_Message_Iter *iter, uint32_t v)
+ {
+ eldbus_message_iter_arguments_append(iter, sig().c_str(), v);
+ }
+ /**
+ * @brief Marshals value from marshalled type into variable v
+ */
+ static bool get(Eldbus_Message_Iter *iter, uint32_t &v)
+ {
+ return eldbus_message_iter_get_and_next(iter, sig()[0], &v);
+ }
+ };
+
+ /**
+ * @brief Signature class for marshalling uint64 type.
+ */
+ template <> struct signature<uint64_t> {
+ /**
+ * @brief Returns name of type marshalled, for informative purposes
+ */
+ static std::string name()
+ {
+ return "uint64_t";
+ }
+ /**
+ * @brief Returns DBUS' signature of type marshalled
+ */
+ static std::string sig()
+ {
+ return "t";
+ }
+ /**
+ * @brief Marshals value v as marshalled type into message
+ */
+ static void set(Eldbus_Message_Iter *iter, uint64_t v)
+ {
+ eldbus_message_iter_arguments_append(iter, sig().c_str(), v);
+ }
+ /**
+ * @brief Marshals value from marshalled type into variable v
+ */
+ static bool get(Eldbus_Message_Iter *iter, uint64_t &v)
+ {
+ return eldbus_message_iter_get_and_next(iter, sig()[0], &v);
+ }
+ };
+
+ /**
+ * @brief Signature class for marshalling int16 type.
+ */
+ template <> struct signature<int16_t> {
+ /**
+ * @brief Returns name of type marshalled, for informative purposes
+ */
+ static std::string name()
+ {
+ return "int16_t";
+ }
+ /**
+ * @brief Returns DBUS' signature of type marshalled
+ */
+ static std::string sig()
+ {
+ return "n";
+ }
+ /**
+ * @brief Marshals value v as marshalled type into message
+ */
+ static void set(Eldbus_Message_Iter *iter, int16_t v)
+ {
+ eldbus_message_iter_arguments_append(iter, sig().c_str(), v);
+ }
+ /**
+ * @brief Marshals value from marshalled type into variable v
+ */
+ static bool get(Eldbus_Message_Iter *iter, int16_t &v)
+ {
+ return eldbus_message_iter_get_and_next(iter, sig()[0], &v);
+ }
+ };
+ /**
+ * @brief Signature class for marshalling int32 type.
+ */
+ template <> struct signature<int32_t> {
+ /**
+ * @brief Returns name of type marshalled, for informative purposes
+ */
+ static std::string name()
+ {
+ return "int32_t";
+ }
+ /**
+ * @brief Returns DBUS' signature of type marshalled
+ */
+ static std::string sig()
+ {
+ return "i";
+ }
+ /**
+ * @brief Marshals value v as marshalled type into message
+ */
+ static void set(Eldbus_Message_Iter *iter, int32_t v)
+ {
+ eldbus_message_iter_arguments_append(iter, sig().c_str(), v);
+ }
+ /**
+ * @brief Marshals value from marshalled type into variable v
+ */
+ static bool get(Eldbus_Message_Iter *iter, int32_t &v)
+ {
+ return eldbus_message_iter_get_and_next(iter, sig()[0], &v);
+ }
+ };
+
+ /**
+ * @brief Signature class for marshalling int64 type.
+ */
+ template <> struct signature<int64_t> {
+ /**
+ * @brief Returns name of type marshalled, for informative purposes
+ */
+ static std::string name()
+ {
+ return "int64_t";
+ }
+ /**
+ * @brief Returns DBUS' signature of type marshalled
+ */
+ static std::string sig()
+ {
+ return "x";
+ }
+ /**
+ * @brief Marshals value v as marshalled type into message
+ */
+ static void set(Eldbus_Message_Iter *iter, int64_t v)
+ {
+ eldbus_message_iter_arguments_append(iter, sig().c_str(), v);
+ }
+ /**
+ * @brief Marshals value from marshalled type into variable v
+ */
+ static bool get(Eldbus_Message_Iter *iter, int64_t &v)
+ {
+ return eldbus_message_iter_get_and_next(iter, sig()[0], &v);
+ }
+ };
+
+ /**
+ * @brief Signature class for marshalling double type.
+ */
+ template <> struct signature<double> {
+ /**
+ * @brief Returns name of type marshalled, for informative purposes
+ */
+ static std::string name()
+ {
+ return "double";
+ }
+ /**
+ * @brief Returns DBUS' signature of type marshalled
+ */
+ static std::string sig()
+ {
+ return "d";
+ }
+ /**
+ * @brief Marshals value v as marshalled type into message
+ */
+ static void set(Eldbus_Message_Iter *iter, double v)
+ {
+ eldbus_message_iter_arguments_append(iter, sig().c_str(), v);
+ }
+ /**
+ * @brief Marshals value from marshalled type into variable v
+ */
+ static bool get(Eldbus_Message_Iter *iter, double &v)
+ {
+ return eldbus_message_iter_get_and_next(iter, sig()[0], &v);
+ }
+ /**
+ * @brief Marshals value from marshalled type into variable v
+ */
+ static bool get(Eldbus_Message_Iter *iter, float &v2)
+ {
+ double v = 0;
+ auto r = eldbus_message_iter_get_and_next(iter, sig()[0], &v);
+ v2 = static_cast<float>(v);
+ return r;
+ }
+ };
+
+ /**
+ * @brief Signature class for marshalling float type.
+ */
+ template <> struct signature<float> {
+ /**
+ * @brief Returns name of type marshalled, for informative purposes
+ */
+ static std::string name()
+ {
+ return "float";
+ }
+ /**
+ * @brief Returns DBUS' signature of type marshalled
+ */
+ static std::string sig()
+ {
+ return "d";
+ }
+ /**
+ * @brief Marshals value v as marshalled type into message
+ */
+ static void set(Eldbus_Message_Iter *iter, float v)
+ {
+ eldbus_message_iter_arguments_append(iter, sig().c_str(), v);
+ }
+ /**
+ * @brief Marshals value from marshalled type into variable v
+ */
+ static bool get(Eldbus_Message_Iter *iter, double &v)
+ {
+ return eldbus_message_iter_get_and_next(iter, sig()[0], &v);
+ }
+ /**
+ * @brief Marshals value from marshalled type into variable v
+ */
+ static bool get(Eldbus_Message_Iter *iter, float &v2)
+ {
+ double v = 0;
+ auto r = eldbus_message_iter_get_and_next(iter, sig()[0], &v);
+ v2 = static_cast<float>(v);
+ return r;
+ }
+ };
+
+ /**
+ * @brief Signature class for marshalling boolean type.
+ */
template <> struct signature<bool> {
+ /**
+ * @brief Returns name of type marshalled, for informative purposes
+ */
static std::string name()
{
return "bool";
}
+ /**
+ * @brief Returns DBUS' signature of type marshalled
+ */
static std::string sig()
{
return "b";
}
+ /**
+ * @brief Marshals value v as marshalled type into message
+ */
static void set(Eldbus_Message_Iter *iter, bool v)
{
eldbus_message_iter_arguments_append(iter, sig().c_str(), v ? 1 : 0);
}
+ /**
+ * @brief Marshals value from marshalled type into variable v
+ */
static bool get(Eldbus_Message_Iter *iter, bool &v)
{
unsigned char q;
return z;
}
};
+
+ /**
+ * @brief Signature class for marshalling string type.
+ *
+ * Both (const) char * and std::string types are accepted as value to send.
+ * Only std::string is accepted as value to receive.
+ */
template <> struct signature<std::string> {
+ /**
+ * @brief Returns name of type marshalled, for informative purposes
+ */
static std::string name()
{
return "string";
}
+ /**
+ * @brief Returns DBUS' signature of type marshalled
+ */
static std::string sig()
{
return "s";
}
+ /**
+ * @brief Marshals value v as marshalled type into message
+ */
static void set(Eldbus_Message_Iter *iter, const std::string &v)
{
eldbus_message_iter_arguments_append(iter, sig().c_str(), v.c_str());
}
+ /**
+ * @brief Marshals value v as marshalled type into message
+ */
static void set(Eldbus_Message_Iter *iter, const char *v)
{
eldbus_message_iter_arguments_append(iter, sig().c_str(), v);
}
+ /**
+ * @brief Marshals value from marshalled type into variable v
+ */
static bool get(Eldbus_Message_Iter *iter, std::string &v)
{
const char *q;
return true;
}
};
+
+ /**
+ * @brief Signature class for marshalling (const) char * type.
+ *
+ * Both (const) char * and std::string types are accepted as value to send.
+ * You can't use (const) char * variable type to receive value.
+ */
template <> struct signature<char *> {
+ /**
+ * @brief Returns name of type marshalled, for informative purposes
+ */
static std::string name()
{
return "string";
}
+ /**
+ * @brief Returns DBUS' signature of type marshalled
+ */
static std::string sig()
{
return "s";
}
+ /**
+ * @brief Marshals value v as marshalled type into message
+ */
static void set(Eldbus_Message_Iter *iter, const std::string &v)
{
eldbus_message_iter_arguments_append(iter, sig().c_str(), v.c_str());
}
+ /**
+ * @brief Marshals value v as marshalled type into message
+ */
static void set(Eldbus_Message_Iter *iter, const char *v)
{
eldbus_message_iter_arguments_append(iter, sig().c_str(), v);
}
};
+
+ /**
+ * @brief Signature class for marshalling (const) char[N] type.
+ *
+ * Both (const) char[N] and std::string types are accepted as value to send.
+ * You can't use (const) char[N] variable type to receive value.
+ */
template <size_t N> struct signature<char [N]> {
+ /**
+ * @brief Returns name of type marshalled, for informative purposes
+ */
static std::string name()
{
return "string";
}
+ /**
+ * @brief Returns DBUS' signature of type marshalled
+ */
static std::string sig()
{
return "s";
}
+ /**
+ * @brief Marshals value v as marshalled type into message
+ */
static void set(Eldbus_Message_Iter *iter, const std::string &v)
{
eldbus_message_iter_arguments_append(iter, sig().c_str(), v.c_str());
}
+ /**
+ * @brief Marshals value v as marshalled type into message
+ */
static void set(Eldbus_Message_Iter *iter, const char *v)
{
eldbus_message_iter_arguments_append(iter, sig().c_str(), v);
}
};
+ /// \cond
template <size_t INDEX, typename A, typename ... ARGS> struct signature_tuple_element_type_helper {
using type = typename signature_tuple_element_type_helper < INDEX - 1, ARGS... >::type;
};
template <typename A, typename ... ARGS> struct signature_tuple_element_type_helper<0, A, ARGS...> {
using type = A;
};
-
+ /// \endcond
+
+ /**
+ * @brief Helper class to marshall tuples
+ *
+ * This class marshals all elements of the tuple value starting at the index INDEX
+ * and incrementing. This class recursively calls itself with increasing INDEX value
+ * until INDEX is equal to SIZE, where recursive calling ends.
+ */
template <size_t INDEX, size_t SIZE, typename ... ARGS> struct signature_tuple_helper {
using current_type = typename signature_tuple_element_type_helper<INDEX, ARGS...>::type;
+ /**
+ * @brief Returns name of type marshalled, for informative purposes
+ */
static std::string name()
{
if (INDEX + 1 >= SIZE)
return signature<current_type>::name();
return signature<current_type>::name() + ", " + signature_tuple_helper < INDEX + 1, SIZE, ARGS... >::name();
}
+ /**
+ * @brief Returns DBUS' signature of type marshalled
+ */
static std::string sig()
{
return signature<current_type>::sig() + signature_tuple_helper < INDEX + 1, SIZE, ARGS... >::sig();
}
+ /**
+ * @brief Marshals value v as marshalled type into message
+ */
static void set(Eldbus_Message_Iter *iter, const std::tuple<ARGS...> &args)
{
signature<current_type>::set(iter, std::get<INDEX>(args));
signature_tuple_helper < INDEX + 1, SIZE, ARGS... >::set(iter, args);
}
+ /**
+ * @brief Marshals value from marshalled type into variable v
+ */
static bool get(Eldbus_Message_Iter *iter, std::tuple<ARGS...> &args)
{
return signature<current_type>::get(iter, std::get<INDEX>(args)) &&
signature_tuple_helper < INDEX + 1, SIZE, ARGS... >::get(iter, args);
}
};
+
+ /**
+ * @brief Helper class to marshall tuples
+ *
+ * This class marks end of the tuple marshalling. Members of this class are called
+ * when INDEX value is equal to SIZE.
+ */
template <size_t SIZE, typename ... ARGS> struct signature_tuple_helper<SIZE, SIZE, ARGS...> {
+ /**
+ * @brief Returns name of type marshalled, for informative purposes
+ */
static std::string name()
{
return "";
}
+ /**
+ * @brief Returns DBUS' signature of type marshalled
+ */
static std::string sig()
{
return "";
}
+ /**
+ * @brief Marshals value v as marshalled type into message
+ */
static void set(Eldbus_Message_Iter *iter, const std::tuple<ARGS...> &args)
{
}
+ /**
+ * @brief Marshals value from marshalled type into variable v
+ */
static bool get(Eldbus_Message_Iter *iter, std::tuple<ARGS...> &args)
{
return true;
}
};
+
+ /**
+ * @brief Signature class for marshalling tuple of values
+ *
+ * This class marshalls tuple of values. This represents
+ * DBUS struct typle, encoded with character 'r'
+ */
template <typename ... ARGS> struct signature<std::tuple<ARGS...>> {
+ /**
+ * @brief Returns name of type marshalled, for informative purposes
+ */
static std::string name()
{
return "tuple<" + signature_tuple_helper<0, sizeof...(ARGS), ARGS...>::name() + ">";
}
+ /**
+ * @brief Returns DBUS' signature of type marshalled
+ */
static std::string sig()
{
return "(" + signature_tuple_helper<0, sizeof...(ARGS), ARGS...>::sig() + ")";
}
+ /**
+ * @brief Marshals value v as marshalled type into message
+ */
static void set(Eldbus_Message_Iter *iter, const std::tuple<ARGS...> &args)
{
auto entry = eldbus_message_iter_container_new(iter, 'r', NULL);
signature_tuple_helper<0, sizeof...(ARGS), ARGS...>::set(entry, args);
eldbus_message_iter_container_close(iter, entry);
}
+ /**
+ * @brief Marshals value from marshalled type into variable v
+ */
static bool get(Eldbus_Message_Iter *iter, std::tuple<ARGS...> &args)
{
Eldbus_Message_Iter *entry;
return z;
}
};
+ /**
+ * @brief Signature class for marshalling ValueOrError template type
+ *
+ * ValueOrError template type is used to marshall list of values passed to
+ * DBUS (or received from) at the "top" level. For example ss(s) is represented as
+ * \code{.cpp} ValueOrError<std::string, std::string, std::tuple<std::string>> \endcode
+ * While (ss(s)) is represented as
+ * \code{.cpp} std::tuple<std::string, std::string, std::tuple<std::string>> \endcode
+ * or
+ * \code{.cpp} ValueOrError<std::tuple<std::string, std::string, std::tuple<std::string>>> \endcode
+ */
template <typename ... ARGS> struct signature<ValueOrError<ARGS...>> {
+ /**
+ * @brief Returns name of type marshalled, for informative purposes
+ */
static std::string name()
{
return "ValueOrError<" + signature_tuple_helper<0, sizeof...(ARGS), ARGS...>::name() + ">";
}
+ /**
+ * @brief Returns DBUS' signature of type marshalled
+ */
static std::string sig()
{
return signature_tuple_helper<0, sizeof...(ARGS), ARGS...>::sig();
}
+ /**
+ * @brief Marshals value v as marshalled type into message
+ */
static void set(Eldbus_Message_Iter *iter, const ValueOrError<ARGS...> &args)
{
signature_tuple_helper<0, sizeof...(ARGS), ARGS...>::set(iter, args.getValues());
}
+ /**
+ * @brief Marshals value from marshalled type into variable v
+ */
static bool get(Eldbus_Message_Iter *iter, ValueOrError<ARGS...> &args)
{
return signature_tuple_helper<0, sizeof...(ARGS), ARGS...>::get(iter, args.getValues());
}
};
+ /**
+ * @brief Signature class for marshalling ValueOrError<void> type
+ */
template <> struct signature<ValueOrError<void>> {
+ /**
+ * @brief Returns name of type marshalled, for informative purposes
+ */
static std::string name()
{
return "";
}
+ /**
+ * @brief Returns DBUS' signature of type marshalled
+ */
static std::string sig()
{
return "";
}
+ /**
+ * @brief Marshals value v as marshalled type into message
+ */
static void set(Eldbus_Message_Iter *iter, const ValueOrError<void> &args)
{
}
+ /**
+ * @brief Marshals value from marshalled type into variable v
+ */
static bool get(Eldbus_Message_Iter *iter, ValueOrError<void> &args)
{
return true;
}
};
+ /**
+ * @brief Signature class for marshalling pair of types
+ */
template <typename A, typename B> struct signature<std::pair<A, B>> {
+ /**
+ * @brief Returns name of type marshalled, for informative purposes
+ */
static std::string name()
{
return "pair<" + signature_tuple_helper<0, 2, A, B>::name() + ">";
}
+ /**
+ * @brief Returns DBUS' signature of type marshalled
+ */
static std::string sig()
{
return "(" + signature_tuple_helper<0, 2, A, B>::sig() + ")";
}
+ /**
+ * @brief Marshals value v as marshalled type into message
+ */
static void set(Eldbus_Message_Iter *iter, const std::pair<A, B> &ab, bool dictionary = false)
{
auto entry = eldbus_message_iter_container_new(iter, dictionary ? 'e' : 'r', NULL);
signature_tuple_helper<0, 2, A, B>::set(entry, ab);
eldbus_message_iter_container_close(iter, entry);
}
+ /**
+ * @brief Marshals value from marshalled type into variable v
+ */
static bool get(Eldbus_Message_Iter *iter, std::pair<A, B> &ab)
{
char sg = 'r';
return z;
}
};
+ /**
+ * @brief Signature class for marshalling std::vector template type
+ *
+ * This marshals container's content as DBUS a ascii character type code.
+ */
template <typename A> struct signature<std::vector<A>> {
+ /**
+ * @brief Returns name of type marshalled, for informative purposes
+ */
static std::string name()
{
return "vector<" + signature<A>::name() + ">";
}
+ /**
+ * @brief Returns DBUS' signature of type marshalled
+ */
static std::string sig()
{
return "a" + signature<A>::sig();
}
+ /**
+ * @brief Marshals value v as marshalled type into message
+ */
static void set(Eldbus_Message_Iter *iter, const std::vector<A> &v)
{
auto lst = eldbus_message_iter_container_new(iter, 'a', signature<A>::sig().c_str());
}
eldbus_message_iter_container_close(iter, lst);
}
+ /**
+ * @brief Marshals value from marshalled type into variable v
+ */
static bool get(Eldbus_Message_Iter *iter, std::vector<A> &v)
{
Eldbus_Message_Iter *s;
return true;
}
};
+
+ /**
+ * @brief Signature class for marshalling std::array template type
+ *
+ * This marshals container's content as DBUS a ascii character type code.
+ */
template <typename A, size_t N> struct signature<std::array<A, N>> {
+ /**
+ * @brief Returns name of type marshalled, for informative purposes
+ */
static std::string name()
{
return "array<" + signature<A>::name() + ", " + std::to_string(N) + ">";
}
+ /**
+ * @brief Returns DBUS' signature of type marshalled
+ */
static std::string sig()
{
return "a" + signature<A>::sig();
}
+ /**
+ * @brief Marshals value v as marshalled type into message
+ */
static void set(Eldbus_Message_Iter *iter, const std::array<A, N> &v)
{
auto lst = eldbus_message_iter_container_new(iter, 'a', signature<A>::sig().c_str());
}
eldbus_message_iter_container_close(iter, lst);
}
+ /**
+ * @brief Marshals value from marshalled type into variable v
+ */
static bool get(Eldbus_Message_Iter *iter, std::array<A, N> &v)
{
Eldbus_Message_Iter *s;
return true;
}
};
+
+ /**
+ * @brief Signature class for marshalling EldbusVariant type
+ *
+ * This marshals variant's content as DBUS v ascii character type code.
+ */
template <typename A> struct signature<EldbusVariant<A>> {
+ /**
+ * @brief Returns name of type marshalled, for informative purposes
+ */
static std::string name()
{
return "variant<" + signature<A>::name() + ">";
}
+ /**
+ * @brief Returns DBUS' signature of type marshalled
+ */
static std::string sig()
{
return "v";
}
+ /**
+ * @brief Marshals value v as marshalled type into message
+ */
static void set(Eldbus_Message_Iter *iter, const EldbusVariant<A> &v)
{
set(iter, v.value);
}
+ /**
+ * @brief Marshals value v as marshalled type into message
+ */
static void set(Eldbus_Message_Iter *iter, const A &v)
{
auto var = eldbus_message_iter_container_new(iter, 'v', signature<A>::sig().c_str());
signature<A>::set(var, v);
eldbus_message_iter_container_close(iter, var);
}
+ /**
+ * @brief Marshals value from marshalled type into variable v
+ */
static bool get(Eldbus_Message_Iter *iter, EldbusVariant<A> &v)
{
Eldbus_Message_Iter *s;
return signature<A>::get(s, v.value);
}
};
+ /**
+ * @brief Signature class for marshalling std::unordered_map template type
+ *
+ * This marshals container's content as DBUS {} ascii character type code.
+ * Note, that library doesnt check, if the key is basic type, as DBUS
+ * specification mandates.
+ * User can always exchange std::unordered_map for std::map and the reverse.
+ * User can receive such values as std::vector of std::pair<key, value> values.
+ * Order of such values is unspecified.
+ */
template <typename A, typename B> struct signature<std::unordered_map<A, B>> {
+ /**
+ * @brief Returns name of type marshalled, for informative purposes
+ */
static std::string name()
{
return "unordered_map<" + signature<A>::name() + ", " + signature<B>::name() + ">";
}
+ /**
+ * @brief Returns DBUS' signature of type marshalled
+ */
static std::string sig()
{
return "a{" + signature_tuple_helper<0, 2, A, B>::sig() + "}";
}
+ /**
+ * @brief Marshals value v as marshalled type into message
+ */
static void set(Eldbus_Message_Iter *iter, const std::unordered_map<A, B> &v)
{
auto sig = "{" + signature_tuple_helper<0, 2, A, B>::sig() + "}";
}
eldbus_message_iter_container_close(iter, lst);
}
+ /**
+ * @brief Marshals value from marshalled type into variable v
+ */
static bool get(Eldbus_Message_Iter *iter, std::unordered_map<A, B> &v)
{
Eldbus_Message_Iter *s;
return true;
}
};
+ /**
+ * @brief Signature class for marshalling std::unordered_map template type
+ *
+ * This marshals container's content as DBUS {} ascii character type code.
+ * Note, that library doesnt check, if the key is basic type, as DBUS
+ * specification mandates.
+ * User can always exchange std::unordered_map for std::map and the reverse.
+ * User can receive such values as std::vector of std::pair<key, value> values.
+ * Order of such values is unspecified.
+ */
template <typename A, typename B> struct signature<std::map<A, B>> {
+ /**
+ * @brief Returns name of type marshalled, for informative purposes
+ */
static std::string name()
{
return "map<" + signature<A>::name() + ", " + signature<B>::name() + ">";
}
+ /**
+ * @brief Returns DBUS' signature of type marshalled
+ */
static std::string sig()
{
return "a{" + signature_tuple_helper<0, 2, A, B>::sig() + "}";
}
+ /**
+ * @brief Marshals value v as marshalled type into message
+ */
static void set(Eldbus_Message_Iter *iter, const std::map<A, B> &v)
{
auto sig = "{" + signature_tuple_helper<0, 2, A, B>::sig() + "}";
}
eldbus_message_iter_container_close(iter, lst);
}
+ /**
+ * @brief Marshals value from marshalled type into variable v
+ */
static bool get(Eldbus_Message_Iter *iter, std::map<A, B> &v)
{
Eldbus_Message_Iter *s;
return true;
}
};
+ /**
+ * @brief Signature helper class for marshalling const reference types
+ */
template <typename A> struct signature<const A &> {
+ /**
+ * @brief Returns name of type marshalled, for informative purposes
+ */
static std::string name()
{
return "const " + signature<A>::name() + "&";
}
+ /**
+ * @brief Returns DBUS' signature of type marshalled
+ */
static std::string sig()
{
return signature<A>::sig();
}
+ /**
+ * @brief Marshals value v as marshalled type into message
+ */
static void set(Eldbus_Message_Iter *iter, const A &v)
{
signature<A>::set(iter, v);
}
+ /**
+ * @brief Marshals value from marshalled type into variable v
+ */
static void get(Eldbus_Message_Iter *iter, A &v)
{
signature<A>::get(iter, v);
}
};
+ /**
+ * @brief Signature helper class for marshalling reference types
+ */
template <typename A> struct signature<A &> {
+ /**
+ * @brief Returns name of type marshalled, for informative purposes
+ */
static std::string name()
{
return signature<A>::name() + "&";
}
+ /**
+ * @brief Returns DBUS' signature of type marshalled
+ */
static std::string sig()
{
return signature<A>::sig();
}
+ /**
+ * @brief Marshals value v as marshalled type into message
+ */
static void set(Eldbus_Message_Iter *iter, const A &v)
{
signature<A>::set(iter, v);
}
+ /**
+ * @brief Marshals value from marshalled type into variable v
+ */
static void get(Eldbus_Message_Iter *iter, A &v)
{
signature<A>::get(iter, v);
}
};
+ /**
+ * @brief Signature helper class for marshalling const types
+ */
template <typename A> struct signature<const A> {
+ /**
+ * @brief Returns name of type marshalled, for informative purposes
+ */
static std::string name()
{
return "const " + signature<A>::name();
}
+ /**
+ * @brief Returns DBUS' signature of type marshalled
+ */
static std::string sig()
{
return signature<A>::sig();
}
+ /**
+ * @brief Marshals value v as marshalled type into message
+ */
static void set(Eldbus_Message_Iter *iter, const A &v)
{
signature<A>::set(iter, v);
}
+ /**
+ * @brief Marshals value from marshalled type into variable v
+ */
static void get(Eldbus_Message_Iter *iter, A &v)
{
signature<A>::get(iter, v);
}
};
+ /**
+ * @brief Signature helper class for marshalling AT-SPI Accessible pointer values
+ *
+ * In AT-SPI specification those values are mandated to be marshalled as struct (so)
+ * where o is object (exactly as string, but with different ascii
+ * character code.
+ */
template <> struct signature<std::shared_ptr<AtspiAccessible>> {
using subtype = std::pair<std::string, std::string>;
+ /**
+ * @brief Returns name of type marshalled, for informative purposes
+ */
static std::string name()
{
return "AtspiAccessiblePtr";
}
+ /**
+ * @brief Returns DBUS' signature of type marshalled
+ */
static std::string sig()
{
return "(so)";
}
+ /**
+ * @brief Marshals value v as marshalled type into message
+ */
static void set(Eldbus_Message_Iter *iter, const std::shared_ptr<AtspiAccessible> &v)
{
const auto prefixPath = "/org/a11y/atspi/accessible/";
signature<subtype>::set(iter, { {}, std::string{nullPath} });
}
}
+ /**
+ * @brief Marshals value from marshalled type into variable v
+ */
static bool get(Eldbus_Message_Iter *iter, std::shared_ptr<AtspiAccessible> &v);
};
+ /// \cond
struct CallId {
friend class ::DBus::DBusServer;
friend class ::DBus::DBusClient;
return tmp;
}
};
+ /// \endcond
}
+ /**
+ * @brief Enumeration determining, which DBUS session user wants to connect to.
+ */
enum class ConnectionType {
SYSTEM, SESSION
};
+ /**
+ * @brief Class representing client's end of DBUS connection
+ *
+ * Allows calling (synchronous and asynchronos) methods on selected interface
+ * Allows (synchronous and asynchronos) setting / getting properties.
+ * Allows registering signals.
+ */
class DBusClient : private detail::EldbusProxyBase
{
public:
+ /**
+ * @brief Default constructor, creates non-connected object.
+ */
DBusClient() = default;
+ /**
+ * @brief Connects to dbus choosen by tp, using given arguments
+ *
+ * @param bus_name name of the bus to connect to
+ * @param path_name object's path
+ * @param interface_name interface name
+ */
DBusClient(std::string bus_name, std::string path_name, std::string interface_name,
ConnectionType tp);
+ /**
+ * @brief Connects to dbus using connection conn
+ *
+ * @param bus_name name of the bus to connect to
+ * @param path_name object's path
+ * @param interface_name interface name
+ * @param conn connection object from getDBusConnectionByType call
+ */
DBusClient(std::string bus_name, std::string path_name, std::string interface_name,
const EldbusConnectionCallbackHandle &conn = {});
+ /**
+ * @brief Destructor object.
+ *
+ * All signals added will be disconnected.
+ * All asynchronous calls will be cancelled, their callback's will be called
+ * with failure message.
+ */
~DBusClient();
-
DBusClient(const DBusClient &) = delete;
DBusClient(DBusClient &&) = default;
DBusClient &operator = (DBusClient &&) = default;
DBusClient &operator = (const DBusClient &) = delete;
+ /**
+ * @brief bool operator
+ *
+ * Returns true, if object is connected to DBUS
+ */
explicit operator bool () const
{
return bool(connectionState.proxy);
}
+ /**
+ * @brief Helper class for calling a method
+ *
+ * Template type T defines both arguments sent to the method
+ * and expected values. Receiving different values will be reported as
+ * error. For example:
+ * \code{.cpp} Method<int(float, float)> \endcode
+ * defines method, which takes two arguments (two floats) and return
+ * single value of type int.
+ */
template <typename T> struct Method {
+ /// \cond
using RetType = typename detail::dbus_interface_traits<T>::Ret;
detail::ConnectionState connectionState;
std::string funcName, interfaceName;
std::string info;
-
+ /// \endcond
+
+ /**
+ * @brief Executes synchronous call on DBUS's method
+ *
+ * The function returns ValueOrError<...> object, which
+ * contains either received values or error message.
+ *
+ * @param args arguments to pass to the method
+ */
template <typename ... ARGS> RetType call(const ARGS &... args)
{
detail::CallId callId;
detail::displayDebugCallInfo(callId, funcName, info, interfaceName);
return detail::call<RetType>(callId, connectionState, false, funcName, args...);
}
+
+ /**
+ * @brief Executes asynchronous call on DBUS's method
+ *
+ * The function calls callback with either received values or error message.
+ *
+ * @param callback callback functor, which will be called with return value(s) or error message
+ * @param args arguments to pass to the method
+ */
template <typename ... ARGS> void asyncCall(std::function<void(RetType)> callback, const ARGS &... args)
{
detail::CallId callId;
detail::asyncCall<RetType>(callId, connectionState, false, funcName, std::move(callback), args...);
}
};
+
+ /**
+ * @brief Helper class for calling a property
+ *
+ * Template type T defines type of the value hidden under property.
+ * Note, that library automatically wraps both sent and received value into
+ * DBUS's wrapper type.
+ */
template <typename T> struct Property {
+ /// \cond
using RetType = typename detail::dbus_interface_return_type_traits<T>::type;
using VariantRetType = typename detail::dbus_interface_return_type_traits<EldbusVariant<T>>::type;
detail::ConnectionState connectionState;
std::string propName, interfaceName;
std::string info;
-
+ /// \endcond
+
+ /**
+ * @brief executes synchronous get on property
+ *
+ * The function returns ValueOrError<...> object, which
+ * contains either received values or error message.
+ */
RetType get()
{
detail::CallId callId;
if (!z) return z.getError();
return { std::get<0>(z.getValues()).value };
}
+
+ /**
+ * @brief executes asynchronous get on property
+ *
+ * The function calls callback with either received values or error message.
+ *
+ * @param callback callback functor, which will be called with return value(s) or error message
+ */
void asyncGet(std::function<void(RetType)> callback)
{
detail::CallId callId;
};
detail::asyncCall<VariantRetType>(callId, connectionState, true, "Get", std::move(cc), interfaceName, propName);
}
+
+ /**
+ * @brief executes synchronous set on property
+ *
+ * The function returns ValueOrError<void> object, with
+ * possible error message.
+ */
ValueOrError<void> set(const T &r)
{
detail::CallId callId;
EldbusVariant<T> variantValue { std::move(r) };
return detail::call<ValueOrError<void>>(callId, connectionState, true, "Set", interfaceName, propName, variantValue);
}
+
+ /**
+ * @brief executes asynchronous get on property
+ *
+ * The function calls callback with either received values or error message.
+ *
+ * @param callback callback functor, which will be called with return value(s) or error message
+ */
void asyncSet(std::function<void(ValueOrError<void>)> callback, const T &r)
{
detail::CallId callId;
}
};
+ /**
+ * @brief Constructs Property<...> object for calling properties
+ *
+ * The function constructs and returns proxy object for calling property.
+ *
+ * @param propName property name to set and / or query
+ */
template <typename PropertyType>
auto property(std::string propName)
{
return Property<PropertyType> { connectionState, std::move(propName), interfaceName, info };
}
+
+ /**
+ * @brief Constructs Method<...> object for calling methods
+ *
+ * The function constructs and returns proxy object for calling method.
+ *
+ * @param funcName function name to call
+ */
template <typename MethodType>
auto method(std::string funcName)
{
return Method<MethodType> { connectionState, std::move(funcName), interfaceName, info };
}
+ /**
+ * @brief Registers callback on the DBUS' signal
+ *
+ * The function registers callback signalName. When signal comes, callback will be called.
+ * Callback object will exists as long as signal is registered. You can unregister signal
+ * by destroying DBusClient object.
+ *
+ * @param signalName name of the signal to register
+ * @param callback callback to call
+ */
template <typename SignalType> void addSignal(std::string signalName, std::function<SignalType> callback)
{
detail::CallId callId;
}
private:
+ /// \cond
detail::ConnectionState connectionState;
std::vector<std::function<void()>> destructors;
std::string info, interfaceName;
{
(*((std::function<void(const Eldbus_Message *msg)> *)data))(msg);
}
+ /// \endcond
};
+ /**
+ * @brief Helper class describing DBUS's server interface
+ *
+ */
class DBusInterfaceDescription
{
friend class DBusServer;
public:
- enum class type {
- method, property
- };
+ // enum class type {
+ // method, property
+ // };
+ /// \cond
struct MethodInfo {
detail::CallId id;
std::string memberName;
SignalId() = default;
SignalId(detail::CallId id) : id(id) { }
};
+ /// \endcond
+
+ /**
+ * @brief Creates empty interface description with given name
+ *
+ * @param interfaceName name of the interface
+ */
DBusInterfaceDescription(std::string interfaceName);
+ /**
+ * @brief adds new, synchronous method to the interface
+ *
+ * When method memberName is called on DBUS, callback functor will be called
+ * with values received from DBUS. callback won't be called, if method was
+ * called with invalid signature. Value returned from functor (or error message)
+ * will be marshalled back to the caller.
+ *
+ * Template type T defines both arguments sent to the method
+ * and expected values. Receiving different values will be reported as
+ * error. For example:
+ * \code{.cpp} Method<int(float, float)> \endcode
+ * defines method, which takes two arguments (two floats) and return
+ * single value of type int.
+ *
+ * @param memberName name of the method
+ * @param callback functor, which will be called
+ */
template <typename T> void addMethod(const std::string &memberName, typename detail::dbus_interface_traits<T>::SyncCB callback)
{
detail::CallId callId;
z.callback = construct<T>(callId, callback);
z.id = callId;
}
+
+ /**
+ * @brief adds new, asynchronous method to the interface
+ *
+ * When method memberName is called on DBUS, callback functor will be called
+ * with values received from DBUS. callback won't be called, if method was
+ * called with invalid signature. callback will called with reply callback functor.
+ * Reply callback functor must be called with reply value, when it's ready.
+ * It's safe to ignore calling reply callback, but some resources might be kept
+ * as long as either reply callback exists or reply timeout hasn't yet been met.
+ *
+ * Template type T defines both arguments sent to the method
+ * and expected values. Receiving different values will be reported as
+ * error. For example:
+ * \code{.cpp} Method<int(float, float)> \endcode
+ * defines method, which takes two arguments (two floats) and return
+ * single value of type int.
+ *
+ * @param memberName name of the method
+ * @param callback functor, which will be called
+ */
template <typename T> void addAsyncMethod(const std::string &memberName, typename detail::dbus_interface_traits<T>::AsyncCB callback);
+
+ /**
+ * @brief adds new, synchronous property to the interface
+ *
+ * When property memberName is called on DBUS, respective callback functor will be called
+ * with values received from DBUS. callback won't be called, if method was
+ * called with invalid signature. Value returned from functor (or error message)
+ * will be marshalled back to the caller.
+ *
+ * Template type T defines type of the value hidden under property.
+ * Note, that library automatically wraps both sent and received value into
+ * DBUS's wrapper type.
+ *
+ * @param memberName name of the method
+ * @param getter functor, which will be called when property is being read
+ * @param setter functor, which will be called when property is being set
+ */
template <typename T> void addProperty(const std::string &memberName, std::function<ValueOrError<T>()> getter, std::function<ValueOrError<void>(T)> setter)
{
properties.push_back({});
}
}
+
+ /**
+ * @brief adds new signal to the interface
+ *
+ * Template types ARGS defines values, which will be emited with the signal
+ *
+ * @param memberName name of the method
+ */
template <typename ... ARGS> SignalId addSignal(const std::string &memberName)
{
detail::CallId callId;
}
private:
+ /// \cond
std::vector<MethodInfo> methods;
std::vector<PropertyInfo> properties;
std::vector<SignalInfo> signals;
return ret;
};
}
+ /// \endcond
};
+ /**
+ * @brief Class representing server's end of DBUS connection
+ *
+ * Allows listening (synchronously and asynchronosly) on methods on selected interface
+ * Allows listening (synchronously and asynchronosly) on setting / getting properties.
+ * Allows emiting signals.
+ */
class DBusServer : private detail::EldbusProxyBase
{
public:
+ /**
+ * @brief Constructs non-connected dbus server.
+ */
DBusServer();
+ /**
+ * @brief Constructs dbus server on either system or user dbus connection.
+ */
DBusServer(ConnectionType tp);
+ /**
+ * @brief Constructs dbus server on connection from getDBusConnectionByType
+ */
DBusServer(const EldbusConnectionCallbackHandle &conn);
+ /**
+ * @brief Destructor
+ *
+ * Destructor will properly destroy everything. Destructor will cancel
+ * pending replies.
+ */
~DBusServer();
DBusServer(const DBusServer &) = delete;
DBusServer &operator = (DBusServer &&) = default;
DBusServer &operator = (const DBusServer &) = delete;
+ /**
+ * @brief Registers interface on given path name
+ *
+ * @param pathName path object to register interface on.
+ * @param dscr
+ * @param fallback
+ */
void addInterface(const std::string &pathName, DBusInterfaceDescription &dscr, bool fallback = false);
+
+ /**
+ * @brief Gets bus name of the current connection (must be connected)
+ */
std::string getBusName() const;
+ /**
+ * @brief Emits signal
+ *
+ * You must pass identifier of the signal, got as result of calling DBusInterfaceDescription::addSignal.
+ * Types of the arguments must match EXACTLY types used to call addSignal.
+ *
+ * @param signal identifier of the signal
+ * @param args values to emit
+ */
template <typename ... ARGS> void emit(DBusInterfaceDescription::SignalId signal, const ARGS &... args)
{
auto it = signalData.find(signal.id.id);
DBUS_DEBUG("signal %d not found", signal.id.id);
}
}
+ /**
+ * @brief Returns current object path, when handling call to property / method
+ *
+ * User can call this function from inside callback used to handle property / method calls.
+ * It will retrieve object's path used in the call. Note, that in asynchronous handling
+ * of those calls user need to retrieve and store the current object / current connection
+ * as the value will change at the moment user's callback handling will exit. For example:
+ * \code{.cpp}
+ * DBusInterfaceDescription interface{"name"};
+ * auto handler_later = [](std::function<void(void)> done_cb) {
+ * // process something later on
+ * DBusServer::getCurrentObjectPath(); // this will return empty string
+ * };
+ * interface.addAsyncMethod<void()>("m", [=](std::function<void(void)> done_cb) {
+ * DBusServer::getCurrentObjectPath(); // this will current object's path
+ *
+ * // do some processing later on and call done_cb, when it's done
+ * register_to_call_sometime_later_on(std::move(done_cb));
+ * };
+ * \endcode
+ */
static std::string getCurrentObjectPath();
+
+ /**
+ * @brief Returns current connection object, when handling call to property / method
+ *
+ * User can call this function from inside callback used to handle property / method calls.
+ * It will retrieve object's path used in the call. Note, that in asynchronous handling
+ * of those calls user need to retrieve and store the current object / current connection
+ * as the value will change at the moment user's callback handling will exit. For example:
+ * \code{.cpp}
+ * DBusInterfaceDescription interface{"name"};
+ * auto handler_later = [](std::function<void(void)> done_cb) {
+ * // process something later on
+ * DBusServer::getCurrentObjectPath(); // this will return empty string
+ * };
+ * interface.addAsyncMethod<void()>("m", [=](std::function<void(void)> done_cb) {
+ * DBusServer::getCurrentObjectPath(); // this will current object's path
+ *
+ * // do some processing later on and call done_cb, when it's done
+ * register_to_call_sometime_later_on(std::move(done_cb));
+ * };
+ * \endcode
+ */
static EldbusConnectionCallbackHandle getCurrentConnection();
private:
+ /// \cond
EldbusConnectionCallbackHandle connection;
std::vector<std::function<void()>> destructors;
std::unordered_map<unsigned int, std::pair<const Eldbus_Service_Interface *, unsigned int>> signalData;
+ /// \endcond
};
template <typename T> void DBusInterfaceDescription::addAsyncMethod(const std::string &memberName, typename detail::dbus_interface_traits<T>::AsyncCB callback)
z.id = callId;
}
+ /// \cond
EldbusConnectionCallbackHandle getDBusConnectionByType(ConnectionType tp);
EldbusConnectionCallbackHandle getDBusConnectionByName(const std::string &name);
std::string getConnectionName(const EldbusConnectionCallbackHandle &);
+ /// \endcond
}
+/// \cond
namespace std
{
template <size_t INDEX, typename ... ARGS> inline auto &get(DBus::ValueOrError<ARGS...> &v)
return std::get<INDEX>(v.getValues());
}
}
+/// \endcond
#undef DBUS_DEBUG