/* Cataract - Static web photo gallery generator * Copyright (C) 2008 Tomas Bzatek * * 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 #include #include #include #include #include #include #include #include #include "setup.h" #include "job-manager.h" #include "stats.h" #include "atom-writer.h" #include "gallery-utils.h" #include "jpeg-utils.h" /* Commandline arguments */ static gchar *source_dir = NULL; static gchar *dst_dir = NULL; static gboolean verbose = FALSE; static gboolean update = FALSE; static gboolean fullsize = FALSE; static gboolean dont_strip_unused_tags = FALSE; static gboolean warn_resize = FALSE; static int jobs = 0; /* * parse_cmd: parse commandline and fill global variable parameters */ gboolean parse_cmd (int argc, char *argv[]) { 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 the source structure", "PATH" }, { "output", 'o', 0, G_OPTION_ARG_STRING, &dst_dir, "Generate files to the specified directory instead of current", "DIR" }, { "jobs", 'j', 0, G_OPTION_ARG_INT, &jobs, "Allow N jobs at once" #ifdef HAVE_G_GET_NUM_PROCESSORS " (default=autodetect)", #else " (default=1)", #endif "N" }, { "update", 'u', 0, G_OPTION_ARG_NONE, &update, "Update the output structure", NULL }, { "fullsize", 'f', 0, G_OPTION_ARG_NONE, &fullsize, "Override the nofullsize switch and generate full gallery", NULL }, { "debug-dont-strip-unused-tags", 0, 0, G_OPTION_ARG_NONE, &dont_strip_unused_tags, "Don't strip unused/unknown template tags", NULL }, { "debug-warn-resize", 0, 0, G_OPTION_ARG_NONE, &warn_resize, "Warn when image is being resized", NULL }, { NULL } }; GError *error = NULL; GOptionContext *context; gchar *s1; g_set_prgname ("cgg"); context = g_option_context_new ("- web gallery generator"); s1 = g_strdup_printf ("cgg v%s [%s] %s", VERSION, APP_BUILD_DATE, APP_COPYRIGHT_STRING); g_option_context_set_summary (context, s1); g_free (s1); g_option_context_add_main_entries (context, entries, NULL); if (argc == 1) { s1 = g_option_context_get_help (context, TRUE, NULL); g_print ("%s", s1); g_free (s1); g_option_context_free (context); return FALSE; } if (! g_option_context_parse (context, &argc, &argv, &error)) { g_print ("option parsing failed: %s\n", error->message); s1 = g_option_context_get_help (context, TRUE, NULL); g_print ("%s", s1); g_free (s1); g_option_context_free (context); return FALSE; } g_option_context_free (context); return TRUE; } int main (int argc, char* argv[]) { TGallerySetup *setup; time_t time_start = time (NULL); time_t time_stop; gchar *s; gchar *templates_basedir; TPathInfo *path_info; /* * this initialize the library and check potential ABI mismatches * between the version it was compiled for and the actual shared * library used. */ LIBXML_TEST_VERSION; #ifndef HAVE_GLIB_NEW_THREADS g_thread_init (NULL); #endif /* Initialize imaging libraries */ init_jpeg_utils (); /* Parse commandline */ if (! parse_cmd (argc, argv)) return -1; if (! source_dir || access (source_dir, R_OK)) { fprintf (stderr, "error: source directory must be specified and pointing to valid structure\n"); return -4; } if (! dst_dir) { fprintf (stderr, "error: target directory must be specified\n"); return -5; } /* Read gallery settings */ setup = find_setup_xml (); if (! setup) { fprintf (stderr, "error: could not parse gallery settings file\n"); return -2; } if (SETUP_IS_LEGACY (setup)) { /* Design legacy mode */ setup->design = makeup_legacy_design (setup->setup_xml_path); if (! setup->design) { fprintf (stderr, "error: could not parse design from legacy setup file\n"); return -6; } } else { /* Design native mode */ setup->design = parse_design_setup_xml (setup->design_setup_file); if (! setup->design) { fprintf (stderr, "error: could not parse design setup file\n"); return -6; } } if (! validate_design_setup (setup)) return -7; templates_basedir = find_design_directory (setup); if (templates_basedir == NULL) { fprintf (stderr, "error: could not determine design templates directory\n"); return -3; } stats_errors = 0; stats_dirs = 0; stats_images = 0; /* Print banner */ if (verbose) { printf ("cgg v%s [%s]\n\n", VERSION, APP_BUILD_DATE); printf ("Using setup file \"%s\"\n", setup->setup_xml_path); if (SETUP_IS_NEWER (setup)) printf ("WARNING: Reported setup.xml version is greater than current cgg engine, consider upgrading or expect random issues\n"); if (SETUP_IS_LEGACY (setup)) printf ("WARNING: Parsing setup.xml in legacy mode\n"); } /* Setup number of threads */ if (jobs == 0) { #ifdef HAVE_G_GET_NUM_PROCESSORS jobs = g_get_num_processors (); #else jobs = 1; #endif if (verbose) printf ("Number of jobs: %d (autodetected)\n", jobs); } else { if (verbose) printf ("Number of jobs: %d\n", jobs); } /* Setup feeds */ news_feed = NULL; if (setup->feed_enabled) { news_feed = atom_writer_new (); atom_writer_set_title (news_feed, setup->feed_title ? setup->feed_title : setup->site_title); } /* Start building the gallery tree */ setup->verbose = verbose; setup->update_mode = update; setup->override_nofullsize = fullsize; setup->strip_unused_tags = ! dont_strip_unused_tags; setup->warn_resize = warn_resize; path_info = g_malloc0 (sizeof (TPathInfo)); path_info->templates_root = templates_basedir; path_info->source_root = g_strdup (source_dir); path_info->src_dir = g_strdup (source_dir); path_info->dest_root = g_strdup (dst_dir); path_info->dest_dir = g_strdup (dst_dir); path_info->album_path = g_strdup ("/"); build_tree (setup, path_info, NULL, -1, jobs); free_path_info (path_info); /* Write feeds */ if (news_feed) { if (verbose) printf ("Writing Atom feed: %s\n", setup->feed_filename); if (setup->location_base_url == NULL || strlen (setup->location_base_url) == 0) log_error ("Error: feed base URL not defined!\n"); else if (setup->feed_filename == NULL || strlen (setup->feed_filename) == 0) log_error ("Error: feed file name not defined!\n"); else { atom_writer_set_base_url (news_feed, setup->location_base_url); s = g_build_filename (setup->location_base_url, setup->feed_filename, NULL); atom_writer_set_feed_url (news_feed, s); g_free (s); s = g_strdup_printf ("%s/%s", dst_dir, setup->feed_filename); atom_writer_write_to_file (news_feed, s, setup); g_free (s); } atom_writer_free (news_feed); } /* Write stats */ if (verbose) { time_stop = time (NULL); printf ("\nProcessed %d images in %d albums, elapsed time = %dm %ds\n", stats_images, stats_dirs, (int) ((time_stop - time_start) / 60), (int) ((time_stop - time_start) % 60)); if (stats_errors == 1) printf ("%d error occured.\n", stats_errors); if (stats_errors > 1) printf ("%d errors occured.\n", stats_errors); } destroy_jpeg_utils (); /* Cleanup function for the XML library. */ xmlCleanupParser(); g_free (source_dir); g_free (dst_dir); free_setup_data (setup); return 0; }