diff options
| author | Tomas Bzatek <tbzatek@users.sourceforge.net> | 2009-03-28 22:00:06 +0100 |
|---|---|---|
| committer | Tomas Bzatek <tbzatek@users.sourceforge.net> | 2009-03-28 22:00:06 +0100 |
| commit | 29aeb95a28d518944f1eb268f93a96cbb9dff7f2 (patch) | |
| tree | 154c8870d72229a95f0ab0bd93f8c4d3048b9f91 /src | |
| parent | d9ff1192a7b5eb7defca68e90e06c68e9b986c94 (diff) | |
| download | cataract-29aeb95a28d518944f1eb268f93a96cbb9dff7f2.tar.xz | |
Multithreading support
Also made progress output a little bit nicer
default = 1 thread at once, for safety reasons
I've encountered critical issues with ImageMagick compiled with OpenMP support. Hope that package maintainers are clever.
ShittyMagickWandGenesis(), ShittyMagickWandTerminus() :-)
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile.am | 2 | ||||
| -rw-r--r-- | src/cgg.c | 23 | ||||
| -rw-r--r-- | src/gallery-utils.h | 2 | ||||
| -rw-r--r-- | src/generators.c | 345 | ||||
| -rw-r--r-- | src/generators.h | 40 | ||||
| -rw-r--r-- | src/items.c | 4 | ||||
| -rw-r--r-- | src/items.h | 6 | ||||
| -rw-r--r-- | src/job-manager.c | 362 | ||||
| -rw-r--r-- | src/job-manager.h | 36 | ||||
| -rw-r--r-- | src/jpeg-utils.cpp | 4 |
10 files changed, 480 insertions, 344 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index f8b46c9..1300d8d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -27,6 +27,8 @@ cgg_SOURCES = \ generators-replace-table.h \ items.c \ items.h \ + job-manager.h \ + job-manager.c \ jpeg-utils.cpp \ jpeg-utils.h \ setup.c \ @@ -22,13 +22,16 @@ #include <unistd.h> #include <glib.h> +#include <glib/gthread.h> #include <libxml/xmlmemory.h> +#include <wand/magick-wand.h> + #include <config.h> #include "setup.h" -#include "generators.h" +#include "job-manager.h" @@ -39,17 +42,19 @@ * parse_cmd: parse commandline and fill global variable parameters */ gboolean -parse_cmd (int argc, char* argv[], char **source_dir, char **dst_dir, gboolean *verbose) +parse_cmd (int argc, char* argv[], char **source_dir, char **dst_dir, gboolean *verbose, int *jobs) { static gboolean _verbose = FALSE; static gchar *_source_dir = NULL; static gchar *_dst_dir = NULL; + static int _jobs = 1; static GOptionEntry entries[] = { { "verbose", 'v', 0, G_OPTION_ARG_NONE, &_verbose, "Be verbose", NULL }, { "source", 's', 0, G_OPTION_ARG_STRING, &_source_dir, "Specifies path to source structure", NULL }, { "output", 'o', 0, G_OPTION_ARG_STRING, &_dst_dir, "Generate files to the specified directory instead of current", NULL }, + { "jobs", 'j', 0, G_OPTION_ARG_INT, &_jobs, "Allow N jobs at once (default=1)", NULL }, { NULL } }; @@ -86,6 +91,7 @@ parse_cmd (int argc, char* argv[], char **source_dir, char **dst_dir, gboolean * *source_dir = _source_dir; *dst_dir = _dst_dir; *verbose = _verbose; + *jobs = _jobs; return TRUE; } @@ -98,6 +104,7 @@ main(int argc, char* argv[]) char *source_dir; char *dst_dir; gboolean verbose; + int jobs; TGallerySetup *setup; /* @@ -107,13 +114,19 @@ main(int argc, char* argv[]) */ LIBXML_TEST_VERSION; + g_thread_init (NULL); + + /* Initialize ImageMagick at this point, for multithreading safety */ + MagickWandGenesis(); + + source_dir = NULL; dst_dir = NULL; setup = malloc(sizeof(TGallerySetup)); /* Parse commandline */ - if (! parse_cmd (argc, argv, &source_dir, &dst_dir, &verbose)) + if (! parse_cmd (argc, argv, &source_dir, &dst_dir, &verbose, &jobs)) return -1; if ((! source_dir) || (access (source_dir, R_OK))) { @@ -140,8 +153,10 @@ main(int argc, char* argv[]) /* Start building the gallery tree */ setup->verbose = verbose; - build_tree (setup, source_dir, dst_dir, NULL); + build_tree (setup, source_dir, dst_dir, NULL, -1, jobs); + + MagickWandTerminus(); /* Cleanup function for the XML library. */ xmlCleanupParser(); diff --git a/src/gallery-utils.h b/src/gallery-utils.h index 7e5e2c0..123879b 100644 --- a/src/gallery-utils.h +++ b/src/gallery-utils.h @@ -16,9 +16,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include <glib.h> +#include <string.h> #define IS_DIR_SEP(ch) ((ch) == '/' || (ch) == '~') #define IS_EQUAL_SIGN(ch) ((ch) == '=') +#define GET_EXT(s) strrchr (s, '.') /* diff --git a/src/generators.c b/src/generators.c index e2f9d7f..a3d2585 100644 --- a/src/generators.c +++ b/src/generators.c @@ -33,21 +33,15 @@ #include "generators-replace-table.h" -#define DEFAULT_DATA_DIR_MODE S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH -#define GET_EXT(s) strrchr (s, '.') - /* - * generate_image: auxiliary function for write_html_album - * - img_src and thumb should be freed afterwards + * generate_image: generate needed image sizes */ void generate_image (TGallerySetup *setup, TAlbum *items, TIndexItem *item, unsigned int item_index, - const char *dst, - unsigned long *img_w, unsigned long *img_h, - char **img_src, char **thumb) + const char *dst_dir) { unsigned long new_w, new_h; unsigned long thumb_w, thumb_h; @@ -61,10 +55,8 @@ generate_image (TGallerySetup *setup, int bigq; - *img_src = NULL; - *thumb = NULL; - *img_w = 0; - *img_h = 0; + item->gen_img_src = NULL; + item->gen_thumb = NULL; thumb_src_full = NULL; img_src_full = NULL; @@ -73,58 +65,50 @@ generate_image (TGallerySetup *setup, return; img_src_full = g_strconcat (items->base_dir, "/", item->thumbnail, NULL); thumb_src_full = g_strconcat (items->base_dir, "/", item->thumbnail, NULL); - *img_src = g_path_get_basename (item->thumbnail); + item->gen_img_src = g_path_get_basename (item->thumbnail); s1 = g_path_get_basename (item->thumbnail); - *thumb = g_strdup_printf ("thn_%.3d_%s", item_index, s1); + item->gen_thumb = g_strdup_printf ("thn_%.3d_%s", item_index, s1); g_free (s1); } else if (items->type == GALLERY_TYPE_ALBUM) { - *img_src = (item->path == NULL && item->preview) ? item->preview : item->path; - *thumb = (item->thumbnail) ? item->thumbnail : *img_src; - img_src_full = g_strconcat (items->base_dir, "/", *img_src, NULL); - thumb_src_full = g_strconcat (items->base_dir, "/", *thumb, NULL); - *img_src = g_path_get_basename (*img_src); - s1 = g_path_get_basename (*thumb); - *thumb = g_strdup_printf ("thn_%.3d_%s", item_index, s1); + item->gen_img_src = (item->path == NULL && item->preview) ? item->preview : item->path; + item->gen_thumb = (item->thumbnail) ? item->thumbnail : item->gen_img_src; + img_src_full = g_strconcat (items->base_dir, "/", item->gen_img_src, NULL); + thumb_src_full = g_strconcat (items->base_dir, "/", item->gen_thumb, NULL); + item->gen_img_src = g_path_get_basename (item->gen_img_src); + s1 = g_path_get_basename (item->gen_thumb); + item->gen_thumb = g_strdup_printf ("thn_%.3d_%s", item_index, s1); g_free (s1); } - get_image_sizes (img_src_full, img_w, img_h); + get_image_sizes (img_src_full, &new_w, &new_h); - if ((img_w > 0) && (img_h > 0)) { - new_w = *img_w; - new_h = *img_h; + if ((new_w > 0) && (new_h > 0)) { + item->gen_portrait = (new_w / new_h) < 1; /* Generate thumbnail */ g_assert (thumb_src_full != NULL); get_image_sizes (thumb_src_full, &thumb_w, &thumb_h); - s1 = g_path_get_dirname (dst); - thumb_dst = g_strconcat (s1, "/", THUMBNAIL_DIR, "/", *thumb, NULL); - g_free (s1); - if (setup->verbose) printf (" Generating thumbnail of '%s' ...", *thumb); + thumb_dst = g_strconcat (dst_dir, "/", THUMBNAIL_DIR, "/", item->gen_thumb, NULL); if ((thumb_w > 0) && (thumb_h > 0)) { - if ((thumb_w / thumb_h) >= 1) + if (! item->gen_portrait) calculate_sizes (setup->thumbnail_landscape_width, setup->thumbnail_landscape_height, &thumb_w, &thumb_h); else calculate_sizes (setup->thumbnail_portrait_width, setup->thumbnail_portrait_height, &thumb_w, &thumb_h); if (! resize_image (thumb_src_full, thumb_dst, thumb_w, thumb_h, setup->thumbnail_quality, TRUE)) - fprintf (stderr, "write_html_index: error resizing thumbnail %s\n", thumb_src_full); + fprintf (stderr, "generate_image: error resizing thumbnail %s\n", thumb_src_full); else - if (setup->verbose) printf (" done.\n"); g_free (thumb_dst); } else - printf (" failed!\n"); + fprintf (stderr, "generate_image: thumbnail %s sizes are %lux%lu\n", thumb_src_full, thumb_w, thumb_h); /* Generate/copy preview and original image */ if (items->type == GALLERY_TYPE_ALBUM) { - s1 = g_path_get_dirname (dst); - big_dst = g_strconcat (s1, "/", IMG_BIG_DIR, "/", *img_src, NULL); - g_free (s1); - + big_dst = g_strconcat (dst_dir, "/", IMG_BIG_DIR, "/", item->gen_img_src, NULL); if (item->preview == NULL) { /* No preview image supplied, generate it from original */ bigq = setup->preview_quality; @@ -132,14 +116,11 @@ generate_image (TGallerySetup *setup, bigq = items->quality; if ((item->quality > 0) && (item->quality <= 100)) bigq = item->quality; - new_w = *img_w; - new_h = *img_h; - if (setup->verbose) printf (" Generating preview of '%s' ...", *img_src); if ((item->width > 0) && (item->height > 0)) { calculate_sizes (item->width, item->height, &new_w, &new_h); } else { - if ((*img_w / *img_h) >= 1) + if (! item->gen_portrait) { if ((items->landscape_width > 0) && (items->landscape_height > 0)) calculate_sizes (items->landscape_width, items->landscape_height, &new_w, &new_h); @@ -157,19 +138,14 @@ generate_image (TGallerySetup *setup, g_assert (img_src_full != NULL); if (! resize_image (img_src_full, big_dst, new_w, new_h, bigq, FALSE)) - fprintf (stderr, "write_html_index: error resizing big image %s\n", img_src_full); - else - if (setup->verbose) printf (" done.\n"); + fprintf (stderr, "generate_image: error resizing big image %s\n", img_src_full); } else { /* Copy the preview (big) image provided */ big_src = g_strconcat (items->base_dir, "/", item->preview, NULL); - if (setup->verbose) printf (" Copying preview image '%s' ...", *img_src); if (! copy_file (big_src, big_dst)) - fprintf (stderr, "write_html_index: error copying preview image %s\n", big_src); - else - if (setup->verbose) printf (" done.\n"); + fprintf (stderr, "generate_image: error copying preview image %s\n", big_src); g_free (big_src); } modify_exif (big_dst, setup->erase_exif_thumbnail, setup->add_copyright); @@ -178,14 +154,9 @@ generate_image (TGallerySetup *setup, if (item->force_fullsize || (items->fullsize && ! item->force_nofullsize) || (! item->force_nofullsize && ! items->nofullsize && ! setup->nofullsize)) { - s1 = g_path_get_dirname(dst); - orig_dst = g_strconcat (s1, "/", IMG_ORIG_DIR, "/", *img_src, NULL); - g_free (s1); - if (setup->verbose) printf (" Copying original image '%s' ...", *img_src); + orig_dst = g_strconcat (dst_dir, "/", IMG_ORIG_DIR, "/", item->gen_img_src, NULL); if (! copy_file(img_src_full, orig_dst)) - fprintf (stderr, "write_html_index: error copying original image %s\n", img_src_full); - else - if (setup->verbose) printf(" done.\n"); + fprintf (stderr, "generate_image: error copying original image %s\n", img_src_full); modify_exif (orig_dst, setup->erase_exif_thumbnail, setup->add_copyright); g_free (orig_dst); } @@ -234,9 +205,6 @@ write_html_album (TGallerySetup *setup, int level, old_parent_item_index; gboolean res, bb; int i; - unsigned long img_w, img_h; - char *img_src; - char *thumb; unsigned int real_total_items; ReplaceTable *global_replace_table; ReplaceTable *local_replace_table; @@ -463,39 +431,28 @@ write_html_album (TGallerySetup *setup, /* Generate the images (preview, original, thumbnail) */ local_replace_table = replace_table_new (); - img_w = 0; - img_h = 0; s1 = NULL; switch (item->type) { case INDEX_ITEM_TYPE_PICTURE: - img_src = NULL; - thumb = NULL; - generate_image (setup, items, item, i, dst, &img_w, &img_h, &img_src, &thumb); /* Skip HTML code generation if it's a hidden item */ if (! item->hidden) { - if (img_w == 0 || img_h == 0 || (img_w / img_h) >= 1) - s1 = strdup (buf_img_list_landscape); - else - s1 = strdup (buf_img_list_portrait); + s1 = strdup (item->gen_portrait ? buf_img_list_portrait : buf_img_list_landscape); replace_table_add_key_printf (local_replace_table, "ALBUM_SUBPATH", "%s/%s", item->path, setup->index_file_name); - replace_table_add_key_printf (local_replace_table, "IMG_SUBPAGE", "%s%s", img_src, GET_EXT (setup->index_file_name)); + replace_table_add_key_printf (local_replace_table, "IMG_SUBPAGE", "%s%s", item->gen_img_src, GET_EXT (setup->index_file_name)); replace_table_add_key (local_replace_table, "IMG_TITLE", item->title); replace_table_add_key (local_replace_table, "IMG_DESCRIPTION", item->title_description); replace_table_add_key_printf (local_replace_table, "IMG_LIST_ID", "i%d", i + 1); - replace_table_add_key_printf (local_replace_table, "IMG_THUMBNAIL", "%s/%s", THUMBNAIL_DIR, thumb); - replace_table_add_key (local_replace_table, "IMG_FILENAME", img_src); + if (item->gen_thumb != NULL) + replace_table_add_key_printf (local_replace_table, "IMG_THUMBNAIL", "%s/%s", THUMBNAIL_DIR, item->gen_thumb); + replace_table_add_key (local_replace_table, "IMG_FILENAME", item->gen_img_src); if (items->type == GALLERY_TYPE_INDEX) { s3 = g_strconcat (items->base_dir, "/", item->path, "/index.xml", NULL); replace_table_add_key_int (local_replace_table, "ALBUM_NUM_ITEMS", get_album_objects_count (s3)); g_free (s3); } } - if (img_src) - g_free (img_src); - if (thumb) - g_free (thumb); break; case INDEX_ITEM_TYPE_SEPARATOR: @@ -917,243 +874,3 @@ write_html_image (TGallerySetup *setup, return res; } - - -static void -mirror_files (TGallerySetup *setup, char **files, const char *src_tree, const char *dst_dir, const char *label) -{ - char **extra; - char *s1, *s2, *s3; - - if (files && g_strv_length (files) > 0) { - extra = files; - if (setup->verbose) printf ("%s", label); - while (*extra) { - s1 = g_strstrip (*extra); - if (strlen (s1) > 0) { - /* First create target directory if it doesn't exist */ - s2 = g_strconcat (dst_dir, "/", s1, NULL); - s3 = g_path_get_dirname (s2); - g_free (s2); - if (g_mkdir_with_parents (s3, DEFAULT_DATA_DIR_MODE)) { - fprintf (stderr, "error making target extra directory '%s': %s\n", s3, strerror (errno)); - g_free (s3); - continue; - } - g_free (s3); - - /* Copy the file */ - if (setup->verbose) printf (" %s", s1); - s2 = g_strconcat (src_tree, "/", s1, NULL); - s3 = g_strconcat (dst_dir, "/", s1, NULL); - copy_file (s2, s3); - g_free (s2); - g_free (s3); - } - extra++; - } - if (setup->verbose) printf ("\n"); - } -} - -/* - * build_tree: generate complete gallery tree based on source xml files - * - * src_tree = source directory of the items - * dst_dir = destination of the generated items - * parent_index = parent album to determine our descent in the tree - * - */ -gboolean -build_tree (TGallerySetup *setup, - const char *src_tree, - const char *dst_dir, - TAlbum *parent_index, - int parent_item_index) -{ - char *idx_file; - TAlbum *items; - TIndexItem *item; - char *s1, *s2, *s3; - char *thumb_dir; - char *img_big_dir; - char *img_orig_dir; - char *template; - char *imgname; - gboolean res; - int i; - - printf ("*** Entering directory '%s'\n", src_tree); - #ifdef __DEBUG_ALL__ - printf ("setup->real_templates_dir = %s\n", setup->real_templates_dir); - #endif - - /* Check access permissions */ - if (access (src_tree, R_OK)) { - fprintf (stderr, "error accessing source directory: %s\n", strerror (errno)); - return FALSE; - } - if (access (dst_dir, R_OK | W_OK | X_OK)) { - if (g_mkdir_with_parents (dst_dir, DEFAULT_DATA_DIR_MODE)) { - fprintf (stderr, "error creating destination directory: %s\n", strerror (errno)); - return FALSE; - } - } - - /* Check the index file */ - idx_file = g_strconcat (src_tree, "/index.xml", NULL); - if (access (idx_file, R_OK)) { - fprintf (stderr, "error accessing index file '%s': %s\n", idx_file, strerror (errno)); - g_free (idx_file); - return FALSE; - } - - /* Read the index file and fill items array */ - items = malloc (sizeof (TAlbum)); - memset (items, 0, sizeof (TAlbum)); - if (! parse_album_xml (idx_file, items)) { - fprintf (stderr, "error reading index file '%s'\n", idx_file); - g_free (idx_file); - free_album_data (items); - return FALSE; - } - g_free (idx_file); - items->parent_index = parent_index; - items->parent_item_index = parent_item_index; - - /* Copy support files */ - if (! setup->support_files_use_common_root || parent_index == NULL) { - /* copy only if we're in root level or old-style is active */ - mirror_files (setup, setup->template_files, setup->real_templates_dir, dst_dir, "Copying template files: "); - - /* favicon */ - if (setup->favicon_file && strlen (setup->favicon_file) > 0) { - if (setup->verbose) printf ("Copying favicon: %s\n", setup->favicon_file); - s3 = g_path_get_dirname (setup->setup_xml_path); - s1 = g_strconcat (s3, "/", setup->favicon_file, NULL); - s2 = g_strconcat (dst_dir, "/", setup->favicon_file, NULL); - copy_file (s1, s2); - g_free (s1); - g_free (s2); - g_free (s3); - } - } - - /* Prepare target thumbnail directory */ - thumb_dir = g_strconcat (dst_dir, "/", THUMBNAIL_DIR, NULL); - if (access (thumb_dir, R_OK | W_OK | X_OK)) - if (g_mkdir_with_parents (thumb_dir, DEFAULT_DATA_DIR_MODE)) { - fprintf (stderr, "error making target thumbnail directory: %s\n", strerror (errno)); - g_free (thumb_dir); - free_album_data (items); - return FALSE; - } - g_free (thumb_dir); - - /* Prepare target preview and orig directories */ - if (items->type == GALLERY_TYPE_ALBUM) - { - res = TRUE; - img_big_dir = g_strconcat (dst_dir, "/", IMG_BIG_DIR, NULL); - img_orig_dir = g_strconcat (dst_dir, "/", IMG_ORIG_DIR, NULL); - if (access (img_big_dir, R_OK | W_OK | X_OK)) - if (g_mkdir_with_parents (img_big_dir, DEFAULT_DATA_DIR_MODE)) { - fprintf (stderr, "error making target preview directory: %s\n", strerror (errno)); - res = FALSE; - } - if (access (img_orig_dir, R_OK | W_OK | X_OK)) - if (g_mkdir_with_parents (img_orig_dir, DEFAULT_DATA_DIR_MODE)) { - fprintf (stderr, "error making target full size directory: %s\n", strerror (errno)); - res = FALSE; - } - g_free (img_big_dir); - g_free (img_orig_dir); - if (! res) { - free_album_data (items); - return FALSE; - } - } - - - /* Start generating items */ - if (items->type == GALLERY_TYPE_INDEX) - template = g_strconcat ("/", setup->template_index, NULL); - else - if (items->type == GALLERY_TYPE_ALBUM) - template = g_strconcat ("/", setup->template_album, NULL); - else - /* default to album */ - template = g_strconcat ("/", setup->template_album, NULL); - - if (setup->verbose) printf ("Writing '%s' ...\n", setup->index_file_name); - s1 = g_strconcat (setup->real_templates_dir, template, NULL); - s2 = g_strconcat (dst_dir, "/", setup->index_file_name, NULL); - res = write_html_album (setup, s1, s2, items); - g_free (s1); - g_free (s2); - g_free (template); - if (! res) { - fprintf (stderr, "error generating target index file\n"); - free_album_data (items); - return FALSE; - } - if (setup->verbose) printf (" done.\n"); - - - /* Recurse to sub-albums (in case of album index) */ - if (items->type == GALLERY_TYPE_INDEX) - { - if (items->items->len > 0) { - for (i = 0; i < items->items->len; i++) { - item = g_ptr_array_index (items->items, i); - if (item == NULL) { - fprintf (stderr, "build_tree: error getting item %d\n", i); - continue; - } - if (item->type == INDEX_ITEM_TYPE_PICTURE) { - s1 = g_strconcat (src_tree, "/", item->path, "/", NULL); - s2 = g_strconcat (dst_dir, "/", item->path, "/", NULL); - build_tree (setup, s1, s2, items, i); - g_free (s1); - g_free (s2); - } - } - } - } - - /* Generate separate image pages (in case of album) */ - if (items->type == GALLERY_TYPE_ALBUM) - { - if (items->items->len > 0) { - for (i = 0; i < items->items->len; i++) { - item = g_ptr_array_index (items->items, i); - if (item == NULL) { - fprintf (stderr, "build_tree: error getting item %d\n", i); - continue; - } - if (item->type == INDEX_ITEM_TYPE_PICTURE) { - imgname = g_path_get_basename ((item->path == NULL && item->preview) ? item->preview : item->path); - if (setup->verbose) printf ("Writing '%s%s' ...", imgname, GET_EXT (setup->index_file_name)); - s1 = g_strconcat (setup->real_templates_dir, "/", setup->template_photo, NULL); - s2 = g_strconcat (items->base_dir, "/", (item->path == NULL && item->preview) ? item->preview : item->path, NULL); - s3 = g_strconcat (dst_dir, "/", imgname, GET_EXT (setup->index_file_name), NULL); - res = write_html_image (setup, s1, s2, s3, item, items); - g_free (s1); - g_free (s2); - g_free (s3); - g_free (imgname); - if (! res ) continue; - if (setup->verbose) printf (" done.\n"); - } - } - } - } - - /* Copy extra files */ - mirror_files (setup, items->extra_files, src_tree, dst_dir, "Copying extra files: "); - - printf ("*** Leaving directory '%s'\n", src_tree); - free_album_data (items); - - return TRUE; -} diff --git a/src/generators.h b/src/generators.h index c87e8a3..584cff3 100644 --- a/src/generators.h +++ b/src/generators.h @@ -19,6 +19,16 @@ #include "items.h" + +/* + * generate_image: generate needed image sizes + */ +void generate_image (TGallerySetup *setup, + TAlbum *items, + TIndexItem *item, + unsigned int item_index, + const char *dst_dir); + /* * write_html_album: process album and index template files * @@ -28,9 +38,9 @@ * */ gboolean write_html_album (TGallerySetup *setup, - const char *template_src, - const char *dst, - TAlbum *items); + const char *template_src, + const char *dst, + TAlbum *items); /* * write_html_image: process single image template file @@ -43,22 +53,8 @@ gboolean write_html_album (TGallerySetup *setup, * */ gboolean write_html_image (TGallerySetup *setup, - const char *template_src, - const char *original_img, - const char *dst, - TIndexItem *item, - TAlbum *parent_items); - -/* - * build_tree: generate complete gallery tree based on source xml files - * - * src_tree = source directory of the items - * dst_dir = destination of the generated items - * parent_index = parent album to determine our descent in the tree - * - */ -gboolean build_tree (TGallerySetup *setup, - const char *src_tree, - const char *dst_dir, - TAlbum *parent_index); - + const char *template_src, + const char *original_img, + const char *dst, + TIndexItem *item, + TAlbum *parent_items); diff --git a/src/items.c b/src/items.c index 5cce7c3..255ef5f 100644 --- a/src/items.c +++ b/src/items.c @@ -266,6 +266,10 @@ free_album_data (TAlbum *album) free (item->preview); if (item->border_style) free (item->border_style); + if (item->gen_img_src) + free (item->gen_img_src); + if (item->gen_thumb) + free (item->gen_thumb); free (item); } } diff --git a/src/items.h b/src/items.h index 0b053b9..daaefb0 100644 --- a/src/items.h +++ b/src/items.h @@ -70,6 +70,12 @@ typedef struct { char *border_style; TIndexItemType type; gboolean hidden; + + /* generated item info */ + char *gen_img_src; + char *gen_thumb; + gboolean gen_portrait; + gboolean gen_done; } TIndexItem; diff --git a/src/job-manager.c b/src/job-manager.c new file mode 100644 index 0000000..352229b --- /dev/null +++ b/src/job-manager.c @@ -0,0 +1,362 @@ +/* Cataract - Static web photo gallery generator + * Copyright (C) 2009 Tomas Bzatek <tbzatek@users.sourceforge.net> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <errno.h> +#include <sys/stat.h> +#include <unistd.h> + +#include <glib.h> + +#include <config.h> + +#include "setup.h" +#include "items.h" +#include "gallery-utils.h" +#include "generators.h" + + + +#define DEFAULT_DATA_DIR_MODE S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH + + +typedef struct { + TGallerySetup *setup; + TAlbum *items; + const char *dst_dir; +} TJob; + + + + +static void +mirror_files (TGallerySetup *setup, char **files, const char *src_tree, const char *dst_dir, const char *label) +{ + char **extra; + char *s1, *s2, *s3; + + if (files && g_strv_length (files) > 0) { + extra = files; + if (setup->verbose) printf ("%s", label); + while (*extra) { + s1 = g_strstrip (*extra); + if (strlen (s1) > 0) { + /* First create target directory if it doesn't exist */ + s2 = g_strconcat (dst_dir, "/", s1, NULL); + s3 = g_path_get_dirname (s2); + g_free (s2); + if (g_mkdir_with_parents (s3, DEFAULT_DATA_DIR_MODE)) { + fprintf (stderr, "error making target extra directory '%s': %s\n", s3, strerror (errno)); + g_free (s3); + continue; + } + g_free (s3); + + /* Copy the file */ + if (setup->verbose) printf (" %s", s1); + s2 = g_strconcat (src_tree, "/", s1, NULL); + s3 = g_strconcat (dst_dir, "/", s1, NULL); + copy_file (s2, s3); + g_free (s2); + g_free (s3); + } + extra++; + } + if (setup->verbose) printf ("\n"); + } +} + + + + +G_LOCK_DEFINE (items); +G_LOCK_DEFINE (items_print); + +/* run in a cycle, returns when all completed */ +static gpointer +thread_func (gpointer data) +{ + TIndexItem *item; + char *imgname; + int i; + char *s1, *s2, *s3; + int total, index, real_index; + TJob *job = data; + + do { + item = NULL; + total = 0; + real_index = -1; + index = -1; + G_LOCK (items); + if (job->items->items->len > 0) { + for (i = 0; i < job->items->items->len; i++) { + TIndexItem *item_tmp = g_ptr_array_index (job->items->items, i); + if (item_tmp == NULL) { + fprintf (stderr, "run_job: error getting item %d\n", i); + continue; + } + if (item_tmp->type == INDEX_ITEM_TYPE_PICTURE) { + total++; + if (item_tmp->gen_done == FALSE && item == NULL) { + item_tmp->gen_done = TRUE; + item = item_tmp; + index = total; + real_index = i; + } + } + } + } + G_UNLOCK (items); + + /* actually do some work */ + if (item != NULL) { + imgname = g_path_get_basename ((item->path == NULL && item->preview) ? item->preview : item->path); + G_LOCK (items_print); + if (job->setup->verbose) + g_print (" [%d/%d] Processing item \"%s\"\n", index, total, imgname); + G_UNLOCK (items_print); + + generate_image (job->setup, job->items, item, real_index, job->dst_dir); + if (job->items->type == GALLERY_TYPE_ALBUM) { + s1 = g_strconcat (job->setup->real_templates_dir, "/", job->setup->template_photo, NULL); + s2 = g_strconcat (job->items->base_dir, "/", (item->path == NULL && item->preview) ? item->preview : item->path, NULL); + s3 = g_strconcat (job->dst_dir, "/", imgname, GET_EXT (job->setup->index_file_name), NULL); + write_html_image (job->setup, s1, s2, s3, item, job->items); + g_free (s1); + g_free (s2); + g_free (s3); + } + g_free (imgname); + } + + } while (item != NULL); + return NULL; +} + + + +/* + * build_tree: generate complete gallery tree based on source xml files + * + * src_tree = source directory of the items + * dst_dir = destination of the generated items + * parent_index = parent album to determine our descent in the tree + * + */ +gboolean +build_tree (TGallerySetup *setup, + const char *src_tree, + const char *dst_dir, + TAlbum *parent_index, + int parent_item_index, + int jobs) +{ + char *idx_file; + TAlbum *items; + TIndexItem *item; + char *s1, *s2, *s3; + char *thumb_dir; + char *img_big_dir; + char *img_orig_dir; + char *template; + gboolean res; + int i; + TJob *job; + GError *error; + GThread *thread; + GList *thread_list; + + printf ("Processing directory \"%s\"\n", src_tree); + #ifdef __DEBUG_ALL__ + printf ("setup->real_templates_dir = %s\n", setup->real_templates_dir); + #endif + + /* Check access permissions */ + if (access (src_tree, R_OK)) { + fprintf (stderr, "error accessing source directory: %s\n", strerror (errno)); + return FALSE; + } + if (access (dst_dir, R_OK | W_OK | X_OK)) { + if (g_mkdir_with_parents (dst_dir, DEFAULT_DATA_DIR_MODE)) { + fprintf (stderr, "error creating destination directory: %s\n", strerror (errno)); + return FALSE; + } + } + + /* Check the index file */ + idx_file = g_strconcat (src_tree, "/index.xml", NULL); + if (access (idx_file, R_OK)) { + fprintf (stderr, "error accessing index file '%s': %s\n", idx_file, strerror (errno)); + g_free (idx_file); + return FALSE; + } + + /* Read the index file and fill items array */ + items = malloc (sizeof (TAlbum)); + memset (items, 0, sizeof (TAlbum)); + if (! parse_album_xml (idx_file, items)) { + fprintf (stderr, "error reading index file '%s'\n", idx_file); + g_free (idx_file); + free_album_data (items); + return FALSE; + } + g_free (idx_file); + items->parent_index = parent_index; + items->parent_item_index = parent_item_index; + + /* Copy support files */ + if (! setup->support_files_use_common_root || parent_index == NULL) { + /* copy only if we're in root level or old-style is active */ + mirror_files (setup, setup->template_files, setup->real_templates_dir, dst_dir, " Copying template files: "); + + /* favicon */ + if (setup->favicon_file && strlen (setup->favicon_file) > 0) { + if (setup->verbose) printf (" Copying favicon: %s\n", setup->favicon_file); + s3 = g_path_get_dirname (setup->setup_xml_path); + s1 = g_strconcat (s3, "/", setup->favicon_file, NULL); + s2 = g_strconcat (dst_dir, "/", setup->favicon_file, NULL); + copy_file (s1, s2); + g_free (s1); + g_free (s2); + g_free (s3); + } + } + + /* Prepare target thumbnail directory */ + thumb_dir = g_strconcat (dst_dir, "/", THUMBNAIL_DIR, NULL); + if (access (thumb_dir, R_OK | W_OK | X_OK)) + if (g_mkdir_with_parents (thumb_dir, DEFAULT_DATA_DIR_MODE)) { + fprintf (stderr, "error making target thumbnail directory: %s\n", strerror (errno)); + g_free (thumb_dir); + free_album_data (items); + return FALSE; + } + g_free (thumb_dir); + + /* Prepare target preview and orig directories */ + if (items->type == GALLERY_TYPE_ALBUM) + { + res = TRUE; + img_big_dir = g_strconcat (dst_dir, "/", IMG_BIG_DIR, NULL); + img_orig_dir = g_strconcat (dst_dir, "/", IMG_ORIG_DIR, NULL); + if (access (img_big_dir, R_OK | W_OK | X_OK)) + if (g_mkdir_with_parents (img_big_dir, DEFAULT_DATA_DIR_MODE)) { + fprintf (stderr, "error making target preview directory: %s\n", strerror (errno)); + res = FALSE; + } + if (access (img_orig_dir, R_OK | W_OK | X_OK)) + if (g_mkdir_with_parents (img_orig_dir, DEFAULT_DATA_DIR_MODE)) { + fprintf (stderr, "error making target full size directory: %s\n", strerror (errno)); + res = FALSE; + } + g_free (img_big_dir); + g_free (img_orig_dir); + if (! res) { + free_album_data (items); + return FALSE; + } + } + + /* Generate images + particular html pages */ + job = g_new0 (TJob, 1); + job->items = items; + job->setup = setup; + job->dst_dir = dst_dir; + +#ifdef G_THREADS_ENABLED + thread_list = NULL; + + for (i = 0; i < jobs; i++) + { + error = NULL; + thread = g_thread_create (thread_func, job, TRUE, &error); + if (thread) + thread_list = g_list_append (thread_list, thread); + if (error) { + fprintf (stderr, "build_tree: error starting new thread: %s\n", error->message); + g_clear_error (&error); + } + } + + /* wait for threads are finished */ + GList *l; + for (l = thread_list; l != NULL; l = l->next) { + g_thread_join (l->data); + } + /* TODO: free threads? */ + g_list_free (thread_list); + +#else /* threads are disabled */ + thread_func (job); +#endif + g_free (job); + + + /* Start generating items */ + if (items->type == GALLERY_TYPE_INDEX) + template = g_strconcat ("/", setup->template_index, NULL); + else + if (items->type == GALLERY_TYPE_ALBUM) + template = g_strconcat ("/", setup->template_album, NULL); + else + /* default to album */ + template = g_strconcat ("/", setup->template_album, NULL); + + if (setup->verbose) printf (" Writing %s\n", setup->index_file_name); + s1 = g_strconcat (setup->real_templates_dir, template, NULL); + s2 = g_strconcat (dst_dir, "/", setup->index_file_name, NULL); + res = write_html_album (setup, s1, s2, items); + g_free (s1); + g_free (s2); + g_free (template); + if (! res) { + fprintf (stderr, "error generating target index file\n"); + free_album_data (items); + return FALSE; + } + + + /* Recurse to sub-albums (in case of album index) */ + if (items->type == GALLERY_TYPE_INDEX) + { + if (items->items->len > 0) { + for (i = 0; i < items->items->len; i++) { + item = g_ptr_array_index (items->items, i); + if (item == NULL) { + fprintf (stderr, "build_tree: error getting item %d\n", i); + continue; + } + if (item->type == INDEX_ITEM_TYPE_PICTURE) { + s1 = g_strconcat (src_tree, "/", item->path, "/", NULL); + s2 = g_strconcat (dst_dir, "/", item->path, "/", NULL); + build_tree (setup, s1, s2, items, i, jobs); + g_free (s1); + g_free (s2); + } + } + } + } + + /* Copy extra files */ + mirror_files (setup, items->extra_files, src_tree, dst_dir, " Copying extra files: "); + + free_album_data (items); + return TRUE; +} diff --git a/src/job-manager.h b/src/job-manager.h new file mode 100644 index 0000000..13f08e0 --- /dev/null +++ b/src/job-manager.h @@ -0,0 +1,36 @@ +/* Cataract - Static web photo gallery generator + * Copyright (C) 2009 Tomas Bzatek <tbzatek@users.sourceforge.net> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include "setup.h" +#include "items.h" + + +/* + * build_tree: generate complete gallery tree based on source xml files + * + * src_tree = source directory of the items + * dst_dir = destination of the generated items + * parent_index = parent album to determine our descent in the tree + * + */ +gboolean build_tree (TGallerySetup *setup, + const char *src_tree, + const char *dst_dir, + TAlbum *parent_index, + int parent_item_index, + int jobs); + diff --git a/src/jpeg-utils.cpp b/src/jpeg-utils.cpp index b4abeef..483bf4a 100644 --- a/src/jpeg-utils.cpp +++ b/src/jpeg-utils.cpp @@ -292,7 +292,6 @@ resize_image (const char *src, const char *dst, MagickWand *magick_wand; /* Read an image. */ - MagickWandGenesis(); magick_wand = NewMagickWand(); status = MagickReadImage (magick_wand, src); if (status == MagickFalse) @@ -308,7 +307,6 @@ resize_image (const char *src, const char *dst, if (status == MagickFalse) ThrowWandException (magick_wand); magick_wand = DestroyMagickWand (magick_wand); - MagickWandTerminus(); return TRUE; } @@ -339,7 +337,6 @@ get_image_sizes (const char *img, *height = -1; /* Read an image. */ - MagickWandGenesis(); magick_wand = NewMagickWand(); status = MagickPingImage (magick_wand, img); if (status == MagickFalse) @@ -348,7 +345,6 @@ get_image_sizes (const char *img, *height = MagickGetImageHeight (magick_wand); magick_wand = DestroyMagickWand (magick_wand); - MagickWandTerminus(); } |
