diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2009-03-17 11:59:19 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2009-03-17 11:59:19 +0200 |
commit | e25a44d9bdc40ca8bf2efcd12ed73e2104fdb360 (patch) | |
tree | b805996c317f299b5421d6f48c9528664da00981 | |
parent | a0a067bde62b828a09f165524dc993580ac7e450 (diff) | |
download | idest-e25a44d9bdc40ca8bf2efcd12ed73e2104fdb360.tar.gz idest-e25a44d9bdc40ca8bf2efcd12ed73e2104fdb360.tar.bz2 |
Improve scripting, implement v1->v2 conversion, implement --delete command.
* libid3tag/file.c (v2_write): Change for make it possible to
convert v1 to v2.
* src/.gitignore: Add guile.x.
* src/Makefile.am (idest_SOURCES): Add guile.x
(BUILT_SOURCES): Add guile.x
(SUFFIXES): Add .x
(.c.x): New rule
* src/cmdline.opt: New option: --trace.
* src/guile.c: Rewrite.
* src/idest.h (MODE_QUERY, MODE_MOD, MODE_DELETE): New defines (from main.c).
(guile_transform, guile_list): New protos.
(guile_apply): Remove.
* src/idop.c (set_tags): Handle convert_version == 2.
(del_tags): New function.
* src/main.c (del_id3): Call del_tags
-rw-r--r-- | libid3tag/file.c | 20 | ||||
-rw-r--r-- | src/.gitignore | 1 | ||||
-rw-r--r-- | src/Makefile.am | 11 | ||||
-rw-r--r-- | src/cmdline.opt | 10 | ||||
-rw-r--r-- | src/guile.c | 111 | ||||
-rw-r--r-- | src/idest.h | 10 | ||||
-rw-r--r-- | src/idop.c | 39 | ||||
-rw-r--r-- | src/main.c | 9 |
8 files changed, 161 insertions, 50 deletions
diff --git a/libid3tag/file.c b/libid3tag/file.c index 5ad025b..9210571 100644 --- a/libid3tag/file.c +++ b/libid3tag/file.c @@ -704,17 +704,17 @@ int v2_write(struct id3_file *file, if (!tmp) return -1; - rc = copy_block(file->iofile, tmp, 0, file->tags[0].location); - if (rc == 0) { - if (data && length) - rc = fwrite(data, length, 1, tmp) != 1; - else - rc = 0; + if (data && length) + rc = fwrite(data, length, 1, tmp) != 1; + else + rc = 0; - if (rc == 0) - rc = copy_block(file->iofile, tmp, - file->tags[0].location + file->tags[0].length, -1); - } + if (rc == 0) + rc = copy_block(file->iofile, tmp, + /* FIXME: Should I check tag->version instead? */ + (file->tags[0].location == 0) ? + file->tags[0].length : 0, -1); + fclose(tmp); if (rc) unlink(tmpname); diff --git a/src/.gitignore b/src/.gitignore index 97d1ee5..43f7eeb 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -1,3 +1,4 @@ .gdbinit cmdline.h idest +guile.x diff --git a/src/Makefile.am b/src/Makefile.am index 7d34d0b..66c9095 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -18,18 +18,25 @@ bin_PROGRAMS=idest idest_SOURCES=\ backup.c\ guile.c\ + guile.x\ idest.h\ idop.c\ main.c\ cmdline.h\ slist.c -BUILT_SOURCES=cmdline.h +BUILT_SOURCES=cmdline.h guile.x EXTRA_DIST=cmdline.opt getopt.m4 INCLUDES=-I$(top_srcdir)/gnu -I$(top_builddir)/gnu -I$(top_srcdir)/libid3tag @GUILE_INCLUDES@ LDADD=../gnu/libgnu.a ../libid3tag/libid3tag.a -lz @GUILE_LIBS@ -SUFFIXES=.opt .c .h +SUFFIXES=.opt .c .h .x .opt.h: m4 -s $(srcdir)/getopt.m4 $< | sed '1d' > $@ +DOT_X_FILES = guile.x + +snarfcppopts = -I../ $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) + +.c.x: + guile-snarf -o $@ $< $(snarfcppopts) diff --git a/src/cmdline.opt b/src/cmdline.opt index faf7323..06fd798 100644 --- a/src/cmdline.opt +++ b/src/cmdline.opt @@ -109,6 +109,16 @@ OPTION(function,f,NAME, BEGIN guile_function = optarg; END + +OPTION(trace,,[LEVEL], + [<Start with debugging evaluator and backtraces>]) +BEGIN + if (optarg) + guile_debug = atoi(optarg); + else + guile_debug = 1; +END + >]) OPTIONS_END diff --git a/src/guile.c b/src/guile.c index 9b1f9c2..1efcb15 100644 --- a/src/guile.c +++ b/src/guile.c @@ -23,10 +23,22 @@ #include <libguile.h> #include <setjmp.h> +int guile_inited = 0; int guile_debug = 1; char *guile_script; -char *guile_function = "main"; -SCM guile_proc = SCM_EOL; +char *guile_function; + +SCM_GLOBAL_VARIABLE_INIT (sym_idest_main, "idest-main", SCM_EOL); +SCM_GLOBAL_VARIABLE_INIT (sym_idest_readonly, "idest-readonly", SCM_BOOL_F); + + + +static char * +proc_name(SCM proc) +{ + return scm_to_locale_string( + scm_symbol_to_string(scm_procedure_name(proc))); +} static SCM eval_catch_body(void *list) @@ -276,56 +288,107 @@ scm_to_tag(SCM scm, struct id3_tag *tag) return modified; } +SCM +guile_apply_main(const char *file, struct id3_tag *tag) +{ + jmp_buf jmp_env; + SCM cell; + + if (setjmp(jmp_env)) + error(1, 0, "idest-main failed"); + + cell = scm_cons(SCM_VARIABLE_REF(sym_idest_main), + scm_list_2( + scm_cons(SCM_IM_QUOTE, scm_makfrom0str(file)), + scm_cons(SCM_IM_QUOTE, tag_to_scm(tag)))); + return scm_internal_lazy_catch(SCM_BOOL_T, + eval_catch_body, cell, + eval_catch_handler, &jmp_env); +} + +int +guile_transform(const char *file, struct id3_tag *tag) +{ + SCM result; + + if (!guile_inited) + return 0; + + result = guile_apply_main(file, tag); + + if (scm_is_pair(result)) + return scm_to_tag(result, tag); + return 0; +} + int -guile_apply(const char *file, struct id3_tag *tag) +guile_list(const char *file, struct id3_tag *tag) { - jmp_buf jmp_env; - SCM cell, result; + SCM result; - if (guile_proc == SCM_EOL) - return 0; + if (!guile_inited) + return 0; - if (setjmp(jmp_env)) - error(1, 0, "%s failed", guile_function); - - cell = scm_cons(guile_proc, - scm_list_2( - scm_cons(SCM_IM_QUOTE, scm_makfrom0str(file)), - scm_cons(SCM_IM_QUOTE, tag_to_scm(tag)))); - result = scm_internal_lazy_catch(SCM_BOOL_T, - eval_catch_body, cell, - eval_catch_handler, &jmp_env); - if (scm_is_pair(result)) - return scm_to_tag(result, tag); - return 0; + guile_apply_main(file, tag); + return 1; } void guile_init() { + SCM readonly, proc; + if (!guile_script) return; scm_init_guile(); scm_load_goops(); +#include "guile.x" + if (guile_debug) { SCM_DEVAL_P = 1; SCM_BACKTRACE_P = 1; SCM_RECORD_POSITIONS_P = 1; SCM_RESET_DEBUG_MODE; } + if (guile_load(guile_script)) error(1, 0, "cannot load init script %s", guile_script); - guile_proc = SCM_VARIABLE_REF(scm_c_lookup(guile_function)); - if (scm_procedure_p(guile_proc) != SCM_BOOL_T) + proc = SCM_VARIABLE_REF(sym_idest_main); + if (proc == SCM_EOL) { + if (guile_function) { + proc = SCM_VARIABLE_REF(scm_c_lookup(guile_function)); + SCM_VARIABLE_SET(sym_idest_main, proc); + } else + error(1, 0, "idest-main not defined"); + } + + if (scm_procedure_p(proc) != SCM_BOOL_T) + error(1, 0, + "idest-main is not a procedure object"); + + readonly = SCM_VARIABLE_REF(sym_idest_readonly); + if (readonly == SCM_BOOL_F) + mode = MODE_MOD; + else if (readonly == SCM_BOOL_T) + mode = MODE_QUERY; + else error(1, 0, - "%s is not a procedure object", guile_function); + "script %s set non-boolean value of idest-readonly", + guile_script); + guile_inited = 1; } #else int -guile_apply(struct id3_tag *tag) +guile_transform(const char *file, struct id3_tag *tag) +{ + return 0; +} + +int +guile_list(const char *file, struct id3_tag *tag) { return 0; } diff --git a/src/idest.h b/src/idest.h index 21960e4..f758977 100644 --- a/src/idest.h +++ b/src/idest.h @@ -27,7 +27,7 @@ #include <argmatch.h> #include <backupfile.h> #include <id3tag.h> -#include <libid3tag/frametype.h> +#include <frametype.h> #define gettext(s) s #define _(s) s @@ -54,6 +54,11 @@ struct ed_item { } v; }; +#define MODE_QUERY 0 +#define MODE_MOD 1 +#define MODE_DELETE 2 + +extern int mode; extern int latin1_option; extern enum backup_type backup_type; extern char *backup_dir; @@ -92,5 +97,6 @@ int backup_file(const char *file); /* guile.c */ -int guile_apply(const char *file, struct id3_tag *tag); void guile_init (void); +int guile_transform(const char *file, struct id3_tag *tag); +int guile_list(const char *file, struct id3_tag *tag); @@ -105,14 +105,22 @@ set_tags(const char *name) } /* FIXME */ - modified |= guile_apply(name, tag); - - if (convert_version == 1) { + modified |= guile_transform(name, tag); + + switch (convert_version) { + case 1: id3_tag_options(tag, ID3_TAG_OPTION_NO_ID3V2, ID3_TAG_OPTION_NO_ID3V2); version_option = 1; modified |= 1; + break; + + case 2: + id3_tag_options(tag, ID3_TAG_OPTION_ID3V1, 0); + version_option = 0; + modified |= 1; + break; } if (version_option == 1) { @@ -125,6 +133,25 @@ set_tags(const char *name) id3_file_close(file); } +void +del_tags(const char *name) +{ + struct id3_file *file; + struct id3_tag *tag; + + file = id3_file_open(name, ID3_FILE_MODE_READWRITE); + if (!file) + error(1, errno, "cannot open file %s", name); + tag = id3_file_tag(file); + if (!tag) + abort(); /* FIXME */ + id3_tag_options(tag, + ID3_TAG_OPTION_ID3V1|ID3_TAG_OPTION_NO_ID3V2, + ID3_TAG_OPTION_NO_ID3V2); + id3_file_update(file); + id3_file_close(file); +} + char * idest_ucs4_cvt(id3_ucs4_t const *ucs4) @@ -230,8 +257,10 @@ query_tags(const char *name) error(1, errno, "cannot open file %s", name); tag = id3_file_tag(file); - if (tag) - show_tags(tag); + if (tag) { + if (guile_list(name, tag) == 0) + show_tags(tag); + } id3_file_close(file); } @@ -285,10 +285,6 @@ verify_mp3(FILE *fp, const char *name) } } -#define MODE_QUERY 0 -#define MODE_MOD 1 -#define MODE_DELETE 2 - void query_id3(const char *name) { @@ -312,8 +308,7 @@ del_id3(const char *name) { if (backup_file(name)) error(1, 0, "cannot backup file %s", name); - error(1, 0, "Deleting ID3 data is not yet implemented"); - abort(); + del_tags(name); } void (*id3_mode[])(const char *) = { @@ -341,7 +336,7 @@ main(int argc, char **argv) guile_init(); - if (convert_version || guile_script) + if (convert_version) mode = MODE_MOD; while (argc--) |