1
/* vi:set et ai sw=2 sts=2 ts=2: */
3
* Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org>
5
* This program is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU General Public License as
7
* published by the Free Software Foundation; either version 2 of
8
* the License, or (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public
16
* License along with this program; if not, write to the Free
17
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18
* Boston, MA 02110-1301, USA.
26
#include <glib/gi18n.h>
27
#include <glib-object.h>
29
#include <tumbler/tumbler.h>
30
#include <tumbler/tumbler-marshal.h>
32
#include <tumblerd/tumbler-specialized-thumbnailer.h>
36
/* Property identifiers */
50
typedef struct _SpecializedInfo SpecializedInfo;
54
static void tumbler_specialized_thumbnailer_iface_init (TumblerThumbnailerIface *iface);
55
static void tumbler_specialized_thumbnailer_constructed (GObject *object);
56
static void tumbler_specialized_thumbnailer_finalize (GObject *object);
57
static void tumbler_specialized_thumbnailer_get_property (GObject *object,
61
static void tumbler_specialized_thumbnailer_set_property (GObject *object,
65
static void tumbler_specialized_thumbnailer_create (TumblerThumbnailer *thumbnailer,
66
GCancellable *cancellable,
67
TumblerFileInfo *info);
68
static void tumbler_specialized_thumbnailer_proxy_destroyed (DBusGProxy *proxy,
69
TumblerSpecializedThumbnailer *thumbnailer);
73
struct _TumblerSpecializedThumbnailerClass
75
TumblerAbstractThumbnailerClass __parent__;
78
struct _TumblerSpecializedThumbnailer
80
TumblerAbstractThumbnailer __parent__;
82
DBusGConnection *connection;
92
struct _SpecializedInfo
94
TumblerThumbnailer *thumbnailer;
98
const gchar *mime_type;
99
gboolean had_callback;
105
G_DEFINE_TYPE_WITH_CODE (TumblerSpecializedThumbnailer,
106
tumbler_specialized_thumbnailer,
107
TUMBLER_TYPE_ABSTRACT_THUMBNAILER,
108
G_IMPLEMENT_INTERFACE (TUMBLER_TYPE_THUMBNAILER,
109
tumbler_specialized_thumbnailer_iface_init));
114
tumbler_specialized_thumbnailer_class_init (TumblerSpecializedThumbnailerClass *klass)
116
GObjectClass *gobject_class;
118
gobject_class = G_OBJECT_CLASS (klass);
119
gobject_class->constructed = tumbler_specialized_thumbnailer_constructed;
120
gobject_class->finalize = tumbler_specialized_thumbnailer_finalize;
121
gobject_class->get_property = tumbler_specialized_thumbnailer_get_property;
122
gobject_class->set_property = tumbler_specialized_thumbnailer_set_property;
124
g_object_class_install_property (gobject_class,
126
g_param_spec_string ("name",
130
G_PARAM_CONSTRUCT_ONLY |
133
g_object_class_install_property (gobject_class,
135
g_param_spec_string ("object-path",
139
G_PARAM_CONSTRUCT_ONLY |
142
g_object_class_install_property (gobject_class,
144
g_param_spec_pointer ("connection",
147
G_PARAM_CONSTRUCT_ONLY |
150
g_object_class_install_property (gobject_class,
152
g_param_spec_object ("proxy",
158
g_object_class_install_property (gobject_class,
160
g_param_spec_boolean ("foreign",
164
G_PARAM_CONSTRUCT_ONLY |
167
g_object_class_install_property (gobject_class,
169
g_param_spec_uint64 ("modified",
173
G_PARAM_CONSTRUCT_ONLY |
176
dbus_g_object_register_marshaller (tumbler_marshal_VOID__UINT_STRING,
182
dbus_g_object_register_marshaller (g_cclosure_marshal_VOID__UINT,
187
dbus_g_object_register_marshaller (tumbler_marshal_VOID__UINT_STRING_INT_STRING,
200
tumbler_specialized_thumbnailer_iface_init (TumblerThumbnailerIface *iface)
202
iface->create = tumbler_specialized_thumbnailer_create;
208
tumbler_specialized_thumbnailer_init (TumblerSpecializedThumbnailer *thumbnailer)
215
tumbler_specialized_thumbnailer_constructed (GObject *object)
217
TumblerSpecializedThumbnailer *thumbnailer = TUMBLER_SPECIALIZED_THUMBNAILER (object);
219
g_return_if_fail (TUMBLER_SPECIALIZED_THUMBNAILER (thumbnailer));
221
/* chain up to parent classes */
222
if (G_OBJECT_CLASS (tumbler_specialized_thumbnailer_parent_class)->constructed != NULL)
223
(G_OBJECT_CLASS (tumbler_specialized_thumbnailer_parent_class)->constructed) (object);
226
dbus_g_proxy_new_for_name (thumbnailer->connection,
228
thumbnailer->object_path,
229
"org.freedesktop.thumbnails.SpecializedThumbnailer1");
231
dbus_g_proxy_add_signal (thumbnailer->proxy, "Ready",
232
G_TYPE_UINT, G_TYPE_STRING,
235
dbus_g_proxy_add_signal (thumbnailer->proxy, "Error",
236
G_TYPE_UINT, G_TYPE_STRING,
237
G_TYPE_INT, G_TYPE_STRING,
240
dbus_g_proxy_add_signal (thumbnailer->proxy, "Finished",
244
if (thumbnailer->foreign) {
245
g_signal_connect (thumbnailer->proxy, "destroy",
246
G_CALLBACK (tumbler_specialized_thumbnailer_proxy_destroyed),
254
tumbler_specialized_thumbnailer_finalize (GObject *object)
256
TumblerSpecializedThumbnailer *thumbnailer = TUMBLER_SPECIALIZED_THUMBNAILER (object);
258
g_free (thumbnailer->name);
259
g_free (thumbnailer->object_path);
261
g_signal_handlers_disconnect_matched (thumbnailer->proxy, G_SIGNAL_MATCH_DATA,
262
0, 0, NULL, NULL, thumbnailer);
264
g_object_unref (thumbnailer->proxy);
266
dbus_g_connection_unref (thumbnailer->connection);
268
(*G_OBJECT_CLASS (tumbler_specialized_thumbnailer_parent_class)->finalize) (object);
274
tumbler_specialized_thumbnailer_get_property (GObject *object,
279
TumblerSpecializedThumbnailer *thumbnailer = TUMBLER_SPECIALIZED_THUMBNAILER (object);
283
case PROP_CONNECTION:
284
g_value_set_pointer (value, dbus_g_connection_ref (thumbnailer->connection));
287
g_value_set_string (value, thumbnailer->name);
289
case PROP_OBJECT_PATH:
290
g_value_set_string (value, thumbnailer->object_path);
293
g_value_set_object (value, thumbnailer->proxy);
296
g_value_set_boolean (value, thumbnailer->foreign);
299
g_value_set_uint64 (value, thumbnailer->modified);
302
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
310
tumbler_specialized_thumbnailer_set_property (GObject *object,
315
TumblerSpecializedThumbnailer *thumbnailer = TUMBLER_SPECIALIZED_THUMBNAILER (object);
319
case PROP_CONNECTION:
320
thumbnailer->connection = dbus_g_connection_ref (g_value_get_pointer (value));
323
thumbnailer->name = g_value_dup_string (value);
325
case PROP_OBJECT_PATH:
326
thumbnailer->object_path = g_value_dup_string (value);
329
thumbnailer->foreign = g_value_get_boolean (value);
332
thumbnailer->modified = g_value_get_uint64 (value);
335
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
343
specialized_error (DBusGProxy *proxy,
350
SpecializedInfo *info = user_data;
352
if (info->handle == handle)
353
g_signal_emit_by_name (info->thumbnailer, "error", uri, error_code, error_msg);
359
specialized_ready (DBusGProxy *proxy,
364
SpecializedInfo *info = user_data;
366
if (info->handle == handle)
367
g_signal_emit_by_name (info->thumbnailer, "ready", uri);
373
specialized_finished (DBusGProxy *proxy,
377
SpecializedInfo *info = user_data;
379
if (info->handle == handle)
381
g_mutex_lock (info->mutex);
382
g_cond_broadcast (info->condition);
383
info->had_callback = TRUE;
384
g_mutex_unlock (info->mutex);
389
tumbler_specialized_thumbnailer_create (TumblerThumbnailer *thumbnailer,
390
GCancellable *cancellable,
391
TumblerFileInfo *info)
393
TumblerSpecializedThumbnailer *s;
394
SpecializedInfo sinfo;
396
TumblerThumbnail *thumbnail;
397
TumblerThumbnailFlavor *flavor;
398
const gchar *flavor_name;
400
GError *error = NULL;
403
g_return_if_fail (TUMBLER_IS_SPECIALIZED_THUMBNAILER (thumbnailer));
405
uri = tumbler_file_info_get_uri (info);
406
thumbnail = tumbler_file_info_get_thumbnail (info);
407
flavor = tumbler_thumbnail_get_flavor (thumbnail);
408
flavor_name = tumbler_thumbnail_flavor_get_name (flavor);
410
s = TUMBLER_SPECIALIZED_THUMBNAILER (thumbnailer);
412
sinfo.condition = g_cond_new ();
413
sinfo.had_callback = FALSE;
414
sinfo.mutex = g_mutex_new ();
416
sinfo.mime_type = tumbler_file_info_get_mime_type (info);
417
sinfo.thumbnailer = thumbnailer;
419
dbus_g_proxy_connect_signal (s->proxy, "Finished",
420
G_CALLBACK (specialized_finished),
424
dbus_g_proxy_connect_signal (s->proxy, "Ready",
425
G_CALLBACK (specialized_ready),
429
dbus_g_proxy_connect_signal (s->proxy, "Error",
430
G_CALLBACK (specialized_error),
434
dbus_g_proxy_call_with_timeout (s->proxy, "Queue",
435
100000000, /* 100 seconds worth of timeout */
438
G_TYPE_STRING, sinfo.mime_type,
439
G_TYPE_STRING, flavor_name,
440
/* TODO: Get this bool from scheduler type */
441
G_TYPE_BOOLEAN, FALSE,
443
G_TYPE_UINT, &sinfo.handle,
448
g_get_current_time (&timev);
450
/* 100 seconds worth of timeout */
451
g_time_val_add (&timev, 100000000);
453
g_mutex_lock (sinfo.mutex);
455
/* we are a thread, so the mainloop will still be
456
* be running to receive the error and ready signals */
457
if (!sinfo.had_callback)
459
if (!g_cond_timed_wait (sinfo.condition, sinfo.mutex, &timev))
461
message = g_strdup (_("Failed to call the specialized thumbnailer: timeout"));
462
g_signal_emit_by_name (thumbnailer, "error", uri, 1, message);
466
g_mutex_unlock (sinfo.mutex);
470
message = g_strdup_printf (_("Failed to call the specialized thumbnailer: %s"),
472
g_signal_emit_by_name (thumbnailer, "error", uri, 1, message);
474
g_clear_error (&error);
477
dbus_g_proxy_disconnect_signal (s->proxy, "Finished",
478
G_CALLBACK (specialized_finished),
481
dbus_g_proxy_disconnect_signal (s->proxy, "Ready",
482
G_CALLBACK (specialized_ready),
485
dbus_g_proxy_disconnect_signal (s->proxy, "Error",
486
G_CALLBACK (specialized_error),
491
tumbler_specialized_thumbnailer_proxy_destroyed (DBusGProxy *proxy,
492
TumblerSpecializedThumbnailer *thumbnailer)
494
g_return_if_fail (DBUS_IS_G_PROXY (proxy));
495
g_return_if_fail (TUMBLER_IS_SPECIALIZED_THUMBNAILER (thumbnailer));
497
g_signal_emit_by_name (thumbnailer, "unregister");
503
tumbler_specialized_thumbnailer_new (DBusGConnection *connection,
505
const gchar *object_path,
506
const gchar *const *uri_schemes,
507
const gchar *const *mime_types,
510
TumblerSpecializedThumbnailer *thumbnailer;
512
g_return_val_if_fail (connection != NULL, NULL);
513
g_return_val_if_fail (object_path != NULL && *object_path != '\0', NULL);
514
g_return_val_if_fail (name != NULL && *name != '\0', NULL);
515
g_return_val_if_fail (uri_schemes != NULL, NULL);
516
g_return_val_if_fail (mime_types != NULL, NULL);
518
thumbnailer = g_object_new (TUMBLER_TYPE_SPECIALIZED_THUMBNAILER,
519
"connection", connection, "foreign", FALSE, "name", name,
520
"object-path", object_path, "uri-schemes", uri_schemes,
521
"mime-types", mime_types,
522
"modified", modified, NULL);
524
return TUMBLER_THUMBNAILER (thumbnailer);
530
tumbler_specialized_thumbnailer_new_foreign (DBusGConnection *connection,
532
const gchar *const *uri_schemes,
533
const gchar *const *mime_types)
535
TumblerSpecializedThumbnailer *thumbnailer;
536
GTimeVal current_time;
538
g_return_val_if_fail (connection != NULL, NULL);
539
g_return_val_if_fail (name != NULL, NULL);
540
g_return_val_if_fail (uri_schemes != NULL, NULL);
541
g_return_val_if_fail (mime_types != NULL, NULL);
543
g_get_current_time (¤t_time);
545
thumbnailer = g_object_new (TUMBLER_TYPE_SPECIALIZED_THUMBNAILER,
546
"connection", connection, "foreign", TRUE, "name", name,
547
"uri-schemes", uri_schemes, "mime-types", mime_types,
548
"modified", current_time.tv_sec, NULL);
550
return TUMBLER_THUMBNAILER (thumbnailer);
556
tumbler_specialized_thumbnailer_get_name (TumblerSpecializedThumbnailer *thumbnailer)
558
g_return_val_if_fail (TUMBLER_IS_SPECIALIZED_THUMBNAILER (thumbnailer), FALSE);
559
return thumbnailer->name;
565
tumbler_specialized_thumbnailer_get_foreign (TumblerSpecializedThumbnailer *thumbnailer)
567
g_return_val_if_fail (TUMBLER_IS_SPECIALIZED_THUMBNAILER (thumbnailer), FALSE);
568
return thumbnailer->foreign;
574
tumbler_specialized_thumbnailer_get_modified (TumblerSpecializedThumbnailer *thumbnailer)
576
g_return_val_if_fail (TUMBLER_IS_SPECIALIZED_THUMBNAILER (thumbnailer), 0);
577
return thumbnailer->modified;