PageRenderTime 29ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/libid3tag/libid3tag/metadata.c

https://github.com/theuni/xbmc
C | 524 lines | 393 code | 101 blank | 30 comment | 99 complexity | 531a1c632c7ff57b6accbeaa077fe64e MD5 | raw file
  1. /*
  2. * libid3tag - ID3 tag manipulation library
  3. * Copyright (C) 2000-2004 Underbit Technologies, Inc.
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18. *
  19. * $Id: metadata.c,v 1.00 2005/09/03 09:41:32 bobbin007 Exp $
  20. */
  21. # ifdef HAVE_CONFIG_H
  22. # include "config.h"
  23. # endif
  24. #include <string.h>
  25. #include <stdlib.h>
  26. # include "metadata.h"
  27. # include "global.h"
  28. # include "ucs4.h"
  29. id3_ucs4_list_t *metadata_getstrings(const struct id3_tag* tag, const char* id, enum id3_field_textencoding* encoding)
  30. {
  31. int nstrings, j;
  32. union id3_field const *field;
  33. struct id3_frame const *frame;
  34. id3_ucs4_list_t *list;
  35. frame = id3_tag_findframe(tag, id, 0);
  36. if (frame == 0)
  37. return 0;
  38. *encoding = id3_field_gettextencoding(id3_frame_field(frame, 0));
  39. field = id3_frame_field(frame, 1);
  40. if (field == 0)
  41. return 0;
  42. nstrings = id3_field_getnstrings(field);
  43. list = 0;
  44. if (nstrings)
  45. {
  46. list = (id3_ucs4_list_t*)malloc(sizeof(*list));
  47. if (list)
  48. list->strings = (const id3_ucs4_t**)malloc(nstrings * sizeof(*list->strings));
  49. }
  50. if (list && list->strings)
  51. {
  52. list->nstrings = nstrings;
  53. for (j = 0; j < list->nstrings; ++j)
  54. list->strings[j] = id3_field_getstrings(field, j);
  55. }
  56. return list;
  57. }
  58. void id3_ucs4_list_free(id3_ucs4_list_t *list)
  59. {
  60. if (list)
  61. {
  62. if (list->strings)
  63. free(list->strings);
  64. free(list);
  65. }
  66. }
  67. const id3_ucs4_t* metadata_getstring(const struct id3_tag* tag, const char* id, enum id3_field_textencoding* encoding)
  68. {
  69. int nstrings, j;
  70. char const *name;
  71. id3_ucs4_t const *ucs4;
  72. union id3_field const *field;
  73. struct id3_frame const *frame;
  74. frame = id3_tag_findframe(tag, id, 0);
  75. if (frame == 0)
  76. return id3_ucs4_empty;
  77. *encoding = id3_field_gettextencoding(id3_frame_field(frame, 0));
  78. field = id3_frame_field(frame, 1);
  79. if (field == 0)
  80. return id3_ucs4_empty;
  81. nstrings = id3_field_getnstrings(field);
  82. ucs4 = id3_ucs4_empty;
  83. for (j = 0; j < nstrings; ++j)
  84. {
  85. ucs4 = id3_field_getstrings(field, j);
  86. if (ucs4 && *ucs4)
  87. break;
  88. }
  89. return ucs4;
  90. }
  91. int metadata_setstring(struct id3_tag* tag, const char* id, id3_ucs4_t* value)
  92. {
  93. union id3_field *field;
  94. struct id3_frame *frame;
  95. frame = id3_tag_findframe(tag, id, 0);
  96. if (frame == 0)
  97. {
  98. frame = id3_frame_new(id);
  99. id3_tag_attachframe(tag, frame);
  100. }
  101. id3_field_settextencoding(id3_frame_field(frame, 0), ID3_FIELD_TEXTENCODING_UTF_16);
  102. field = id3_frame_field(frame, 1);
  103. if (field == 0)
  104. return 0;
  105. return (id3_field_setstrings(field, 1, &value)==0);
  106. }
  107. const id3_ucs4_t* id3_metadata_getartist(const struct id3_tag* tag, enum id3_field_textencoding* encoding)
  108. {
  109. id3_ucs4_t const *ucs4;
  110. if ((ucs4=metadata_getstring(tag, ID3_FRAME_ARTIST, encoding)) ||
  111. (ucs4=metadata_getstring(tag, "TPE2", encoding)) ||
  112. (ucs4=metadata_getstring(tag, "TPE3", encoding)) ||
  113. (ucs4=metadata_getstring(tag, "TPE4", encoding)) ||
  114. (ucs4=metadata_getstring(tag, "TCOM", encoding)))
  115. return ucs4;
  116. return id3_ucs4_empty;
  117. }
  118. int id3_metadata_setartist(struct id3_tag* tag, id3_ucs4_t* value)
  119. {
  120. return metadata_setstring(tag, ID3_FRAME_ARTIST, value);
  121. }
  122. const id3_ucs4_t* id3_metadata_getalbum(const struct id3_tag* tag, enum id3_field_textencoding* encoding)
  123. {
  124. return metadata_getstring(tag, ID3_FRAME_ALBUM, encoding);
  125. }
  126. int id3_metadata_setalbum(struct id3_tag* tag, id3_ucs4_t* value)
  127. {
  128. return metadata_setstring(tag, ID3_FRAME_ALBUM, value);
  129. }
  130. const id3_ucs4_t* id3_metadata_getalbumartist(const struct id3_tag* tag, enum id3_field_textencoding* encoding)
  131. {
  132. id3_ucs4_t const *ucs4 = metadata_getstring(tag, "TPE2", encoding);
  133. if (ucs4 && *ucs4) return ucs4;
  134. ucs4 = id3_metadata_getusertext(tag, "ALBUM ARTIST");
  135. if (ucs4 && *ucs4) return ucs4;
  136. ucs4 = id3_metadata_getusertext(tag, "ALBUMARTIST");
  137. if (ucs4 && *ucs4) return ucs4;
  138. return id3_ucs4_empty;
  139. }
  140. int id3_metadata_setalbumartist(struct id3_tag* tag, id3_ucs4_t* value)
  141. {
  142. return metadata_setstring(tag, "TPE2", value);
  143. }
  144. char id3_metadata_getrating(const struct id3_tag* tag)
  145. {
  146. union id3_field const *field;
  147. struct id3_frame const *frame;
  148. int value;
  149. frame = id3_tag_findframe(tag, "POPM", 0);
  150. if (frame)
  151. {
  152. field = id3_frame_field(frame, 1);
  153. if (field)
  154. { // based on mediamonkey's values, simplified down a bit
  155. // http://www.mediamonkey.com/forum/viewtopic.php?f=7&t=40532
  156. value = id3_field_getint(field);
  157. if (value == 1) return '1'; // WMP11 madness
  158. if (value < 9) return '0';
  159. if (value < 50) return '1';
  160. if (value < 114) return '2';
  161. if (value < 168) return '3';
  162. if (value < 219) return '4';
  163. return '5';
  164. }
  165. }
  166. else
  167. {
  168. const id3_ucs4_t *ucs4 = id3_metadata_getusertext(tag, "RATING");
  169. if (ucs4 && *ucs4 > '0' && *ucs4 < '6')
  170. return (char)*ucs4;
  171. }
  172. return '0';
  173. }
  174. int id3_metadata_setrating(struct id3_tag* tag, char value)
  175. {
  176. union id3_field *field;
  177. struct id3_frame *frame;
  178. char popm[] = { 3, 53, 104, 154, 205, 255 };
  179. if (value < '0' || value > '5')
  180. return -1;
  181. frame = id3_tag_findframe(tag, "POPM", 0);
  182. if (frame == 0)
  183. {
  184. frame = id3_frame_new("POPM");
  185. id3_tag_attachframe(tag, frame);
  186. }
  187. field = id3_frame_field(frame, 1);
  188. if (field == 0)
  189. return 0;
  190. return id3_field_setint(field, popm[value - '0']);
  191. }
  192. const id3_ucs4_t *id3_metadata_getcompilation(const struct id3_tag* tag, enum id3_field_textencoding *encoding)
  193. {
  194. return metadata_getstring(tag, "TCMP", encoding);
  195. }
  196. int id3_metadata_setcompilation(struct id3_tag* tag, id3_ucs4_t *value)
  197. {
  198. return metadata_setstring(tag, "TCMP", value);
  199. }
  200. const id3_ucs4_t* id3_metadata_gettitle(const struct id3_tag* tag, enum id3_field_textencoding* encoding)
  201. {
  202. return metadata_getstring(tag, ID3_FRAME_TITLE, encoding);
  203. }
  204. int id3_metadata_settitle(struct id3_tag* tag, id3_ucs4_t* value)
  205. {
  206. return metadata_setstring(tag, ID3_FRAME_TITLE, value);
  207. }
  208. const id3_ucs4_t* id3_metadata_gettrack(const struct id3_tag* tag, enum id3_field_textencoding* encoding)
  209. {
  210. return metadata_getstring(tag, ID3_FRAME_TRACK, encoding);
  211. }
  212. int id3_metadata_settrack(struct id3_tag* tag, id3_ucs4_t* value)
  213. {
  214. return metadata_setstring(tag, ID3_FRAME_TRACK, value);
  215. }
  216. const id3_ucs4_t* id3_metadata_getpartofset(const struct id3_tag* tag, enum id3_field_textencoding* encoding)
  217. {
  218. return metadata_getstring(tag, "TPOS", encoding);
  219. }
  220. int id3_metadata_setpartofset(struct id3_tag* tag, id3_ucs4_t* value)
  221. {
  222. return metadata_setstring(tag, "TPOS", value);
  223. }
  224. const id3_ucs4_t* id3_metadata_getyear(const struct id3_tag* tag, enum id3_field_textencoding* encoding)
  225. {
  226. return metadata_getstring(tag, ID3_FRAME_YEAR, encoding);
  227. }
  228. int id3_metadata_setyear(struct id3_tag* tag, id3_ucs4_t* value)
  229. {
  230. return metadata_setstring(tag, ID3_FRAME_YEAR, value);
  231. }
  232. const id3_ucs4_t* id3_metadata_getgenre(const struct id3_tag* tag, enum id3_field_textencoding* encoding)
  233. {
  234. return metadata_getstring(tag, ID3_FRAME_GENRE, encoding);
  235. }
  236. id3_ucs4_list_t* id3_metadata_getgenres(const struct id3_tag* tag, enum id3_field_textencoding* encoding)
  237. {
  238. return metadata_getstrings(tag, ID3_FRAME_GENRE, encoding);
  239. }
  240. int id3_metadata_setgenre(struct id3_tag* tag, id3_ucs4_t* value)
  241. {
  242. return metadata_setstring(tag, ID3_FRAME_GENRE, value);
  243. }
  244. const id3_ucs4_t* id3_metadata_getcomment(const struct id3_tag* tag, enum id3_field_textencoding* encoding)
  245. {
  246. union id3_field const *field;
  247. struct id3_frame const *frame;
  248. const id3_ucs4_t* ucs4 = id3_ucs4_empty;
  249. int commentNumber = 0;
  250. // return the first non-empty comment
  251. do
  252. {
  253. frame = id3_tag_findframe(tag, ID3_FRAME_COMMENT, commentNumber++);
  254. if (frame && frame->nfields == 4)
  255. {
  256. //get short description
  257. field = id3_frame_field(frame, 2);
  258. if (field == 0)
  259. continue;
  260. ucs4 = id3_field_getstring(field);
  261. // Multiple values are allowed per comment field, but storing different comment
  262. // frames requires a different description for each frame. The first COMM frame
  263. // encountered without a description will be used as the comment field.
  264. // Source http://puddletag.sourceforge.net/source/id3.html
  265. if (ucs4 && *ucs4 == 0)//if short description on this frame is empty - consider this the wanted comment frame
  266. {
  267. //fetch encoding of the frame
  268. field = id3_frame_field(frame, 0);
  269. if(field == 0)
  270. continue;
  271. *encoding = id3_field_gettextencoding(field);
  272. //finally fetch the comment
  273. field = id3_frame_field(frame, 3);
  274. if (field == 0)
  275. break;
  276. ucs4 = id3_field_getfullstring(field);
  277. //done
  278. break;
  279. }
  280. }
  281. }
  282. while (frame);
  283. return ucs4;
  284. }
  285. int id3_metadata_setcomment(struct id3_tag* tag, id3_ucs4_t* value)
  286. {
  287. union id3_field *field;
  288. struct id3_frame *frame;
  289. frame = id3_tag_findframe(tag, ID3_FRAME_COMMENT, 0);
  290. if (frame == 0)
  291. {
  292. frame = id3_frame_new(ID3_FRAME_COMMENT);
  293. id3_tag_attachframe(tag, frame);
  294. }
  295. id3_field_settextencoding(id3_frame_field(frame, 0), ID3_FIELD_TEXTENCODING_UTF_16);
  296. field = id3_frame_field(frame, 3);
  297. if (field == 0)
  298. return 0;
  299. return id3_field_setfullstring(field, value);
  300. }
  301. const id3_ucs4_t* id3_metadata_getencodedby(const struct id3_tag* tag, enum id3_field_textencoding* encoding)
  302. {
  303. return metadata_getstring(tag, "TENC", encoding);
  304. }
  305. int id3_metadata_setencodedby(struct id3_tag* tag, id3_ucs4_t* value)
  306. {
  307. return metadata_setstring(tag, "TENC", value);
  308. }
  309. struct id3_frame const* id3_metadata_getpictureframebytype(const struct id3_tag* tag, enum id3_picture_type picture_type)
  310. {
  311. int i;
  312. union id3_field const *field;
  313. struct id3_frame const *frame;
  314. for (i=0; ; ++i)
  315. {
  316. frame = id3_tag_findframe(tag, "APIC", i);
  317. if (frame == 0)
  318. return 0;
  319. field = id3_frame_field(frame, 2);
  320. if (field == 0)
  321. return 0;
  322. if (id3_field_getint(field)==picture_type)
  323. break;
  324. }
  325. return frame;
  326. }
  327. int id3_metadata_haspicture(const struct id3_tag* tag, enum id3_picture_type picture_type)
  328. {
  329. return (id3_metadata_getpictureframebytype(tag, picture_type)!=0);
  330. }
  331. const id3_latin1_t* id3_metadata_getpicturemimetype(const struct id3_tag* tag, enum id3_picture_type picture_type)
  332. {
  333. union id3_field const *field;
  334. struct id3_frame const *frame;
  335. frame=id3_metadata_getpictureframebytype(tag, picture_type);
  336. if (frame==0)
  337. return 0;
  338. field = id3_frame_field(frame, 1);
  339. if (field == 0)
  340. return 0;
  341. return id3_field_getlatin1(field);
  342. }
  343. id3_byte_t const* id3_metadata_getpicturedata(const struct id3_tag* tag, enum id3_picture_type picture_type, id3_length_t* length)
  344. {
  345. union id3_field const *field;
  346. struct id3_frame const *frame;
  347. frame=id3_metadata_getpictureframebytype(tag, picture_type);
  348. if (frame==0)
  349. return 0;
  350. field = id3_frame_field(frame, 4);
  351. if (field == 0)
  352. return 0;
  353. return id3_field_getbinarydata(field, length);
  354. }
  355. int id3_metadata_getfirstnonstandardpictype(const struct id3_tag* tag, enum id3_picture_type* picture_type)
  356. {
  357. int i=0;
  358. union id3_field const *field;
  359. struct id3_frame const *frame;
  360. for (i=0; ; ++i)
  361. {
  362. frame = id3_tag_findframe(tag, "APIC", i);
  363. if (frame == 0)
  364. return 0;
  365. field = id3_frame_field(frame, 2);
  366. if (field == 0)
  367. return 0;
  368. if ((*picture_type=id3_field_getint(field))>ID3_PICTURE_TYPE_PUBLISHERLOGO)
  369. break;
  370. }
  371. return 1;
  372. }
  373. id3_byte_t const* id3_metadata_getuniquefileidentifier(const struct id3_tag* tag, const char* owner_identifier, id3_length_t* length)
  374. {
  375. int i=0, result;
  376. id3_ucs4_t const * ucs4;
  377. id3_latin1_t* latin1;
  378. union id3_field const *field;
  379. struct id3_frame const *frame;
  380. id3_byte_t const* identifier;
  381. for (i=0; ; ++i)
  382. {
  383. frame = id3_tag_findframe(tag, "UFID", i);
  384. if (frame == 0)
  385. return 0;
  386. field = id3_frame_field(frame, 0);
  387. if (field == 0)
  388. return 0;
  389. if (strcmp(id3_field_getlatin1(field), owner_identifier)==0)
  390. break;
  391. }
  392. field = id3_frame_field(frame, 1);
  393. if (field == 0)
  394. return 0;
  395. return id3_field_getbinarydata(field, length);
  396. }
  397. const id3_ucs4_t* id3_metadata_getusertext(const struct id3_tag* tag, const char* description)
  398. {
  399. id3_ucs4_t const * ucs4;
  400. id3_latin1_t* latin1;
  401. union id3_field const *field;
  402. struct id3_frame const *frame;
  403. id3_length_t length;
  404. int i=0, result;
  405. for (i=0; ; ++i)
  406. {
  407. frame = id3_tag_findframe(tag, "TXXX", i);
  408. if (frame == 0)
  409. return id3_ucs4_empty;
  410. field = id3_frame_field(frame, 1);
  411. if (field == 0)
  412. return id3_ucs4_empty;
  413. latin1=id3_ucs4_latin1duplicate(id3_field_getstring(field));
  414. result=strcmp(latin1, description);
  415. free(latin1);
  416. if (result==0)
  417. break;
  418. }
  419. field = id3_frame_field(frame, 2);
  420. if (field == 0)
  421. return id3_ucs4_empty;
  422. return id3_field_getstring(field);
  423. }