Index: configure.in =================================================================== --- configure.in (revision 374) +++ configure.in (working copy) @@ -119,14 +119,17 @@ dnl Set TRACKER_LOCALEDIR in config.h. if test "x${prefix}" = "xNONE"; then - TRACKER_LOCALEDIR="${ac_default_prefix}/${DATADIRNAME}/locale" + DATADIR="${ac_default_prefix}/${DATADIRNAME}" else - TRACKER_LOCALEDIR="${prefix}/${DATADIRNAME}/locale" + DATADIR="${prefix}/${DATADIRNAME}" fi -AC_DEFINE_UNQUOTED(TRACKER_LOCALEDIR, "$TRACKER_LOCALEDIR", +AC_DEFINE_UNQUOTED(TRACKER_LOCALEDIR, "$DATADIR/locale", [The directory in which locale data will be stored]) +AC_DEFINE_UNQUOTED(TRACKER_THUMBNAILDIR, "$DATADIR/thumbnailers", + [The directory in which data will be stored]) + # end of AM_GLIB_DEFINE_LOCALEDIR(TRACKER_LOCALEDIR) replacement #################################################################### Index: thumbnailers/Makefile.am =================================================================== --- thumbnailers/Makefile.am (revision 374) +++ thumbnailers/Makefile.am (working copy) @@ -1 +1,8 @@ -SUBDIRS = application image +thumbdir = $(datadir)/thumbnailers + +thumb_DATA = ooo-thumbnailer.desktop \ + dia-thumbnailer.desktop \ + pdf-thumbnailer.desktop \ + ps-thumbnailer.desktop + +bin_SCRIPTS = tracker-thumbnailer-extra --- /dev/null 2006-10-18 06:41:50.000000000 -0400 +++ thumbnailers/ooo-thumbnailer.desktop 2007-01-09 18:12:43.000000000 -0500 @@ -0,0 +1,8 @@ +[Desktop Entry] +Version=1.0 +Encoding=UTF-8 +Type=X-Thumbnailer +Name=OO.o Thumbnailer +TryExec=unzip +MimeType=application/vnd.oasis.opendocument.text;application/vnd.oasis.opendocument.graphics;application/vnd.oasis.opendocument.presentation;application/vnd.oasis.opendocument.spreadsheet +X-Thumbnailer-Exec=tracker-thumbnailer-extra --open-office %i %o %s --- /dev/null 2006-10-18 06:41:50.000000000 -0400 +++ thumbnailers/dia-thumbnailer.desktop 2007-01-09 18:12:52.000000000 -0500 @@ -0,0 +1,8 @@ +[Desktop Entry] +Version=1.0 +Encoding=UTF-8 +Type=X-Thumbnailer +Name=Dia Thumbnailer +TryExec=dia +MimeType=application/x-dia-diagram +X-Thumbnailer-Exec=tracker-thumbnailer-extra --dia-diagram %i %o %s --- /dev/null 2006-10-18 06:41:50.000000000 -0400 +++ thumbnailers/pdf-thumbnailer.desktop 2007-01-10 21:13:17.000000000 -0500 @@ -0,0 +1,8 @@ +[Desktop Entry] +Version=1.0 +Encoding=UTF-8 +Type=X-Thumbnailer +Name=PDF Thumbnailer +TryExec=convert +MimeType=application/pdf +X-Thumbnailer-Exec=convert pdf:%i[0] -thumbnail %s png:%o --- /dev/null 2006-10-18 06:41:50.000000000 -0400 +++ thumbnailers/ps-thumbnailer.desktop 2007-01-13 15:23:11.000000000 -0500 @@ -0,0 +1,8 @@ +[Desktop Entry] +Version=1.0 +Encoding=UTF-8 +Type=X-Thumbnailer +Name=PostScript Thumbnailer +TryExec=convert +MimeType=application/ps +X-Thumbnailer-Exec=convert ps:%i[0] -thumbnail %s png:%o Index: src/tracker-thumbnailer/tracker-thumbnailer.c =================================================================== --- src/tracker-thumbnailer/tracker-thumbnailer.c (revision 374) +++ src/tracker-thumbnailer/tracker-thumbnailer.c (working copy) @@ -26,61 +26,114 @@ #include #include #include +#include #include +#include "../../config.h" #include "md5.h" -#ifndef LIBDIR -#define LIBDIR "/usr/lib" -#endif +static gchar *mime = NULL; +static gchar *size = NULL; +static gboolean generate_thumbnail = FALSE; +static gchar **files = NULL; -/* argv[1] == full path of file to be nailed - * argv[2] == mime type of said file - * argv[3] == requested size: "normal", "large", "preview" - */ +static GOptionEntry entries[] = { + {"mime", 'm', 0, G_OPTION_ARG_STRING, &mime, "Mimetype of the file", NULL}, + {"size", 's', 0, G_OPTION_ARG_STRING, &size, "Size of the requested thumbnail ('normal' only valid option)", NULL}, + {"generate-thumbnail", 'g', 0, G_OPTION_ARG_NONE, &generate_thumbnail, "Generate the thumbnail if non-existant or invalid", NULL}, + {G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &files, "Files", NULL}, + {NULL} +}; +/* Thanks, Saleem. #394455 */ +guint +create_thumbnails_dir(const gchar * const subdir) +{ + gchar *thumbnails_dir = NULL; + thumbnails_dir = g_build_filename (g_get_home_dir (), ".thumbnails", NULL); + + /* Ensure that ~/.thumbnails is not a file if it exists */ + if (g_file_test (thumbnails_dir, G_FILE_TEST_EXISTS) && + !g_file_test (thumbnails_dir, G_FILE_TEST_IS_DIR)) { + g_printerr ("%s exists but is not a directory.\n", thumbnails_dir); + goto error; + } + + g_free(thumbnails_dir); + thumbnails_dir = g_build_filename(g_get_home_dir(), ".thumbnails", subdir, NULL); + if (g_mkdir_with_parents(thumbnails_dir, 00775) == -1) { + g_printerr ("failed: g_mkdir_with_parents(%s)\n", thumbnails_dir); + goto error; + } + + g_free(thumbnails_dir); + return 0; + +error: + g_free(thumbnails_dir); + return -1; +} + int main (int argc, char *argv[]) { - gchar *uri; - struct stat stat_info; - gchar *mtime; - md5_state_t hash_state; - guchar hash[16]; - gchar uri_hash[20], *p; - int i; - guint32 j; - gchar *thumbnail_filename; - FILE *fp; - png_structp png_ptr; - png_infop info_ptr; - png_textp pngtext; - int count, tests_passed; - gchar *thumbnailer; - gchar *args[5]; - png_uint_32 width, height; - int bit_depth, color_type, interlace_method; - int compression_method, filter_method; - png_colorp palette; - int num_palette; - png_bytepp row_pointers; + GOptionContext *context = NULL; + gchar *uri; + struct stat stat_info; + gchar *mtime; + md5_state_t hash_state; + guchar hash[16]; + gchar uri_hash[20], *p; + int i; + guint32 j; + gchar *thumbnail_filename; + FILE *fp; + png_structp png_ptr; + png_infop info_ptr; + png_textp pngtext; + int count, tests_passed; + glob_t desktops; + gchar *thumbpath; + GKeyFile *desktop = NULL; + gchar *args[4]; + gint exit_status; + gchar *thumbnailer_raw, *c; + GString *thumbnailer_s; + gchar *thumbnailer; + gchar *cstdout, *cstderr; + png_uint_32 width, height; + int bit_depth, color_type, interlace_method; + int compression_method, filter_method; + png_colorp palette; + int num_palette; + png_bytepp row_pointers; + gchar *thumbname; + context = g_option_context_new ("FILE... - file to create thumbnail for"); + g_option_context_add_main_entries (context, entries, NULL); + g_option_context_parse (context, &argc, &argv, NULL); + + g_option_context_free (context); + + if (create_thumbnails_dir (size) != 0) + return EXIT_FAILURE; + /* only make normal size thumbnails for now */ - if (strcmp (argv[3], "normal") != 0) { + if (strcmp (size, "normal") != 0) { g_printerr ("Only normal sized thumbnails are supported\n"); return EXIT_FAILURE; } /* make sure the actual file exists */ - if (!g_file_test (argv[1], G_FILE_TEST_EXISTS)) { - g_printerr ("%s does not exist\n", argv[1]); + if (!g_file_test (files[0], G_FILE_TEST_EXISTS)) { + g_printerr ("%s does not exist\n", files[0]); return EXIT_FAILURE; } /* convert file name to URI */ - uri = g_filename_to_uri (argv[1], NULL, NULL); + uri = g_filename_to_uri (files[0], NULL, NULL); /* get stat information on the file */ - if (g_stat (argv[1], &stat_info) == -1) { - g_printerr ("stat () failed for %s\n", argv[1]); + if (g_stat (files[0], &stat_info) == -1) { + g_printerr ("stat () failed for %s\n", files[0]); return EXIT_FAILURE; } mtime = g_strdup_printf ("%lu", stat_info.st_mtime); @@ -96,7 +149,7 @@ } g_sprintf (p, ".png"); thumbnail_filename = g_build_filename ( - g_get_home_dir (), ".thumbnails", argv[3], uri_hash, NULL); + g_get_home_dir (), ".thumbnails", size, uri_hash, NULL); /* check to see if the thumbnail already exists */ if (g_file_test (thumbnail_filename, G_FILE_TEST_EXISTS)) { @@ -126,33 +179,149 @@ } g_printerr ("Not all tests passed. Recreating thumbnail...\n"); } - /* thumbnail either doesn't exist or is invalid; contiue... */ + if (!generate_thumbnail) { + return EXIT_SUCCESS; + } + /* needed thumbnail either doesn't exist or is invalid; contiue... */ - /* do we have a thumbnailer for this mime type? */ - thumbnailer = g_strconcat (LIBDIR "/tracker/thumbnailers/", - argv[2], "_thumbnailer", NULL); + /* scan for .desktop files describing thumbnailers */ + thumbpath = g_strdup (TRACKER_THUMBNAILDIR "/*.desktop"); + for (i = 0; i < 2; i++) { + glob (thumbpath, 0, NULL, &desktops); + for (j = 0; j < desktops.gl_pathc; j++) { + gchar *value; + gchar **mimev, **p; - if (!g_file_test (thumbnailer, G_FILE_TEST_EXISTS)) { - g_printerr ("%s not found\n", thumbnailer); + desktop = g_key_file_new (); + g_key_file_load_from_file (desktop, desktops.gl_pathv[j], + G_KEY_FILE_NONE, NULL); + value = g_key_file_get_string (desktop, "Desktop Entry", "Type", NULL); + if (strcmp (value, "X-Thumbnailer") != 0) { + g_free (value); + g_free (desktop); + desktop = NULL; + continue; + } + g_free (value); + value = g_key_file_get_string (desktop, "Desktop Entry", "MimeType", NULL); + mimev = g_strsplit (value, ";", -1); + g_free (value); + for (p = mimev; *p != NULL; ++p) { + if (strcmp (*p, mime) == 0) { + break; + } + } + if (*p != NULL) { + g_strfreev (mimev); + break; + } + g_strfreev (mimev); + g_free (desktop); + desktop = NULL; + } + g_free (thumbpath); + thumbpath = g_strconcat (g_get_home_dir (), + "/.local/share/thumbnailers/*.desktop", + NULL); + } + g_free (thumbpath); + +#if 0 + if (desktop == NULL) { + g_printerr ("No thumbnailer for mime %s\n", mime); return EXIT_FAILURE; } +#endif + /* no desktop file, give gconf a shot */ + if (desktop == NULL) { + for (p = mime; *p != NULL; ++p) { + if (*p == '/' || *p == '+') + *p = '@'; + } + /* gconftool does not return an error code if the key doesn't exist + * so we need to use the --dir-exists command first + */ + args[0] = g_strdup ("gconftool-2"); + args[1] = g_strdup ("--dir-exists"); + args[2] = g_strconcat ("/desktop/gnome/thumbnailers/", mime, NULL); + args[3] = NULL; + if (!g_spawn_sync (NULL, args, NULL, + G_SPAWN_SEARCH_PATH | G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, NULL, NULL, &exit_status, NULL)) { - /* execute the thumbnailer */ - args[0] = thumbnailer; - args[1] = g_filename_from_utf8 (argv[1], -1, NULL, NULL, NULL); - args[2] = thumbnail_filename; - if (strcmp (argv[3], "normal") == 0) - args[3] = g_strdup ("128"); - args[4] = NULL; + g_printerr ("Failed executing gconftool.\n"); + return EXIT_FAILURE; + } + if (exit_status != 0) { + g_printerr ("No gconf directory: %s\n", args[2]); + return EXIT_FAILURE; + } + g_free (args[2]); + g_free (args[1]); + args[1] = g_strdup ("--get"); + args[2] = g_strconcat ("/desktop/gnome/thumbnailers/", mime, "/command", NULL); + if (!g_spawn_sync (NULL, args, NULL, + G_SPAWN_SEARCH_PATH | G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, &thumbnailer_raw, NULL, NULL, NULL)) { - if (!g_spawn_sync (NULL, args, NULL, - G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL, - NULL, NULL, NULL, NULL, NULL, NULL)) { + g_printerr ("Failed executing gconftool.\n"); + return EXIT_FAILURE; + } + if (strcmp (thumbnailer_raw, "") == 0) { + g_printerr ("Error retrieving thumbnailer command.\n"); + return EXIT_FAILURE; + } + g_free (args[2]); + g_free (args[1]); + g_free (args[0]); + thumbname = g_strdup ("gconf"); + } + else { + thumbnailer_raw = g_key_file_get_string (desktop, "Desktop Entry", "X-Thumbnailer-Exec", NULL); + thumbname = g_key_file_get_string (desktop, "Desktop Entry", "Name", NULL); + } - g_printerr ("%s failed to create %s\n", thumbnailer, thumbnail_filename); + /* fill in the field codes */ + thumbnailer_s = g_string_sized_new (strlen (thumbnailer_raw) + + strlen (uri) + + strlen (thumbnail_filename) + 3); + for (c = thumbnailer_raw; *c != '\0'; c++) { + gchar *tmp; + if (*c == '%') { + c++; + if (*c == 'i') { + tmp = g_shell_quote (files[0]); + g_string_append (thumbnailer_s, tmp); + g_free (tmp); + } + else if (*c == 'o') { + tmp = g_shell_quote (thumbnail_filename); + g_string_append (thumbnailer_s, tmp); + g_free (tmp); + } + else if (*c == 's') { + g_string_append (thumbnailer_s, "128"); + } + else if (*c == 'u') { + g_string_append (thumbnailer_s, uri); + } + else if (*c == '%') { + g_string_append (thumbnailer_s, "%"); + } + } + else { + g_string_append_c (thumbnailer_s, *c); + } + } + thumbnailer = g_string_free (thumbnailer_s, FALSE); + + /* execute the thumbnailer */ + if (!g_spawn_command_line_sync (thumbnailer, &cstdout, &cstderr, NULL, NULL)) { + g_printerr ("Failed to create %s\n", thumbnail_filename); g_remove (thumbnail_filename); return EXIT_FAILURE; } + g_free (thumbnailer); /* the fd.o spec requires us to set certain PNG keys. As far as I can * see, libpng doesn't allow you to just set metadata, you have to do @@ -218,7 +387,8 @@ pngtext[1].compression = PNG_TEXT_COMPRESSION_NONE; /* set some optional fields */ pngtext[2].key = "Software"; - pngtext[2].text = "Tracker thumbnail factory"; + pngtext[2].text = g_strdup_printf ( + "Tracker thumbnail factory (via %s)", thumbname); pngtext[2].compression = PNG_TEXT_COMPRESSION_NONE; png_set_text(png_ptr, info_ptr, pngtext, 3); --- /dev/null 2006-10-18 06:41:50.000000000 -0400 +++ thumbnailers/tracker-thumbnailer-extra 2007-01-13 15:38:53.000000000 -0500 @@ -0,0 +1,27 @@ +#!/bin/sh + +# $1: type of thumbnail to create +# $2: file to create thumbnail for +# $3: destination of thumbnail +# $4: size of thumbnail (in pixels) + +case $1 in + --open-office) + # the default thumbnail has a transparent background. + # let's make that white + unzip -p "$2" Thumbnails/thumbnail.png \ + | convert - -resize $4x$4 -background white \ + -flatten -bordercolor black -border 1x1 \ + +swap -flatten $3 + ;; + + --dia-diagram) + # dia's --size parameters is a clipper, not a scaler + dia --export=$3 --filter=png --nosplash "$2" + mogrify -thumbnail $4x$4 $3 + ;; + + *) + echo "Unknown type: $1" >/dev/stderr + ;; +esac Index: src/trackerd/trackerd.c =================================================================== --- src/trackerd/trackerd.c (revision 374) +++ src/trackerd/trackerd.c (working copy) @@ -1414,7 +1414,7 @@ if (info) { if (info->uri && (info->uri[0] == '/')) { char *file_as_text; - + char *small_thumb_file = NULL, *large_thumb_file = NULL; GHashTable *meta_table; if (!tracker->is_indexing) { @@ -1465,21 +1465,17 @@ - if (tracker->enable_thumbnails) { - char *small_thumb_file = NULL, *large_thumb_file = NULL; + small_thumb_file = tracker_metadata_get_thumbnail (info->uri, info->mime, + "normal", tracker->enable_thumbnails); - small_thumb_file = tracker_metadata_get_thumbnail (info->uri, info->mime, "normal"); + tracker_db_save_thumbs (db_con, small_thumb_file, large_thumb_file, info->file_id); - tracker_db_save_thumbs (db_con, small_thumb_file, large_thumb_file, info->file_id); - - /* to do - emit dbus signal ThumbNailChanged */ - if (small_thumb_file) { - g_free (small_thumb_file); - } - - + /* to do - emit dbus signal ThumbNailChanged */ + if (small_thumb_file) { + g_free (small_thumb_file); } + file_as_text = tracker_metadata_get_text_file (info->uri, info->mime); if (tracker->enable_content_indexing && file_as_text) { Index: src/trackerd/tracker-metadata.h =================================================================== --- src/trackerd/tracker-metadata.h (revision 374) +++ src/trackerd/tracker-metadata.h (working copy) @@ -31,7 +31,7 @@ void tracker_metadata_get_embedded (const char *uri, const char *mime, GHashTable *table); char * tracker_metadata_get_text_file (const char *uri, const char *mime); void tracker_metadata_parse_text_contents (const char *file_as_text, unsigned int ID); -char * tracker_metadata_get_thumbnail (const char *path, const char *mime, const char *size); +char * tracker_metadata_get_thumbnail (const char *path, const char *mime, const char *size, gboolean generate_thumb); char * tracker_get_service_type_for_mime (const char *mime); #endif Index: src/trackerd/tracker-metadata.c =================================================================== --- src/trackerd/tracker-metadata.c (revision 374) +++ src/trackerd/tracker-metadata.c (working copy) @@ -331,17 +331,21 @@ char * -tracker_metadata_get_thumbnail (const char *path, const char *mime, const char *size) +tracker_metadata_get_thumbnail (const char *path, const char *mime, const char *size, gboolean generate_thumb) { gchar *thumbnail; - gchar *argv[5]; + gchar *argv[6]; gint exit_status; argv[0] = g_strdup ("tracker-thumbnailer"); argv[1] = g_filename_from_utf8 (path, -1, NULL, NULL, NULL); - argv[2] = g_strdup (mime); - argv[3] = g_strdup (size); - argv[4] = NULL; + argv[2] = g_strdup_printf ("--mime=%s", mime); + argv[3] = g_strdup_printf ("--size=%s", size); + if (generate_thumb) + argv[4] = g_strdup ("--generate-thumbnail"); + else + argv[4] = NULL; + argv[5] = NULL; if (!g_spawn_sync (NULL, argv, @@ -365,7 +369,8 @@ g_free (argv[1]); g_free (argv[2]); g_free (argv[3]); - + if (argv[4]) + g_free (argv[4]); return thumbnail; }