1 /*
2 * Copyright (C) 2009-2015 Christian Heckendorf <heckendorfc@gmail.com>
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (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, see <http://www.gnu.org/licenses/>.
16 */
17
18 /* ID3......TTAG.....valueTTG2......value */
19
intpow(const int base,int exp)20 static int intpow(const int base, int exp){
21 int ret=base;
22 if(!exp)return 1;
23 while(--exp){
24 ret*=base;
25 }
26 return ret;
27 }
28
getTagData(unsigned char * buf,struct musicInfo * mi)29 int getTagData(unsigned char *buf, struct musicInfo *mi){
30 int x=0,ret=0,y;
31 unsigned char *tag=buf+4;
32 unsigned char *temp=calloc(5,sizeof(char));
33
34 for(x=4;*tag==0 && x>0;x--)tag++;
35 memcpy(temp,tag,x); // Info Size
36 tag+=(x+3);
37 y=ret=x;
38
39 //for(x=0;ret>0;ret--)x+=(int)pow((double)temp[y-ret],(double)ret); // Prep for strtol
40 for(x=0;ret>0;ret--)x+=intpow(temp[y-ret],ret); // Should this be x+=temp[y-ret]*intpow(256,ret)? Not that it matters since max field size will be ~200.
41
42 if(memcmp("TIT2",buf,4)==0){
43 memcpy(mi->title,tag,(x-1)>MI_TITLE_SIZE?MI_TITLE_SIZE:x-1);
44 }
45 else if(memcmp("TRCK",buf,4)==0){
46 memcpy(mi->track,tag,(x-1)>MI_TRACK_SIZE?MI_TRACK_SIZE:x-1);
47 }
48 else if(memcmp("TALB",buf,4)==0){
49 memcpy(mi->album,tag,(x-1)>MI_ALBUM_SIZE?MI_ALBUM_SIZE:x-1);
50 }
51 else if(memcmp("TYER",buf,4)==0){
52 memcpy(mi->year,tag,(x-1)>MI_YEAR_SIZE?MI_YEAR_SIZE:x-1);
53 }
54 //else if(memcmp("TLEN",buf,4)==0){
55 //memcpy(mi->length,tag,(x-1)>MI_LENGTH_SIZE?MI_LENGTH_SIZE:x-1);
56 //}
57 else if(memcmp("TPE1",buf,4)==0){
58 memcpy(mi->artist,tag,(x-1)>MI_ARTIST_SIZE?MI_ARTIST_SIZE:x-1);
59 }
60 else if(memcmp("\0\0\0\0",buf,4)==0)return -1;
61
62 free(temp);
63 return x+10;
64 }
65
ID3v2Parse(FILE * ffd,struct musicInfo * mi)66 void ID3v2Parse(FILE *ffd, struct musicInfo *mi){
67 int ret,total=3000,next=0;
68 unsigned char buffer[255];
69 fseek(ffd,next,SEEK_SET);
70 if(fread(buffer,sizeof(char),10,ffd)<10)return;
71
72 next+=10;
73 do{
74 fseek(ffd,next,SEEK_SET);
75 if(fread(buffer,sizeof(char),255,ffd)<255)next=total;
76 ret=getTagData(buffer,mi);
77 next+=ret;
78 }while(ret>0 && next<total);
79 }
80
ID3v1Parse(FILE * ffd,struct musicInfo * mi)81 void ID3v1Parse(FILE *ffd, struct musicInfo *mi){
82 int next=-125;
83 fseek(ffd,next,SEEK_END);
84 if(fread(mi->title,sizeof(char),30,ffd)<30)return;
85 next+=30;
86
87 fseek(ffd,next,SEEK_END);
88 if(fread(mi->artist,sizeof(char),30,ffd)<30)return;
89 next+=30;
90
91 fseek(ffd,next,SEEK_END);
92 if(fread(mi->album,sizeof(char),30,ffd)<30)return;
93 next+=30;
94
95 fseek(ffd,next,SEEK_END);
96 if(fread(mi->year,sizeof(char),4,ffd)<4)return;
97 next+=4;
98 }
99
mp3Length(FILE * ffd,int quick)100 int mp3Length(FILE *ffd, int quick){
101 int len;
102 long rate;
103 mpg123_init();
104 mpg123_handle *m;
105 if(!(m = mpg123_new(NULL, NULL))){
106 fprintf(stderr,"Unable to create mpg123 handle\n");
107 return -1;
108 }
109 mpg123_param(m, MPG123_FLAGS, MPG123_QUIET, 0);
110 mpg123_open_fd(m,fileno(ffd));
111 if(m == NULL) return -1;
112
113 if(!quick)
114 mpg123_scan(m);
115
116 mpg123_getformat(m,&rate,NULL,NULL);
117
118 if(rate && (len=mpg123_length(m))!=MPG123_ERR)
119 len/=rate;
120 else
121 len=-1;
122
123 mpg123_delete(m);
124 mpg123_exit();
125 return len;
126 }
127
mp3_plugin_meta(FILE * ffd,struct musicInfo * mi)128 void mp3_plugin_meta(FILE *ffd, struct musicInfo *mi){
129 int MAX_VERSION=4;
130 int next=0;
131 unsigned char buffer[255];
132 fseek(ffd,next,SEEK_SET);
133 if(fread(buffer,sizeof(char),10,ffd)<10)return;
134 if(memcmp("ID3",buffer,3)==0 && buffer[4]<=MAX_VERSION){ // ID3v2
135 ID3v2Parse(ffd,mi);
136 }
137 else{
138 fseek(ffd,-128,SEEK_END);
139 if(fread(buffer,sizeof(char),4,ffd)<4)return;
140 if(memcmp("TAG",buffer,3)==0)ID3v1Parse(ffd,mi); // ID3v1
141 }
142
143 mi->length=mp3Length(ffd,mi->length);
144 }
145