aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/datetime/clock.h2
-rw-r--r--include/datetime/timezone-file.h17
-rw-r--r--include/datetime/timezone-geoclue.h22
-rw-r--r--src/timezone-file.cpp175
-rw-r--r--src/timezone-geoclue.cpp391
-rw-r--r--src/wakeup-timer-powerd.cpp2
6 files changed, 329 insertions, 280 deletions
diff --git a/include/datetime/clock.h b/include/datetime/clock.h
index 64d275b..8745d24 100644
--- a/include/datetime/clock.h
+++ b/include/datetime/clock.h
@@ -25,8 +25,6 @@
#include <core/property.h>
#include <core/signal.h>
-#include <gio/gio.h> // GDBusConnection
-
#include <memory> // std::shared_ptr, std::unique_ptr
namespace unity {
diff --git a/include/datetime/timezone-file.h b/include/datetime/timezone-file.h
index a67c01a..eca9c29 100644
--- a/include/datetime/timezone-file.h
+++ b/include/datetime/timezone-file.h
@@ -24,9 +24,6 @@
#include <string> // std::string
-#include <glib.h>
-#include <gio/gio.h>
-
namespace unity {
namespace indicator {
namespace datetime {
@@ -37,21 +34,15 @@ namespace datetime {
class FileTimezone: public Timezone
{
public:
- FileTimezone();
FileTimezone(const std::string& filename);
~FileTimezone();
private:
- void set_filename(const std::string& filename);
- static void on_file_changed(gpointer gself);
- void clear();
- void reload();
-
- std::string m_filename;
- GFileMonitor * m_monitor = nullptr;
- unsigned long m_monitor_handler_id = 0;
+ class Impl;
+ friend Impl;
+ std::unique_ptr<Impl> impl;
- // we have raw pointers and glib tags in here, so disable copying
+ // we have pointers in here, so disable copying
FileTimezone(const FileTimezone&) =delete;
FileTimezone& operator=(const FileTimezone&) =delete;
};
diff --git a/include/datetime/timezone-geoclue.h b/include/datetime/timezone-geoclue.h
index 4a5b726..ab6b815 100644
--- a/include/datetime/timezone-geoclue.h
+++ b/include/datetime/timezone-geoclue.h
@@ -22,11 +22,6 @@
#include <datetime/timezone.h> // base class
-#include <string>
-
-#include <glib.h>
-#include <gio/gio.h>
-
namespace unity {
namespace indicator {
namespace datetime {
@@ -41,21 +36,10 @@ public:
~GeoclueTimezone();
private:
- static void on_bus_got (GObject*, GAsyncResult*, gpointer);
- static void on_client_created (GObject*, GAsyncResult*, gpointer);
- static void on_address_changed (GDBusConnection*, const gchar*, const gchar*, const gchar*, const gchar*, GVariant*, gpointer);
- static void on_requirements_set (GObject*, GAsyncResult*, gpointer);
- static void on_address_started (GObject*, GAsyncResult*, gpointer);
- static void on_address_got (GObject*, GAsyncResult*, gpointer);
- void setTimezoneFromAddressVariant (GVariant*);
- static GVariant * call_finish (GObject*, GAsyncResult*);
-
- GCancellable * m_cancellable = nullptr;
- GDBusConnection * m_connection = nullptr;
- std::string m_client_object_path;
- guint m_signal_subscription = 0;
+ struct Impl;
+ std::unique_ptr<Impl> impl;
- // we've got pointers and gsignal tags in here, so don't allow copying
+ // we've got pointers in here, so don't allow copying
GeoclueTimezone(const GeoclueTimezone&) =delete;
GeoclueTimezone& operator=(const GeoclueTimezone&) =delete;
};
diff --git a/src/timezone-file.cpp b/src/timezone-file.cpp
index bbe48f7..3c73913 100644
--- a/src/timezone-file.cpp
+++ b/src/timezone-file.cpp
@@ -19,11 +19,97 @@
#include <datetime/timezone-file.h>
+#include <gio/gio.h>
+
#include <cerrno>
#include <cstdlib>
-namespace
+namespace unity {
+namespace indicator {
+namespace datetime {
+
+/***
+****
+***/
+
+class FileTimezone::Impl
{
+public:
+
+ Impl(FileTimezone& owner, const std::string& filename):
+ m_owner(owner)
+ {
+ set_filename(filename);
+ }
+
+ ~Impl()
+ {
+ clear();
+ }
+
+private:
+
+ void clear()
+ {
+ if (m_monitor_handler_id)
+ g_signal_handler_disconnect(m_monitor, m_monitor_handler_id);
+
+ g_clear_object (&m_monitor);
+
+ m_filename.clear();
+ }
+
+ void set_filename(const std::string& filename)
+ {
+ clear();
+
+ auto tmp = realpath(filename.c_str(), nullptr);
+ if(tmp != nullptr)
+ {
+ m_filename = tmp;
+ free(tmp);
+ }
+ else
+ {
+ g_warning("Unable to resolve path '%s': %s", filename.c_str(), g_strerror(errno));
+ m_filename = filename; // better than nothing?
+ }
+
+ auto file = g_file_new_for_path(m_filename.c_str());
+ GError * err = nullptr;
+ m_monitor = g_file_monitor_file(file, G_FILE_MONITOR_NONE, nullptr, &err);
+ g_object_unref(file);
+ if (err)
+ {
+ g_warning("%s Unable to monitor timezone file '%s': %s", G_STRLOC, TIMEZONE_FILE, err->message);
+ g_error_free(err);
+ }
+ else
+ {
+ m_monitor_handler_id = g_signal_connect_swapped(m_monitor, "changed", G_CALLBACK(on_file_changed), this);
+ g_debug("%s Monitoring timezone file '%s'", G_STRLOC, m_filename.c_str());
+ }
+
+ reload();
+ }
+
+ static void on_file_changed(gpointer gself)
+ {
+ static_cast<Impl*>(gself)->reload();
+ }
+
+ void reload()
+ {
+ const auto new_timezone = get_timezone_from_file(m_filename);
+
+ if (!new_timezone.empty())
+ m_owner.timezone.set(new_timezone);
+ }
+
+ /***
+ ****
+ ***/
+
std::string get_timezone_from_file(const std::string& filename)
{
GError * error;
@@ -73,86 +159,33 @@ namespace
return ret;
}
-}
-namespace unity {
-namespace indicator {
-namespace datetime {
+ /***
+ ****
+ ***/
-FileTimezone::FileTimezone()
-{
-}
+ FileTimezone & m_owner;
+ std::string m_filename;
+ GFileMonitor * m_monitor = nullptr;
+ unsigned long m_monitor_handler_id = 0;
+};
-FileTimezone::FileTimezone(const std::string& filename)
-{
- set_filename(filename);
-}
-
-FileTimezone::~FileTimezone()
-{
- clear();
-}
+/***
+****
+***/
-void
-FileTimezone::clear()
+FileTimezone::FileTimezone(const std::string& filename):
+ impl(new Impl{*this, filename})
{
- if (m_monitor_handler_id)
- g_signal_handler_disconnect(m_monitor, m_monitor_handler_id);
-
- g_clear_object (&m_monitor);
-
- m_filename.clear();
}
-void
-FileTimezone::set_filename(const std::string& filename)
-{
- clear();
-
- auto tmp = realpath(filename.c_str(), nullptr);
- if(tmp != nullptr)
- {
- m_filename = tmp;
- free(tmp);
- }
- else
- {
- g_warning("Unable to resolve path '%s': %s", filename.c_str(), g_strerror(errno));
- m_filename = filename; // better than nothing?
- }
-
- auto file = g_file_new_for_path(m_filename.c_str());
- GError * err = nullptr;
- m_monitor = g_file_monitor_file(file, G_FILE_MONITOR_NONE, nullptr, &err);
- g_object_unref(file);
- if (err)
- {
- g_warning("%s Unable to monitor timezone file '%s': %s", G_STRLOC, TIMEZONE_FILE, err->message);
- g_error_free(err);
- }
- else
- {
- m_monitor_handler_id = g_signal_connect_swapped(m_monitor, "changed", G_CALLBACK(on_file_changed), this);
- g_debug("%s Monitoring timezone file '%s'", G_STRLOC, m_filename.c_str());
- }
-
- reload();
-}
-
-void
-FileTimezone::on_file_changed(gpointer gself)
+FileTimezone::~FileTimezone()
{
- static_cast<FileTimezone*>(gself)->reload();
}
-void
-FileTimezone::reload()
-{
- const auto new_timezone = get_timezone_from_file(m_filename);
-
- if (!new_timezone.empty())
- timezone.set(new_timezone);
-}
+/***
+****
+***/
} // namespace datetime
} // namespace indicator
diff --git a/src/timezone-geoclue.cpp b/src/timezone-geoclue.cpp
index b8847a4..ca9132f 100644
--- a/src/timezone-geoclue.cpp
+++ b/src/timezone-geoclue.cpp
@@ -19,225 +19,266 @@
#include <datetime/timezone-geoclue.h>
+#include <gio/gio.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
#define GEOCLUE_BUS_NAME "org.freedesktop.Geoclue.Master"
namespace unity {
namespace indicator {
namespace datetime {
-
-GeoclueTimezone::GeoclueTimezone():
- m_cancellable(g_cancellable_new())
-{
- g_bus_get(G_BUS_TYPE_SESSION, m_cancellable, on_bus_got, this);
-}
-
-GeoclueTimezone::~GeoclueTimezone()
+class GeoclueTimezone::Impl
{
- g_cancellable_cancel(m_cancellable);
- g_object_unref(m_cancellable);
- if (m_signal_subscription)
- g_dbus_connection_signal_unsubscribe(m_connection, m_signal_subscription);
+public:
- g_object_unref(m_connection);
-}
-
-/***
-****
-***/
-
-void
-GeoclueTimezone::on_bus_got(GObject* /*source*/,
- GAsyncResult* res,
- gpointer gself)
-{
- GError * error;
- GDBusConnection * connection;
-
- error = nullptr;
- connection = g_bus_get_finish(res, &error);
- if (error)
+ Impl(GeoclueTimezone& owner):
+ m_owner(owner),
+ m_cancellable(g_cancellable_new())
{
- if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
- g_warning("Couldn't get bus: %s", error->message);
-
- g_error_free(error);
+ g_bus_get(G_BUS_TYPE_SESSION, m_cancellable, on_bus_got, this);
}
- else
+
+ ~Impl()
{
- auto self = static_cast<GeoclueTimezone*>(gself);
-
- self->m_connection = connection;
-
- g_dbus_connection_call(self->m_connection,
- GEOCLUE_BUS_NAME,
- "/org/freedesktop/Geoclue/Master",
- "org.freedesktop.Geoclue.Master",
- "Create",
- nullptr, // parameters
- G_VARIANT_TYPE("(o)"),
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- self->m_cancellable,
- on_client_created,
- self);
+ g_cancellable_cancel(m_cancellable);
+ g_object_unref(m_cancellable);
+ g_object_unref(m_bus);
}
-}
-void
-GeoclueTimezone::on_client_created(GObject * source, GAsyncResult * res, gpointer gself)
-{
- GVariant * result;
+private:
- if ((result = call_finish(source, res)))
+ void remember_subscription(GDBusConnection * bus,
+ guint tag)
{
- auto self = static_cast<GeoclueTimezone*>(gself);
-
- GVariant * child = g_variant_get_child_value(result, 0);
- self->m_client_object_path = g_variant_get_string(child, nullptr);
- g_variant_unref(child);
- g_variant_unref(result);
-
- self->m_signal_subscription = g_dbus_connection_signal_subscribe(
- self->m_connection,
- GEOCLUE_BUS_NAME,
- "org.freedesktop.Geoclue.Address", // inteface
- "AddressChanged", // signal name
- self->m_client_object_path.c_str(), // object path
- nullptr, // arg0
- G_DBUS_SIGNAL_FLAGS_NONE,
- on_address_changed,
- self,
- nullptr);
-
- g_dbus_connection_call(self->m_connection,
- GEOCLUE_BUS_NAME,
- self->m_client_object_path.c_str(),
- "org.freedesktop.Geoclue.MasterClient",
- "SetRequirements",
- g_variant_new("(iibi)", 2, 0, FALSE, 1023),
- nullptr,
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- self->m_cancellable,
- on_requirements_set,
- self);
- }
-}
+ g_object_ref(bus);
-void
-GeoclueTimezone::on_address_changed(GDBusConnection* /*connection*/,
- const gchar* /*sender_name*/,
- const gchar* /*object_path*/,
- const gchar* /*interface_name*/,
- const gchar* /*signal_name*/,
- GVariant* parameters,
- gpointer gself)
-{
- static_cast<GeoclueTimezone*>(gself)->setTimezoneFromAddressVariant(parameters);
-}
+ auto deleter = [tag](GDBusConnection* bus){
+ g_dbus_connection_signal_unsubscribe(bus, tag);
+ g_object_unref(G_OBJECT(bus));
+ };
-void
-GeoclueTimezone::on_requirements_set(GObject* source, GAsyncResult* res, gpointer gself)
-{
- GVariant * result;
+ m_subscriptions.push_back(std::shared_ptr<GDBusConnection>(bus, deleter));
+ }
- if ((result = call_finish(source, res)))
+ static void on_bus_got(GObject * /*source*/,
+ GAsyncResult * res,
+ gpointer gself)
{
- auto self = static_cast<GeoclueTimezone*>(gself);
-
- g_dbus_connection_call(self->m_connection,
- GEOCLUE_BUS_NAME,
- self->m_client_object_path.c_str(),
- "org.freedesktop.Geoclue.MasterClient",
- "AddressStart",
- nullptr,
- nullptr,
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- self->m_cancellable,
- on_address_started,
- self);
-
- g_variant_unref(result);
- }
-}
+ GError * error;
+ GDBusConnection * connection;
-void
-GeoclueTimezone::on_address_started(GObject * source, GAsyncResult * res, gpointer gself)
-{
- GVariant * result;
+ error = nullptr;
+ connection = g_bus_get_finish(res, &error);
+ if (error)
+ {
+ if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning("Couldn't get bus: %s", error->message);
- if ((result = call_finish(source, res)))
+ g_error_free(error);
+ }
+ else
+ {
+ auto self = static_cast<Impl*>(gself);
+
+ self->m_bus = connection;
+
+ g_dbus_connection_call(self->m_bus,
+ GEOCLUE_BUS_NAME,
+ "/org/freedesktop/Geoclue/Master",
+ "org.freedesktop.Geoclue.Master",
+ "Create",
+ nullptr, // parameters
+ G_VARIANT_TYPE("(o)"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ self->m_cancellable,
+ on_client_created,
+ self);
+ }
+ }
+
+ static void on_client_created(GObject* source, GAsyncResult* res, gpointer gself)
{
- auto self = static_cast<GeoclueTimezone*>(gself);
-
- g_dbus_connection_call(self->m_connection,
- GEOCLUE_BUS_NAME,
- self->m_client_object_path.c_str(),
- "org.freedesktop.Geoclue.Address",
- "GetAddress",
- nullptr,
- G_VARIANT_TYPE("(ia{ss}(idd))"),
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- self->m_cancellable,
- on_address_got,
- self);
-
- g_variant_unref(result);
+ GVariant * result;
+
+ if ((result = call_finish(G_STRFUNC, source, res)))
+ {
+ auto self = static_cast<Impl*>(gself);
+
+ GVariant * child = g_variant_get_child_value(result, 0);
+ self->m_client_object_path = g_variant_get_string(child, nullptr);
+ g_variant_unref(child);
+ g_variant_unref(result);
+
+ auto tag = g_dbus_connection_signal_subscribe(self->m_bus,
+ GEOCLUE_BUS_NAME,
+ "org.freedesktop.Geoclue.Address", // interface
+ "AddressChanged", // signal name
+ self->m_client_object_path.c_str(), // object path
+ nullptr, // arg0
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ on_address_changed,
+ self,
+ nullptr);
+ self->remember_subscription(self->m_bus, tag);
+
+ g_dbus_connection_call(self->m_bus,
+ GEOCLUE_BUS_NAME,
+ self->m_client_object_path.c_str(),
+ "org.freedesktop.Geoclue.MasterClient",
+ "SetRequirements",
+ g_variant_new("(iibi)", 2, 0, FALSE, 1023),
+ nullptr,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ self->m_cancellable,
+ on_requirements_set,
+ self);
+ }
}
-}
-void
-GeoclueTimezone::on_address_got(GObject * source, GAsyncResult * res, gpointer gself)
-{
- GVariant * result;
+ static void on_address_changed(GDBusConnection* /*connection*/,
+ const gchar* /*sender_name*/,
+ const gchar* /*object_path*/,
+ const gchar* /*interface_name*/,
+ const gchar* /*signal_name*/,
+ GVariant* parameters,
+ gpointer gself)
+ {
+ static_cast<Impl*>(gself)->set_timezone_from_address_variant(parameters);
+ }
- if ((result = call_finish(source, res)))
+ static void on_requirements_set(GObject* source, GAsyncResult* res, gpointer gself)
{
- static_cast<GeoclueTimezone*>(gself)->setTimezoneFromAddressVariant(result);
- g_variant_unref(result);
+ GVariant * result;
+
+ if ((result = call_finish(G_STRFUNC, source, res)))
+ {
+ auto self = static_cast<Impl*>(gself);
+
+ g_dbus_connection_call(self->m_bus,
+ GEOCLUE_BUS_NAME,
+ self->m_client_object_path.c_str(),
+ "org.freedesktop.Geoclue.MasterClient",
+ "AddressStart",
+ nullptr,
+ nullptr,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ self->m_cancellable,
+ on_address_started,
+ self);
+
+ g_variant_unref(result);
+ }
}
-}
-void
-GeoclueTimezone::setTimezoneFromAddressVariant(GVariant * variant)
-{
- g_return_if_fail(g_variant_is_of_type(variant, G_VARIANT_TYPE("(ia{ss}(idd))")));
+ static void on_address_started(GObject* source, GAsyncResult* res, gpointer gself)
+ {
+ GVariant * result;
+
+ if ((result = call_finish(G_STRFUNC, source, res)))
+ {
+ auto self = static_cast<Impl*>(gself);
+
+ g_dbus_connection_call(self->m_bus,
+ GEOCLUE_BUS_NAME,
+ self->m_client_object_path.c_str(),
+ "org.freedesktop.Geoclue.Address",
+ "GetAddress",
+ nullptr,
+ G_VARIANT_TYPE("(ia{ss}(idd))"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ self->m_cancellable,
+ on_address_got,
+ self);
+
+ g_variant_unref(result);
+ }
+ }
- const gchar * timezone_string = nullptr;
- GVariant * dict = g_variant_get_child_value(variant, 1);
- if (dict)
+ static void on_address_got(GObject* source, GAsyncResult* res, gpointer gself)
{
- if (g_variant_lookup(dict, "timezone", "&s", &timezone_string))
- timezone.set(timezone_string);
+ GVariant * result;
- g_variant_unref(dict);
+ if ((result = call_finish(G_STRFUNC, source, res)))
+ {
+ static_cast<Impl*>(gself)->set_timezone_from_address_variant(result);
+ g_variant_unref(result);
+ }
}
-}
-GVariant*
-GeoclueTimezone::call_finish(GObject * source, GAsyncResult * res)
-{
- GError * error;
- GVariant * result;
+ /***
+ ****
+ ***/
- error = nullptr;
- result = g_dbus_connection_call_finish(G_DBUS_CONNECTION(source), res, &error);
+ void set_timezone_from_address_variant(GVariant * variant)
+ {
+ g_return_if_fail(g_variant_is_of_type(variant, G_VARIANT_TYPE("(ia{ss}(idd))")));
+
+ const gchar * timezone_string = nullptr;
+ GVariant * dict = g_variant_get_child_value(variant, 1);
+ if (dict)
+ {
+ if (g_variant_lookup(dict, "timezone", "&s", &timezone_string))
+ {
+ g_debug("from geoclue, setting timezone to '%s'", timezone_string);
+ m_owner.timezone.set(timezone_string);
+ }
+
+ g_variant_unref(dict);
+ }
+ }
- if (error)
+ static GVariant* call_finish(const char * funcname, GObject * source, GAsyncResult * res)
{
+ GError * error;
+ GVariant * result;
+
+ error = nullptr;
+ result = g_dbus_connection_call_finish(G_DBUS_CONNECTION(source), res, &error);
+
+ if (error)
+ {
if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
- g_warning("AddressStart() failed: %s", error->message);
+ g_warning("%s failed: %s", funcname, error->message);
g_error_free(error);
g_clear_pointer(&result, g_variant_unref);
+ }
+
+ return result;
}
- return result;
+ /***
+ ****
+ ***/
+
+ GeoclueTimezone & m_owner;
+ GDBusConnection * m_bus = nullptr;
+ GCancellable * m_cancellable = nullptr;
+ std::string m_client_object_path;
+ std::vector<std::shared_ptr<GDBusConnection>> m_subscriptions;
+};
+
+/****
+*****
+****/
+
+GeoclueTimezone::GeoclueTimezone():
+ impl(new Impl{*this})
+{
+}
+
+GeoclueTimezone::~GeoclueTimezone()
+{
}
/****
diff --git a/src/wakeup-timer-powerd.cpp b/src/wakeup-timer-powerd.cpp
index 42d93e7..bbcc9dd 100644
--- a/src/wakeup-timer-powerd.cpp
+++ b/src/wakeup-timer-powerd.cpp
@@ -22,6 +22,8 @@
#include <notifications/dbus-shared.h> // BUS_POWERD_NAME
+#include <gio/gio.h>
+
#include <memory> // std::shared_ptr
namespace unity {