diff xwrited-unique.c @ 0:52694b49dcc4

Initial revision
author Guido Berhoerster <guido+xwrited@berhoerster.name>
date Sun, 27 Apr 2014 23:07:51 +0200
parents
children c53bcdabbba7
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xwrited-unique.c	Sun Apr 27 23:07:51 2014 +0200
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2011 Guido Berhoerster <guido+xwrited@berhoerster.name>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#define	_XOPEN_SOURCE	600
+
+#include <glib.h>
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus.h>
+
+#include "xwrited-unique.h"
+
+G_DEFINE_TYPE(XWritedUnique, xwrited_unique, G_TYPE_OBJECT)
+
+#define	XWRITED_UNIQUE_GET_PRIVATE(obj)	(G_TYPE_INSTANCE_GET_PRIVATE((obj), \
+    XWRITED_TYPE_UNIQUE, XWritedUniquePrivate))
+
+struct	_XWritedUniquePrivate {
+	DBusGConnection	*session_bus;
+	DBusGProxy	*session_bus_proxy;
+	gchar		*name;
+	gboolean	is_unique;
+};
+
+enum {
+	PROP_0,
+	PROP_NAME,
+	PROP_IS_XWRITED_UNIQUE
+};
+
+static gboolean
+request_name(XWritedUnique *self)
+{
+	guint32	request_name_response;
+	GError	*error = NULL;
+
+	g_return_val_if_fail(self->priv->session_bus != NULL, FALSE);
+	g_return_val_if_fail(self->priv->session_bus_proxy != NULL, FALSE);
+
+	if (dbus_g_proxy_call(self->priv->session_bus_proxy, "RequestName",
+	    &error, G_TYPE_STRING, self->priv->name, G_TYPE_UINT,
+	    DBUS_NAME_FLAG_DO_NOT_QUEUE, G_TYPE_INVALID, G_TYPE_UINT,
+	    &request_name_response, G_TYPE_INVALID) == 0) {
+		g_warning("failed to acquire service name \"%s\": %s",
+		    self->priv->name, error->message);
+		g_error_free(error);
+		return (FALSE);
+	}
+
+	switch (request_name_response) {
+	case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER:
+		return (TRUE);
+	case DBUS_REQUEST_NAME_REPLY_EXISTS:
+		break;
+	default:
+		g_warning("failed to acquire service name \"%s\"",
+		    self->priv->name);
+	}
+
+	return (FALSE);
+}
+
+static void
+xwrited_unique_get_property(GObject *gobject, guint property_id, GValue *value,
+    GParamSpec *pspec)
+{
+	XWritedUnique	*app = XWRITED_UNIQUE(gobject);
+
+	switch (property_id) {
+	case PROP_NAME:
+		g_value_set_string(value, app->priv->name);
+		break;
+	case PROP_IS_XWRITED_UNIQUE:
+		g_value_set_boolean(value, app->priv->is_unique);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, property_id,
+		    pspec);
+	}
+}
+
+static void
+xwrited_unique_set_property(GObject *gobject, guint property_id,
+    const GValue *value, GParamSpec *pspec)
+{
+	XWritedUnique	*app = XWRITED_UNIQUE(gobject);
+
+	switch (property_id) {
+	case PROP_NAME:
+		app->priv->name = g_strdup(g_value_get_string(value));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, property_id,
+		    pspec);
+	}
+}
+
+static GObject *
+xwrited_unique_constructor(GType gtype, guint n_params,
+    GObjectConstructParam *params)
+{
+	GObjectClass	*parent_class;
+	GObject		*gobject;
+	XWritedUnique	*app;
+	GError		*error = NULL;
+
+	parent_class = G_OBJECT_CLASS(xwrited_unique_parent_class);
+	gobject = parent_class->constructor(gtype, n_params, params);
+	app = XWRITED_UNIQUE(gobject);
+
+	app->priv->session_bus = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
+	if (app->priv->session_bus == NULL) {
+		g_warning("failed to connect to DBus session bus: %s",
+		    error->message);
+		g_error_free(error);
+		goto out;
+	}
+
+	app->priv->session_bus_proxy =
+	    dbus_g_proxy_new_for_name(app->priv->session_bus,
+	    DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS);
+	if (app->priv->session_bus_proxy == NULL) {
+		g_warning("failed to create DBus proxy");
+		goto out;
+	}
+
+	if (request_name(app)) {
+		app->priv->is_unique = TRUE;
+	}
+
+out:
+	return (gobject);
+}
+
+static void
+xwrited_unique_dispose(GObject *gobject)
+{
+	XWritedUnique	*self = XWRITED_UNIQUE(gobject);
+
+	if (self->priv->session_bus_proxy != NULL) {
+		g_object_unref(self->priv->session_bus_proxy);
+		self->priv->session_bus_proxy = NULL;
+	}
+
+	G_OBJECT_CLASS(xwrited_unique_parent_class)->dispose(gobject);
+}
+
+static void
+xwrited_unique_finalize(GObject *gobject)
+{
+	XWritedUnique	*self = XWRITED_UNIQUE(gobject);
+
+	g_free(self->priv->name);
+
+	G_OBJECT_CLASS(xwrited_unique_parent_class)->finalize(gobject);
+}
+
+static void
+xwrited_unique_class_init(XWritedUniqueClass *klass)
+{
+	GObjectClass	*gobject_class = G_OBJECT_CLASS(klass);
+	GParamSpec	*pspec;
+
+	gobject_class->constructor = xwrited_unique_constructor;
+	gobject_class->get_property = xwrited_unique_get_property;
+	gobject_class->set_property = xwrited_unique_set_property;
+	gobject_class->dispose = xwrited_unique_dispose;
+	gobject_class->finalize = xwrited_unique_finalize;
+
+	pspec = g_param_spec_string("name", "Name",
+	    "The unique name of the application", NULL, G_PARAM_READABLE |
+	    G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME |
+	    G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB);
+	g_object_class_install_property(gobject_class, PROP_NAME, pspec);
+
+	pspec = g_param_spec_boolean("is-unique", "Is unique",
+	    "Whether the current application instance is unique", FALSE,
+	    G_PARAM_READABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK |
+	    G_PARAM_STATIC_BLURB);
+	g_object_class_install_property(gobject_class, PROP_IS_XWRITED_UNIQUE,
+	    pspec);
+
+	g_type_class_add_private(klass, sizeof (XWritedUniquePrivate));
+}
+
+static void
+xwrited_unique_init(XWritedUnique *self)
+{
+	self->priv = XWRITED_UNIQUE_GET_PRIVATE(self);
+
+	self->priv->is_unique = FALSE;
+	self->priv->session_bus_proxy = NULL;
+}
+
+XWritedUnique *
+xwrited_unique_new(const gchar *name)
+{
+	XWritedUnique	*app;
+
+	g_return_val_if_fail(name != NULL, NULL);
+
+	app = g_object_new(XWRITED_TYPE_UNIQUE, "name", name, NULL);
+	if (app->priv->session_bus_proxy == NULL) {
+		g_object_unref(app);
+		return (NULL);
+	}
+
+	return (app);
+}
+
+gboolean
+xwrited_unique_is_unique(XWritedUnique *self)
+{
+	g_return_val_if_fail(XWRITED_IS_UNIQUE(self), FALSE);
+
+	return (self->priv->is_unique);
+}