[maemo-commits] [maemo-commits] r16213 - in projects/haf/trunk/hildon-thumbnail: . daemon daemon/plugins debian thumbs
From: subversion at stage.maemo.org subversion at stage.maemo.orgDate: Wed Sep 24 17:42:36 EEST 2008
- Previous message: [maemo-commits] r16212 - projects/haf/branches/hildon-thumbnail/daemonize/thumbs
- Next message: [maemo-commits] r16214 - projects/haf/branches/hildon-thumbnail/daemonize/daemon
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Author: marivoll Date: 2008-09-24 17:42:35 +0300 (Wed, 24 Sep 2008) New Revision: 16213 Modified: projects/haf/trunk/hildon-thumbnail/ChangeLog projects/haf/trunk/hildon-thumbnail/daemon/hildon-thumbnail-daemon.c projects/haf/trunk/hildon-thumbnail/daemon/manager.c projects/haf/trunk/hildon-thumbnail/daemon/plugin-runner.c projects/haf/trunk/hildon-thumbnail/daemon/plugins/exec-plugin.c projects/haf/trunk/hildon-thumbnail/daemon/plugins/gdkpixbuf-plugin.c projects/haf/trunk/hildon-thumbnail/daemon/plugins/gstreamer-video-plugin.c projects/haf/trunk/hildon-thumbnail/daemon/thumbnailer.c projects/haf/trunk/hildon-thumbnail/debian/changelog projects/haf/trunk/hildon-thumbnail/thumbs/hildon-thumbnail-factory.c Log: Merged daemonize branch. [ Philip Van Hoof ] * Completed API in the daemon. * Monitor plugin directory. * Avoid D-Bus roundtrip for existing thumbnails when using the HildonThumbnailFactory API. * Handle large requests in a separate thread so that small requests are not starved. Modified: projects/haf/trunk/hildon-thumbnail/ChangeLog =================================================================== --- projects/haf/trunk/hildon-thumbnail/ChangeLog 2008-09-24 13:48:05 UTC (rev 16212) +++ projects/haf/trunk/hildon-thumbnail/ChangeLog 2008-09-24 14:42:35 UTC (rev 16213) @@ -1,5 +1,44 @@ +2008-09-24 Philip Van Hoof <pvanhoof at gnome.org> + + * thumbs/hildon-thumbnail-factory.c: Performance improvement when a + thumbnail already exists (avoiding a dbus call) + +2008-09-23 Philip Van Hoof <pvanhoof at gnome.org> + + * daemon/manager.c: Fixed a crash + +2008-09-23 Philip Van Hoof <pvanhoof at gnome.org> + + * daemon/thumbnailer.c: Adding a thread for large tasks + +2008-09-20 Philip Van Hoof <pvanhoof at gnome.org> + + * thumbs/hildon-thumbnail-factory.c + * daemon/plugin-runner.c + * daemon/manager.c + * daemon/thumbnailer.c: Various comments and leak fixes + +2008-09-18 Philip Van Hoof <pvanhoof at gnome.org> + + * daemon/hildon-thumbnail-daemon.c: File monitoring the plugins + + * daemon/hildon-thumbnail-daemon.c + * daemon/manager.c: Using the right kinds of file monitors (dir monitors) + 2008-09-17 Philip Van Hoof <pvanhoof at gnome.org> + * daemon/plugins/gdkpixbuf-plugin.c: + * daemon/plugins/exec-plugin.c: + * daemon/plugins/gstreamer-video-plugin.c: Fixed memory leaks when errors occur + + * daemon/thumbnailer.c: Implemented the move, copy, delete hint handlers + +2008-09-17 Marius Vollmer <marius.vollmer at nokia.com> + + Released 3.0.0 + +2008-09-17 Philip Van Hoof <pvanhoof at gnome.org> + * daemon/plugins/exec-plugin.c * daemon/manager.c: Respecting the override file Modified: projects/haf/trunk/hildon-thumbnail/daemon/hildon-thumbnail-daemon.c =================================================================== --- projects/haf/trunk/hildon-thumbnail/daemon/hildon-thumbnail-daemon.c 2008-09-24 13:48:05 UTC (rev 16212) +++ projects/haf/trunk/hildon-thumbnail/daemon/hildon-thumbnail-daemon.c 2008-09-24 14:42:35 UTC (rev 16213) @@ -25,12 +25,14 @@ #include <glib.h> #include <dbus/dbus-glib-bindings.h> +#include <gio/gio.h> #include "hildon-thumbnail-plugin.h" #include "thumbnailer.h" #include "manager.h" +static GHashTable *registrations; static gboolean do_shut_down_next_time = TRUE; void @@ -54,11 +56,117 @@ return shut; } + +static GHashTable* +init_plugins (DBusGConnection *connection, Thumbnailer *thumbnailer) +{ + GHashTable *regs; + GModule *module; + GError *error = NULL; + GDir *dir; + const gchar *plugin; + + regs = g_hash_table_new_full (g_str_hash, g_str_equal, + (GDestroyNotify) g_free, + (GDestroyNotify) NULL); + + + /* TODO: Monitor this directory for plugin removals and additions */ + + dir = g_dir_open (PLUGINS_DIR, 0, &error); + + if (dir) { + while ((plugin = g_dir_read_name (dir)) != NULL) { + gboolean cropping; + + if (!g_str_has_suffix (plugin, "." G_MODULE_SUFFIX)) { + continue; + } + + module = hildon_thumbnail_plugin_load (plugin); + hildon_thumbnail_plugin_do_init (module, &cropping, + (register_func) thumbnailer_register_plugin, + thumbnailer, + &error); + if (error) { + g_warning ("Can't load plugin [%s]: %s\n", plugin, + error->message); + g_error_free (error); + } else + g_hash_table_replace (regs, g_strdup (plugin), + module); + } + g_dir_close (dir); + } + + return regs; +} + +static void +stop_plugins (GHashTable *regs, Thumbnailer *thumbnailer) +{ + GHashTableIter iter; + gpointer key, value; + + g_hash_table_iter_init (&iter, regs); + + while (g_hash_table_iter_next (&iter, &key, &value)) { + thumbnailer_unregister_plugin (thumbnailer, value); + hildon_thumbnail_plugin_do_stop (value); + } +} + + +static void +on_plugin_changed (GFileMonitor *monitor, GFile *file, GFile *other_file, GFileMonitorEvent event_type, gpointer user_data) +{ + Thumbnailer *thumbnailer = user_data; + GModule *module = NULL; + gchar *path = g_file_get_path (other_file); + + if (path) { + switch (event_type) { + case G_FILE_MONITOR_EVENT_DELETED: { + GModule *module = g_hash_table_lookup (registrations, path); + if (module) { + thumbnailer_unregister_plugin (thumbnailer, module); + hildon_thumbnail_plugin_do_stop (module); + } + } + case G_FILE_MONITOR_EVENT_CREATED: { + GModule *module = hildon_thumbnail_plugin_load (path); + gboolean cropping = FALSE; + + if (module) { + GError *error = NULL; + + hildon_thumbnail_plugin_do_init (module, &cropping, + (register_func) thumbnailer_register_plugin, + thumbnailer, + &error); + if (error) { + g_warning ("Can't load plugin [%s]: %s\n", path, + error->message); + g_error_free (error); + } else + g_hash_table_replace (registrations, g_strdup (path), + module); + } + } + break; + default: + break; + } + } + + g_free (path); +} + + int main (int argc, char **argv) { DBusGConnection *connection; - GModule *module; GError *error = NULL; g_type_init (); @@ -77,12 +185,8 @@ Manager *manager; Thumbnailer *thumbnailer; DBusGProxy *manager_proxy; - gboolean cropping; - GDir *dir; - const gchar *plugin; - GHashTable *registrations; - GHashTableIter iter; - gpointer key, value; + GFile *file; + GFileMonitor *monitor; manager_do_init (connection, &manager, &error); thumbnailer_do_init (connection, manager, &thumbnailer, &error); @@ -92,32 +196,13 @@ MANAGER_PATH, MANAGER_INTERFACE); - registrations = g_hash_table_new_full (g_str_hash, g_str_equal, - (GDestroyNotify) g_free, - (GDestroyNotify) NULL); + registrations = init_plugins (connection, thumbnailer); - /* TODO: Monitor this directory for plugin removals and additions */ - - dir = g_dir_open (PLUGINS_DIR, 0, &error); + file = g_file_new_for_path (PLUGINS_DIR); + monitor = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, NULL, NULL); + g_signal_connect (G_OBJECT (monitor), "changed", + G_CALLBACK (on_plugin_changed), thumbnailer); - if (dir) { - while ((plugin = g_dir_read_name (dir)) != NULL) { - - if (!g_str_has_suffix (plugin, "." G_MODULE_SUFFIX)) { - continue; - } - - module = hildon_thumbnail_plugin_load (plugin); - hildon_thumbnail_plugin_do_init (module, &cropping, - (register_func) thumbnailer_register_plugin, - thumbnailer, - &error); - g_hash_table_replace (registrations, g_strdup (plugin), - module); - } - g_dir_close (dir); - } - main_loop = g_main_loop_new (NULL, FALSE); g_timeout_add_seconds (600, @@ -126,12 +211,10 @@ g_main_loop_run (main_loop); - g_hash_table_iter_init (&iter, registrations); + g_object_unref (monitor); + g_object_unref (file); - while (g_hash_table_iter_next (&iter, &key, &value)) { - thumbnailer_unregister_plugin (thumbnailer, value); - hildon_thumbnail_plugin_do_stop (value); - } + stop_plugins (registrations, thumbnailer); g_hash_table_unref (registrations); Modified: projects/haf/trunk/hildon-thumbnail/daemon/manager.c =================================================================== --- projects/haf/trunk/hildon-thumbnail/daemon/manager.c 2008-09-24 13:48:05 UTC (rev 16212) +++ projects/haf/trunk/hildon-thumbnail/daemon/manager.c 2008-09-24 14:42:35 UTC (rev 16213) @@ -32,6 +32,9 @@ #include "dbus-utils.h" #include "thumbnailer.h" +static GFile *homedir, *thumbdir; +static GFileMonitor *homemon, *thumbmon; + #define MANAGER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TYPE_MANAGER, ManagerPrivate)) G_DEFINE_TYPE (Manager, manager, G_TYPE_OBJECT) @@ -325,7 +328,7 @@ gchar *path = g_file_get_path (file); gboolean override = (strcmp (THUMBNAILERS_DIR, path) == 0); - /* We override when it's the one in the user's homedir*/ + /* We override when it's the dir in the user's homedir*/ manager_check_dir (MANAGER (user_data), path, override); g_free (path); @@ -341,7 +344,6 @@ { ManagerPrivate *priv = MANAGER_GET_PRIVATE (object); GFileMonitor *monitor; - GFile *file; gchar *home_thumbnlrs = g_build_filename (g_get_user_data_dir (), "thumbnailers", NULL); @@ -353,25 +355,19 @@ manager_check_dir (object, home_thumbnlrs, TRUE); /* Monitor the dir for changes */ - file = g_file_new_for_path (home_thumbnlrs); - monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, NULL, NULL); - g_signal_connect (G_OBJECT (monitor), "changed", + homedir = g_file_new_for_path (home_thumbnlrs); + homemon = g_file_monitor_directory (homedir, G_FILE_MONITOR_NONE, NULL, NULL); + g_signal_connect (G_OBJECT (homemon), "changed", G_CALLBACK (on_dir_changed), NULL); - // g_object_unref (file) - // g_object_unref (monitor) - /* Monitor the dir for changes */ - file = g_file_new_for_path (THUMBNAILERS_DIR); - monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, NULL, NULL); - g_signal_connect (G_OBJECT (monitor), "changed", + thumbdir = g_file_new_for_path (THUMBNAILERS_DIR); + thumbmon = g_file_monitor_directory (thumbdir, G_FILE_MONITOR_NONE, NULL, NULL); + g_signal_connect (G_OBJECT (thumbmon), "changed", G_CALLBACK (on_dir_changed), NULL); g_mutex_unlock (priv->mutex); - // g_object_unref (file) - // g_object_unref (monitor) - g_free (home_thumbnlrs); } @@ -600,6 +596,10 @@ void manager_do_stop (void) { + g_object_unref (homemon); + g_object_unref (thumbmon); + g_object_unref (homedir); + g_object_unref (thumbdir); } void Modified: projects/haf/trunk/hildon-thumbnail/daemon/plugin-runner.c =================================================================== --- projects/haf/trunk/hildon-thumbnail/daemon/plugin-runner.c 2008-09-24 13:48:05 UTC (rev 16212) +++ projects/haf/trunk/hildon-thumbnail/daemon/plugin-runner.c 2008-09-24 14:42:35 UTC (rev 16213) @@ -67,11 +67,38 @@ #define plugin_runner_create daemon_create + +static gboolean do_shut_down_next_time = TRUE; + +static void +keep_alive (void) +{ + do_shut_down_next_time = FALSE; +} + +static gboolean +shut_down_after_timeout (gpointer user_data) +{ + GMainLoop *main_loop = user_data; + gboolean shut = FALSE; + + if (do_shut_down_next_time) { + g_main_loop_quit (main_loop); + shut = TRUE; + } else + do_shut_down_next_time = TRUE; + + return shut; +} + void daemon_create (Daemon *object, GStrv uris, DBusGMethodInvocation *context) { DaemonPrivate *priv = DAEMON_GET_PRIVATE (object); GError *error = NULL; + + keep_alive (); + hildon_thumbnail_plugin_do_create (priv->module, uris, &error); if (error) { dbus_g_method_return_error (context, error); @@ -230,6 +257,7 @@ static gboolean dynamic_register = FALSE; static gchar *bus_name; static gchar *bus_path; +static gint timeout = 600; static GOptionEntry entries_daemon[] = { { "module-name", 'm', G_OPTION_FLAG_REVERSE|G_OPTION_FLAG_OPTIONAL_ARG, @@ -240,6 +268,10 @@ G_OPTION_ARG_STRING, &bus_name, "Busname to use (eg. com.company.Thumbnailer) ", NULL }, + { "timeout", 't', 0, + G_OPTION_ARG_INT, &timeout, + "Timeout before the specialized thumbnailer dies (use -1 for inlimited)", + NULL }, { "bus-path", 'p', 0, G_OPTION_ARG_STRING, &bus_path, "Buspath to use (eg. /com/company/Thumbnailer) ", @@ -316,6 +348,11 @@ daemon_start (DAEMON (object), dynamic_register); + if (timeout > -1) + g_timeout_add_seconds (timeout, + shut_down_after_timeout, + main_loop); + main_loop = g_main_loop_new (NULL, FALSE); g_main_loop_run (main_loop); Modified: projects/haf/trunk/hildon-thumbnail/daemon/plugins/exec-plugin.c =================================================================== --- projects/haf/trunk/hildon-thumbnail/daemon/plugins/exec-plugin.c 2008-09-24 13:48:05 UTC (rev 16212) +++ projects/haf/trunk/hildon-thumbnail/daemon/plugins/exec-plugin.c 2008-09-24 14:42:35 UTC (rev 16213) @@ -293,15 +293,17 @@ g_free (r_exec); -// TODO -// if (on_error) { -// if (!errors) -// errors = g_string_new (""); -// g_string_append_printf (errors, "error msg") -// } + nerror_handler: - nerror_handler: + if (nerror) { + if (!errors) + errors = g_string_new (""); + g_string_append_printf (errors, "[`%s': %s] ", + uri, nerror->message); + g_error_free (nerror); + nerror = NULL; + } if (file) g_object_unref (file); Modified: projects/haf/trunk/hildon-thumbnail/daemon/plugins/gdkpixbuf-plugin.c =================================================================== --- projects/haf/trunk/hildon-thumbnail/daemon/plugins/gdkpixbuf-plugin.c 2008-09-24 13:48:05 UTC (rev 16212) +++ projects/haf/trunk/hildon-thumbnail/daemon/plugins/gdkpixbuf-plugin.c 2008-09-24 14:42:35 UTC (rev 16213) @@ -333,8 +333,9 @@ if (!errors) errors = g_string_new (""); g_string_append_printf (errors, "[`%s': %s] ", - uri, - nerror->message); + uri, nerror->message); + g_error_free (nerror); + nerror = NULL; } if (stream) Modified: projects/haf/trunk/hildon-thumbnail/daemon/plugins/gstreamer-video-plugin.c =================================================================== --- projects/haf/trunk/hildon-thumbnail/daemon/plugins/gstreamer-video-plugin.c 2008-09-24 13:48:05 UTC (rev 16212) +++ projects/haf/trunk/hildon-thumbnail/daemon/plugins/gstreamer-video-plugin.c 2008-09-24 14:42:35 UTC (rev 16213) @@ -460,8 +460,9 @@ if (!errors) errors = g_string_new (""); g_string_append_printf (errors, "[`%s': %s] ", - uris[i], - nerror->message); + uris[i], nerror->message); + g_error_free (nerror); + nerror = NULL; } g_free (large); Modified: projects/haf/trunk/hildon-thumbnail/daemon/thumbnailer.c =================================================================== --- projects/haf/trunk/hildon-thumbnail/daemon/thumbnailer.c 2008-09-24 13:48:05 UTC (rev 16212) +++ projects/haf/trunk/hildon-thumbnail/daemon/thumbnailer.c 2008-09-24 14:42:35 UTC (rev 16213) @@ -39,6 +39,9 @@ #include "dbus-utils.h" #include "utils.h" +#define THUMB_ERROR_DOMAIN "HildonThumbnailer" +#define THUMB_ERROR g_quark_from_static_string (THUMB_ERROR_DOMAIN) + #define THUMBNAILER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TYPE_THUMBNAILER, ThumbnailerPrivate)) G_DEFINE_TYPE (Thumbnailer, thumbnailer, G_TYPE_OBJECT) @@ -49,7 +52,8 @@ typedef struct { Manager *manager; GHashTable *plugins; - GThreadPool *pool; + GThreadPool *large_pool; + GThreadPool *normal_pool; GMutex *mutex; GList *tasks; } ThumbnailerPrivate; @@ -74,11 +78,12 @@ { ThumbnailerPrivate *priv = THUMBNAILER_GET_PRIVATE (object); + g_mutex_lock (priv->mutex); g_hash_table_insert (priv->plugins, g_strdup (mime_type), plugin); manager_i_have (priv->manager, mime_type); - + g_mutex_unlock (priv->mutex); } static gboolean @@ -94,9 +99,11 @@ { ThumbnailerPrivate *priv = THUMBNAILER_GET_PRIVATE (object); + g_mutex_lock (priv->mutex); g_hash_table_foreach_remove (priv->plugins, do_delete_or_not, plugin); + g_mutex_unlock (priv->mutex); } @@ -140,6 +147,7 @@ Thumbnailer *object; GStrv urls; guint num; + gboolean poolmax; gboolean unqueued; } WorkTask; @@ -189,11 +197,16 @@ task->num = ++num; task->object = g_object_ref (object); task->urls = g_strdupv (urls); + task->poolmax = FALSE; + g_mutex_lock (priv->mutex); g_list_foreach (priv->tasks, (GFunc) mark_unqueued, (gpointer) handle_to_unqueue); priv->tasks = g_list_prepend (priv->tasks, task); - g_thread_pool_push (priv->pool, task, NULL); + if (g_strv_length (urls) > 10) + g_thread_pool_push (priv->large_pool, task, NULL); + else + g_thread_pool_push (priv->normal_pool, task, NULL); g_mutex_unlock (priv->mutex); dbus_g_method_return (context, num); @@ -342,7 +355,12 @@ * plugin have a go at it */ } else { - GModule *module = g_hash_table_lookup (priv->plugins, key); + GModule *module; + + g_mutex_lock (priv->mutex); + module = g_hash_table_lookup (priv->plugins, key); + g_mutex_unlock (priv->mutex); + if (module) { GError *error = NULL; @@ -393,39 +411,219 @@ void thumbnailer_move (Thumbnailer *object, GStrv from_urls, GStrv to_urls, DBusGMethodInvocation *context) { + guint i = 0; + GString *errors = NULL; + GError *error = NULL; + dbus_async_return_if_fail (from_urls != NULL, context); dbus_async_return_if_fail (to_urls != NULL, context); keep_alive (); - // TODO - - dbus_g_method_return (context); + while (from_urls[i] != NULL && to_urls[i] != NULL) { + + const gchar *from_uri = from_urls[i]; + const gchar *to_uri = to_urls[i]; + GError *nerror = NULL; + gchar *from_normal = NULL, + *from_large = NULL, + *from_cropped = NULL; + gchar *to_normal = NULL, + *to_large = NULL, + *to_cropped = NULL; + + hildon_thumbnail_util_get_thumb_paths (from_uri, &from_large, + &from_normal, + &from_cropped, &error); + + if (nerror) + goto nerror_handler; + + hildon_thumbnail_util_get_thumb_paths (from_uri, &to_large, + &to_normal, + &to_cropped, &error); + + if (nerror) + goto nerror_handler; + + + g_rename (from_large, to_large); + g_rename (from_normal, to_normal); + g_rename (from_cropped, to_cropped); + + nerror_handler: + + if (nerror) { + if (!errors) + errors = g_string_new (""); + g_string_append_printf (errors, "[`%s': %s] ", + from_urls[i], + nerror->message); + g_error_free (nerror); + nerror = NULL; + } + + g_free (from_normal); + g_free (from_large); + g_free (from_cropped); + g_free (to_normal); + g_free (to_large); + g_free (to_cropped); + + i++; + } + + if (errors) { + g_set_error (&error, THUMB_ERROR, 0, + errors->str); + g_string_free (errors, TRUE); + dbus_g_method_return_error (context, error); + g_error_free (error); + } else + dbus_g_method_return (context); } void thumbnailer_copy (Thumbnailer *object, GStrv from_urls, GStrv to_urls, DBusGMethodInvocation *context) { + guint i = 0; + GString *errors = NULL; + GError *error = NULL; + dbus_async_return_if_fail (from_urls != NULL, context); dbus_async_return_if_fail (to_urls != NULL, context); keep_alive (); - // TODO - - dbus_g_method_return (context); + while (from_urls[i] != NULL && to_urls[i] != NULL) { + + const gchar *from_uri = from_urls[i]; + const gchar *to_uri = to_urls[i]; + GError *nerror = NULL; + gchar *from_s[3] = { NULL, NULL, NULL }; + gchar *to_s[3] = { NULL, NULL, NULL }; + guint n; + + hildon_thumbnail_util_get_thumb_paths (from_uri, &from_s[0], + &from_s[1], + &from_s[2], &error); + + if (nerror) + goto nerror_handler; + + hildon_thumbnail_util_get_thumb_paths (from_uri, &to_s[0], + &to_s[1], + &to_s[2], &error); + + for (n = 0; n<3; n++) { + GFile *from, *to; + + if (!from_s[n] || !to_s[n]) + continue; + + from = g_file_new_for_path (from_s[n]); + to = g_file_new_for_path (to_s[n]); + + /* We indeed ignore copy errors here */ + + g_file_copy (from, to, + G_FILE_COPY_NONE|G_FILE_COPY_OVERWRITE|G_FILE_COPY_ALL_METADATA, + NULL, NULL, NULL, + NULL); + + g_object_unref (from); + g_object_unref (to); + + } + + nerror_handler: + + if (nerror) { + if (!errors) + errors = g_string_new (""); + g_string_append_printf (errors, "[`%s': %s] ", + from_urls[i], + nerror->message); + g_error_free (nerror); + nerror = NULL; + } + + for (n = 0; n<3; n++) { + /* These can be NULL, but that's ok for g_free */ + g_free (from_s[n]); + g_free (to_s[n]); + } + + i++; + } + + if (errors) { + g_set_error (&error, THUMB_ERROR, 0, + errors->str); + g_string_free (errors, TRUE); + dbus_g_method_return_error (context, error); + g_error_free (error); + } else + dbus_g_method_return (context); } void thumbnailer_delete (Thumbnailer *object, GStrv urls, DBusGMethodInvocation *context) { + guint i = 0; + GString *errors = NULL; + GError *error = NULL; + dbus_async_return_if_fail (urls != NULL, context); keep_alive (); - // TODO - - dbus_g_method_return (context); + while (urls[i] != NULL) { + + const gchar *uri = urls[i]; + GError *nerror = NULL; + gchar *normal = NULL, + *large = NULL, + *cropped = NULL; + + hildon_thumbnail_util_get_thumb_paths (uri, &large, + &normal, + &cropped, &error); + + if (nerror) + goto nerror_handler; + + g_unlink (large); + g_unlink (normal); + g_unlink (cropped); + + nerror_handler: + + if (nerror) { + if (!errors) + errors = g_string_new (""); + g_string_append_printf (errors, "[`%s': %s] ", + urls[i], + nerror->message); + g_error_free (nerror); + nerror = NULL; + } + + g_free (normal); + g_free (large); + g_free (cropped); + + i++; + } + + if (errors) { + g_set_error (&error, THUMB_ERROR, 0, + errors->str); + g_string_free (errors, TRUE); + dbus_g_method_return_error (context, error); + g_error_free (error); + } else + dbus_g_method_return (context); } static void @@ -433,7 +631,8 @@ { ThumbnailerPrivate *priv = THUMBNAILER_GET_PRIVATE (object); - g_thread_pool_free (priv->pool, TRUE, TRUE); + g_thread_pool_free (priv->normal_pool, TRUE, TRUE); + g_thread_pool_free (priv->large_pool, TRUE, TRUE); g_object_unref (priv->manager); g_hash_table_unref (priv->plugins); @@ -567,11 +766,14 @@ /* We could increase the amount of threads to add some parallelism */ - priv->pool = g_thread_pool_new ((GFunc) do_the_work,NULL,1,TRUE,NULL); + priv->large_pool = g_thread_pool_new ((GFunc) do_the_work,NULL,1,TRUE,NULL); + priv->normal_pool = g_thread_pool_new ((GFunc) do_the_work,NULL,1,TRUE,NULL); /* This sort function makes the pool a LIFO */ - g_thread_pool_set_sort_function (priv->pool, pool_sort_compare, NULL); + g_thread_pool_set_sort_function (priv->large_pool, pool_sort_compare, NULL); + g_thread_pool_set_sort_function (priv->normal_pool, pool_sort_compare, NULL); + } Modified: projects/haf/trunk/hildon-thumbnail/debian/changelog =================================================================== --- projects/haf/trunk/hildon-thumbnail/debian/changelog 2008-09-24 13:48:05 UTC (rev 16212) +++ projects/haf/trunk/hildon-thumbnail/debian/changelog 2008-09-24 14:42:35 UTC (rev 16213) @@ -1,3 +1,15 @@ +hildon-thumbnail (3.0.1~unreleased) unstable; urgency=low + + [ Philip Van Hoof ] + * Completed API in the daemon. + * Monitor plugin directory. + * Avoid D-Bus roundtrip for existing thumbnails when using the + HildonThumbnailFactory API. + * Handle large requests in a separate thread so that small + requests are not starved. + + -- Marius Vollmer <marius.vollmer at nokia.com> Wed, 24 Sep 2008 17:35:38 +0300 + hildon-thumbnail (3.0.0) unstable; urgency=low [ Philip Van Hoof ] Modified: projects/haf/trunk/hildon-thumbnail/thumbs/hildon-thumbnail-factory.c =================================================================== --- projects/haf/trunk/hildon-thumbnail/thumbs/hildon-thumbnail-factory.c 2008-09-24 13:48:05 UTC (rev 16212) +++ projects/haf/trunk/hildon-thumbnail/thumbs/hildon-thumbnail-factory.c 2008-09-24 14:42:35 UTC (rev 16213) @@ -101,26 +101,16 @@ } static void -on_task_finished (DBusGProxy *proxy, - guint handle, - gpointer user_data) +create_pixbuf_and_callback (ThumbsItem *item, gchar *large, gchar *normal, gchar *cropped) { - gchar *key = g_strdup_printf ("%d", handle); - ThumbsItem *item = g_hash_table_lookup (tasks, key); - - if (item) { + GFile *filei = NULL; + GInputStream *stream = NULL; GdkPixbuf *pixbuf = NULL; - gchar *large = NULL, *normal = NULL, *cropped = NULL; + gchar *path; GError *error = NULL; - gchar *path = NULL; - GFile *filei = NULL; - GInputStream *stream = NULL; - hildon_thumbnail_util_get_thumb_paths (item->uri, &large, &normal, &cropped, &error); + /* Determine the exact type of thumbnail being requested */ - if (error) - goto error_handler; - if (item->flags & HILDON_THUMBNAIL_FLAG_CROP) { path = g_strdup (cropped); } else if (item->width > 128) { @@ -129,20 +119,26 @@ path = g_strdup (normal); } + /* Open the original thumbnail as a stream */ filei = g_file_new_for_path (path); stream = G_INPUT_STREAM (g_file_read (filei, NULL, &error)); + g_free (path); if (error) goto error_handler; + /* Read the stream as a pixbuf at the requested exact scale */ pixbuf = gdk_pixbuf_new_from_stream_at_scale (stream, item->width, item->height, TRUE, NULL, &error); error_handler: + /* Callback user function, passing the pixbuf and error */ + item->callback (item, item->user_data, pixbuf, error); + /* Cleanup */ if (filei) g_object_unref (filei); @@ -156,11 +152,40 @@ if (pixbuf) gdk_pixbuf_unref (pixbuf); +} +static void +on_task_finished (DBusGProxy *proxy, + guint handle, + gpointer user_data) +{ + gchar *key = g_strdup_printf ("%d", handle); + ThumbsItem *item = g_hash_table_lookup (tasks, key); + + if (item) { + gchar *large = NULL, *normal = NULL, *cropped = NULL; + GError *error = NULL; + + /* Get the large small and cropped path for the original + * URI */ + + hildon_thumbnail_util_get_thumb_paths (item->uri, &large, + &normal, &cropped, + &error); + + if (error) + goto error_handler; + + create_pixbuf_and_callback (item, large, normal, cropped); + + error_handler: + g_free (cropped); g_free (normal); g_free (large); + /* Remove the key from the hash, which means that we declare it + * handled. */ g_hash_table_remove (tasks, key); } @@ -185,10 +210,10 @@ GError *error = NULL; guint64 mtime, size; - file_path = g_build_filename(path, file, NULL); + file_path = g_build_filename (path, file, NULL); if(file[0] == '.' || !g_file_test(file_path, G_FILE_TEST_IS_REGULAR)) { - g_free(file_path); + g_free (file_path); continue; } @@ -202,6 +227,7 @@ if (error) { g_error_free (error); g_object_unref (filei); + g_free (file_path); continue; } @@ -226,15 +252,15 @@ static void cache_file_free(ThumbsCacheFile *item) { - g_free(item->file); - g_free(item); + g_free (item->file); + g_free (item); } static gint cache_file_compare(gconstpointer a, gconstpointer b) { ThumbsCacheFile *f1 = *(ThumbsCacheFile**)a, - *f2 = *(ThumbsCacheFile**)b; + *f2 = *(ThumbsCacheFile**)b; /* Sort in descending order */ if(f2->mtime == f1->mtime) { @@ -251,10 +277,8 @@ void hildon_thumbnail_factory_clean_cache(gint max_size, time_t min_mtime) { - GPtrArray *files; int i, size = 0; - gboolean deleting = FALSE; gchar *large_dir = g_build_filename (g_get_home_dir (), ".thumbnails", "large", NULL); gchar *normal_dir = g_build_filename (g_get_home_dir (), ".thumbnails", "normal", NULL); gchar *cropped_dir = g_build_filename (g_get_home_dir (), ".thumbnails", "cropped", NULL); @@ -264,30 +288,25 @@ files = g_ptr_array_new(); - read_cache_dir(fail_dir, files); - read_cache_dir(large_dir, files); - read_cache_dir(normal_dir, files); - read_cache_dir(cropped_dir, files); + read_cache_dir (fail_dir, files); + read_cache_dir (large_dir, files); + read_cache_dir (normal_dir, files); + read_cache_dir (cropped_dir, files); - g_ptr_array_sort(files, cache_file_compare); + g_ptr_array_sort (files, cache_file_compare); for(i = 0; i < files->len; i++) { - ThumbsCacheFile *item = g_ptr_array_index(files, i); + ThumbsCacheFile *item = g_ptr_array_index (files, i); size += item->size; - - if((max_size >= 0 && size >= max_size) || item->mtime < min_mtime) { - deleting = TRUE; + if ((max_size >= 0 && size >= max_size) || item->mtime < min_mtime) { + unlink (item->file); } - - if(deleting) { - unlink(item->file); - } } - g_ptr_array_foreach(files, (GFunc)cache_file_free, NULL); + g_ptr_array_foreach (files, (GFunc)cache_file_free, NULL); + g_ptr_array_free (files, TRUE); - g_ptr_array_free(files, TRUE); g_free (fail_dir); g_free (normal_dir); g_free (large_dir); @@ -300,9 +319,37 @@ ThumbsItem *item = userdata; gchar *key = g_strdup_printf ("%d", OUT_handle); item->handle_id = OUT_handle; + + /* Register the item as being handled */ g_hash_table_replace (tasks, key, item); } +typedef struct { + gchar *large, *normal, *cropped; + ThumbsItem *item; +} ThumbsItemAndPaths; + +static void +free_thumbsitem_and_paths (ThumbsItemAndPaths *info) +{ + g_free (info->large); + g_free (info->normal); + g_free (info->cropped); + thumb_item_free (info->item); + g_slice_free (ThumbsItemAndPaths, info); +} + +static gboolean +have_all_cb (gpointer user_data) +{ + ThumbsItemAndPaths *info = user_data; + ThumbsItem *item = info->item; + + create_pixbuf_and_callback (item, info->large, info->normal, info->cropped); + + return FALSE; +} + HildonThumbnailFactoryHandle hildon_thumbnail_factory_load_custom( const gchar *uri, const gchar *mime_type, guint width, guint height, @@ -310,35 +357,43 @@ gpointer user_data, HildonThumbnailFlags flags, ...) { + gchar *large, *normal, *cropped; + GError *error = NULL; ThumbsItem *item; - GStrv uris = (GStrv) g_malloc0 (sizeof (gchar *) * 2); + GStrv uris; + gboolean have_all = FALSE; g_return_val_if_fail(uri != NULL && mime_type != NULL && callback != NULL, NULL); - init (); + hildon_thumbnail_util_get_thumb_paths (uri, &large, &normal, + &cropped, &error); if (flags & HILDON_THUMBNAIL_FLAG_RECREATE) { - gchar *large, *normal, *cropped; - GError *error = NULL; - - hildon_thumbnail_util_get_thumb_paths (uri, &large, &normal, - &cropped, &error); - if (!error) { g_unlink (large); g_unlink (normal); g_unlink (cropped); - } else - g_error_free (error); - - g_free (large); - g_free (normal); - g_free (cropped); + } + } else { + gchar *path; + if (item->flags & HILDON_THUMBNAIL_FLAG_CROP) { + path = cropped; + } else if (item->width > 128) { + path = large; + } else { + path = normal; + } + have_all = g_file_test (path, G_FILE_TEST_EXISTS); } - item = g_new(ThumbsItem, 1); + if (error) + g_error_free (error); + else + have_all = FALSE; + item = g_new (ThumbsItem, 1); + item->uri = g_strdup(uri); item->mime_type = g_strdup(mime_type); item->width = width; @@ -349,13 +404,35 @@ item->canceled = FALSE; item->handle_id = 0; - uris[0] = g_strdup (uri); + if (have_all) { + ThumbsItemAndPaths *info = g_slice_new (ThumbsItemAndPaths); - org_freedesktop_thumbnailer_Generic_queue_async (proxy, (const char **) uris, 0, - on_got_handle, item); + info->item = item; + info->normal = g_strdup (normal); + info->large = g_strdup (large); + info->cropped = g_strdup (cropped); - g_strfreev (uris); + g_idle_add_full (G_PRIORITY_DEFAULT, have_all_cb, info, + (GDestroyNotify) free_thumbsitem_and_paths); + return; + } + + g_free (large); + g_free (normal); + g_free (cropped); + + if (!have_all) { + + init (); + uris = (GStrv) g_malloc0 (sizeof (gchar *) * 2); + uris[0] = g_strdup (uri); + org_freedesktop_thumbnailer_Generic_queue_async (proxy, (const char **) uris, 0, + on_got_handle, item); + + g_strfreev (uris); + } + return THUMBS_HANDLE (item); } @@ -374,6 +451,8 @@ { ThumbsItem *item = userdata; gchar *key = g_strdup_printf ("%d", item->handle_id); + + /* Unregister the item */ g_hash_table_remove (tasks, key); g_free (key); } @@ -387,6 +466,7 @@ if (item->handle_id == 0) return; + /* We don't do real canceling, we just do unqueing */ org_freedesktop_thumbnailer_Generic_unqueue_async (proxy, item->handle_id, on_cancelled, item);
- Previous message: [maemo-commits] r16212 - projects/haf/branches/hildon-thumbnail/daemonize/thumbs
- Next message: [maemo-commits] r16214 - projects/haf/branches/hildon-thumbnail/daemonize/daemon
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]