summaryrefslogtreecommitdiff
diff options
-rw-r--r--UnityCore/GLibDBusProxy.cpp97
-rw-r--r--UnityCore/GLibDBusProxy.h6
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;