summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTomas Bzatek <tbzatek@users.sourceforge.net>2009-03-28 22:00:06 +0100
committerTomas Bzatek <tbzatek@users.sourceforge.net>2009-03-28 22:00:06 +0100
commit29aeb95a28d518944f1eb268f93a96cbb9dff7f2 (patch)
tree154c8870d72229a95f0ab0bd93f8c4d3048b9f91 /src
parentd9ff1192a7b5eb7defca68e90e06c68e9b986c94 (diff)
downloadcataract-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.am2
-rw-r--r--src/cgg.c23
-rw-r--r--src/gallery-utils.h2
-rw-r--r--src/generators.c345
-rw-r--r--src/generators.h40
-rw-r--r--src/items.c4
-rw-r--r--src/items.h6
-rw-r--r--src/job-manager.c362
-rw-r--r--src/job-manager.h36
-rw-r--r--src/jpeg-utils.cpp4
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 \
diff --git a/src/cgg.c b/src/cgg.c
index ea48d52..92debc8 100644
--- a/src/cgg.c
+++ b/src/cgg.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();
}