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>
31
#include <dbus/dbus.h>
32
#include <dbus/dbus-glib.h>
33
#include <dbus/dbus-glib-lowlevel.h>
35
#include <tumbler/tumbler.h>
37
#include <tumblerd/tumbler-scheduler.h>
38
#include <tumblerd/tumbler-service.h>
39
#include <tumblerd/tumbler-service-dbus-bindings.h>
40
#include <tumblerd/tumbler-lifo-scheduler.h>
41
#include <tumblerd/tumbler-group-scheduler.h>
42
#include <tumblerd/tumbler-utils.h>
46
#define THUMBNAILER_PATH "/org/freedesktop/thumbnails/Thumbnailer1"
47
#define THUMBNAILER_SERVICE "org.freedesktop.thumbnails.Thumbnailer1"
48
#define THUMBNAILER_IFACE "org.freedesktop.thumbnails.Thumbnailer1"
52
/* signal identifiers */
62
/* property identifiers */
72
typedef struct _SchedulerIdleInfo SchedulerIdleInfo;
76
static void tumbler_service_constructed (GObject *object);
77
static void tumbler_service_finalize (GObject *object);
78
static void tumbler_service_get_property (GObject *object,
82
static void tumbler_service_set_property (GObject *object,
86
static void tumbler_service_scheduler_error (TumblerScheduler *scheduler,
88
const gchar *const *failed_uris,
92
TumblerService *service);
93
static void tumbler_service_scheduler_finished (TumblerScheduler *scheduler,
96
TumblerService *service);
97
static void tumbler_service_scheduler_ready (TumblerScheduler *scheduler,
101
TumblerService *service);
102
static void tumbler_service_scheduler_started (TumblerScheduler *scheduler,
105
TumblerService *service);
106
static void tumbler_service_pre_unmount (TumblerService *service,
108
GVolumeMonitor *monitor);
109
static void scheduler_idle_info_free (SchedulerIdleInfo *info);
113
struct _TumblerServiceClass
115
GObjectClass __parent__;
118
struct _TumblerService
122
DBusGConnection *connection;
123
TumblerRegistry *registry;
127
GVolumeMonitor *volume_monitor;
130
struct _SchedulerIdleInfo
132
TumblerScheduler *scheduler;
133
TumblerService *service;
143
static guint tumbler_service_signals[LAST_SIGNAL];
147
G_DEFINE_TYPE (TumblerService, tumbler_service, G_TYPE_OBJECT);
152
tumbler_service_class_init (TumblerServiceClass *klass)
154
GObjectClass *gobject_class;
156
gobject_class = G_OBJECT_CLASS (klass);
157
gobject_class->constructed = tumbler_service_constructed;
158
gobject_class->finalize = tumbler_service_finalize;
159
gobject_class->get_property = tumbler_service_get_property;
160
gobject_class->set_property = tumbler_service_set_property;
162
g_object_class_install_property (gobject_class, PROP_CONNECTION,
163
g_param_spec_pointer ("connection",
167
G_PARAM_CONSTRUCT_ONLY));
169
g_object_class_install_property (gobject_class, PROP_REGISTRY,
170
g_param_spec_object ("registry",
173
TUMBLER_TYPE_REGISTRY,
175
G_PARAM_CONSTRUCT_ONLY));
177
tumbler_service_signals[SIGNAL_ERROR] =
178
g_signal_new ("error",
179
TUMBLER_TYPE_SERVICE,
184
tumbler_marshal_VOID__UINT_POINTER_INT_STRING,
192
tumbler_service_signals[SIGNAL_FINISHED] =
193
g_signal_new ("finished",
194
TUMBLER_TYPE_SERVICE,
199
g_cclosure_marshal_VOID__UINT,
204
tumbler_service_signals[SIGNAL_READY] =
205
g_signal_new ("ready",
206
TUMBLER_TYPE_SERVICE,
211
g_cclosure_marshal_VOID__POINTER,
216
tumbler_service_signals[SIGNAL_STARTED] =
217
g_signal_new ("started",
218
TUMBLER_TYPE_SERVICE,
223
g_cclosure_marshal_VOID__UINT,
232
tumbler_service_init (TumblerService *service)
234
service->mutex = g_mutex_new ();
235
service->schedulers = NULL;
237
service->volume_monitor = g_volume_monitor_get ();
238
g_signal_connect_swapped (service->volume_monitor, "mount-pre-unmount",
239
G_CALLBACK (tumbler_service_pre_unmount), service);
245
tumbler_service_add_scheduler (TumblerService *service,
246
TumblerScheduler *scheduler)
248
/* add the scheduler to the list */
249
service->schedulers = g_list_append (service->schedulers, g_object_ref (scheduler));
251
/* connect to the scheduler signals */
252
g_signal_connect (scheduler, "error",
253
G_CALLBACK (tumbler_service_scheduler_error), service);
254
g_signal_connect (scheduler, "finished",
255
G_CALLBACK (tumbler_service_scheduler_finished), service);
256
g_signal_connect (scheduler, "ready",
257
G_CALLBACK (tumbler_service_scheduler_ready), service);
258
g_signal_connect (scheduler, "started",
259
G_CALLBACK (tumbler_service_scheduler_started), service);
265
tumbler_service_remove_scheduler (TumblerScheduler *scheduler,
266
TumblerService *service)
268
g_return_if_fail (TUMBLER_IS_SCHEDULER (scheduler));
269
g_return_if_fail (TUMBLER_IS_SERVICE (service));
271
g_signal_handlers_disconnect_matched (scheduler, G_SIGNAL_MATCH_DATA,
272
0, 0, NULL, NULL, service);
273
g_object_unref (scheduler);
279
tumbler_service_constructed (GObject *object)
281
TumblerService *service = TUMBLER_SERVICE (object);
282
TumblerScheduler *scheduler;
284
/* chain up to parent classes */
285
if (G_OBJECT_CLASS (tumbler_service_parent_class)->constructed != NULL)
286
(G_OBJECT_CLASS (tumbler_service_parent_class)->constructed) (object);
288
/* create the foreground scheduler */
289
scheduler = tumbler_lifo_scheduler_new ("foreground");
290
tumbler_service_add_scheduler (service, scheduler);
291
g_object_unref (scheduler);
293
/* create the background scheduler */
294
scheduler = tumbler_group_scheduler_new ("background");
295
tumbler_service_add_scheduler (service, scheduler);
296
g_object_unref (scheduler);
302
tumbler_service_finalize (GObject *object)
304
TumblerService *service = TUMBLER_SERVICE (object);
306
/* disconnect from the volume monitor */
307
g_signal_handlers_disconnect_matched (service->volume_monitor, G_SIGNAL_MATCH_DATA,
308
0, 0, NULL, NULL, service);
310
/* release the volume monitor */
311
g_object_unref (service->volume_monitor);
313
/* release all schedulers and the scheduler list */
314
g_list_foreach (service->schedulers, (GFunc) tumbler_service_remove_scheduler, service);
315
g_list_free (service->schedulers);
317
/* release the reference on the thumbnailer registry */
318
g_object_unref (service->registry);
320
dbus_g_connection_unref (service->connection);
322
g_mutex_free (service->mutex);
324
(*G_OBJECT_CLASS (tumbler_service_parent_class)->finalize) (object);
330
tumbler_service_get_property (GObject *object,
335
TumblerService *service = TUMBLER_SERVICE (object);
339
case PROP_CONNECTION:
340
g_value_set_pointer (value, service->connection);
343
g_value_set_object (value, service->registry);
346
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
354
tumbler_service_set_property (GObject *object,
359
TumblerService *service = TUMBLER_SERVICE (object);
363
case PROP_CONNECTION:
364
service->connection = dbus_g_connection_ref (g_value_get_pointer (value));
367
service->registry = g_value_dup_object (value);
370
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
378
tumbler_service_error_idle (gpointer user_data)
380
SchedulerIdleInfo *info = user_data;
381
DBusMessageIter iter;
382
DBusMessageIter strv_iter;
383
DBusMessage *message;
386
g_return_val_if_fail (info != NULL, FALSE);
387
g_return_val_if_fail (TUMBLER_IS_SCHEDULER (info->scheduler), FALSE);
388
g_return_val_if_fail (info->uris != NULL && info->uris[0] != NULL && *info->uris[0] != '\0', FALSE);
389
g_return_val_if_fail (info->message != NULL && *info->message != '\0', FALSE);
390
g_return_val_if_fail (info->origin != NULL && *info->origin != '\0', FALSE);
391
g_return_val_if_fail (TUMBLER_IS_SERVICE (info->service), FALSE);
393
/* create a D-Bus message for the error signal */
394
message = dbus_message_new_signal (THUMBNAILER_PATH, THUMBNAILER_IFACE, "Error");
396
/* define the destination (the thumbnailer client) if possible */
398
dbus_message_set_destination (message, info->origin);
400
/* append the request handle */
401
dbus_message_iter_init_append (message, &iter);
402
dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT32, &info->handle);
404
/* start the URI string array */
405
dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY,
406
DBUS_TYPE_STRING_AS_STRING, &strv_iter);
408
/* insert all failed URIs into the array */
409
for (n = 0; info->uris[n] != NULL; n++)
410
dbus_message_iter_append_basic (&strv_iter, DBUS_TYPE_STRING, &info->uris[n]);
412
/* finish the URI string array */
413
dbus_message_iter_close_container (&iter, &strv_iter);
415
/* append the error code and error message */
416
dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &info->error_code);
417
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &info->message);
419
/* send the signal message over D-Bus */
420
dbus_connection_send (dbus_g_connection_get_connection (info->service->connection),
423
/* free the allocated D-Bus message */
424
dbus_message_unref (message);
426
scheduler_idle_info_free (info);
434
tumbler_service_scheduler_error (TumblerScheduler *scheduler,
436
const gchar *const *failed_uris,
438
const gchar *message,
440
TumblerService *service)
442
SchedulerIdleInfo *info;
444
g_return_if_fail (TUMBLER_IS_SCHEDULER (scheduler));
445
g_return_if_fail (failed_uris != NULL);
446
g_return_if_fail (message != NULL && *message != '\0');
447
g_return_if_fail (origin != NULL && *origin != '\0');
448
g_return_if_fail (TUMBLER_IS_SERVICE (service));
450
info = g_slice_new0 (SchedulerIdleInfo);
452
info->scheduler = g_object_ref (scheduler);
453
info->handle = handle;
454
info->uris = g_strdupv ((GStrv) failed_uris);
455
info->error_code = error_code;
456
info->message = g_strdup (message);
457
info->origin = g_strdup (origin);
458
info->service = g_object_ref (service);
460
g_idle_add (tumbler_service_error_idle, info);
466
tumbler_service_finished_idle (gpointer user_data)
468
SchedulerIdleInfo *info = user_data;
469
DBusMessageIter iter;
470
DBusMessage *message;
472
g_return_val_if_fail (info != NULL, FALSE);
473
g_return_val_if_fail (info->origin != NULL && *info->origin != '\0', FALSE);
474
g_return_val_if_fail (TUMBLER_IS_SERVICE (info->service), FALSE);
476
/* create a D-Bus message for the finished signal */
477
message = dbus_message_new_signal (THUMBNAILER_PATH, THUMBNAILER_IFACE, "Finished");
479
/* define the destination (the thumbnailer client) if possible */
481
dbus_message_set_destination (message, info->origin);
483
/* append the request handle */
484
dbus_message_iter_init_append (message, &iter);
485
dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT32, &info->handle);
487
/* send the signal message over D-Bus */
488
dbus_connection_send (dbus_g_connection_get_connection (info->service->connection),
491
/* free the allocated D-Bus message */
492
dbus_message_unref (message);
494
scheduler_idle_info_free (info);
502
tumbler_service_scheduler_finished (TumblerScheduler *scheduler,
505
TumblerService *service)
507
SchedulerIdleInfo *info;
509
g_return_if_fail (TUMBLER_IS_SCHEDULER (scheduler));
510
g_return_if_fail (origin != NULL && *origin != '\0');
511
g_return_if_fail (TUMBLER_IS_SERVICE (service));
513
info = g_slice_new0 (SchedulerIdleInfo);
515
info->scheduler = g_object_ref (scheduler);
516
info->handle = handle;
517
info->origin = g_strdup (origin);
518
info->service = g_object_ref (service);
520
g_idle_add (tumbler_service_finished_idle, info);
526
tumbler_service_ready_idle (gpointer user_data)
528
SchedulerIdleInfo *info = user_data;
529
DBusMessageIter iter;
530
DBusMessageIter strv_iter;
531
DBusMessage *message;
534
g_return_val_if_fail (info != NULL, FALSE);
535
g_return_val_if_fail (TUMBLER_IS_SCHEDULER (info->scheduler), FALSE);
536
g_return_val_if_fail (info->uris != NULL && info->uris[0] != NULL && *info->uris[0] != '\0', FALSE);
537
g_return_val_if_fail (info->origin != NULL && *info->origin != '\0', FALSE);
538
g_return_val_if_fail (TUMBLER_IS_SERVICE (info->service), FALSE);
540
/* create a D-Bus message for the ready signal */
541
message = dbus_message_new_signal (THUMBNAILER_PATH, THUMBNAILER_IFACE, "Ready");
543
/* define the destination (the thumbnailer client) if possible */
545
dbus_message_set_destination (message, info->origin);
547
dbus_message_iter_init_append (message, &iter);
549
/* append the request handle */
550
dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT32, &info->handle);
552
/* start the URI string array */
553
dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY,
554
DBUS_TYPE_STRING_AS_STRING, &strv_iter);
556
/* insert all URIs into the array for which we have thumbnails now */
557
for (n = 0; info->uris[n] != NULL; n++)
558
dbus_message_iter_append_basic (&strv_iter, DBUS_TYPE_STRING, &info->uris[n]);
560
/* finish the URI string array */
561
dbus_message_iter_close_container (&iter, &strv_iter);
563
/* send the signal message over D-Bus */
564
dbus_connection_send (dbus_g_connection_get_connection (info->service->connection),
567
/* free the allocated D-Bus message */
568
dbus_message_unref (message);
570
scheduler_idle_info_free (info);
578
tumbler_service_scheduler_ready (TumblerScheduler *scheduler,
582
TumblerService *service)
584
SchedulerIdleInfo *info;
586
g_return_if_fail (TUMBLER_IS_SCHEDULER (scheduler));
587
g_return_if_fail (origin != NULL && *origin != '\0');
588
g_return_if_fail (uris != NULL && uris[0] != NULL && *uris[0] != '\0');
589
g_return_if_fail (TUMBLER_IS_SERVICE (service));
591
info = g_slice_new0 (SchedulerIdleInfo);
593
info->scheduler = g_object_ref (scheduler);
594
info->handle = handle;
595
info->uris = g_strdupv ((GStrv) uris);
596
info->origin = g_strdup (origin);
597
info->service = g_object_ref (service);
599
g_idle_add (tumbler_service_ready_idle, info);
605
tumbler_service_started_idle (gpointer user_data)
607
SchedulerIdleInfo *info = user_data;
608
DBusMessageIter iter;
609
DBusMessage *message;
611
g_return_val_if_fail (info != NULL, FALSE);
612
g_return_val_if_fail (TUMBLER_IS_SCHEDULER (info->scheduler), FALSE);
613
g_return_val_if_fail (info->origin != NULL && *info->origin != '\0', FALSE);
614
g_return_val_if_fail (TUMBLER_IS_SERVICE (info->service), FALSE);
616
/* create a D-Bus message for the started signal */
617
message = dbus_message_new_signal (THUMBNAILER_PATH, THUMBNAILER_IFACE, "Started");
619
/* define the destination (the thumbnailer client) if possible */
621
dbus_message_set_destination (message, info->origin);
623
/* append the request handle */
624
dbus_message_iter_init_append (message, &iter);
625
dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT32, &info->handle);
627
/* send the signal message over D-Bus */
628
dbus_connection_send (dbus_g_connection_get_connection (info->service->connection),
631
/* free the allocated D-Bus message */
632
dbus_message_unref (message);
634
scheduler_idle_info_free (info);
642
tumbler_service_scheduler_started (TumblerScheduler *scheduler,
645
TumblerService *service)
647
SchedulerIdleInfo *info;
649
g_return_if_fail (TUMBLER_IS_SCHEDULER (scheduler));
650
g_return_if_fail (origin != NULL && *origin != '\0');
651
g_return_if_fail (TUMBLER_IS_SERVICE (service));
653
info = g_slice_new0 (SchedulerIdleInfo);
655
info->scheduler = g_object_ref (scheduler);
656
info->handle = handle;
657
info->origin = g_strdup (origin);
658
info->service = g_object_ref (service);
660
g_idle_add (tumbler_service_started_idle, info);
666
tumbler_service_pre_unmount (TumblerService *service,
668
GVolumeMonitor *volume_monitor)
672
g_return_if_fail (TUMBLER_IS_SERVICE (service));
673
g_return_if_fail (G_IS_MOUNT (mount));
674
g_return_if_fail (volume_monitor == service->volume_monitor);
676
g_mutex_lock (service->mutex);
678
/* iterate over all schedulers, cancelling URIs belonging to the mount */
679
for (iter = service->schedulers; iter != NULL; iter = iter->next)
680
tumbler_scheduler_cancel_by_mount (iter->data, mount);
682
g_mutex_unlock (service->mutex);
688
scheduler_idle_info_free (SchedulerIdleInfo *info)
693
g_free (info->message);
694
g_free (info->origin);
695
g_strfreev (info->uris);
697
g_object_unref (info->scheduler);
698
g_object_unref (info->service);
700
g_slice_free (SchedulerIdleInfo, info);
706
tumbler_service_new (DBusGConnection *connection,
707
TumblerRegistry *registry)
709
return g_object_new (TUMBLER_TYPE_SERVICE, "connection", connection,
710
"registry", registry, NULL);
716
tumbler_service_start (TumblerService *service,
719
DBusConnection *connection;
720
DBusError dbus_error;
723
g_return_val_if_fail (TUMBLER_IS_SERVICE (service), FALSE);
724
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
726
g_mutex_lock (service->mutex);
728
dbus_error_init (&dbus_error);
730
/* get the native D-Bus connection */
731
connection = dbus_g_connection_get_connection (service->connection);
733
/* request ownership for the generic thumbnailer interface */
734
result = dbus_bus_request_name (connection, THUMBNAILER_SERVICE,
735
DBUS_NAME_FLAG_DO_NOT_QUEUE, &dbus_error);
737
/* check if that failed */
738
if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
740
/* propagate the D-Bus error */
741
if (dbus_error_is_set (&dbus_error))
744
dbus_set_g_error (error, &dbus_error);
746
dbus_error_free (&dbus_error);
748
else if (error != NULL)
750
g_set_error (error, DBUS_GERROR, DBUS_GERROR_FAILED,
751
_("Another generic thumbnailer is already running"));
754
g_mutex_unlock (service->mutex);
759
/* everything is fine, install the generic thumbnailer D-Bus info */
760
dbus_g_object_type_install_info (G_OBJECT_TYPE (service),
761
&dbus_glib_tumbler_service_object_info);
763
/* register the service instance as a handler of this interface */
764
dbus_g_connection_register_g_object (service->connection,
768
g_mutex_unlock (service->mutex);
776
tumbler_service_queue (TumblerService *service,
777
const gchar *const *uris,
778
const gchar *const *mime_hints,
779
const gchar *flavor_name,
780
const gchar *scheduler_name,
781
guint handle_to_dequeue,
782
DBusGMethodInvocation *context)
784
TumblerSchedulerRequest *scheduler_request;
785
TumblerThumbnailFlavor *flavor;
786
TumblerThumbnailer **thumbnailers;
787
TumblerScheduler *scheduler = NULL;
788
TumblerFileInfo **infos;
796
dbus_async_return_if_fail (TUMBLER_IS_SERVICE (service), context);
797
dbus_async_return_if_fail (uris != NULL, context);
798
dbus_async_return_if_fail (mime_hints != NULL, context);
800
/* if the scheduler is not defined, fall back to "default" */
801
if (scheduler_name == NULL || *scheduler_name == '\0')
802
scheduler_name = "default";
804
g_mutex_lock (service->mutex);
806
cache = tumbler_cache_get_default ();
807
flavor = tumbler_cache_get_flavor (cache, flavor_name);
808
g_object_unref (cache);
810
g_assert (TUMBLER_IS_CACHE (cache));
812
infos = tumbler_file_info_array_new_with_flavor (uris, mime_hints, flavor,
815
/* get an array with one thumbnailer for each URI in the request */
816
thumbnailers = tumbler_registry_get_thumbnailer_array (service->registry, infos,
819
origin = dbus_g_method_get_sender (context);
821
/* allocate a scheduler request */
822
scheduler_request = tumbler_scheduler_request_new (infos, thumbnailers,
825
/* release the file info array */
826
tumbler_file_info_array_free (infos);
830
/* get the request handle */
831
handle = scheduler_request->handle;
833
/* iterate over all schedulers */
834
for (iter = service->schedulers; iter != NULL; iter = iter->next)
836
/* dequeue the request with the given dequeue handle, in case this
837
* scheduler is responsible for the given handle */
838
if (handle_to_dequeue != 0)
839
tumbler_scheduler_dequeue (TUMBLER_SCHEDULER (iter->data), handle_to_dequeue);
841
/* determine the scheduler name */
842
name = tumbler_scheduler_get_name (TUMBLER_SCHEDULER (iter->data));
844
/* check if this is the scheduler we are looking for */
845
if (g_strcmp0 (name, scheduler_name) == 0)
846
scheduler = TUMBLER_SCHEDULER (iter->data);
848
/* free the scheduler name */
852
/* default to the first scheduler in the list if we couldn't find
853
* the scheduler with the desired name */
854
if (scheduler == NULL)
855
scheduler = TUMBLER_SCHEDULER (service->schedulers->data);
857
/* report unsupported flavors back to the client */
860
/* fake a started signal */
861
tumbler_service_scheduler_started (scheduler, handle, scheduler_request->origin,
864
/* emit an error signal */
865
tumbler_service_scheduler_error (scheduler, handle, uris,
866
TUMBLER_ERROR_UNSUPPORTED_FLAVOR,
867
_("Unsupported thumbnail flavor requested"),
868
scheduler_request->origin,
871
/* fake a finished signal */
872
tumbler_service_scheduler_finished (scheduler, handle, scheduler_request->origin,
875
/* release the request */
876
tumbler_scheduler_request_free (scheduler_request);
880
/* let the scheduler take it from here */
881
tumbler_scheduler_push (scheduler, scheduler_request);
884
/* free the thumbnailer array */
885
tumbler_thumbnailer_array_free (thumbnailers, length);
887
g_mutex_unlock (service->mutex);
889
dbus_g_method_return (context, handle);
895
tumbler_service_dequeue (TumblerService *service,
897
DBusGMethodInvocation *context)
901
dbus_async_return_if_fail (TUMBLER_IS_SERVICE (service), context);
903
g_mutex_lock (service->mutex);
907
/* iterate over all available schedulers */
908
for (iter = service->schedulers; iter != NULL; iter = iter->next)
910
/* dequeue the request with the given dequeue handle, in case this
911
* scheduler is responsible for the given handle */
912
tumbler_scheduler_dequeue (TUMBLER_SCHEDULER (iter->data), handle);
916
g_mutex_unlock (service->mutex);
918
dbus_g_method_return (context);
924
tumbler_service_get_supported (TumblerService *service,
925
DBusGMethodInvocation *context)
927
const gchar *const *uri_schemes;
928
const gchar *const *mime_types;
930
dbus_async_return_if_fail (TUMBLER_IS_SERVICE (service), context);
932
g_mutex_lock (service->mutex);
934
/* fetch all supported URI scheme / MIME type pairs from the registry */
935
tumbler_registry_get_supported (service->registry, &uri_schemes, &mime_types);
937
g_mutex_unlock (service->mutex);
939
/* return the arrays to the caller */
940
dbus_g_method_return (context, uri_schemes, mime_types);
946
tumbler_service_get_flavors (TumblerService *service,
947
DBusGMethodInvocation *context)
950
const gchar **flavor_strings;
955
cache = tumbler_cache_get_default ();
959
flavors = tumbler_cache_get_flavors (cache);
960
flavor_strings = g_new0 (const gchar *, g_list_length (flavors) + 1);
962
for (iter = flavors, n = 0; iter != NULL; iter = iter->next, ++n)
963
flavor_strings[n] = tumbler_thumbnail_flavor_get_name (iter->data);
964
flavor_strings[n] = NULL;
966
dbus_g_method_return (context, flavor_strings);
968
g_free (flavor_strings);
970
g_list_foreach (flavors, (GFunc) g_object_unref, NULL);
971
g_list_free (flavors);
973
g_object_unref (cache);
977
flavor_strings = g_new0 (const gchar *, 1);
978
flavor_strings[0] = NULL;
980
dbus_g_method_return (context, flavor_strings);
982
g_free (flavor_strings);
988
tumbler_service_get_schedulers (TumblerService *service,
989
DBusGMethodInvocation *context)
991
GStrv supported_schedulers;
995
dbus_async_return_if_fail (TUMBLER_IS_SERVICE (service), context);
997
g_mutex_lock (service->mutex);
999
/* allocate an error for the schedulers */
1000
supported_schedulers = g_new0 (gchar *, g_list_length (service->schedulers) + 2);
1002
/* always prepend the "default" scheduler */
1003
supported_schedulers[n++] = g_strdup ("default");
1005
/* append all supported scheduler names */
1006
for (iter = service->schedulers; iter != NULL; iter = iter->next)
1008
supported_schedulers[n++] =
1009
tumbler_scheduler_get_name (TUMBLER_SCHEDULER (iter->data));
1012
g_mutex_unlock (service->mutex);
1014
/* NULL-terminate the array */
1015
supported_schedulers[n] = NULL;
1017
/* return the scheduler array to the caller */
1018
dbus_g_method_return (context, supported_schedulers);
1020
/* free the array */
1021
g_strfreev (supported_schedulers);