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