home *** CD-ROM | disk | FTP | other *** search
- /* gap_decode_xanim.c
- * 1999.11.22 hof (Wolfgang Hofer)
- *
- * GAP ... Gimp Animation Plugins
- *
- * This Module contains:
- *
- * GIMP/GAP-frontend interface for XANIM exporting edition from loki entertainmaint
- * Call xanim exporting edition (the loki version)
- * To split any xanim supported video into
- * anim frames (single images on disk)
- * Audio can also be extracted.
- *
- * xanim exporting edition is available at:
- * Web: http://heroine.linuxbox.com/toys.html
- * http://www.lokigames.com/development/smjpeg.php3
- * download: http://heroine.linuxbox.com/xanim_exporting_edition.tar.gz
- * http://www.lokigames.com/development/download/smjpeg/xanim2801-loki090899.tar.gz
- * Send comments or questions to smjpeg@lokigames.com.
- *
- * Warning: This Module needs UNIX environment to run.
- * It uses programs and commands that are NOT available
- * on other Operating Systems (Win95, NT ...)
- *
- * - xanim 2.80 exporting edition with extensions from loki entertainment.
- * set environment GAP_XANIM_PROG to configure where to find xanim
- * (default: search xanim in your PATH)
- * - grep (UNIX command)
- * - rm (UNIX command is used to delete by wildcard (expanded by /bin/sh)
- * and to delete a directory with all files
- */
- /* The GIMP -- an image manipulation program
- * Copyright (C) 1995 Spencer Kimball and Peter Mattis
- *
- * 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
- * (at your option) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
- /* revision history
- * 1.1.29b; 2000/11/30 hof: used g_snprintf
- * 1.1.17b; 2000/02/26 hof: bugfixes
- * 1.1.14a; 1999/11/22 hof: fixed gcc warning (too many arguments for format)
- * 1.1.13a; 1999/11/22 hof: first release
- */
-
- /* SYTEM (UNIX) includes */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/types.h>
- #include <signal.h>
- #include <sys/stat.h>
- #include <unistd.h>
-
- /* GIMP includes */
- #include "gtk/gtk.h"
- #include "config.h"
- #include "libgimp/stdplugins-intl.h"
- #include "libgimp/gimp.h"
-
- #ifdef G_OS_WIN32
- #include <io.h>
- # ifndef S_ISDIR
- # define S_ISDIR(m) ((m) & _S_IFDIR)
- # endif
- # ifndef S_ISREG
- # define S_ISREG(m) ((m) & _S_IFREG)
- # endif
- #endif
-
- /* GAP includes */
- #include "gap_lib.h"
- #include "gap_arr_dialog.h"
- #include "gap_decode_xanim.h"
-
- extern int gap_debug; /* ==0 ... dont print debug infos */
-
- static char *global_xanim_input_dir = "input";
-
- gchar global_xanim_prog[500];
- gchar *global_errlist = NULL;
-
- gint32 global_delete_number;
-
- #define MKDIR_MODE (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH )
-
- /* ============================================================================
- * p_xanim_info
- * ============================================================================
- */
- static int
- p_xanim_info(char *errlist)
- {
- t_arr_arg argv[20];
- t_but_arg b_argv[2];
-
- int l_idx;
- int l_rc;
-
-
- l_idx = 0;
- p_init_arr_arg(&argv[l_idx], WGT_LABEL_LEFT);
- argv[l_idx].label_txt = _("Conditions to run the xanim based video split");
-
- l_idx++;
- p_init_arr_arg(&argv[l_idx], WGT_LABEL_LEFT);
- argv[l_idx].label_txt = "";
-
- l_idx++;
- p_init_arr_arg(&argv[l_idx], WGT_LABEL_LEFT);
- argv[l_idx].label_txt = _("1.) xanim 2.80.0 exporting edition (the loki version)");
-
- l_idx++;
- p_init_arr_arg(&argv[l_idx], WGT_LABEL_LEFT);
- argv[l_idx].label_txt = _(" must be installed somewhere in your PATH");
-
- l_idx++;
- p_init_arr_arg(&argv[l_idx], WGT_LABEL_LEFT);
- argv[l_idx].label_txt = _(" you can get xanim exporting edition at");
-
- l_idx++;
- p_init_arr_arg(&argv[l_idx], WGT_LABEL_LEFT);
- argv[l_idx].label_txt = " http://heroine.linuxbox.com/toys.html";
-
- l_idx++;
- p_init_arr_arg(&argv[l_idx], WGT_LABEL_LEFT);
- argv[l_idx].label_txt = " http://www.lokigames.com/development/download/smjpeg/xanim2801-loki090899.tar.gz";
-
- l_idx++;
- p_init_arr_arg(&argv[l_idx], WGT_LABEL_LEFT);
- argv[l_idx].label_txt = "";
-
- l_idx++;
- p_init_arr_arg(&argv[l_idx], WGT_LABEL_LEFT);
- argv[l_idx].label_txt = _("2.) if your xanim exporting edition is not in your PATH or is not named xanim");
-
- l_idx++;
- p_init_arr_arg(&argv[l_idx], WGT_LABEL_LEFT);
- argv[l_idx].label_txt = _(" you have to set Environment variable GAP_XANIM_PROG ");
-
- l_idx++;
- p_init_arr_arg(&argv[l_idx], WGT_LABEL_LEFT);
- argv[l_idx].label_txt = _(" to your xanim exporting program and restart gimp");
-
- l_idx++;
- p_init_arr_arg(&argv[l_idx], WGT_LABEL_LEFT);
- argv[l_idx].label_txt = "";
-
- l_idx++;
- p_init_arr_arg(&argv[l_idx], WGT_LABEL_LEFT);
- argv[l_idx].label_txt = _("An ERROR occured while trying to call xanim:");
-
- l_idx++;
- p_init_arr_arg(&argv[l_idx], WGT_LABEL_LEFT);
- argv[l_idx].label_txt = "--------------------------------------------";
-
-
- l_idx++;
- p_init_arr_arg(&argv[l_idx], WGT_LABEL_LEFT);
- argv[l_idx].label_txt = errlist;
-
- l_idx++;
-
- /* the Action Button */
- b_argv[0].but_txt = _("Cancel");
- b_argv[0].but_val = -1;
- b_argv[1].but_txt = _("OK");
- b_argv[1].but_val = 0;
-
- l_rc = p_array_std_dialog(_("XANIM Information"),
- "",
- l_idx, argv, /* widget array */
- 1, b_argv, /* button array */
- -1);
-
- return (l_rc);
- } /* end p_xanim_info */
-
-
- /* ============================================================================
- * p_xanim_dialog
- * ============================================================================
- */
- static int
- p_xanim_dialog (gint32 *first_frame,
- gint32 *last_frame,
- char *filename,
- gint32 len_filename,
- char *basename,
- gint32 len_basename,
- t_gap_xa_formats *Format,
- gint32 *extract_video,
- gint32 *extract_audio,
- gint32 *jpeg_quality,
- gint32 *autoload,
- gint32 *run_xanim_asynchron)
- {
- #define XADIALOG_NUM_ARGS 12
- static t_arr_arg argv[XADIALOG_NUM_ARGS];
- static char *radio_args[3] = { "XCF", "PPM", "JPEG" };
-
- p_init_arr_arg(&argv[0], WGT_FILESEL);
- argv[0].label_txt = _("Video:");
- argv[0].help_txt = _("Name of a videofile to READ by xanim.\n"
- "Frames are extracted from the videofile\n"
- "and written to seprate diskfiles.\n"
- "xanim exporting edition is required.");
- argv[0].text_buf_len = len_filename;
- argv[0].text_buf_ret = filename;
- argv[0].entry_width = 250;
-
- p_init_arr_arg(&argv[1], WGT_INT_PAIR);
- argv[1].label_txt = _("From:");
- argv[1].help_txt = _("Framenumber of 1st frame to extract");
- argv[1].constraint = FALSE;
- argv[1].int_min = 0;
- argv[1].int_max = 9999;
- argv[1].int_ret = 0;
- argv[1].umin = 0;
- argv[1].entry_width = 80;
-
- p_init_arr_arg(&argv[2], WGT_INT_PAIR);
- argv[2].label_txt = _("To:");
- argv[2].help_txt = _("Framenumber of last frame to extract");
- argv[2].constraint = FALSE;
- argv[2].int_min = 0;
- argv[2].int_max = 9999;
- argv[2].int_ret = 9999;
- argv[2].umin = 0;
- argv[2].entry_width = 80;
-
- p_init_arr_arg(&argv[3], WGT_FILESEL);
- argv[3].label_txt = _("Framenames:");
- argv[3].help_txt = _("Basename for the AnimFrames to write on disk\n"
- "(framenumber and extension is added)");
- argv[3].text_buf_len = len_basename;
- argv[3].text_buf_ret = basename;
- argv[3].entry_width = 250;
-
- p_init_arr_arg(&argv[4], WGT_OPTIONMENU);
- argv[4].label_txt = _("Format");
- argv[4].help_txt = _("Fileformat for the extracted AnimFrames\n"
- "(xcf is extracted as ppm and converted to xcf)");
- argv[4].radio_argc = 3;
- argv[4].radio_argv = radio_args;
- argv[4].radio_ret = 0;
-
- p_init_arr_arg(&argv[5], WGT_TOGGLE);
- argv[5].label_txt = _("Extract Frames");
- argv[5].help_txt = _("Enable extraction of Frames");
- argv[5].int_ret = 1;
-
- p_init_arr_arg(&argv[6], WGT_TOGGLE);
- argv[6].label_txt = _("Extract Audio");
- argv[6].help_txt = _("Enable extraction of audio to raw audiofile\n"
- "(frame range limits are ignored for audio)");
- argv[6].int_ret = 0;
-
- p_init_arr_arg(&argv[7], WGT_INT_PAIR);
- argv[7].label_txt = _("Jpeg Quality:");
- argv[7].help_txt = _("Quality for resulting Jpeg frames\n"
- "(is ignored when other formats are used)");
- argv[7].constraint = TRUE;
- argv[7].int_min = 0;
- argv[7].int_max = 100;
- argv[7].int_ret = 90;
-
- p_init_arr_arg(&argv[8], WGT_LABEL);
- argv[8].label_txt = "";
-
- p_init_arr_arg(&argv[9], WGT_TOGGLE);
- argv[9].label_txt = _("Open");
- argv[9].help_txt = _("Open the 1st one of the extracted frames");
- argv[9].int_ret = 1;
-
- p_init_arr_arg(&argv[10], WGT_TOGGLE);
- argv[10].label_txt = _("Run asynchronously");
- argv[10].help_txt = _("Run xanim asynchronously and delete unwanted frames\n"
- "(out of the specified range) while xanim is still running");
- argv[10].int_ret = 1;
-
- p_init_arr_arg(&argv[11], WGT_LABEL_LEFT);
- argv[11].label_txt = _("\nWarning: xanim 2.80 has only limited MPEG support.\n"
- "Most of the frames (type P and B) will be skipped.");
-
- if(TRUE == p_array_dialog(_("Split any Xanim readable Video to Frames"),
- _("Select Frame Range"), XADIALOG_NUM_ARGS, argv))
- {
- if(argv[1].int_ret < argv[2].int_ret )
- {
- *first_frame = (long)(argv[1].int_ret);
- *last_frame = (long)(argv[2].int_ret);
- }
- else
- {
- *first_frame = (long)(argv[2].int_ret);
- *last_frame = (long)(argv[1].int_ret);
- }
- *Format = (t_gap_xa_formats)(argv[4].int_ret);
- *extract_video = (long)(argv[5].int_ret);
- *extract_audio = (long)(argv[6].int_ret);
- *jpeg_quality = (long)(argv[7].int_ret);
- *autoload = (long)(argv[9].int_ret);
- *run_xanim_asynchron = (long)(argv[10].int_ret);
- return (0); /* OK */
- }
- else
- {
- return -1; /* Cancel */
- }
-
-
- } /* end p_xanim_dialog */
-
-
- static gint
- p_overwrite_dialog(char *filename, gint overwrite_mode)
- {
- static t_but_arg l_argv[3];
- static t_arr_arg argv[1];
-
- if(p_file_exists(filename))
- {
- if (overwrite_mode < 1)
- {
- l_argv[0].but_txt = _("Overwrite Frame");
- l_argv[0].but_val = 0;
- l_argv[1].but_txt = _("Overwrite All");
- l_argv[1].but_val = 1;
- l_argv[2].but_txt = _("Cancel");
- l_argv[2].but_val = -1;
-
- p_init_arr_arg(&argv[0], WGT_LABEL);
- argv[0].label_txt = filename;
-
- return(p_array_std_dialog ( _("GAP Question"),
- _("File already exists"),
- 1, argv,
- 3, l_argv, -1));
- }
- }
- return (overwrite_mode);
- }
-
-
-
-
- static void
- p_build_xanim_framename(char *framename, gint32 sizeof_framename, gint32 frame_nr, char *ext)
- {
- g_snprintf(framename, sizeof_framename, "%s/frame%d.%s",
- global_xanim_input_dir,
- (int)frame_nr,
- ext);
- }
-
- static void
- p_build_gap_framename(char *framename, gint32 sizeof_framename, gint32 frame_nr, char *basename, char *ext)
- {
- g_snprintf(framename, sizeof_framename, "%s%04d.%s", basename, (int)frame_nr, ext);
- }
-
- int
- p_is_directory(char *fname)
- {
- struct stat l_stat_buf;
-
- /* get File status */
- if (0 != stat(fname, &l_stat_buf))
- {
- /* stat error (file does not exist) */
- return(0);
- }
-
- if(S_ISDIR(l_stat_buf.st_mode))
- {
- return(1);
- }
-
- return(0);
- } /* end p_is_directory */
-
- void
- p_dirname(char *fname)
- {
- int l_idx;
-
- l_idx = strlen(fname) -1;
- while(l_idx > 0)
- {
- if(fname[l_idx] == G_DIR_SEPARATOR)
- {
- fname[l_idx] = '\0';
- return;
- }
- l_idx--;
- }
- *fname = '\0';
- }
-
- static void
- p_init_xanim_global_name()
- {
- char *l_env;
-
- l_env = g_getenv("GAP_XANIM_PROG");
-
- if(l_env != NULL)
- {
- strcpy(global_xanim_prog, l_env);
- return;
- }
- strcpy(global_xanim_prog, "xanim"); /* default name */
- }
-
- static int
- p_convert_frames(gint32 frame_from, gint32 frame_to, char *basename, char *ext, char *ext2)
- {
- GimpParam *return_vals;
- int nreturn_vals;
- gint32 l_tmp_image_id;
- char l_first_xa_frame[200];
-
- /* load 1st one of those frames generated by xanim */
- p_build_xanim_framename(l_first_xa_frame, sizeof(l_first_xa_frame), frame_from, ext);
- l_tmp_image_id = p_load_image(l_first_xa_frame);
-
- /* convert the xanim frames (from ppm) to xcf fileformat
- * (the gap module for range convert is not linked to the frontends
- * main program, therefore i call the convert procedure by PDB-interface)
- */
- return_vals = gimp_run_procedure ("plug_in_gap_range_convert2",
- &nreturn_vals,
- GIMP_PDB_INT32, GIMP_RUN_NONINTERACTIVE, /* runmode */
- GIMP_PDB_IMAGE, l_tmp_image_id,
- GIMP_PDB_DRAWABLE, 0, /* (unused) */
- GIMP_PDB_INT32, frame_from,
- GIMP_PDB_INT32, frame_to,
- GIMP_PDB_INT32, 0, /* dont flatten */
- GIMP_PDB_INT32, 4444, /* dest type (keep type) */
- GIMP_PDB_INT32, 256, /* colors (unused) */
- GIMP_PDB_INT32, 0, /* no dither (unused) */
- GIMP_PDB_STRING, ext2, /* extension for dest. filetype */
- GIMP_PDB_STRING, basename, /* basename for dest. filetype */
- GIMP_PDB_INT32, 0, /* (unused) */
- GIMP_PDB_INT32, 0, /* (unused) */
- GIMP_PDB_INT32, 0, /* (unused) */
- GIMP_PDB_STRING, "none", /* (unused) palettename */
- GIMP_PDB_END);
-
- /* destroy the tmp image */
- gimp_image_delete(l_tmp_image_id);
-
- if (return_vals[0].data.d_status != GIMP_PDB_SUCCESS)
- {
- return(-1);
- }
-
- return(0); /* OK */
- }
-
-
- static gint32
- p_find_max_xanim_frame(gint32 from_nr, char *ext)
- {
- gint32 l_high;
- gint32 l_max_found;
- gint32 l_nr;
- gint32 l_delta;
- char l_frame[500];
-
- l_nr = from_nr;
- l_max_found = 0;
- l_high = 100000;
-
- while(1 == 1)
- {
- p_build_xanim_framename(l_frame, sizeof(l_frame), l_nr, ext);
-
- if(gap_debug) printf("DEBUG find_MAX :%s\n", l_frame);
-
- if(p_file_exists(l_frame))
- {
- l_max_found = l_nr;
- l_delta = (l_high - l_nr) / 2;
- if(l_delta == 0)
- {
- l_delta = 1;
- }
- l_nr = l_max_found + l_delta;
- }
- else
- {
- if(l_nr == from_nr) { return (-1); } /* no frames found */
-
- if(l_nr < l_high)
- {
- l_high = l_nr;
- l_nr = l_max_found + 1;
- }
- else
- {
- return(l_max_found);
- }
- }
- }
- } /* end p_find_max_xanim_frame */
-
- static int
- p_rename_frames(gint32 frame_from, gint32 frame_to, char *basename, char *ext)
- {
- gint32 l_use_mv;
- gint32 l_frame_nr;
- gint32 l_max_found;
- char l_src_frame[500];
- char l_dst_frame[500];
- gint l_overwrite_mode;
-
-
- if(gap_debug) printf("p_rename_frames:\n");
- l_use_mv = TRUE;
- l_overwrite_mode = 0;
-
-
- l_max_found = p_find_max_xanim_frame (frame_from, ext);
- if(l_max_found < 0)
- {
- global_errlist = g_strdup_printf(
- _("can't find any extracted frames,\n%s\nmaybe xanim has failed or was cancelled"),
- l_src_frame);
- return(-1);
- }
-
-
- l_frame_nr = frame_from;
-
- while (l_frame_nr <= frame_to)
- {
- p_build_xanim_framename(l_src_frame, sizeof(l_src_frame), l_frame_nr, ext);
- p_build_gap_framename(l_dst_frame, sizeof(l_dst_frame), l_frame_nr, basename, ext);
-
- if(!p_file_exists(l_src_frame))
- {
- break; /* srcfile not found, stop */
- }
-
- if (strcmp(l_src_frame, l_dst_frame) != 0)
- {
- /* check overwrite if Destination frame already exsts */
- l_overwrite_mode = p_overwrite_dialog(l_dst_frame, l_overwrite_mode);
- if (l_overwrite_mode < 0)
- {
- global_errlist = g_strdup_printf(
- _("frames are not extracted, because overwrite of %s was cancelled"),
- l_dst_frame);
- return(-1);
- }
- else
- {
- remove(l_dst_frame);
- if (p_file_exists(l_dst_frame))
- {
- global_errlist = g_strdup_printf(
- _("failed to overwrite %s (check permissions ?)"),
- l_dst_frame);
- return(-1);
- }
- }
-
- if (l_use_mv)
- {
- rename(l_src_frame, l_dst_frame);
- }
-
- if (!p_file_exists(l_dst_frame))
- {
- p_file_copy(l_src_frame, l_dst_frame);
- if (p_file_exists(l_dst_frame))
- {
- l_use_mv = FALSE; /* if destination is on another device use copy-remove strategy */
- remove(l_src_frame);
- }
- else
- {
- global_errlist = g_strdup_printf(
- _("failed to write %s (check permissions ?)"),
- l_dst_frame);
- return(-1);
- }
- }
- }
- l_frame_nr++;
- if(l_max_found > 0) gimp_progress_update ((gdouble)l_frame_nr / (gdouble)l_max_found);
- }
- return(0);
- } /* end p_rename_frames */
-
- static void
- p_delete_frames(gint32 max_tries, gint32 frame_from, gint32 frame_to, char *ext)
- {
- /* this procedure is performed repeatedly while polling the xanim process
- * and after xanim process has (or was) terminated to clean up unwanted frames.
- */
- gint32 l_tries;
- gint32 l_next_number;
- char l_framename[500];
-
- if(gap_debug) printf("p_delete_frames: cleaning up unwanted frames (max=%d)\n", (int)max_tries);
-
- l_tries = 0;
-
- while ((global_delete_number < frame_from) && (l_tries < max_tries))
- {
- l_next_number = global_delete_number + 1;
- p_build_xanim_framename(l_framename, sizeof(l_framename), l_next_number, ext);
-
- if (p_file_exists(l_framename))
- {
- /* if xanim has already written the next frame
- * we can delete the previous (unwanted) frame now
- */
- p_build_xanim_framename(l_framename, sizeof(l_framename), global_delete_number, ext);
- if(gap_debug) printf("delete frame: %s\n", l_framename);
- remove(l_framename);
-
- global_delete_number = l_next_number;
- }
- l_tries++;
- }
- } /* end p_delete_frames */
-
-
- static void
- p_poll(pid_t xanim_pid, char *one_past_last_frame, gint32 frame_from, gint32 frame_to, char *ext)
- {
- /* loop as long as the Xanim Process is alive */
-
- if(gap_debug) printf("poll started on xanim pid: %d\n", (int)xanim_pid);
-
-
- /* kill with signal 0 checks only if the process is alive (no signal is sent)
- * returns 0 if alive, 1 if no process with given pid found.
- */
- while (0 == kill(xanim_pid, 0))
- {
- usleep(100000); /* sleep 1 second, and let xanim write some frames */
- if (p_file_exists(one_past_last_frame))
- {
- /* if the last desired frame is written
- * we can stop (kill with signal 9) the xanim process.
- */
- kill(xanim_pid, 9);
- break;
- }
-
- /* check for max unwanted frames and delete (upto 20 of them) */
- p_delete_frames(20, frame_from, frame_to, ext);
- }
-
- if(gap_debug) printf("poll ended on xanim pid: %d\n", (int)xanim_pid);
- } /* end p_poll */
-
-
- static int
- p_grep(char *pattern, char *file)
- {
- gint l_rc;
- gchar *l_cmd;
-
- l_cmd = g_strdup_printf("grep -c '%s' \"%s\" >/dev/null", pattern, file);
- l_rc = system(l_cmd);
- g_free(l_cmd);
- if (l_rc == 0)
- {
- return(0); /* pattern found */
- }
- return(1); /* pattern NOT found */
- }
-
- static gint
- p_check_xanim()
- {
- gint l_rc;
- gint l_grep_counter1;
- gint l_grep_counter2;
- gint l_grep_counter3;
- gchar *l_cmd;
- static char *l_xanim_help_output = "tmp_xanim_help.output";
- FILE *l_fp;
-
- l_fp = fopen(l_xanim_help_output, "w+");
- if (l_fp == NULL)
- {
- global_errlist = g_strdup_printf("no write permission for current directory");
- return(10);
- }
- fprintf(l_fp, "dummy");
- fclose(l_fp);
-
- /* execute xanim with -h option and
- * store its output in a file.
- */
- l_cmd = g_strdup_printf("%s -h 2>&1 >>%s", global_xanim_prog, l_xanim_help_output);
- l_rc = system(l_cmd);
-
- if(gap_debug) printf("DEBUG: executed :%s\n Retcode: %d\n", l_cmd, (int)l_rc);
- g_free(l_cmd);
-
- if ((l_rc == 127) || (l_rc == (127 << 8)))
- {
- global_errlist = g_strdup_printf(
- _("could not execute %s (check if xanim is installed)"),
- global_xanim_prog );
- return(10);
- }
-
- if(!p_file_exists(l_xanim_help_output))
- {
- global_errlist = g_strdup_printf(
- _("%s does not look like xanim"),
- global_xanim_prog );
- return(10);
- }
-
- /* check the help output of xanim (using grep) */
- l_grep_counter1 = 0;
- /* l_grep_counter1 += p_grep("anim", l_xanim_help_output); */
-
- /* check for the exporting options */
- l_grep_counter2 = 0;
- l_grep_counter2 += p_grep("Ea", l_xanim_help_output);
- l_grep_counter2 += p_grep("Ee", l_xanim_help_output);
- l_grep_counter2 += p_grep("Eq", l_xanim_help_output);
-
- /* check for the loki version that is able to write single frames */
- l_grep_counter3 = 0;
- l_grep_counter3 += p_grep("Write video to input/frameN.EXT", l_xanim_help_output);
-
- remove(l_xanim_help_output);
-
- if(l_grep_counter2 != 0)
- {
- global_errlist = g_strdup_printf(
- _("The xanim program on your system \"%s\"\ndoes not support the exporting options Ea, Ee, Eq"),
- global_xanim_prog );
- return(10);
- }
- if(l_grep_counter3 != 0)
- {
- global_errlist = g_strdup_printf(
- _("The xanim program on your system \"%s\"\ndoes not support exporting of single frames"),
- global_xanim_prog );
- return(10);
- }
- return (0); /* OK, xanim output looks like expected */
- } /* end p_check_xanim */
-
- static pid_t
- p_start_xanim_process(gint32 first_frame, gint32 last_frame,
- char *filename,
- t_gap_xa_formats Format,
- gint32 extract_video,
- gint32 extract_audio,
- gint32 jpeg_quality ,
- char *one_past_last_frame,
- gint32 run_xanim_asynchron)
- {
- gchar l_cmd[500];
- gchar l_buf[40];
- pid_t l_xanim_pid;
- int l_rc;
- FILE *l_fp;
- static char *l_xanim_startscript = "tmp_xanim_startscript.sh";
- static char *l_xanim_pidfile = "tmp_xanim_pidfile";
-
- l_xanim_pid = -1;
-
- /* allocate and prepare args for the xanim call */
- g_snprintf(l_cmd, sizeof(l_cmd), "%s +f ", global_xanim_prog); /* programname */
-
- if (extract_audio)
- {
- strcat(l_cmd, "+Ea ");
- }
-
- if (extract_video)
- {
- strcat(l_cmd, "+v "); /* +v is verbose mode */
-
- switch(Format)
- {
- case XAENC_PPMRAW:
- strcat(l_cmd, "+Ee ");
- break;
- case XAENC_JPEG:
- g_snprintf(l_buf, sizeof(l_buf), "+Eq%d ", (int)jpeg_quality);
- strcat(l_cmd, l_buf);
- break;
- default:
- strcat(l_cmd, "+Ee ");
- break;
- }
-
- /* additional option "Pause after N Frames" is used,
- * to stop xanim exporting frames beyond the requested limit
- */
- if (run_xanim_asynchron)
- {
- g_snprintf(l_buf, sizeof(l_buf), "+Zp%d ", (int)(last_frame +1));
- strcat(l_cmd, l_buf);
- }
-
- }
-
- /* add the videofilename as last parameter */
- strcat(l_cmd, filename);
-
- if (run_xanim_asynchron)
- {
- /* asynchron start */
- remove(l_xanim_pidfile);
- /* generate a shelscript */
- l_fp = fopen(l_xanim_startscript, "w+");
- if (l_fp != NULL)
- {
- fprintf(l_fp, "#!/bin/sh\n");
- /* fprintf(l_fp, "(%s ; touch %s) &\n" */
- fprintf(l_fp, "%s & # ; touch %s) &\n"
- , l_cmd /* start xanim as background process */
- , one_past_last_frame /* and create a dummy frame when xanim is done */
- );
- fprintf(l_fp, "XANIM_PID=$!\n");
- fprintf(l_fp, "echo \"$XANIM_PID # XANIM_PID\"\n");
- fprintf(l_fp, "echo \"$XANIM_PID # XANIM_PID\" > \"%s\"\n", l_xanim_pidfile);
-
- /* we pass the xanim pid in a file,
- * exitcodes are truncated to 8 bit
- * by the system call
- */
- /* fprintf(l_fp, "exit $XANIM_PID\n"); */
- fclose(l_fp);
-
- chmod(l_xanim_startscript, MKDIR_MODE);
- }
-
- l_rc = system(l_xanim_startscript);
-
- l_fp = fopen(l_xanim_pidfile, "r");
- if (l_fp != NULL)
- {
- fscanf(l_fp, "%d", &l_rc);
- fclose(l_fp);
- l_xanim_pid = (pid_t)l_rc;
- }
-
- remove(l_xanim_startscript);
- remove(l_xanim_pidfile);
-
-
- if(gap_debug) printf("ASYNCHRON CALL: %s\nl_xanim_pid:%d\n", l_cmd, (int)l_xanim_pid);
- }
- else
- {
- /* synchron start (blocks until xanim process has finished */
- l_rc = system(l_cmd);
- if ((l_rc & 0xff) == 0) l_xanim_pid = 0;
- else l_xanim_pid = -1;
-
- if(gap_debug) printf("ASYNCHRON CALL: %s\nretcode:%d (%d)\n", l_cmd, (int)l_rc, (int)l_xanim_pid);
- }
-
- return(l_xanim_pid);
- } /* end p_start_xanim_process */
-
-
- #ifdef THIS_IS_A_COMMENT_EXEC_DID_NOT_WORK_AND_LEAVES_A_ZOMBIE_PROCESS
- static pid_t
- p_start_xanim_process_exec(gint32 first_frame, gint32 last_frame,
- char *filename,
- t_gap_xa_formats Format,
- gint32 extract_video,
- gint32 extract_audio,
- gint32 jpeg_quality
- )
- {
- char *args[20];
- char l_buf[40];
- int l_idx;
- pid_t l_xanim_pid;
-
- /* allocate and prepare args for the xanim call */
- l_idx = 0;
- args[l_idx] = g_strdup(global_xanim_prog); /* programname */
-
- l_idx++;
- args[l_idx] = g_strdup("+f");
-
- if (extract_audio)
- {
- l_idx++;
- args[l_idx] = g_strdup("+Ea");
- }
-
- if (extract_video)
- {
- l_idx++;
- args[l_idx] = g_strdup("+v"); /* +v is verbose mode */
-
- l_idx++;
- switch(Format)
- {
- case XAENC_PPMRAW:
- args[l_idx] = g_strdup("+Ee");
- break;
- case XAENC_JPEG:
- g_snprintf(l_buf, sizeof(l_buf), "+Eq%d", (int)jpeg_quality);
- args[l_idx] = g_strdup(l_buf);
- break;
- default:
- args[l_idx] = g_strdup("+Ee");
- break;
- }
-
- /* additional option "Pause after N Frames" is used,
- * to stop xanim exporting frames beyond the requested limit
- */
- l_idx++;
- g_snprintf(l_buf, sizeof(l_buf), "+Zp%d", (int)(last_frame +1));
- args[l_idx] = g_strdup(l_buf);
-
- }
-
- /* add the videofilename as last parameter */
- l_idx++;
- args[l_idx] = g_strdup(filename);
-
- l_idx++;
- args[l_idx] = NULL; /* terminate args list with a NULL pointer */
-
- l_xanim_pid = fork();
-
- if(l_xanim_pid == 0)
- {
- /* here we are in the forked child process
- * execute xanim
- */
- execvp(args[0], args);
-
- /* this point should never be reached */
- _exit (1);
- }
-
- return(l_xanim_pid);
- } /* end p_start_xanim_process */
- #endif
-
-
- /* ============================================================================
- * gap_xanim_decode
- * ============================================================================
- */
-
- gint32
- gap_xanim_decode(GimpRunModeType run_mode)
- {
- gint32 l_rc;
- gint32 first_frame;
- gint32 last_frame;
- char filename[200];
- char basename[200];
- char extension[20];
- char extension2[20];
- t_gap_xa_formats Format;
- gint32 extract_audio;
- gint32 extract_video;
- gint32 jpeg_quality;
- gint32 autoload;
- gint32 run_xanim_asynchron;
- char l_cmd[300];
- char l_one_past_last_frame[200];
- char l_first_to_laod[200];
- char *l_dst_dir;
- pid_t l_xanim_pid;
- int l_input_dir_created_by_myself;
-
- l_rc = 0;
- l_input_dir_created_by_myself = FALSE;
- global_errlist = NULL;
- p_init_xanim_global_name();
-
- filename[0] = '\0';
- strcpy(&basename[0], "frame_");
-
- l_rc = p_xanim_dialog (&first_frame,
- &last_frame,
- filename, sizeof(filename),
- basename, sizeof(basename),
- &Format,
- &extract_video,
- &extract_audio,
- &jpeg_quality,
- &autoload,
- &run_xanim_asynchron);
-
-
- if(l_rc != 0)
- {
- return(l_rc);
- }
-
- if(!p_file_exists(filename))
- {
- global_errlist = g_strdup_printf(
- _("videofile %s not existent or empty\n"),
- filename);
- l_rc = 10;
- }
- else
- {
- l_rc = p_check_xanim();
- }
-
-
- if (l_rc == 0)
- {
- switch(Format)
- {
- case XAENC_PPMRAW:
- strcpy(extension, "ppm");
- strcpy(extension2, ".ppm");
- break;
- case XAENC_JPEG:
- strcpy(extension, "jpg");
- strcpy(extension2, ".jpg");
- break;
- default:
- strcpy(extension, "ppm");
- strcpy(extension2, ".xcf");
- break;
-
- }
- p_build_xanim_framename(l_one_past_last_frame, sizeof(l_one_past_last_frame), last_frame +1 , extension);
-
- if (extract_video)
- {
- /* for the frames we need a directory named "input" */
- if (p_is_directory(global_xanim_input_dir))
- {
- /* the input directory already exists,
- * remove frames
- */
- g_snprintf(l_cmd, sizeof(l_cmd), "rm -f %s/*.%s", global_xanim_input_dir, extension);
- system(l_cmd);
- }
- else
- {
- /* create input directory (needed by xanim to store the frames) */
- mkdir(global_xanim_input_dir, MKDIR_MODE);
-
- if (p_is_directory(global_xanim_input_dir))
- {
- l_input_dir_created_by_myself = TRUE;
- }
- else
- {
- global_errlist = g_strdup_printf(
- _("could not create %s directory\n"
- "(that is required for xanim frame export)"),
- global_xanim_input_dir);
- l_rc = 10;
- }
- }
- }
- }
-
- if(l_rc == 0)
- {
- gimp_progress_init (_("extracting frames..."));
- gimp_progress_update (0.1); /* fake some progress */
- /* note:
- * we can't show realistic progress for the extracting process
- * because we know nothing about videofileformat and how much frames
- * are realy stored in the videofile.
- *
- * one guess could assume, that xanim will write 0 upto last_frame
- * to disk, and check for the frames that the xanim process creates.
- * The periodically checking can be done in the poll procedure for asynchron
- * startmode only.
- */
-
- l_xanim_pid = p_start_xanim_process(first_frame, last_frame,
- filename,
- Format,
- extract_video,
- extract_audio,
- jpeg_quality,
- l_one_past_last_frame,
- run_xanim_asynchron);
-
- if (l_xanim_pid == -1 )
- {
- global_errlist = g_strdup_printf(
- _("could not start xanim process\n(program=%s)"),
- global_xanim_prog );
- l_rc = -1;
- }
- }
-
- if(l_rc == 0)
- {
- if(run_xanim_asynchron)
- {
- p_poll(l_xanim_pid, l_one_past_last_frame, first_frame, last_frame, extension);
- }
-
- p_delete_frames(99999, first_frame, last_frame, extension);
- remove(l_one_past_last_frame);
-
- gimp_progress_update (1.0);
-
- if (p_find_max_xanim_frame (first_frame, extension) < first_frame)
- {
- global_errlist = g_strdup_printf(
- _("can't find any extracted frames,\n"
- "xanim has failed or was cancelled"));
- l_rc = -1;
- }
- else
- {
- /* if destination directorypart does not exist, try to create it */
- l_dst_dir = g_strdup(basename);
- p_dirname(l_dst_dir);
- if (*l_dst_dir != '\0')
- {
- if ( !p_is_directory(l_dst_dir) )
- {
- mkdir (l_dst_dir, MKDIR_MODE);
- }
- }
-
- if(strcmp(extension, &extension2[1]) == 0)
- {
- gimp_progress_init (_("renaming frames..."));
- l_rc = p_rename_frames(first_frame, last_frame, basename, extension);
- }
- else
- {
- gimp_progress_init (_("converting frames..."));
- l_rc = p_convert_frames(first_frame, last_frame, basename, extension, extension2);
- }
-
- if (l_input_dir_created_by_myself)
- {
- if (strcmp(l_dst_dir, global_xanim_input_dir) != 0)
- {
- /* remove input dir with all files */
- g_snprintf(l_cmd, sizeof(l_cmd), "rm -rf \"%s\"", global_xanim_input_dir);
- system(l_cmd);
- }
- }
- g_free(l_dst_dir);
- gimp_progress_update (1.0);
- }
-
- }
-
- if(l_rc != 0)
- {
- if(global_errlist == NULL)
- {
- p_xanim_info("ERROR: could not execute xanim");
- }
- else
- {
- p_xanim_info(global_errlist);
- }
- l_rc = -1;
- }
- else
- {
- if(autoload)
- {
- /* load first frame and add a display */
- p_build_gap_framename(l_first_to_laod, sizeof(l_first_to_laod), first_frame, basename, &extension2[1]);
- l_rc = p_load_image(l_first_to_laod);
-
- if(l_rc >= 0) gimp_display_new(l_rc);
- }
- }
-
- return(l_rc);
- } /* end gap_xanim_decode */
-