diff options
| -rw-r--r-- | UnityCore/GLibDBusProxy.cpp | 97 | ||||
| -rw-r--r-- | UnityCore/GLibDBusProxy.h | 6 |
2 files changed, 87 insertions, 16 deletions
diff --git a/UnityCore/GLibDBusProxy.cpp b/UnityCore/GLibDBusProxy.cpp index 81fb94ee6..04d15eea7 100644 --- a/UnityCore/GLibDBusProxy.cpp +++ b/UnityCore/GLibDBusProxy.cpp @@ -80,8 +80,8 @@ public: bool IsConnected() const; void OnProxyNameOwnerChanged(GDBusProxy*, GParamSpec*); - void OnProxySignal(GDBusProxy* proxy, char* sender_name, char* signal_name, - GVariant* parameters); + void OnProxySignal(GDBusProxy* proxy, const char*, const char*, GVariant*); + void OnPropertyChanged(GDBusProxy*, GVariant*, GStrv*); static void OnProxyConnectCallback(GObject* source, GAsyncResult* res, gpointer impl); static void OnCallCallback(GObject* source, GAsyncResult* res, gpointer call_data); @@ -104,12 +104,14 @@ public: bool connected_; unsigned reconnection_attempts_; - glib::Signal<void, GDBusProxy*, char*, char*, GVariant*> g_signal_connection_; + glib::Signal<void, GDBusProxy*, const char*, const char*, GVariant*> g_signal_connection_; + glib::Signal<void, GDBusProxy*, GVariant*, GStrv*> g_property_signal_; glib::Signal<void, GDBusProxy*, GParamSpec*> name_owner_signal_; glib::Source::UniquePtr reconnect_timeout_; sigc::signal<void> proxy_acquired; - SignalHandlers handlers_; + SignalHandlers signal_handlers_; + SignalHandlers property_handlers_; }; DBusProxy::Impl::Impl(DBusProxy* owner, @@ -202,13 +204,20 @@ void DBusProxy::Impl::OnProxyConnectCallback(GObject* source, self->name_owner_signal_.Connect(self->proxy_, "notify::g-name-owner", sigc::mem_fun(self, &Impl::OnProxyNameOwnerChanged)); - if (!self->handlers_.empty()) + if (!self->signal_handlers_.empty()) { // Connecting to the signals only if we have handlers if (glib::object_cast<GObject>(self->proxy_) != self->g_signal_connection_.object()) self->g_signal_connection_.Connect(self->proxy_, "g-signal", sigc::mem_fun(self, &Impl::OnProxySignal)); } + if (!self->property_handlers_.empty()) + { + // Connecting to the property-changed only if we have handlers + if (glib::object_cast<GObject>(self->proxy_) != self->g_property_signal_.object()) + self->g_property_signal_.Connect(self->proxy_, "g-properties-changed", sigc::mem_fun(self, &Impl::OnPropertyChanged)); + } + // If a proxy cannot autostart a service, it doesn't throw an error, but // sets name_owner to NULL if (glib::String(g_dbus_proxy_get_name_owner(proxy))) @@ -243,25 +252,51 @@ void DBusProxy::Impl::OnProxyNameOwnerChanged(GDBusProxy* proxy, GParamSpec* par } } -void DBusProxy::Impl::OnProxySignal(GDBusProxy* proxy, - char* sender_name, - char* signal_name, - GVariant* parameters) +void DBusProxy::Impl::OnProxySignal(GDBusProxy* proxy, const char* sender_name, const char* signal_name, GVariant* parameters) { LOG_DEBUG(logger) << "Signal Received for proxy (" << object_path_ << ") " << "SenderName: " << sender_name << " " << "SignalName: " << signal_name << " " << "ParameterType: " << g_variant_get_type_string(parameters); - auto handler_it = handlers_.find(signal_name); + auto handler_it = signal_handlers_.find(signal_name); - if (handler_it != handlers_.end()) + if (handler_it != signal_handlers_.end()) { for (ReplyCallback const& callback : handler_it->second) callback(parameters); } } +void DBusProxy::Impl::OnPropertyChanged(GDBusProxy* proxy, GVariant* changed_props, GStrv* invalidated) +{ + LOG_DEBUG(logger) << "Properties changed for proxy (" << object_path_ << ")"; + + if (g_variant_n_children(changed_props) > 0) + { + GVariantIter *iter; + const gchar *property_name; + GVariant *value; + + g_variant_get(changed_props, "a{sv}", &iter); + while (g_variant_iter_loop (iter, "{&sv}", &property_name, &value)) + { + LOG_DEBUG(logger) << "Property: '" << property_name << "': " + << glib::String(g_variant_print(value, TRUE)); + + auto handler_it = property_handlers_.find(property_name); + + if (handler_it != property_handlers_.end()) + { + for (ReplyCallback const& callback : handler_it->second) + callback(value); + } + } + + g_variant_iter_free (iter); + } +} + void DBusProxy::Impl::WaitForProxy(GCancellable* cancellable, int timeout_msec, std::function<void(glib::Error const&)> const& callback) @@ -402,21 +437,21 @@ void DBusProxy::Impl::Connect(std::string const& signal_name, ReplyCallback cons g_signal_connection_.Connect(proxy_, "g-signal", sigc::mem_fun(this, &Impl::OnProxySignal)); } - handlers_[signal_name].push_back(callback); + signal_handlers_[signal_name].push_back(callback); } void DBusProxy::Impl::DisconnectSignal(std::string const& signal_name) { if (signal_name.empty()) { - handlers_.clear(); + signal_handlers_.clear(); } else { - handlers_.erase(signal_name); + signal_handlers_.erase(signal_name); } - if (handlers_.empty()) + if (signal_handlers_.empty()) g_signal_connection_.Disconnect(); } @@ -530,6 +565,38 @@ void DBusProxy::SetProperty(std::string const& name, GVariant* value) } } +void DBusProxy::ConnectProperty(std::string const& name, ReplyCallback const& callback) +{ + if (!callback || name.empty()) + { + LOG_WARN(logger) << "Impossible to connect to empty property or with invalid callback"; + return; + } + + if (pimpl->proxy_ && glib::object_cast<GObject>(pimpl->proxy_) != pimpl->g_property_signal_.object()) + { + // It's the first time we connect to a property so we need to setup the call handler + pimpl->g_property_signal_.Connect(pimpl->proxy_, "g-properties-changed", sigc::mem_fun(pimpl.get(), &Impl::OnPropertyChanged)); + } + + pimpl->property_handlers_[name].push_back(callback); +} + +void DBusProxy::DisconnectProperty(std::string const& name) +{ + if (name.empty()) + { + pimpl->property_handlers_.clear(); + } + else + { + pimpl->property_handlers_.erase(name); + } + + if (pimpl->property_handlers_.empty()) + pimpl->g_property_signal_.Disconnect(); +} + void DBusProxy::Connect(std::string const& signal_name, ReplyCallback const& callback) { pimpl->Connect(signal_name, callback); diff --git a/UnityCore/GLibDBusProxy.h b/UnityCore/GLibDBusProxy.h index aa2582b80..67ccf8559 100644 --- a/UnityCore/GLibDBusProxy.h +++ b/UnityCore/GLibDBusProxy.h @@ -65,13 +65,17 @@ public: GDBusCallFlags flags = G_DBUS_CALL_FLAGS_NONE, int timeout_msec = -1); + bool IsConnected() const; + Variant GetProperty(std::string const& property_name) const; void GetProperty(std::string const& property_name, ReplyCallback const&); void SetProperty(std::string const& property_name, GVariant* value); void Connect(std::string const& signal_name, ReplyCallback const& callback); void DisconnectSignal(std::string const& signal_name = ""); - bool IsConnected() const; + + void ConnectProperty(std::string const& property_name, ReplyCallback const& callback); + void DisconnectProperty(std::string const& property_name = ""); sigc::signal<void> connected; sigc::signal<void> disconnected; |
