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

Windows CE

开发平台:

C/C++

  1. /* plugin_common - Routines common to several plugins
  2.  * Copyright (C) 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 <stdio.h>
  19. #include <string.h>
  20. #include <stdlib.h>
  21. #include "tags.h"
  22. #include "FLAC/assert.h"
  23. #include "FLAC/metadata.h"
  24. static __inline unsigned local__wide_strlen(const FLAC__uint16 *s)
  25. {
  26. unsigned n = 0;
  27. while(*s++)
  28. n++;
  29. return n;
  30. }
  31. static __inline unsigned local__utf8len(const FLAC__byte *utf8)
  32. {
  33. FLAC__ASSERT(0 != utf8);
  34. if ((utf8[0] & 0x80) == 0)
  35. return 1;
  36. else if ((utf8[0] & 0xE0) == 0xC0 && (utf8[1] & 0xC0) == 0x80)
  37. return 2;
  38. else if ((utf8[0] & 0xF0) == 0xE0 && (utf8[1] & 0xC0) == 0x80 && (utf8[2] & 0xC0) == 0x80)
  39. return 3;
  40. else
  41. return 0;
  42. }
  43. static __inline unsigned local__utf8_to_ucs2(const FLAC__byte *utf8, FLAC__uint16 *ucs2)
  44. {
  45. const unsigned len = local__utf8len(utf8);
  46. FLAC__ASSERT(0 != ucs2);
  47. if (len == 1)
  48. *ucs2 = *utf8;
  49. else if (len == 2)
  50. *ucs2 = (*utf8 & 0x3F)<<6 | (*(utf8+1) & 0x3F);
  51. else if (len == 3)
  52. *ucs2 = (*utf8 & 0x1F)<<12 | (*(utf8+1) & 0x3F)<<6 | (*(utf8+2) & 0x3F);
  53. return len;
  54. }
  55. static FLAC__uint16 *local__convert_utf8_to_ucs2(const char *src, unsigned length)
  56. {
  57. FLAC__uint16 *out;
  58. unsigned chars = 0;
  59. FLAC__ASSERT(0 != src);
  60. /* calculate length */
  61. {
  62. const char *s, *end;
  63. for (s=src, end=src+length; s<end; chars++) {
  64. const unsigned n = local__utf8len(s);
  65. if (n == 0)
  66. return 0;
  67. s += n;
  68. }
  69. FLAC__ASSERT(s == end);
  70. }
  71. /* allocate */
  72. out = (FLAC__uint16*)malloc(chars * sizeof(FLAC__uint16));
  73. if (0 == out) {
  74. FLAC__ASSERT(0);
  75. return 0;
  76. }
  77. /* convert */
  78. {
  79. FLAC__uint16 *u = out;
  80. for ( ; chars; chars--)
  81. src += local__utf8_to_ucs2(src, u++);
  82. }
  83. return out;
  84. }
  85. static __inline unsigned local__ucs2len(FLAC__uint16 ucs2)
  86. {
  87. if (ucs2 < 0x0080)
  88. return 1;
  89. else if (ucs2 < 0x0800)
  90. return 2;
  91. else
  92. return 3;
  93. }
  94. static __inline unsigned local__ucs2_to_utf8(FLAC__uint16 ucs2, FLAC__byte *utf8)
  95. {
  96. if (ucs2 < 0x080) {
  97. utf8[0] = (FLAC__byte)ucs2;
  98. return 1;
  99. }
  100. else if (ucs2 < 0x800) {
  101. utf8[0] = 0xc0 | (ucs2 >> 6);
  102. utf8[1] = 0x80 | (ucs2 & 0x3f);
  103. return 2;
  104. }
  105. else {
  106. utf8[0] = 0xe0 | (ucs2 >> 12);
  107. utf8[1] = 0x80 | ((ucs2 >> 6) & 0x3f);
  108. utf8[2] = 0x80 | (ucs2 & 0x3f);
  109. return 3;
  110. }
  111. }
  112. static char *local__convert_ucs2_to_utf8(const FLAC__uint16 *src, unsigned length)
  113. {
  114. char *out;
  115. unsigned len = 0;
  116. FLAC__ASSERT(0 != src);
  117. /* calculate length */
  118. {
  119. unsigned i;
  120. for (i = 0; i < length; i++)
  121. len += local__ucs2len(src[i]);
  122. }
  123. /* allocate */
  124. out = (char*)malloc(len * sizeof(char));
  125. if (0 == out)
  126. return 0;
  127. /* convert */
  128. {
  129. char *u = out;
  130. for ( ; *src; src++)
  131. u += local__ucs2_to_utf8(*src, u);
  132. local__ucs2_to_utf8(*src, u);
  133. }
  134. return out;
  135. }
  136. FLAC__bool FLAC_plugin__tags_get(const char *filename, FLAC__StreamMetadata **tags)
  137. {
  138. if(!FLAC__metadata_get_tags(filename, tags))
  139. if(0 == (*tags = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT)))
  140. return false;
  141. return true;
  142. }
  143. FLAC__bool FLAC_plugin__tags_set(const char *filename, const FLAC__StreamMetadata *tags)
  144. {
  145. FLAC__Metadata_Chain *chain;
  146. FLAC__Metadata_Iterator *iterator;
  147. FLAC__StreamMetadata *block;
  148. FLAC__bool got_vorbis_comments = false;
  149. FLAC__bool ok;
  150. if(0 == (chain = FLAC__metadata_chain_new()))
  151. return false;
  152. if(!FLAC__metadata_chain_read(chain, filename)) {
  153. FLAC__metadata_chain_delete(chain);
  154. return false;
  155. }
  156. if(0 == (iterator = FLAC__metadata_iterator_new())) {
  157. FLAC__metadata_chain_delete(chain);
  158. return false;
  159. }
  160. FLAC__metadata_iterator_init(iterator, chain);
  161. do {
  162. if(FLAC__metadata_iterator_get_block_type(iterator) == FLAC__METADATA_TYPE_VORBIS_COMMENT)
  163. got_vorbis_comments = true;
  164. } while(!got_vorbis_comments && FLAC__metadata_iterator_next(iterator));
  165. if(0 == (block = FLAC__metadata_object_clone(tags))) {
  166. FLAC__metadata_chain_delete(chain);
  167. FLAC__metadata_iterator_delete(iterator);
  168. return false;
  169. }
  170. if(got_vorbis_comments)
  171. ok = FLAC__metadata_iterator_set_block(iterator, block);
  172. else
  173. ok = FLAC__metadata_iterator_insert_block_after(iterator, block);
  174. FLAC__metadata_iterator_delete(iterator);
  175. if(ok) {
  176. FLAC__metadata_chain_sort_padding(chain);
  177. ok = FLAC__metadata_chain_write(chain, /*use_padding=*/true, /*preserve_file_stats=*/true);
  178. }
  179. FLAC__metadata_chain_delete(chain);
  180. return ok;
  181. }
  182. void FLAC_plugin__tags_destroy(FLAC__StreamMetadata **tags)
  183. {
  184. FLAC__metadata_object_delete(*tags);
  185. *tags = 0;
  186. }
  187. const char *FLAC_plugin__tags_get_tag_utf8(const FLAC__StreamMetadata *tags, const char *name)
  188. {
  189. const int i = FLAC__metadata_object_vorbiscomment_find_entry_from(tags, /*offset=*/0, name);
  190. return (i < 0? 0 : strchr(tags->data.vorbis_comment.comments[i].entry, '=')+1);
  191. }
  192. FLAC__uint16 *FLAC_plugin__tags_get_tag_ucs2(const FLAC__StreamMetadata *tags, const char *name)
  193. {
  194. const char *utf8 = FLAC_plugin__tags_get_tag_utf8(tags, name);
  195. if(0 == utf8)
  196. return 0;
  197. return local__convert_utf8_to_ucs2(utf8, strlen(utf8)+1); /* +1 for terminating null */
  198. }
  199. int FLAC_plugin__tags_delete_tag(FLAC__StreamMetadata *tags, const char *name)
  200. {
  201. return FLAC__metadata_object_vorbiscomment_remove_entries_matching(tags, name);
  202. }
  203. int FLAC_plugin__tags_delete_all(FLAC__StreamMetadata *tags)
  204. {
  205. int n = (int)tags->data.vorbis_comment.num_comments;
  206. if(n > 0) {
  207. if(!FLAC__metadata_object_vorbiscomment_resize_comments(tags, 0))
  208. n = -1;
  209. }
  210. return n;
  211. }
  212. FLAC__bool FLAC_plugin__tags_add_tag_utf8(FLAC__StreamMetadata *tags, const char *name, const char *value, const char *separator)
  213. {
  214. int i;
  215. FLAC__ASSERT(0 != tags);
  216. FLAC__ASSERT(0 != name);
  217. FLAC__ASSERT(0 != value);
  218. if(separator && (i = FLAC__metadata_object_vorbiscomment_find_entry_from(tags, /*offset=*/0, name)) >= 0) {
  219. FLAC__StreamMetadata_VorbisComment_Entry *entry = tags->data.vorbis_comment.comments+i;
  220. const size_t value_len = strlen(value);
  221. const size_t separator_len = strlen(separator);
  222. FLAC__byte *new_entry;
  223. if(0 == (new_entry = (FLAC__byte*)realloc(entry->entry, entry->length + value_len + separator_len + 1)))
  224. return false;
  225. memcpy(new_entry+entry->length, separator, separator_len);
  226. entry->length += separator_len;
  227. memcpy(new_entry+entry->length, value, value_len);
  228. entry->length += value_len;
  229. new_entry[entry->length] = '';
  230. entry->entry = new_entry;
  231. }
  232. else {
  233. FLAC__StreamMetadata_VorbisComment_Entry entry;
  234. if(!FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, name, value))
  235. return false;
  236. FLAC__metadata_object_vorbiscomment_append_comment(tags, entry, /*copy=*/false);
  237. }
  238. return true;
  239. }
  240. FLAC__bool FLAC_plugin__tags_set_tag_ucs2(FLAC__StreamMetadata *tags, const char *name, const FLAC__uint16 *value, FLAC__bool replace_all)
  241. {
  242. FLAC__StreamMetadata_VorbisComment_Entry entry;
  243. FLAC__ASSERT(0 != tags);
  244. FLAC__ASSERT(0 != name);
  245. FLAC__ASSERT(0 != value);
  246. {
  247. char *utf8 = local__convert_ucs2_to_utf8(value, local__wide_strlen(value)+1); /* +1 for the terminating null */
  248. if(0 == utf8)
  249. return false;
  250. if(!FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, name, utf8)) {
  251. free(utf8);
  252. return false;
  253. }
  254. free(utf8);
  255. }
  256. if(!FLAC__metadata_object_vorbiscomment_replace_comment(tags, entry, replace_all, /*copy=*/false))
  257. return false;
  258. return true;
  259. }