/* output batch-file Written by Matthias Hensler Copyright WSPse 1999+2000 eMail: wsp@gmx.de Created: 1999/06/26 Updated: 2000/07/26 */ /* Copying: This program is free software; you can redistribute it and/or modify it under the terms of the GNU Gerneral Public License as published by the Free Soft- ware Foundation; either version 2 of 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 MERCHANTABILTY 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include "mp3creat.h" #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_SYS_STAT_H #include #endif /* Externals */ extern void wuuush(int); extern void setup_stat_win(int max_length); extern void print_stat_win(char *text); extern void destroy_stat_win(); extern BOOL select_yesno_box(char *tx); extern void popup_error_win(char *tx); extern char *create_sub_string(song_typ *track, int mode); extern int get_config(char *file); extern int build_data_tree(char *cddb_server, char *local_cddb_db, song_typ **ret_tree, BOOL force_sampler); extern int init_cd(); extern void free_song_typ(song_typ **anchor); extern char *build_m3u_fname(song_typ *song); extern char *build_mp3_filenm(song_typ *track); extern void init_config(); extern char *kill_double_slashs(char *string); extern char *extract_dirname(char *file_str); extern char *return_track_tmpname(song_typ *track); extern char *file_build_m3u_entry(song_typ *track); extern int open_cdrom(); extern int close_cdrom(); extern char *def_cddb_server; extern char *def_cddb_bank; extern char *def_cdrom_dev; extern char *external_config_file; extern char *def_tmp_file; extern int track_last; extern BOOL rip_enc_ordered; extern BOOL def_on_fly; extern char *def_mp3_info; /* Globals */ BOOL careful_batch; char *batch_alt_tmp_file; #define BATCH_VERSION "1.1a" /***************************************************************/ /* Subfunctions for single tasks: output rip, encode, tag, m3u */ /***************************************************************/ /* Escape unallowed characters */ char *batch_set_shell_escapes(char *input) { char *output; char escaped[5]; int len; int i; if(! input) return NULL; len = strlen(input)+1; output = (char *) malloc(sizeof(char) * len); if(! output) { wuuush(1); } *output = '\0'; for(i=0;itoc)+1); cmd_line = extract_dirname(return_track_tmpname(track)); if(cmd_line) { fprintf(script, "mkdir -p \"%s\"\t\t\t\t\t\t# So, we need tmpdir, eh\n", cmd_line); free(cmd_line); } fprintf(script, "if [ $verbose ]; then echo \"ripping track %d in progress\"; fi;\n", (track->toc)+1); cmd_line = batch_create_sub_string(track, 3); if(cmd_line) { fputs(cmd_line, script); fputs(" 1> $dev1 2> $dev2 \t# Grabprogram\n", script); free(cmd_line); } else { return 1; } fprintf(script, "if [ ! \"$?\" == \"0\" ]; then\n" " echo \"ripping track %d failed, abort now\"\n" " exit 1\n" "fi\n" "if [ $verbose ]; then echo \"track %d ripped.\"; fi;\n\n", (track->toc)+1, (track->toc)+1); return 0; } int batch_task_single_enc(song_typ *track, FILE *script) { char *cmd_line; fprintf(script, "#--- Batchtask: encoding track %d----------------------------------\n", (track->toc)+1); cmd_line = extract_dirname(build_mp3_filenm(track)); if(cmd_line) { fprintf(script, "mkdir -p \"%s\"\t\t\t\t\t\t# MP3-destination dir\n", cmd_line); free(cmd_line); } fprintf(script, "if [ $verbose ]; then echo \"encoding track %d in progress\"; fi;\n", (track->toc)+1); cmd_line = batch_create_sub_string(track, 1); if(cmd_line) { fputs(cmd_line, script); fputs(" 1> $dev1 2> $dev2\t# Encoder\n", script); free(cmd_line); } else { return 1; } fprintf(script, "if [ ! \"$?\" == \"0\" ]; then\n" " echo \"encoding track %d failed, abort now\"\n" " exit 1\n" "fi\n" "rm -f \"%s\"\t\t# delete tempfile\n" "if [ $verbose ]; then echo \"track %d encoded.\"; fi;\n\n", (track->toc)+1, return_track_tmpname(track), (track->toc)+1); return 0; } int batch_task_rip_and_enc(song_typ *track, FILE *script) { char *cmd_line; fprintf(script, "#--- Batchtask: ripping and encoding track %d (on the fly)---------\n", (track->toc)+1); cmd_line = extract_dirname(build_mp3_filenm(track)); if(cmd_line) { fprintf(script, "mkdir -p \"%s\"\t\t\t\t\t\t# MP3-destination dir\n", cmd_line); free(cmd_line); } fprintf(script, "if [ $verbose ]; then echo \"on the fly creation of track %d in progress\"; fi;\n", (track->toc)+1); cmd_line = batch_create_sub_string(track, 4); if(cmd_line) { fputs(cmd_line, script); free(cmd_line); cmd_line = batch_create_sub_string(track, 2); if(cmd_line) { fputs(" 2> $dev2 | ", script); fputs(cmd_line, script); free(cmd_line); fputs(" 1> $dev1 2> $dev2\n", script); } else { return 1; } } else { return 1; } fprintf(script, "if [ ! \"$?\" == \"0\" ]; then\n" " echo \"encoding track %d failed, abort now\"\n" " exit 1\n" "fi\n" "if [ $verbose ]; then echo \"track %d encoded.\"; fi;\n\n", (track->toc)+1, (track->toc)+1); return 0; } int batch_task_set_tag(song_typ *track, FILE *script) { char *cmd_line; if(def_mp3_info && strcmp(def_mp3_info, "0") == 0) return 0; fprintf(script, "#--- Batchtask: set mp3-tags for track %d--------------------------\n", (track->toc)+1); fprintf(script, "if [ $verbose ]; then echo \"setting tags for track %d\"; fi;\n", (track->toc)+1); cmd_line = batch_create_sub_string(track, 5); if(cmd_line) { fputs(cmd_line, script); fputs(" 1> $dev1 2> $dev2\t# ID-Tagprg\n", script); free(cmd_line); } else { return 1; } fprintf(script, "if [ ! \"$?\" == \"0\" ]; then\n" " echo \"setting of tags for track %d failed, abort now\"\n" " exit 1\n" "fi\n" "if [ $verbose ]; then echo \"track %d ready.\"; fi;\n\n", (track->toc)+1, (track->toc)+1); return 0; } int batch_task_update_m3u(song_typ *track, FILE *script) { char *cmd_line; char *dir_name; char *file_name; file_name = build_m3u_fname(track); if(! file_name) return 0; fprintf(script, "#--- Batchtask: insert track %d into m3u-file----------------------\n", (track->toc)+1); cmd_line = batch_set_shell_escapes(file_name); if(file_name) { free(file_name); file_name = NULL; } if(cmd_line) { file_name = batch_set_shell_escapes(build_mp3_filenm(track)); fprintf(script, "if test -e \"%s\"; then\t# if mp3-file exists\n", file_name); if(file_name) { free(file_name); file_name = NULL; } dir_name = extract_dirname(cmd_line); if(dir_name) { fprintf(script, " mkdir -p \"%s\"\t\t# directory for m3u-file\n", dir_name); free(dir_name); } file_name = batch_set_shell_escapes(file_build_m3u_entry(track)); fprintf(script, " echo \"%s\" >> \"%s\"\n" "else\n" " echo \"warning, new mp3-file wasn't found\"\n" "fi\n", file_name, cmd_line); if(file_name) { free(file_name); file_name = NULL; } free(cmd_line); } else { return 1; } fprintf(script, "if [ $verbose ]; then echo \"m3u-list updated.\"; fi;\n\n"); return 0; } /* Here we create the header of the script file, which consists of the main-part * with parsing options, setting global variables, etc. */ int batch_task_output_header(song_typ *track, FILE *script) { int mode; int order; if(rip_enc_ordered) { order = 1; } else { order = 0; } if(def_on_fly) { mode = 4; } else { mode = 3; } fprintf(script, "#!/bin/sh\n" "# Batchfile for encoding CD %08lX to MP3\n" "# Album \"%s\"\n\n" "# Generated by WSPse's MP3c V" PRG_VERSION " (Batch V" BATCH_VERSION ")\n\n" "dev1=/dev/stdout\t# show STDOUT messages\n" "dev2=/dev/null\t\t# ignore STDERR stream\n" "unset verbose\t\t# reduce output by this script\n" "mode=%d\t\t\t# rip and encode\n" "order=%d\t\t\t# rip tracks before encode\n\n" "while [ \"$1\" != \"\" ]; do\n" " case $1 in\n" " -1) mode=1;;\n" " -2) mode=2;;\n" " -3) mode=4;;\n" " -a) mode=3\n" " if [ \"$2\" == \"0\" ]; then order=0; shift;\n" " elif [ \"$2\" == \"1\" ]; then order=1; shift;\n" " fi;;\n" " -v) verbose=1;;\n" " -O) dev1=/dev/null;;\n" " -o) dev1=/dev/stdout;;\n" " -E) dev2=/dev/null;;\n" " -e) dev2=/dev/stderr;;\n" " -V) cat <cddb_id, track->album, mode, order, track->cddb_id); if(def_on_fly) { fprintf(script, " (default)"); } fprintf(script, "\n-a : rip and encode by "); if(! def_on_fly) { fprintf(script, " (default)"); } fprintf(script, "\n order = 0: encode track directly after ripping"); if(! rip_enc_ordered) { fprintf(script, " (default)"); } fprintf(script, "\n order = 1: first rip all tracks and then start encoding"); if(rip_enc_ordered) { fprintf(script, " (default)"); } fprintf(script, "\n" "-v: activate verbose mode\n" "-O: disable STDOUT from external programs\n" "-o: enable STDOUT (default)\n" "-E: disable STDERR (default)\n" "-e: enable STDERR\n" "-V: show script-version information\n" "-h: this help\n" "EOF\n" " exit 0;;\n" " *) echo \"unkown option '$1' (try -h for help)\"\n" " exit 1;;\n" " esac\n" " shift\n" "done\n\n"); return 0; } /* output shell script for batch encoding * * 0: action was successful * * 1: couldn't write to file */ int output_batch(song_typ *anchor, char *filenm, BOOL ask_overwrite) { FILE *script; song_typ *curr; if(access(filenm, F_OK) == 0) { /* a script already exists */ if(access(filenm, W_OK) != 0) { if(ask_overwrite) popup_error_win(_("script already exists, and isn't writeable")); return 1; } /* script is writeable */ if(ask_overwrite) { if(! select_yesno_box(_("overwrite existing script?"))) return 1; } } script = fopen(filenm, "wb"); if(script == NULL) { if(ask_overwrite) popup_error_win(_("couldn't open file for writing!")); return 1; } batch_task_output_header(anchor, script); /* Create header for scriptfile */ /* A 2-pass way is needed to offer all these options * start now with pass 1, which rip the tracks (encoding is also done, if * we are in mode 4 (=on-the-fly encoding) or mode 3 with order 0 (=1:1 rip * and enc) */ fputs("##########\n" "# PASS 1 #\n" "##########\n\n" "if [ $verbose ]; then echo \"* * * * * PASS 1 * * * * *\"; fi;\n\n" "if [ \"$mode\" != \"2\" ]; then\t# encoding only is part of pass 2\n", script); curr = anchor; while(curr) { if(curr->convert) { fputs("#-{\nif [ \"$mode\" == \"4\" ]; then\t# on-the-fly encode\n", script); batch_task_rip_and_enc(curr, script); /* insert on-the-fly encoding part */ fputs("else\t\t\t# rip following track\n", script); batch_task_single_rip(curr, script); /* insert ripping part */ fputs(" if [ \"$mode\" == \"3\" -a \"$order\" == \"0\" ]; then\t# encoding should be also done\n", script); batch_task_single_enc(curr, script); /* insert encoding part */ fputs(" fi\nfi\nif [ \"$mode\" == \"3\" -a \"$order\" == \"0\" -o \"$mode\" == \"4\" ]; then\t# was encoded\n", script); batch_task_set_tag(curr, script); /* insert tag setting part */ batch_task_update_m3u(curr, script); /* insert m3u-update part */ fputs("fi\n#-}\n\n", script); } curr = curr->next; } fputs("if [ \"$mode\" == \"3\" -a \"$order\" == \"0\" -o \"$mode\" == \"4\" ]; then\n" " echo \"ENCODING FINISHED!\"\n" " exit 0\n" "fi\n" "if [ \"$mode\" == \"1\" ]; then\n" " echo \"RIPPING FINISHED!\"\n" " exit 0\n" "fi\nfi\n\n", script); /* now we are entering pass 2 (if we not ready yet) * Here only encoding (and following things) are done. * This pass will only occur, if we are in mode 2 (=encoding only) * or mode 3 with order 1 (=first rip all tracks, then encode) */ fputs("##########\n" "# PASS 2 #\n" "##########\n\n" "if [ $verbose ]; then echo \"* * * * * PASS 2 * * * * *\"; fi;\n\n", script); curr = anchor; while(curr) { if(curr->convert) { fprintf(script, "if [ -f \"%s\" ]; then\n", return_track_tmpname(curr)); batch_task_single_enc(curr, script); /* encoding part */ batch_task_set_tag(curr, script); /* tag-set part */ batch_task_update_m3u(curr, script); /* m3u-update */ fprintf(script, "else\n" " echo Skipping %d\n" "fi\n", (curr->toc)+1); } curr = curr->next; } /* Finally all is done, so insert a little footer and exit */ fputs("echo \"ENCODING FINISHED!\"\n" "exit 0\n\n" "# End of script. Thanks for using MP3c\n" "# MP3c is available here: http://www.wspse.de/WSPse/Linux-MP3c.php3\n" "# WSPse, Matthias Hensler 1999/2000\n", script); fclose(script); chmod(filenm, 0777); return 0; } /* Routines for non-interactive batch-creation * will result in configuration reading, TOC and CDDB-setup and finally * creating scriptfile */ int start_non_interact(char *batchfile) { song_typ *anchor; char *tmp_file; fprintf(stderr, _("WSPse MP3c - Batchmode, noninteractive\nreading config\n")); careful_batch = TRUE; anchor = NULL; init_config(); get_config(external_config_file); if(open_cdrom() < 1) { fprintf(stderr, _("opening cdrom device \"%s\" failed!\n"), def_cdrom_dev); return 1; } fprintf(stderr, _("reading TOC of cd\n")); if(init_cd() != 0) { fprintf(stderr, _("no cd in cdrom-drive\n")); return 1; } close_cdrom(); fprintf(stderr, _("building up data tree\n")); build_data_tree(def_cddb_server, def_cddb_bank, &anchor, FALSE); fprintf(stderr, _("building shellscript\n")); tmp_file = NULL; if(batch_alt_tmp_file) { if(*(batch_alt_tmp_file + strlen(batch_alt_tmp_file) -1) == '/') { tmp_file = (char *) malloc(sizeof(char) * (strlen(batch_alt_tmp_file)+17)); if(! tmp_file) { perror("malloc"); wuuush(1); } strcpy(tmp_file, batch_alt_tmp_file); strcat(tmp_file, "mp3c-tmp-.wav"); batch_alt_tmp_file = tmp_file; } fprintf(stderr, _("using alternate tmp-file \"%s\"\n"), batch_alt_tmp_file); def_tmp_file = batch_alt_tmp_file; } output_batch(anchor, batchfile, FALSE); free_song_typ(&anchor); if(tmp_file) free(tmp_file); fprintf(stderr, _("ready...\n\n")); return 0; }