diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2011-07-16 22:41:20 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2011-07-16 22:41:20 +0300 |
commit | 9a2df634f322d174014ac8d5090bfa87a25bb775 (patch) | |
tree | 4346c4b392898c087c55fd20ca998eb39294027b /src/idop.c | |
parent | 8d89ce088cc25786cb9520f67e9fe81c86c70277 (diff) | |
download | idest-9a2df634f322d174014ac8d5090bfa87a25bb775.tar.gz idest-9a2df634f322d174014ac8d5090bfa87a25bb775.tar.bz2 |
Major rewrite.
* src/idest.h (ed_item): Remove union, leave only value instead.
<ref>: New member.
(describe_option,verbose_option,all_frames): New externs.
(set_frame_value): Return int.
(IDEST_OK,IDEST_ERR_*): New constants.
(_idest_errstr, _idest_nerrs): New externs.
(idest_frame_cmp_t,idest_frame_encoder_t)
(idest_frame_decoder_t): New typedefs.
(idest_frametab): New struct.
(idest_frame_lookup)
(find_matching_frame): New protos.
(ed_list_add_item)
(ed_list_print,ed_list_add_assignment)
(ed_list_clear,ed_item_matches_frame)
(ed_item_set_comment_fields): Remove.
(qv_free,input_list_locate)
(parse_ed_items): New protos.
* src/idop.c: Rewrite.
* src/.gitignore: Add src/frametab.c
* src/Makefile.am (idest_SOURCES): Add editem.c and frametab.c
(BUILT_SOURCES): Add frametab.c
(.gperf.c): New rule
(GPERF_FLAGS): New variable.
* src/editem.c: New source.
* src/frametab.gperf: New source.
* src/cmdline.opt: Use input_list_add_assignment in --set handler.
* src/guile.c (frame_to_scm,scm_to_tag): Rewrite using the new
logic.
Diffstat (limited to 'src/idop.c')
-rw-r--r-- | src/idop.c | 567 |
1 files changed, 305 insertions, 262 deletions
@@ -18,231 +18,136 @@ | |||
18 | #include <file.h> | 18 | #include <file.h> |
19 | #include <signal.h> | 19 | #include <signal.h> |
20 | 20 | ||
21 | gl_list_t input_list, output_list; | ||
22 | |||
21 | void | 23 | void |
22 | set_frame_value(struct id3_frame *frame, const struct ed_item *item) | 24 | input_list_add_assignment(const char *name, const char *value) |
23 | { | 25 | { |
24 | const char *value = item->v.value; | 26 | struct ed_item *itm; |
25 | union id3_field *field; | 27 | |
26 | enum id3_field_textencoding encoding = | 28 | if (!input_list) |
27 | (latin1_option ? ID3_FIELD_TEXTENCODING_ISO_8859_1 | 29 | input_list = ed_list_create(); |
28 | : ID3_FIELD_TEXTENCODING_UTF_8); | 30 | itm = ed_item_from_frame_spec(name, strlen(name)); |
29 | id3_ucs4_t *ucs4; | 31 | itm->value = xstrdup(value); |
30 | const char *condesc; | 32 | gl_list_add_last(input_list, itm); |
33 | } | ||
34 | |||
35 | struct ed_item const * | ||
36 | input_list_locate(struct id3_frame *frame, idest_frame_cmp_t cmp) | ||
37 | { | ||
38 | gl_list_iterator_t itr; | ||
39 | const void *p; | ||
40 | const struct ed_item *item = NULL; | ||
31 | 41 | ||
32 | switch (frame_to_item_id(frame->id)) { | 42 | itr = gl_list_iterator(input_list); |
33 | default: | 43 | while (gl_list_iterator_next(&itr, &p, NULL)) { |
34 | field = id3_frame_field(frame, 0); | 44 | item = p; |
35 | id3_field_settextencoding(field, encoding); | 45 | if (memcmp(item->id, frame->id, 4) == 0 && |
36 | 46 | (!cmp || item->qc == 0 || cmp(frame, item) == 0)) | |
37 | if (latin1_option) | 47 | break; |
38 | ucs4 = id3_latin1_ucs4duplicate( | 48 | item = NULL; |
39 | (const id3_latin1_t *) value); | ||
40 | else | ||
41 | ucs4 = id3_utf8_ucs4duplicate( | ||
42 | (const id3_utf8_t *)value); | ||
43 | |||
44 | field = id3_frame_field(frame, 1); | ||
45 | id3_field_setstrings(field, 1, &ucs4); | ||
46 | free(ucs4); | ||
47 | break; | ||
48 | |||
49 | case item_comment: | ||
50 | /* Field 0: Encoding */ | ||
51 | field = id3_frame_field(frame, 0); | ||
52 | id3_field_settextencoding(field, encoding); | ||
53 | /* Field 1: Language */ | ||
54 | field = id3_frame_field(frame, 1); | ||
55 | id3_field_setlanguage(field, item->lang ? item->lang : "eng"); | ||
56 | /* Field 2: Short content descriptor */ | ||
57 | field = id3_frame_field(frame, 2); | ||
58 | condesc = item->condesc ? item->condesc : ""; | ||
59 | if (latin1_option) | ||
60 | ucs4 = id3_latin1_ucs4duplicate( | ||
61 | (const id3_latin1_t *)condesc); | ||
62 | else | ||
63 | ucs4 = id3_utf8_ucs4duplicate( | ||
64 | (const id3_utf8_t *)condesc); | ||
65 | id3_field_setstring(field, ucs4); | ||
66 | /* Field 3: Comment */ | ||
67 | field = id3_frame_field(frame, 3); | ||
68 | if (latin1_option) | ||
69 | ucs4 = id3_latin1_ucs4duplicate( | ||
70 | (const id3_latin1_t *) value); | ||
71 | else | ||
72 | ucs4 = id3_utf8_ucs4duplicate( | ||
73 | (const id3_utf8_t *)value); | ||
74 | id3_field_setfullstring(field, ucs4); | ||
75 | free(ucs4); | ||
76 | break; | ||
77 | } | 49 | } |
50 | gl_list_iterator_free(&itr); | ||
51 | return item; | ||
78 | } | 52 | } |
79 | 53 | ||
80 | void | 54 | void |
81 | safe_id3_file_update_and_close(struct id3_file *file) | 55 | parse_ed_items(const char *arg) |
82 | { | 56 | { |
83 | sigset_t set, oldset; | 57 | if (!input_list) |
84 | 58 | input_list = ed_list_create(); | |
85 | sigemptyset(&set); | 59 | while (*arg) { |
86 | sigaddset(&set, SIGINT); | 60 | struct ed_item *itm; |
87 | sigaddset(&set, SIGTERM); | 61 | size_t len = strcspn(arg, " \t,"); |
88 | 62 | ||
89 | sigprocmask(SIG_BLOCK, &set, &oldset); | 63 | itm = ed_item_from_frame_spec(arg, len); |
90 | id3_file_update(file); | 64 | gl_list_add_last(input_list, itm); |
91 | id3_file_close(file); | 65 | arg += len; |
92 | sigprocmask(SIG_SETMASK, &oldset, NULL); | 66 | if (!*arg) |
93 | } | 67 | break; |
94 | 68 | arg += strspn(arg, " \t,"); | |
95 | static void | ||
96 | update_frame(struct id3_tag *tag, const struct ed_item *item) | ||
97 | { | ||
98 | struct id3_frame *frame = id3_tag_findframe(tag, item->id, 0); | ||
99 | if (!frame) { | ||
100 | frame = id3_frame_new(item->id); | ||
101 | if (id3_tag_attachframe(tag, frame)) | ||
102 | error(1, 0, "cannot attach new frame"); | ||
103 | } else if (strcmp(item->id, ID3_FRAME_COMMENT) == 0 | ||
104 | && item->condesc) { | ||
105 | /* Special handling for comments */ | ||
106 | int i = 0; | ||
107 | |||
108 | do { | ||
109 | union id3_field *field = id3_frame_field(frame, 2); | ||
110 | char *s; | ||
111 | |||
112 | if (field && (s = field_to_string(field, 0)) | ||
113 | && strcmp(s, item->condesc) == 0) | ||
114 | break; | ||
115 | } while (frame = id3_tag_findframe(tag, item->id, ++i)); | ||
116 | if (!frame) { | ||
117 | frame = id3_frame_new(item->id); | ||
118 | if (id3_tag_attachframe(tag, frame)) | ||
119 | error(1, 0, "cannot attach new frame"); | ||
120 | } | ||
121 | } else { | ||
122 | struct id3_frame *fp; | ||
123 | |||
124 | while (fp = id3_tag_findframe(tag, item->id, 1)) { | ||
125 | id3_tag_detachframe(tag, fp); | ||
126 | id3_frame_delete(fp); | ||
127 | } | ||
128 | } | 69 | } |
129 | set_frame_value(frame, item); | ||
130 | } | 70 | } |
131 | 71 | ||
132 | static int | 72 | void |
133 | build_tag_options(struct id3_tag *tag, unsigned long location, | 73 | input_list_init() |
134 | id3_length_t length, void *data) | ||
135 | { | 74 | { |
136 | unsigned int ver = id3_tag_version(tag); | 75 | if (all_frames) |
137 | 76 | input_list = NULL; | |
138 | if (ID3_TAG_VERSION_MAJOR(ver) == 1) | 77 | else if (!input_list) |
139 | *(unsigned int*)data |= IDEST_ID3V_1; | 78 | parse_ed_items(DEFAULT_ED_LIST); |
140 | else | 79 | } |
141 | *(unsigned int*)data |= IDEST_ID3V_2; | 80 | |
142 | return 0; | 81 | void |
82 | output_list_append(struct ed_item const *item, struct ed_item const *ref) | ||
83 | { | ||
84 | struct ed_item *elt = ed_item_dup(item); | ||
85 | if (!output_list) | ||
86 | output_list = ed_list_create(); | ||
87 | elt->ref = ref; | ||
88 | gl_list_add_last(output_list, elt); | ||
143 | } | 89 | } |
144 | 90 | ||
145 | void | 91 | void |
146 | set_tags(const char *name) | 92 | output_list_print() |
147 | { | 93 | { |
148 | struct id3_file *file; | 94 | gl_list_iterator_t itr; |
149 | struct id3_tag *tag; | 95 | const void *p; |
150 | int modified = 0; | ||
151 | int vopt = version_option; | ||
152 | |||
153 | file = id3_file_open(name, ID3_FILE_MODE_READWRITE); | ||
154 | if (!file) | ||
155 | error(1, errno, "cannot open file %s", name); | ||
156 | tag = id3_file_tag(file); | ||
157 | if (!tag) | ||
158 | abort(); /* FIXME */ | ||
159 | 96 | ||
160 | if (ed_list) { | 97 | if (all_frames) { |
161 | gl_list_iterator_t itr; | 98 | itr = gl_list_iterator(output_list); |
162 | const void *p; | ||
163 | |||
164 | itr = gl_list_iterator(ed_list); | ||
165 | while (gl_list_iterator_next(&itr, &p, NULL)) { | 99 | while (gl_list_iterator_next(&itr, &p, NULL)) { |
166 | const struct ed_item *item = p; | 100 | const struct ed_item *item = p; |
167 | update_frame(tag, item); | 101 | ed_item_print(item); |
168 | modified |= 1; | ||
169 | } | 102 | } |
170 | gl_list_iterator_free(&itr); | 103 | gl_list_iterator_free(&itr); |
171 | } | 104 | } else { |
172 | 105 | itr = gl_list_iterator(input_list); | |
173 | /* FIXME */ | 106 | while (gl_list_iterator_next(&itr, &p, NULL)) { |
174 | modified |= guile_transform(name, tag); | 107 | int printed = 0; |
175 | 108 | const struct ed_item *input_item = p; | |
176 | if (convert_version == 0) { | 109 | if (output_list) { |
177 | if (modified && !vopt) { | 110 | gl_list_iterator_t oitr; |
178 | if (id3_file_struct_ntags(file) |