27#ifndef SDBUS_CPP_CONVENIENCEAPICLASSES_INL_
28#define SDBUS_CPP_CONVENIENCEAPICLASSES_INL_
50 inline VTableAdder::VTableAdder(
IObject&
object, std::vector<VTableItem> vtable)
52 , vtable_(std::move(vtable))
56 inline void VTableAdder::forInterface(InterfaceName interfaceName)
58 object_.addVTable(std::move(interfaceName), std::move(vtable_));
61 inline void VTableAdder::forInterface(std::string interfaceName)
63 forInterface(InterfaceName{std::move(interfaceName)});
66 [[nodiscard]]
inline Slot VTableAdder::forInterface(InterfaceName interfaceName, return_slot_t)
68 return object_.addVTable(std::move(interfaceName), std::move(vtable_), return_slot);
71 [[nodiscard]]
inline Slot VTableAdder::forInterface(std::string interfaceName, return_slot_t)
73 return forInterface(InterfaceName{std::move(interfaceName)}, return_slot);
80 inline SignalEmitter::SignalEmitter(IObject&
object,
const SignalName& signalName)
81 : SignalEmitter(object, signalName.c_str())
85 inline SignalEmitter::SignalEmitter(IObject&
object,
const char* signalName)
87 , signalName_(signalName)
88 , exceptions_(std::uncaught_exceptions())
92 inline SignalEmitter::~SignalEmitter() noexcept(false)
95 if (std::uncaught_exceptions() != exceptions_)
107 object_.emitSignal(signal_);
110 inline SignalEmitter& SignalEmitter::onInterface(
const InterfaceName& interfaceName)
112 return onInterface(interfaceName.c_str());
115 inline SignalEmitter& SignalEmitter::onInterface(
const std::string& interfaceName)
117 return onInterface(interfaceName.c_str());
120 inline SignalEmitter& SignalEmitter::onInterface(
const char* interfaceName)
122 signal_ = object_.createSignal(interfaceName, signalName_);
127 template <
typename... Args>
128 inline void SignalEmitter::withArguments(Args&&... args)
130 assert(signal_.isValid());
132 detail::serialize_pack(signal_, std::forward<Args>(args)...);
139 inline MethodInvoker::MethodInvoker(IProxy& proxy,
const MethodName& methodName)
140 : MethodInvoker(proxy, methodName.c_str())
144 inline MethodInvoker::MethodInvoker(IProxy& proxy,
const char* methodName)
146 , methodName_(methodName)
147 , exceptions_(std::uncaught_exceptions())
151 inline MethodInvoker::~MethodInvoker() noexcept(false)
155 if (methodCalled_ || std::uncaught_exceptions() != exceptions_)
167 proxy_.callMethod(method_, timeout_);
170 inline MethodInvoker& MethodInvoker::onInterface(
const InterfaceName& interfaceName)
172 return onInterface(interfaceName.c_str());
175 inline MethodInvoker& MethodInvoker::onInterface(
const std::string& interfaceName)
177 return onInterface(interfaceName.c_str());
180 inline MethodInvoker& MethodInvoker::onInterface(
const char* interfaceName)
182 method_ = proxy_.createMethodCall(interfaceName, methodName_);
187 inline MethodInvoker& MethodInvoker::withTimeout(uint64_t usec)
194 template <
typename Rep,
typename Period>
195 inline MethodInvoker& MethodInvoker::withTimeout(
const std::chrono::duration<Rep, Period>& timeout)
197 auto microsecs = std::chrono::duration_cast<std::chrono::microseconds>(timeout);
198 return withTimeout(microsecs.count());
201 template <
typename... Args>
202 inline MethodInvoker& MethodInvoker::withArguments(Args&&... args)
204 assert(method_.isValid());
206 detail::serialize_pack(method_, std::forward<Args>(args)...);
211 template <
typename... Args>
212 inline void MethodInvoker::storeResultsTo(Args&... args)
214 assert(method_.isValid());
216 auto reply = proxy_.callMethod(method_, timeout_);
217 methodCalled_ =
true;
219 detail::deserialize_pack(reply, args...);
222 inline void MethodInvoker::dontExpectReply()
224 assert(method_.isValid());
226 method_.dontExpectReply();
233 inline AsyncMethodInvoker::AsyncMethodInvoker(IProxy& proxy,
const MethodName& methodName)
234 : AsyncMethodInvoker(proxy, methodName.c_str())
238 inline AsyncMethodInvoker::AsyncMethodInvoker(IProxy& proxy,
const char* methodName)
240 , methodName_(methodName)
244 inline AsyncMethodInvoker& AsyncMethodInvoker::onInterface(
const InterfaceName& interfaceName)
246 return onInterface(interfaceName.c_str());
249 inline AsyncMethodInvoker& AsyncMethodInvoker::onInterface(
const std::string& interfaceName)
251 return onInterface(interfaceName.c_str());
254 inline AsyncMethodInvoker& AsyncMethodInvoker::onInterface(
const char* interfaceName)
256 method_ = proxy_.createMethodCall(interfaceName, methodName_);
261 inline AsyncMethodInvoker& AsyncMethodInvoker::withTimeout(uint64_t usec)
268 template <
typename Rep,
typename Period>
269 inline AsyncMethodInvoker& AsyncMethodInvoker::withTimeout(
const std::chrono::duration<Rep, Period>& timeout)
271 auto microsecs = std::chrono::duration_cast<std::chrono::microseconds>(timeout);
272 return withTimeout(microsecs.count());
275 template <
typename... Args>
276 inline AsyncMethodInvoker& AsyncMethodInvoker::withArguments(Args&&... args)
278 assert(method_.isValid());
280 detail::serialize_pack(method_, std::forward<Args>(args)...);
285 template <
typename Function>
286 PendingAsyncCall AsyncMethodInvoker::uponReplyInvoke(Function&& callback)
288 assert(method_.isValid());
290 return proxy_.callMethodAsync(method_, makeAsyncReplyHandler(std::forward<Function>(callback)), timeout_);
293 template <
typename Function>
294 [[nodiscard]] Slot AsyncMethodInvoker::uponReplyInvoke(Function&& callback, return_slot_t)
296 assert(method_.isValid());
298 return proxy_.callMethodAsync( method_
299 , makeAsyncReplyHandler(std::forward<Function>(callback))
304 template <
typename Function>
305 inline async_reply_handler AsyncMethodInvoker::makeAsyncReplyHandler(Function&& callback)
307 return [callback = std::forward<Function>(callback)](MethodReply reply, std::optional<Error> error)
311 tuple_of_function_input_arg_types_t<Function> args;
320 catch (
const Error& e)
324 sdbus::apply(callback, e, args);
330 sdbus::apply(callback, std::move(error), args);
334 template <
typename... Args>
335 std::future<future_return_t<Args...>> AsyncMethodInvoker::getResultAsFuture()
337 auto promise = std::make_shared<std::promise<future_return_t<Args...>>>();
338 auto future = promise->get_future();
340 uponReplyInvoke([promise = std::move(promise)](std::optional<Error> error, Args... args)
343 if constexpr (!std::is_void_v<future_return_t<Args...>>)
344 promise->set_value({std::move(args)...});
346 promise->set_value();
348 promise->set_exception(std::make_exception_ptr(*std::move(error)));
357 template <
typename... Args>
358 Awaitable<awaitable_return_t<Args...>> AsyncMethodInvoker::getResultAsAwaitable()
363 auto data = std::make_shared<AwaitableData<awaitable_return_t<Args...>>>();
365 uponReplyInvoke([data](std::optional<Error> error, Args... args)
368 if constexpr (!std::is_void_v<awaitable_return_t<Args...>>)
369 data->result = {std::move(args)...};
371 data->result = std::monostate{};
373 data->result = std::make_exception_ptr(*std::move(error));
375 auto previous = data->status.exchange(AwaitableState::Completed, std::memory_order_acq_rel);
376 if (previous == AwaitableState::Waiting)
377 data->resumeCoroutine();
380 return Awaitable(data);
387 inline SignalSubscriber::SignalSubscriber(IProxy& proxy,
const SignalName& signalName)
388 : SignalSubscriber(proxy, signalName.c_str())
392 inline SignalSubscriber::SignalSubscriber(IProxy& proxy,
const char* signalName)
394 , signalName_(signalName)
398 inline SignalSubscriber& SignalSubscriber::onInterface(
const InterfaceName& interfaceName)
400 return onInterface(interfaceName.c_str());
403 inline SignalSubscriber& SignalSubscriber::onInterface(
const std::string& interfaceName)
405 return onInterface(interfaceName.c_str());
408 inline SignalSubscriber& SignalSubscriber::onInterface(
const char* interfaceName)
410 interfaceName_ = std::move(interfaceName);
415 template <
typename Function>
416 inline void SignalSubscriber::call(Function&& callback)
418 assert(interfaceName_ !=
nullptr);
420 proxy_.registerSignalHandler( interfaceName_
422 , makeSignalHandler(std::forward<Function>(callback)) );
425 template <
typename Function>
426 [[nodiscard]]
inline Slot SignalSubscriber::call(Function&& callback, return_slot_t)
428 assert(interfaceName_ !=
nullptr);
430 return proxy_.registerSignalHandler( interfaceName_
432 , makeSignalHandler(std::forward<Function>(callback))
436 template <
typename Function>
437 inline signal_handler SignalSubscriber::makeSignalHandler(Function&& callback)
439 return [callback = std::forward<Function>(callback)](Signal signal)
443 tuple_of_function_input_arg_types_t<Function> signalArgs;
449 if constexpr (has_error_param_v<Function>)
454 signal >> signalArgs;
456 catch (
const Error& e)
460 sdbus::apply(callback, e, signalArgs);
465 sdbus::apply(callback, {}, signalArgs);
470 signal >> signalArgs;
473 sdbus::apply(callback, signalArgs);
482 inline PropertyGetter::PropertyGetter(IProxy& proxy, std::string_view propertyName)
484 , propertyName_(std::move(propertyName))
488 inline Variant PropertyGetter::onInterface(std::string_view interfaceName)
491 proxy_.callMethod(
"Get")
492 .onInterface(DBUS_PROPERTIES_INTERFACE_NAME)
493 .withArguments(interfaceName, propertyName_)
494 .storeResultsTo(var);
502 inline AsyncPropertyGetter::AsyncPropertyGetter(IProxy& proxy, std::string_view propertyName)
504 , propertyName_(std::move(propertyName))
508 inline AsyncPropertyGetter& AsyncPropertyGetter::onInterface(std::string_view interfaceName)
510 interfaceName_ = std::move(interfaceName);
515 template <
typename Function>
516 PendingAsyncCall AsyncPropertyGetter::uponReplyInvoke(Function&& callback)
518 static_assert( std::is_invocable_r_v<void, Function, std::optional<Error>, Variant>
519 ,
"Property get callback function must accept std::optional<Error> and property value as Variant" );
521 assert(!interfaceName_.empty());
523 return proxy_.callMethodAsync(
"Get")
524 .onInterface(DBUS_PROPERTIES_INTERFACE_NAME)
525 .withArguments(interfaceName_, propertyName_)
526 .uponReplyInvoke(std::forward<Function>(callback));
529 template <
typename Function>
530 [[nodiscard]] Slot AsyncPropertyGetter::uponReplyInvoke(Function&& callback, return_slot_t)
532 static_assert( std::is_invocable_r_v<void, Function, std::optional<Error>, Variant>
533 ,
"Property get callback function must accept std::optional<Error> and property value as Variant" );
535 assert(!interfaceName_.empty());
537 return proxy_.callMethodAsync(
"Get")
538 .onInterface(DBUS_PROPERTIES_INTERFACE_NAME)
539 .withArguments(interfaceName_, propertyName_)
540 .uponReplyInvoke(std::forward<Function>(callback), return_slot);
543 inline std::future<Variant> AsyncPropertyGetter::getResultAsFuture()
545 assert(!interfaceName_.empty());
547 return proxy_.callMethodAsync(
"Get")
548 .onInterface(DBUS_PROPERTIES_INTERFACE_NAME)
549 .withArguments(interfaceName_, propertyName_)
550 .getResultAsFuture<Variant>();
553 inline Awaitable<Variant> AsyncPropertyGetter::getResultAsAwaitable()
555 assert(!interfaceName_.empty());
557 return proxy_.callMethodAsync(
"Get")
558 .onInterface(DBUS_PROPERTIES_INTERFACE_NAME)
559 .withArguments(interfaceName_, propertyName_)
560 .getResultAsAwaitable<Variant>();
567 inline PropertySetter::PropertySetter(IProxy& proxy, std::string_view propertyName)
569 , propertyName_(std::move(propertyName))
573 inline PropertySetter& PropertySetter::onInterface(std::string_view interfaceName)
575 interfaceName_ = std::move(interfaceName);
580 template <
typename Value>
581 inline void PropertySetter::toValue(
const Value& value)
583 PropertySetter::toValue(Variant{value});
586 template <
typename Value>
587 inline void PropertySetter::toValue(
const Value& value, dont_expect_reply_t)
589 PropertySetter::toValue(Variant{value}, dont_expect_reply);
592 inline void PropertySetter::toValue(
const Variant& value)
594 assert(!interfaceName_.empty());
596 proxy_.callMethod(
"Set")
597 .onInterface(DBUS_PROPERTIES_INTERFACE_NAME)
598 .withArguments(interfaceName_, propertyName_, value);
601 inline void PropertySetter::toValue(
const Variant& value, dont_expect_reply_t)
603 assert(!interfaceName_.empty());
605 proxy_.callMethod(
"Set")
606 .onInterface(DBUS_PROPERTIES_INTERFACE_NAME)
607 .withArguments(interfaceName_, propertyName_, value)
615 inline AsyncPropertySetter::AsyncPropertySetter(IProxy& proxy, std::string_view propertyName)
617 , propertyName_(propertyName)
621 inline AsyncPropertySetter& AsyncPropertySetter::onInterface(std::string_view interfaceName)
623 interfaceName_ = std::move(interfaceName);
628 template <
typename Value>
629 inline AsyncPropertySetter& AsyncPropertySetter::toValue(Value&& value)
631 return AsyncPropertySetter::toValue(Variant{std::forward<Value>(value)});
634 inline AsyncPropertySetter& AsyncPropertySetter::toValue(Variant value)
636 value_ = std::move(value);
641 template <
typename Function>
642 PendingAsyncCall AsyncPropertySetter::uponReplyInvoke(Function&& callback)
644 static_assert( std::is_invocable_r_v<void, Function, std::optional<Error>>
645 ,
"Property set callback function must accept std::optional<Error> only" );
647 assert(!interfaceName_.empty());
649 return proxy_.callMethodAsync(
"Set")
650 .onInterface(DBUS_PROPERTIES_INTERFACE_NAME)
651 .withArguments(interfaceName_, propertyName_, std::move(value_))
652 .uponReplyInvoke(std::forward<Function>(callback));
655 template <
typename Function>
656 [[nodiscard]] Slot AsyncPropertySetter::uponReplyInvoke(Function&& callback, return_slot_t)
658 static_assert( std::is_invocable_r_v<void, Function, std::optional<Error>>
659 ,
"Property set callback function must accept std::optional<Error> only" );
661 assert(!interfaceName_.empty());
663 return proxy_.callMethodAsync(
"Set")
664 .onInterface(DBUS_PROPERTIES_INTERFACE_NAME)
665 .withArguments(interfaceName_, propertyName_, std::move(value_))
666 .uponReplyInvoke(std::forward<Function>(callback), return_slot);
669 inline std::future<void> AsyncPropertySetter::getResultAsFuture()
671 assert(!interfaceName_.empty());
673 return proxy_.callMethodAsync(
"Set")
674 .onInterface(DBUS_PROPERTIES_INTERFACE_NAME)
675 .withArguments(interfaceName_, propertyName_, std::move(value_))
676 .getResultAsFuture<>();
679 inline Awaitable<void> AsyncPropertySetter::getResultAsAwaitable()
681 assert(!interfaceName_.empty());
683 return proxy_.callMethodAsync(
"Set")
684 .onInterface(DBUS_PROPERTIES_INTERFACE_NAME)
685 .withArguments(interfaceName_, propertyName_, std::move(value_))
686 .getResultAsAwaitable<>();
693 inline AllPropertiesGetter::AllPropertiesGetter(IProxy& proxy)
698 inline std::map<PropertyName, Variant> AllPropertiesGetter::onInterface(std::string_view interfaceName)
700 std::map<PropertyName, Variant> props;
701 proxy_.callMethod(
"GetAll")
702 .onInterface(DBUS_PROPERTIES_INTERFACE_NAME)
703 .withArguments(std::move(interfaceName))
704 .storeResultsTo(props);
712 inline AsyncAllPropertiesGetter::AsyncAllPropertiesGetter(IProxy& proxy)
717 inline AsyncAllPropertiesGetter& AsyncAllPropertiesGetter::onInterface(std::string_view interfaceName)
719 interfaceName_ = std::move(interfaceName);
724 template <
typename Function>
725 PendingAsyncCall AsyncAllPropertiesGetter::uponReplyInvoke(Function&& callback)
727 static_assert( std::is_invocable_r_v<void, Function, std::optional<Error>, std::map<PropertyName, Variant>>
728 ,
"All properties get callback function must accept std::optional<Error> and a map of property names to their values" );
730 assert(!interfaceName_.empty());
732 return proxy_.callMethodAsync(
"GetAll")
733 .onInterface(DBUS_PROPERTIES_INTERFACE_NAME)
734 .withArguments(interfaceName_)
735 .uponReplyInvoke(std::forward<Function>(callback));
738 template <
typename Function>
739 [[nodiscard]] Slot AsyncAllPropertiesGetter::uponReplyInvoke(Function&& callback, return_slot_t)
741 static_assert( std::is_invocable_r_v<void, Function, std::optional<Error>, std::map<PropertyName, Variant>>
742 ,
"All properties get callback function must accept std::optional<Error> and a map of property names to their values" );
744 assert(!interfaceName_.empty());
746 return proxy_.callMethodAsync(
"GetAll")
747 .onInterface(DBUS_PROPERTIES_INTERFACE_NAME)
748 .withArguments(interfaceName_)
749 .uponReplyInvoke(std::forward<Function>(callback), return_slot);
752 inline std::future<std::map<PropertyName, Variant>> AsyncAllPropertiesGetter::getResultAsFuture()
754 assert(!interfaceName_.empty());
756 return proxy_.callMethodAsync(
"GetAll")
757 .onInterface(DBUS_PROPERTIES_INTERFACE_NAME)
758 .withArguments(interfaceName_)
759 .getResultAsFuture<std::map<PropertyName, Variant>>();
762 inline Awaitable<std::map<PropertyName, Variant>> AsyncAllPropertiesGetter::getResultAsAwaitable()
764 assert(!interfaceName_.empty());
766 return proxy_.callMethodAsync(
"GetAll")
767 .onInterface(DBUS_PROPERTIES_INTERFACE_NAME)
768 .withArguments(interfaceName_)
769 .getResultAsAwaitable<std::map<PropertyName, Variant>>();