operations_shorthand_vorbiscomment.c
上传用户:wstnjxml
上传日期:2014-04-03
资源大小:7248k
文件大小:9k
源码类别:

Windows CE

开发平台:

C/C++

  1. /* metaflac - Command-line FLAC metadata editor
  2.  * Copyright (C) 2001,2002,2003,2004,2005  Josh Coalson
  3.  *
  4.  * This program is free software; you can redistribute it and/or
  5.  * modify it under the terms of the GNU General Public License
  6.  * as published by the Free Software Foundation; either version 2
  7.  * of the License, or (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  17.  */
  18. #include "options.h"
  19. #include "utils.h"
  20. #include "FLAC/assert.h"
  21. #include "share/utf8.h"
  22. #include <stdlib.h>
  23. #include <string.h>
  24. static FLAC__bool remove_vc_all(const char *filename, FLAC__StreamMetadata *block, FLAC__bool *needs_write);
  25. static FLAC__bool remove_vc_field(const char *filename, FLAC__StreamMetadata *block, const char *field_name, FLAC__bool *needs_write);
  26. static FLAC__bool remove_vc_firstfield(const char *filename, FLAC__StreamMetadata *block, const char *field_name, FLAC__bool *needs_write);
  27. static FLAC__bool set_vc_field(const char *filename, FLAC__StreamMetadata *block, const Argument_VcField *field, FLAC__bool *needs_write, FLAC__bool raw);
  28. static FLAC__bool import_vc_from(const char *filename, FLAC__StreamMetadata *block, const Argument_Filename *vc_filename, FLAC__bool *needs_write, FLAC__bool raw);
  29. static FLAC__bool export_vc_to(const char *filename, FLAC__StreamMetadata *block, const Argument_Filename *vc_filename, FLAC__bool raw);
  30. FLAC__bool do_shorthand_operation__vorbis_comment(const char *filename, FLAC__bool prefix_with_filename, FLAC__Metadata_Chain *chain, const Operation *operation, FLAC__bool *needs_write, FLAC__bool raw)
  31. {
  32. FLAC__bool ok = true, found_vc_block = false;
  33. FLAC__StreamMetadata *block = 0;
  34. FLAC__Metadata_Iterator *iterator = FLAC__metadata_iterator_new();
  35. if(0 == iterator)
  36. die("out of memory allocating iterator");
  37. FLAC__metadata_iterator_init(iterator, chain);
  38. do {
  39. block = FLAC__metadata_iterator_get_block(iterator);
  40. if(block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT)
  41. found_vc_block = true;
  42. } while(!found_vc_block && FLAC__metadata_iterator_next(iterator));
  43. if(!found_vc_block) {
  44. /* create a new block if necessary */
  45. if(operation->type == OP__SET_VC_FIELD || operation->type == OP__IMPORT_VC_FROM) {
  46. block = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT);
  47. if(0 == block)
  48. die("out of memory allocating VORBIS_COMMENT block");
  49. while(FLAC__metadata_iterator_next(iterator))
  50. ;
  51. if(!FLAC__metadata_iterator_insert_block_after(iterator, block)) {
  52. print_error_with_chain_status(chain, "%s: ERROR: adding new VORBIS_COMMENT block to metadata", filename);
  53. return false;
  54. }
  55. /* iterator is left pointing to new block */
  56. FLAC__ASSERT(FLAC__metadata_iterator_get_block(iterator) == block);
  57. }
  58. else {
  59. FLAC__metadata_iterator_delete(iterator);
  60. return ok;
  61. }
  62. }
  63. FLAC__ASSERT(0 != block);
  64. FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT);
  65. switch(operation->type) {
  66. case OP__SHOW_VC_VENDOR:
  67. write_vc_field(prefix_with_filename? filename : 0, &block->data.vorbis_comment.vendor_string, raw, stdout);
  68. break;
  69. case OP__SHOW_VC_FIELD:
  70. write_vc_fields(prefix_with_filename? filename : 0, operation->argument.vc_field_name.value, block->data.vorbis_comment.comments, block->data.vorbis_comment.num_comments, raw, stdout);
  71. break;
  72. case OP__REMOVE_VC_ALL:
  73. ok = remove_vc_all(filename, block, needs_write);
  74. break;
  75. case OP__REMOVE_VC_FIELD:
  76. ok = remove_vc_field(filename, block, operation->argument.vc_field_name.value, needs_write);
  77. break;
  78. case OP__REMOVE_VC_FIRSTFIELD:
  79. ok = remove_vc_firstfield(filename, block, operation->argument.vc_field_name.value, needs_write);
  80. break;
  81. case OP__SET_VC_FIELD:
  82. ok = set_vc_field(filename, block, &operation->argument.vc_field, needs_write, raw);
  83. break;
  84. case OP__IMPORT_VC_FROM:
  85. ok = import_vc_from(filename, block, &operation->argument.filename, needs_write, raw);
  86. break;
  87. case OP__EXPORT_VC_TO:
  88. ok = export_vc_to(filename, block, &operation->argument.filename, raw);
  89. break;
  90. default:
  91. ok = false;
  92. FLAC__ASSERT(0);
  93. break;
  94. };
  95. FLAC__metadata_iterator_delete(iterator);
  96. return ok;
  97. }
  98. /*
  99.  * local routines
  100.  */
  101. FLAC__bool remove_vc_all(const char *filename, FLAC__StreamMetadata *block, FLAC__bool *needs_write)
  102. {
  103. FLAC__ASSERT(0 != block);
  104. FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT);
  105. FLAC__ASSERT(0 != needs_write);
  106. if(0 != block->data.vorbis_comment.comments) {
  107. FLAC__ASSERT(block->data.vorbis_comment.num_comments > 0);
  108. if(!FLAC__metadata_object_vorbiscomment_resize_comments(block, 0)) {
  109. fprintf(stderr, "%s: ERROR: memory allocation failuren", filename);
  110. return false;
  111. }
  112. *needs_write = true;
  113. }
  114. else {
  115. FLAC__ASSERT(block->data.vorbis_comment.num_comments == 0);
  116. }
  117. return true;
  118. }
  119. FLAC__bool remove_vc_field(const char *filename, FLAC__StreamMetadata *block, const char *field_name, FLAC__bool *needs_write)
  120. {
  121. int n;
  122. FLAC__ASSERT(0 != needs_write);
  123. n = FLAC__metadata_object_vorbiscomment_remove_entries_matching(block, field_name);
  124. if(n < 0) {
  125. fprintf(stderr, "%s: ERROR: memory allocation failuren", filename);
  126. return false;
  127. }
  128. else if(n > 0)
  129. *needs_write = true;
  130. return true;
  131. }
  132. FLAC__bool remove_vc_firstfield(const char *filename, FLAC__StreamMetadata *block, const char *field_name, FLAC__bool *needs_write)
  133. {
  134. int n;
  135. FLAC__ASSERT(0 != needs_write);
  136. n = FLAC__metadata_object_vorbiscomment_remove_entry_matching(block, field_name);
  137. if(n < 0) {
  138. fprintf(stderr, "%s: ERROR: memory allocation failuren", filename);
  139. return false;
  140. }
  141. else if(n > 0)
  142. *needs_write = true;
  143. return true;
  144. }
  145. FLAC__bool set_vc_field(const char *filename, FLAC__StreamMetadata *block, const Argument_VcField *field, FLAC__bool *needs_write, FLAC__bool raw)
  146. {
  147. FLAC__StreamMetadata_VorbisComment_Entry entry;
  148. char *converted;
  149. FLAC__bool needs_free = false;
  150. FLAC__ASSERT(0 != block);
  151. FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT);
  152. FLAC__ASSERT(0 != field);
  153. FLAC__ASSERT(0 != needs_write);
  154. if(raw) {
  155. entry.entry = (FLAC__byte *)field->field;
  156. }
  157. else if(utf8_encode(field->field, &converted) >= 0) {
  158. entry.entry = (FLAC__byte *)converted;
  159. needs_free = true;
  160. }
  161. else {
  162. fprintf(stderr, "%s: ERROR: couldn't convert comment to UTF-8n", filename);
  163. return false;
  164. }
  165. entry.length = strlen((const char *)entry.entry);
  166. if(!FLAC__metadata_object_vorbiscomment_append_comment(block, entry, /*copy=*/true)) {
  167. if(needs_free)
  168. free(converted);
  169. fprintf(stderr, "%s: ERROR: memory allocation failuren", filename);
  170. return false;
  171. }
  172. else {
  173. *needs_write = true;
  174. if(needs_free)
  175. free(converted);
  176. return true;
  177. }
  178. }
  179. FLAC__bool import_vc_from(const char *filename, FLAC__StreamMetadata *block, const Argument_Filename *vc_filename, FLAC__bool *needs_write, FLAC__bool raw)
  180. {
  181. FILE *f;
  182. char line[65536];
  183. FLAC__bool ret;
  184. if(0 == vc_filename->value || strlen(vc_filename->value) == 0) {
  185. fprintf(stderr, "%s: ERROR: empty import file namen", filename);
  186. return false;
  187. }
  188. if(0 == strcmp(vc_filename->value, "-"))
  189. f = stdin;
  190. else
  191. f = fopen(vc_filename->value, "r");
  192. if(0 == f) {
  193. fprintf(stderr, "%s: ERROR: can't open import file %sn", filename, vc_filename->value);
  194. return false;
  195. }
  196. ret = true;
  197. while(ret && !feof(f)) {
  198. fgets(line, sizeof(line), f);
  199. if(!feof(f)) {
  200. char *p = strchr(line, 'n');
  201. if(0 == p) {
  202. fprintf(stderr, "%s: ERROR: line too long, abortingn", vc_filename->value);
  203. ret = false;
  204. }
  205. else {
  206. const char *violation;
  207. Argument_VcField field;
  208. *p = '';
  209. memset(&field, 0, sizeof(Argument_VcField));
  210. if(!parse_vorbis_comment_field(line, &field.field, &field.field_name, &field.field_value, &field.field_value_length, &violation)) {
  211. FLAC__ASSERT(0 != violation);
  212. fprintf(stderr, "%s: ERROR: malformed vorbis comment field "%s",n       %sn", vc_filename->value, line, violation);
  213. ret = false;
  214. }
  215. else {
  216. ret = set_vc_field(filename, block, &field, needs_write, raw);
  217. }
  218. if(0 != field.field)
  219. free(field.field);
  220. if(0 != field.field_name)
  221. free(field.field_name);
  222. if(0 != field.field_value)
  223. free(field.field_value);
  224. }
  225. }
  226. };
  227. if(f != stdin)
  228. fclose(f);
  229. return ret;
  230. }
  231. FLAC__bool export_vc_to(const char *filename, FLAC__StreamMetadata *block, const Argument_Filename *vc_filename, FLAC__bool raw)
  232. {
  233. FILE *f;
  234. FLAC__bool ret;
  235. if(0 == vc_filename->value || strlen(vc_filename->value) == 0) {
  236. fprintf(stderr, "%s: ERROR: empty export file namen", filename);
  237. return false;
  238. }
  239. if(0 == strcmp(vc_filename->value, "-"))
  240. f = stdout;
  241. else
  242. f = fopen(vc_filename->value, "w");
  243. if(0 == f) {
  244. fprintf(stderr, "%s: ERROR: can't open export file %sn", filename, vc_filename->value);
  245. return false;
  246. }
  247. ret = true;
  248. write_vc_fields(0, 0, block->data.vorbis_comment.comments, block->data.vorbis_comment.num_comments, raw, f);
  249. if(f != stdout)
  250. fclose(f);
  251. return ret;
  252. }