1
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
4
* Copyright (C) Philip Withnall 2009 <philip@tecnocode.co.uk>
6
* Almanah is free software: you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation, either version 3 of the License, or
9
* (at your option) any later version.
11
* Almanah is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with Almanah. If not, see <http://www.gnu.org/licenses/>.
21
#include <dbus/dbus-glib.h>
27
#include "../event-factory.h"
28
#include "../events/f-spot-photo.h"
30
static void almanah_f_spot_event_factory_dispose (GObject *object);
31
static void almanah_f_spot_event_factory_finalize (GObject *object);
32
static void query_events (AlmanahEventFactory *event_factory, GDate *date);
33
static GSList *get_events (AlmanahEventFactory *event_factory, GDate *date);
34
static void cancel_query (DBusGProxyCall *call, AlmanahFSpotEventFactory *self);
36
struct _AlmanahFSpotEventFactoryPrivate {
37
DBusGConnection *connection;
40
GSList *current_queries;
43
G_DEFINE_TYPE (AlmanahFSpotEventFactory, almanah_f_spot_event_factory, ALMANAH_TYPE_EVENT_FACTORY)
44
#define ALMANAH_F_SPOT_EVENT_FACTORY_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ALMANAH_TYPE_F_SPOT_EVENT_FACTORY, AlmanahFSpotEventFactoryPrivate))
47
almanah_f_spot_event_factory_class_init (AlmanahFSpotEventFactoryClass *klass)
49
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
50
AlmanahEventFactoryClass *event_factory_class = ALMANAH_EVENT_FACTORY_CLASS (klass);
52
g_type_class_add_private (klass, sizeof (AlmanahFSpotEventFactoryPrivate));
54
gobject_class->dispose = almanah_f_spot_event_factory_dispose;
55
gobject_class->finalize = almanah_f_spot_event_factory_finalize;
57
event_factory_class->type_id = ALMANAH_EVENT_FACTORY_F_SPOT;
58
event_factory_class->query_events = query_events;
59
event_factory_class->get_events = get_events;
63
almanah_f_spot_event_factory_init (AlmanahFSpotEventFactory *self)
67
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, ALMANAH_TYPE_F_SPOT_EVENT_FACTORY, AlmanahFSpotEventFactoryPrivate);
69
self->priv->connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
70
if (self->priv->connection == NULL) {
71
/* TODO: something neater than this */
72
g_error ("Error connecting to D-Bus for F-Spot event factory: %s", error->message);
77
/* Connect to the F-Spot D-Bus service */
78
self->priv->proxy = dbus_g_proxy_new_for_name (self->priv->connection,
80
"/org/gnome/FSpot/PhotoRemoteControl",
81
"org.gnome.FSpot.PhotoRemoteControl");
85
almanah_f_spot_event_factory_dispose (GObject *object)
87
AlmanahFSpotEventFactoryPrivate *priv = ALMANAH_F_SPOT_EVENT_FACTORY_GET_PRIVATE (object);
89
if (priv->proxy != NULL)
90
g_object_unref (priv->proxy);
93
if (priv->connection != NULL)
94
dbus_g_connection_unref (priv->connection);
95
priv->connection = NULL;
97
/* Chain up to the parent class */
98
G_OBJECT_CLASS (almanah_f_spot_event_factory_parent_class)->dispose (object);
102
almanah_f_spot_event_factory_finalize (GObject *object)
104
AlmanahFSpotEventFactoryPrivate *priv = ALMANAH_F_SPOT_EVENT_FACTORY_GET_PRIVATE (object);
106
g_slist_foreach (priv->current_queries, (GFunc) cancel_query, object);
107
g_slist_free (priv->current_queries);
109
g_slist_foreach (priv->photos, (GFunc) g_object_unref, NULL);
110
g_slist_free (priv->photos);
112
/* Chain up to the parent class */
113
G_OBJECT_CLASS (almanah_f_spot_event_factory_parent_class)->finalize (object);
117
query_info_complete_cb (DBusGProxy *proxy, DBusGProxyCall *call, AlmanahFSpotEventFactory *self)
119
AlmanahFSpotEventFactoryPrivate *priv = self->priv;
120
GError *error = NULL;
121
GHashTable *properties;
125
/* Remove the call from the list of current queries */
126
priv->current_queries = g_slist_remove (priv->current_queries, call);
128
if (dbus_g_proxy_end_call (proxy, call, &error,
129
dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), &properties,
130
G_TYPE_INVALID) == FALSE) {
131
g_error ("Error getting photo properties: %s", error->message);
132
g_error_free (error);
136
name = g_hash_table_lookup (properties, "Name");
137
uri = g_hash_table_lookup (properties, "Uri");
139
if (almanah->debug == TRUE)
140
g_debug ("Received properties for F-Spot photo \"%s\".", g_value_get_string (name));
142
/* Create a new AlmanahFSpotPhotoEvent for the photo and add it to the list */
143
event = ALMANAH_EVENT (almanah_f_spot_photo_event_new (g_value_get_string (uri), g_value_get_string (name)));
144
priv->photos = g_slist_prepend (priv->photos, event);
145
g_signal_emit_by_name (self, "events-updated");
147
g_hash_table_destroy (properties);
151
query_events_complete_cb (DBusGProxy *proxy, DBusGProxyCall *call, AlmanahFSpotEventFactory *self)
153
AlmanahFSpotEventFactoryPrivate *priv = self->priv;
154
GError *error = NULL;
158
/* Remove the call from the list of current queries */
159
priv->current_queries = g_slist_remove (priv->current_queries, call);
161
if (dbus_g_proxy_end_call (proxy, call, &error,
162
DBUS_TYPE_G_UINT_ARRAY, &id_array,
163
G_TYPE_INVALID) == FALSE) {
164
/* Ignore errors about unknown services or methods; it means the F-Spot service isn't available or is out-of-date */
165
if (g_error_matches (error, DBUS_GERROR, DBUS_GERROR_SERVICE_UNKNOWN) == TRUE ||
166
g_error_matches (error, DBUS_GERROR, DBUS_GERROR_UNKNOWN_METHOD) == TRUE)
169
g_error ("Error getting photo list from F-Spot: %s", error->message);
170
g_error_free (error);
174
if (almanah->debug == TRUE)
175
g_debug ("Received list of photos from F-Spot.");
177
/* Now query for the photo information */
178
for (i = 0; i < id_array->len; i++) {
179
DBusGProxyCall *sub_call;
182
photo_id = g_array_index (id_array, guint, i);
183
sub_call = dbus_g_proxy_begin_call (priv->proxy, "GetPhotoProperties",
184
(DBusGProxyCallNotify) query_info_complete_cb, g_object_ref (self), g_object_unref,
185
G_TYPE_UINT, photo_id,
187
priv->current_queries = g_slist_prepend (priv->current_queries, sub_call);
189
g_array_free (id_array, TRUE);
193
date_to_int64 (GDate *date)
195
struct tm localtime_tm = { 0, };
197
localtime_tm.tm_mday = g_date_get_day (date);
198
localtime_tm.tm_mon = g_date_get_month (date) - 1;
199
localtime_tm.tm_year = g_date_get_year (date) - 1900;
200
localtime_tm.tm_isdst = -1;
202
return mktime (&localtime_tm);
206
cancel_query (DBusGProxyCall *call, AlmanahFSpotEventFactory *self)
208
dbus_g_proxy_cancel_call (self->priv->proxy, call);
212
query_events (AlmanahEventFactory *event_factory, GDate *date)
214
DBusGProxyCall *call;
216
AlmanahFSpotEventFactoryPrivate *priv = ALMANAH_F_SPOT_EVENT_FACTORY (event_factory)->priv;
218
/* Cancel all current queries */
219
g_slist_foreach (priv->current_queries, (GFunc) cancel_query, event_factory);
220
g_slist_free (priv->current_queries);
221
priv->current_queries = NULL;
223
/* Create a new list of photos for the new query */
224
g_slist_foreach (priv->photos, (GFunc) g_object_unref, NULL);
225
g_slist_free (priv->photos);
228
/* Sort out the dates */
230
g_date_add_days (&next_date, 1);
232
/* Execute the D-Bus query */
233
call = dbus_g_proxy_begin_call (priv->proxy, "QueryByDate",
234
(DBusGProxyCallNotify) query_events_complete_cb, g_object_ref (event_factory), g_object_unref,
235
G_TYPE_INT64, date_to_int64 (date),
236
G_TYPE_INT64, date_to_int64 (&next_date),
239
/* Append the query to the list of current queries, so that it can be cancelled in future if we find
240
* we need to query for events for a different date. */
241
priv->current_queries = g_slist_prepend (priv->current_queries, call);
245
get_events (AlmanahEventFactory *event_factory, GDate *date)
247
GSList *photos = ALMANAH_F_SPOT_EVENT_FACTORY (event_factory)->priv->photos;
248
g_slist_foreach (photos, (GFunc) g_object_ref, NULL);
249
return g_slist_copy (photos);