1 #include <vector>
2 #include <cstdio>
3 #include <cstring>
4 #include "getid3.h"
5
6 /*
7
8 copyright (c) 2004, 2005 squell <squell@alumina.nl>
9
10 use, modification, copying and distribution of this software is permitted
11 under the conditions described in the file 'COPYING'.
12
13 */
14
15 using namespace std;
16 using namespace charset;
17
18 using tag::read::ID3;
19 using tag::ID3field;
20
21 namespace {
readtag(const char * fn)22 inline ID3v1 readtag(const char *fn)
23 {
24 struct ID3v1 tag = { { 0, } };
25 if( FILE* f = fopen(fn, "rb") ) {
26 fseek(f, -128, SEEK_END) == 0 &&
27 fread(&tag, 1, 128, f) == 128 &&
28 memcmp(tag.TAG, "TAG", 3) == 0 || (tag.TAG[0] = 0);
29 fclose(f);
30 }
31 return tag;
32 }
33 }
34
ID3(const char * fn)35 ID3::ID3(const char* fn) : tag(readtag(fn))
36 {
37 }
38
operator [](ID3field field) const39 ID3::value_string ID3::operator[](ID3field field) const
40 {
41 char buf[31] = { 0, }; // enough to hold largest ID3 field+1
42
43 if(*tag.TAG)
44 switch( field ) {
45 case title:
46 strncpy(buf, tag.title, sizeof tag.title);
47 break;
48 case artist:
49 strncpy(buf, tag.artist, sizeof tag.artist);
50 break;
51 case album:
52 strncpy(buf, tag.album, sizeof tag.album);
53 break;
54 case year:
55 strncpy(buf, tag.year, sizeof tag.year);
56 break;
57 case cmnt:
58 strncpy(buf, tag.cmnt, sizeof tag.cmnt + (tag.zero?2:0));
59 break;
60 case track:
61 if(tag.zero == 0 && tag.track != 0)
62 sprintf(buf, "%u", tag.track & 0xFF);
63 break;
64 case genre:
65 if(tag.genre < ID3v1_numgenres)
66 return conv<latin1>(ID3v1_genre[tag.genre]);
67 break;
68 case FIELD_MAX:
69 char ver[] = "ID3v1._";
70 ver[6] = '0'+!tag.zero;
71 return ver;
72 }
73 return conv<latin1>(buf);
74 }
75
76 /* ====================================================== */
77
78 namespace { // don't display in the order of of ID3field
79 using namespace tag;
80
81 const char* desc[] = {
82 "Title", "Artist", "Album", "Track", "Year", "Genre", "Comment"
83 };
84
85 const ID3field tab[] = {
86 title, artist, album, track, year, genre, cmnt
87 };
88 }
89
listing() const90 ID3::array ID3::listing() const
91 {
92 array vec;
93 vec.push_back( array::value_type("ID3", tag.zero? "1.0" : "1.1") );
94 for(int x = 0; x < FIELD_MAX; ++x) {
95 conv<> s = operator[](tab[x]);
96 if(!s.empty())
97 vec.push_back( array::value_type(desc[x], s) );
98 }
99 return vec;
100 }
101
102