27#ifndef SDBUS_CPP_CONVENIENCEAPICLASSES_INL_
28#define SDBUS_CPP_CONVENIENCEAPICLASSES_INL_
48 inline MethodRegistrator::MethodRegistrator(IObject&
object, std::string methodName)
50 , methodName_(std::move(methodName))
51 , exceptions_(std::uncaught_exceptions())
55 inline MethodRegistrator::~MethodRegistrator() noexcept(false)
58 if (std::uncaught_exceptions() != exceptions_)
61 assert(!interfaceName_.empty());
62 assert(methodCallback_);
73 object_.registerMethod( interfaceName_
74 , std::move(methodName_)
75 , std::move(inputSignature_)
77 , std::move(outputSignature_)
79 , std::move(methodCallback_)
83 inline MethodRegistrator& MethodRegistrator::onInterface(std::string interfaceName)
85 interfaceName_ = std::move(interfaceName);
90 template <
typename _Function>
91 MethodRegistrator& MethodRegistrator::implementedAs(_Function&& callback)
93 inputSignature_ = signature_of_function_input_arguments<_Function>::str();
94 outputSignature_ = signature_of_function_output_arguments<_Function>::str();
95 methodCallback_ = [callback = std::forward<_Function>(callback)](MethodCall call)
99 tuple_of_function_input_arg_types_t<_Function> inputArgs;
104 if constexpr (!is_async_method_v<_Function>)
107 auto ret = sdbus::apply(callback, inputArgs);
110 auto reply = call.createReply();
117 using AsyncResult =
typename function_traits<_Function>::async_result_t;
118 sdbus::apply(callback, AsyncResult{std::move(call)}, std::move(inputArgs));
125 inline MethodRegistrator& MethodRegistrator::withInputParamNames(std::vector<std::string> paramNames)
127 inputParamNames_ = std::move(paramNames);
132 template <
typename... _String>
133 inline MethodRegistrator& MethodRegistrator::withInputParamNames(_String... paramNames)
135 static_assert(std::conjunction_v<std::is_convertible<_String, std::string>...>,
"Parameter names must be (convertible to) strings");
137 return withInputParamNames({paramNames...});
140 inline MethodRegistrator& MethodRegistrator::withOutputParamNames(std::vector<std::string> paramNames)
142 outputParamNames_ = std::move(paramNames);
147 template <
typename... _String>
148 inline MethodRegistrator& MethodRegistrator::withOutputParamNames(_String... paramNames)
150 static_assert(std::conjunction_v<std::is_convertible<_String, std::string>...>,
"Parameter names must be (convertible to) strings");
152 return withOutputParamNames({paramNames...});
155 inline MethodRegistrator& MethodRegistrator::markAsDeprecated()
157 flags_.set(Flags::DEPRECATED);
162 inline MethodRegistrator& MethodRegistrator::markAsPrivileged()
164 flags_.set(Flags::PRIVILEGED);
169 inline MethodRegistrator& MethodRegistrator::withNoReply()
171 flags_.set(Flags::METHOD_NO_REPLY);
180 inline SignalRegistrator::SignalRegistrator(IObject&
object, std::string signalName)
182 , signalName_(std::move(signalName))
183 , exceptions_(std::uncaught_exceptions())
187 inline SignalRegistrator::~SignalRegistrator() noexcept(false)
190 if (std::uncaught_exceptions() != exceptions_)
193 assert(!interfaceName_.empty());
204 object_.registerSignal( interfaceName_
205 , std::move(signalName_)
206 , std::move(signalSignature_)
208 , std::move(flags_) );
211 inline SignalRegistrator& SignalRegistrator::onInterface(std::string interfaceName)
213 interfaceName_ = std::move(interfaceName);
218 template <
typename... _Args>
219 inline SignalRegistrator& SignalRegistrator::withParameters()
221 signalSignature_ = signature_of_function_input_arguments<void(_Args...)>::str();
226 template <
typename... _Args>
227 inline SignalRegistrator& SignalRegistrator::withParameters(std::vector<std::string> paramNames)
229 paramNames_ = std::move(paramNames);
231 return withParameters<_Args...>();
234 template <
typename... _Args,
typename... _String>
235 inline SignalRegistrator& SignalRegistrator::withParameters(_String... paramNames)
237 static_assert(std::conjunction_v<std::is_convertible<_String, std::string>...>,
"Parameter names must be (convertible to) strings");
238 static_assert(
sizeof...(_Args) ==
sizeof...(_String),
"Numbers of signal parameters and their names don't match");
240 return withParameters<_Args...>({paramNames...});
243 inline SignalRegistrator& SignalRegistrator::markAsDeprecated()
245 flags_.set(Flags::DEPRECATED);
254 inline PropertyRegistrator::PropertyRegistrator(IObject&
object,
const std::string& propertyName)
256 , propertyName_(propertyName)
257 , exceptions_(std::uncaught_exceptions())
261 inline PropertyRegistrator::~PropertyRegistrator() noexcept(false)
264 if (std::uncaught_exceptions() != exceptions_)
267 assert(!interfaceName_.empty());
278 object_.registerProperty( interfaceName_
286 inline PropertyRegistrator& PropertyRegistrator::onInterface(std::string interfaceName)
288 interfaceName_ = std::move(interfaceName);
293 template <
typename _Function>
294 inline PropertyRegistrator& PropertyRegistrator::withGetter(_Function&& callback)
296 static_assert(function_argument_count_v<_Function> == 0,
"Property getter function must not take any arguments");
297 static_assert(!std::is_void<function_result_t<_Function>>::value,
"Property getter function must return property value");
299 if (propertySignature_.empty())
300 propertySignature_ = signature_of_function_output_arguments<_Function>::str();
302 getter_ = [callback = std::forward<_Function>(callback)](PropertyGetReply& reply)
311 template <
typename _Function>
312 inline PropertyRegistrator& PropertyRegistrator::withSetter(_Function&& callback)
314 static_assert(function_argument_count_v<_Function> == 1,
"Property setter function must take one parameter - the property value");
315 static_assert(std::is_void<function_result_t<_Function>>::value,
"Property setter function must not return any value");
317 if (propertySignature_.empty())
318 propertySignature_ = signature_of_function_input_arguments<_Function>::str();
320 setter_ = [callback = std::forward<_Function>(callback)](PropertySetCall& call)
323 using property_type = function_argument_t<_Function, 0>;
324 std::decay_t<property_type> property;
336 inline PropertyRegistrator& PropertyRegistrator::markAsDeprecated()
338 flags_.set(Flags::DEPRECATED);
343 inline PropertyRegistrator& PropertyRegistrator::markAsPrivileged()
345 flags_.set(Flags::PRIVILEGED);
350 inline PropertyRegistrator& PropertyRegistrator::withUpdateBehavior(Flags::PropertyUpdateBehaviorFlags behavior)
352 flags_.set(behavior);
361 inline InterfaceFlagsSetter::InterfaceFlagsSetter(IObject&
object,
const std::string& interfaceName)
363 , interfaceName_(interfaceName)
364 , exceptions_(std::uncaught_exceptions())
368 inline InterfaceFlagsSetter::~InterfaceFlagsSetter() noexcept(false)
371 if (std::uncaught_exceptions() != exceptions_)
383 object_.setInterfaceFlags(interfaceName_, std::move(flags_));
386 inline InterfaceFlagsSetter& InterfaceFlagsSetter::markAsDeprecated()
388 flags_.set(Flags::DEPRECATED);
393 inline InterfaceFlagsSetter& InterfaceFlagsSetter::markAsPrivileged()
395 flags_.set(Flags::PRIVILEGED);
400 inline InterfaceFlagsSetter& InterfaceFlagsSetter::withNoReplyMethods()
402 flags_.set(Flags::METHOD_NO_REPLY);
407 inline InterfaceFlagsSetter& InterfaceFlagsSetter::withPropertyUpdateBehavior(Flags::PropertyUpdateBehaviorFlags behavior)
409 flags_.set(behavior);
418 inline SignalEmitter::SignalEmitter(IObject&
object,
const std::string& signalName)
420 , signalName_(signalName)
421 , exceptions_(std::uncaught_exceptions())
425 inline SignalEmitter::~SignalEmitter() noexcept(false)
428 if (std::uncaught_exceptions() != exceptions_)
440 object_.emitSignal(signal_);
443 inline SignalEmitter& SignalEmitter::onInterface(
const std::string& interfaceName)
445 signal_ = object_.createSignal(interfaceName, signalName_);
450 template <
typename... _Args>
451 inline void SignalEmitter::withArguments(_Args&&... args)
453 assert(signal_.isValid());
455 detail::serialize_pack(signal_, std::forward<_Args>(args)...);
462 inline MethodInvoker::MethodInvoker(IProxy& proxy,
const std::string& methodName)
464 , methodName_(methodName)
465 , exceptions_(std::uncaught_exceptions())
469 inline MethodInvoker::~MethodInvoker() noexcept(false)
473 if (methodCalled_ || std::uncaught_exceptions() != exceptions_)
485 proxy_.callMethod(method_, timeout_);
488 inline MethodInvoker& MethodInvoker::onInterface(
const std::string& interfaceName)
490 method_ = proxy_.createMethodCall(interfaceName, methodName_);
495 inline MethodInvoker& MethodInvoker::withTimeout(uint64_t usec)
502 template <
typename _Rep,
typename _Period>
503 inline MethodInvoker& MethodInvoker::withTimeout(
const std::chrono::duration<_Rep, _Period>& timeout)
505 auto microsecs = std::chrono::duration_cast<std::chrono::microseconds>(timeout);
506 return withTimeout(microsecs.count());
509 template <
typename... _Args>
510 inline MethodInvoker& MethodInvoker::withArguments(_Args&&... args)
512 assert(method_.isValid());
514 detail::serialize_pack(method_, std::forward<_Args>(args)...);
519 template <
typename... _Args>
520 inline void MethodInvoker::storeResultsTo(_Args&... args)
522 assert(method_.isValid());
524 auto reply = proxy_.callMethod(method_, timeout_);
525 methodCalled_ =
true;
527 detail::deserialize_pack(reply, args...);
530 inline void MethodInvoker::dontExpectReply()
532 assert(method_.isValid());
534 method_.dontExpectReply();
541 inline AsyncMethodInvoker::AsyncMethodInvoker(IProxy& proxy,
const std::string& methodName)
543 , methodName_(methodName)
547 inline AsyncMethodInvoker& AsyncMethodInvoker::onInterface(
const std::string& interfaceName)
549 method_ = proxy_.createMethodCall(interfaceName, methodName_);
554 inline AsyncMethodInvoker& AsyncMethodInvoker::withTimeout(uint64_t usec)
561 template <
typename _Rep,
typename _Period>
562 inline AsyncMethodInvoker& AsyncMethodInvoker::withTimeout(
const std::chrono::duration<_Rep, _Period>& timeout)
564 auto microsecs = std::chrono::duration_cast<std::chrono::microseconds>(timeout);
565 return withTimeout(microsecs.count());
568 template <
typename... _Args>
569 inline AsyncMethodInvoker& AsyncMethodInvoker::withArguments(_Args&&... args)
571 assert(method_.isValid());
573 detail::serialize_pack(method_, std::forward<_Args>(args)...);
578 template <
typename _Function>
579 PendingAsyncCall AsyncMethodInvoker::uponReplyInvoke(_Function&& callback)
581 assert(method_.isValid());
583 auto asyncReplyHandler = [callback = std::forward<_Function>(callback)](MethodReply& reply,
const Error* error)
587 tuple_of_function_input_arg_types_t<_Function> args;
590 if (error ==
nullptr)
596 catch (
const Error& e)
600 sdbus::apply(callback, &e, args);
606 sdbus::apply(callback, error, args);
609 return proxy_.callMethod(method_, std::move(asyncReplyHandler), timeout_);
612 template <
typename... _Args>
613 std::future<future_return_t<_Args...>> AsyncMethodInvoker::getResultAsFuture()
615 auto promise = std::make_shared<std::promise<future_return_t<_Args...>>>();
616 auto future = promise->get_future();
618 uponReplyInvoke([promise = std::move(promise)](
const Error* error, _Args... args)
620 if (error == nullptr)
621 if constexpr (!std::is_void_v<future_return_t<_Args...>>)
622 promise->set_value({std::move(args)...});
624 promise->set_value();
626 promise->set_exception(std::make_exception_ptr(*error));
639 inline SignalSubscriber::SignalSubscriber(IProxy& proxy,
const std::string& signalName)
641 , signalName_(signalName)
645 inline SignalSubscriber& SignalSubscriber::onInterface(std::string interfaceName)
647 interfaceName_ = std::move(interfaceName);
652 template <
typename _Function>
653 inline void SignalSubscriber::call(_Function&& callback)
655 assert(!interfaceName_.empty());
657 proxy_.registerSignalHandler( interfaceName_
659 , [callback = std::forward<_Function>(callback)](Signal& signal)
663 tuple_of_function_input_arg_types_t<_Function> signalArgs;
669 if constexpr (has_error_param_v<_Function>)
674 signal >> signalArgs;
680 sdbus::apply(callback, &e, signalArgs);
685 sdbus::apply(callback,
nullptr, signalArgs);
690 signal >> signalArgs;
693 sdbus::apply(callback, signalArgs);
702 inline SignalUnsubscriber::SignalUnsubscriber(IProxy& proxy,
const std::string& signalName)
704 , signalName_(signalName)
708 inline void SignalUnsubscriber::onInterface(
const std::string& interfaceName)
710 proxy_.unregisterSignalHandler(interfaceName, signalName_);
717 inline PropertyGetter::PropertyGetter(IProxy& proxy,
const std::string& propertyName)
719 , propertyName_(propertyName)
723 inline Variant PropertyGetter::onInterface(
const std::string& interfaceName)
726 proxy_.callMethod(
"Get")
727 .onInterface(
"org.freedesktop.DBus.Properties")
728 .withArguments(interfaceName, propertyName_)
729 .storeResultsTo(var);
737 inline AsyncPropertyGetter::AsyncPropertyGetter(IProxy& proxy,
const std::string& propertyName)
739 , propertyName_(propertyName)
743 inline AsyncPropertyGetter& AsyncPropertyGetter::onInterface(
const std::string& interfaceName)
745 interfaceName_ = &interfaceName;
750 template <
typename _Function>
751 PendingAsyncCall AsyncPropertyGetter::uponReplyInvoke(_Function&& callback)
753 static_assert(std::is_invocable_r_v<void, _Function, const Error*, Variant>,
"Property get callback function must accept Error* and property value as Variant");
755 assert(interfaceName_ !=
nullptr);
757 return proxy_.callMethodAsync(
"Get")
758 .onInterface(
"org.freedesktop.DBus.Properties")
759 .withArguments(*interfaceName_, propertyName_)
760 .uponReplyInvoke(std::forward<_Function>(callback));
763 inline std::future<Variant> AsyncPropertyGetter::getResultAsFuture()
765 assert(interfaceName_ !=
nullptr);
767 return proxy_.callMethodAsync(
"Get")
768 .onInterface(
"org.freedesktop.DBus.Properties")
769 .withArguments(*interfaceName_, propertyName_)
770 .getResultAsFuture<Variant>();
777 inline PropertySetter::PropertySetter(IProxy& proxy,
const std::string& propertyName)
779 , propertyName_(propertyName)
783 inline PropertySetter& PropertySetter::onInterface(
const std::string& interfaceName)
785 interfaceName_ = &interfaceName;
790 template <
typename _Value>
791 inline void PropertySetter::toValue(
const _Value& value)
793 PropertySetter::toValue(Variant{value});
796 template <
typename _Value>
797 inline void PropertySetter::toValue(
const _Value& value, dont_expect_reply_t)
799 PropertySetter::toValue(Variant{value}, dont_expect_reply);
802 inline void PropertySetter::toValue(
const Variant& value)
804 assert(interfaceName_ !=
nullptr);
806 proxy_.callMethod(
"Set")
807 .onInterface(
"org.freedesktop.DBus.Properties")
808 .withArguments(*interfaceName_, propertyName_, value);
811 inline void PropertySetter::toValue(
const Variant& value, dont_expect_reply_t)
813 assert(interfaceName_ !=
nullptr);
815 proxy_.callMethod(
"Set")
816 .onInterface(
"org.freedesktop.DBus.Properties")
817 .withArguments(*interfaceName_, propertyName_, value)
825 inline AsyncPropertySetter::AsyncPropertySetter(IProxy& proxy,
const std::string& propertyName)
827 , propertyName_(propertyName)
831 inline AsyncPropertySetter& AsyncPropertySetter::onInterface(
const std::string& interfaceName)
833 interfaceName_ = &interfaceName;
838 template <
typename _Value>
839 inline AsyncPropertySetter& AsyncPropertySetter::toValue(_Value&& value)
841 return AsyncPropertySetter::toValue(Variant{std::forward<_Value>(value)});
844 inline AsyncPropertySetter& AsyncPropertySetter::toValue(Variant value)
846 value_ = std::move(value);
851 template <
typename _Function>
852 PendingAsyncCall AsyncPropertySetter::uponReplyInvoke(_Function&& callback)
854 static_assert(std::is_invocable_r_v<void, _Function, const Error*>,
"Property set callback function must accept Error* only");
856 assert(interfaceName_ !=
nullptr);
858 return proxy_.callMethodAsync(
"Set")
859 .onInterface(
"org.freedesktop.DBus.Properties")
860 .withArguments(*interfaceName_, propertyName_, std::move(value_))
861 .uponReplyInvoke(std::forward<_Function>(callback));
864 inline std::future<void> AsyncPropertySetter::getResultAsFuture()
866 assert(interfaceName_ !=
nullptr);
868 return proxy_.callMethodAsync(
"Set")
869 .onInterface(
"org.freedesktop.DBus.Properties")
870 .withArguments(*interfaceName_, propertyName_, std::move(value_))
871 .getResultAsFuture<>();
878 inline AllPropertiesGetter::AllPropertiesGetter(IProxy& proxy)
883 inline std::map<std::string, Variant> AllPropertiesGetter::onInterface(
const std::string& interfaceName)
885 std::map<std::string, Variant> props;
886 proxy_.callMethod(
"GetAll")
887 .onInterface(
"org.freedesktop.DBus.Properties")
888 .withArguments(interfaceName)
889 .storeResultsTo(props);
897 inline AsyncAllPropertiesGetter::AsyncAllPropertiesGetter(IProxy& proxy)
902 inline AsyncAllPropertiesGetter& AsyncAllPropertiesGetter::onInterface(
const std::string& interfaceName)
904 interfaceName_ = &interfaceName;
909 template <
typename _Function>
910 PendingAsyncCall AsyncAllPropertiesGetter::uponReplyInvoke(_Function&& callback)
912 static_assert( std::is_invocable_r_v<void, _Function, const Error*, std::map<std::string, Variant>>
913 ,
"All properties get callback function must accept Error* and a map of property names to their values" );
915 assert(interfaceName_ !=
nullptr);
917 return proxy_.callMethodAsync(
"GetAll")
918 .onInterface(
"org.freedesktop.DBus.Properties")
919 .withArguments(*interfaceName_)
920 .uponReplyInvoke(std::forward<_Function>(callback));
923 inline std::future<std::map<std::string, Variant>> AsyncAllPropertiesGetter::getResultAsFuture()
925 assert(interfaceName_ !=
nullptr);
927 return proxy_.callMethodAsync(
"GetAll")
928 .onInterface(
"org.freedesktop.DBus.Properties")
929 .withArguments(*interfaceName_)
930 .getResultAsFuture<std::map<std::string, Variant>>();