1 /*
2 MP3Info - Displays and allows editing of MP3 ID3 tags and various
3 technical aspects of MP3 files.
4
5 mp3info.c - main part of console version of MP3Info
6
7 Copyright (C) 2000-2006 Cedric Tefft <cedric@phreaker.net>
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22
23 ***************************************************************************
24
25 This program is based in part on MP3Info 0.5 by Ricardo Cerqueira <rmc@rccn.net>
26
27 */
28
29
30 #define __MAIN
31 #include "mp3info.h"
32 #undef __MAIN
33 #include <sys/stat.h>
34
35 char FILENAME_FORMAT_STRING[]="File: %F\n";
36 char ID3_FORMAT_STRING[]="Title: %-30t Track: %n\nArtist: %a\nAlbum: %-30l Year: %y\nComment: %-30c Genre: %g [%G]\n";
37 char TECH_FORMAT_STRING[]="Media Type: MPEG %2.1v Layer %L\nAudio: %r KB/s, %qKHz (%o)\nEmphasis: %e\nCRC: %E\nCopyright: %C\nOriginal: %O\nPadding: %p\nLength: %m:%02s\n";
38
main(int argc,char * argv[])39 int main(int argc, char *argv[]) {
40 FILE *fp;
41 int c, i, interactive = 0, view_only=1,delete_tag=0,file_open,retcode=0;
42 int want_id3=1,scantype=SCAN_NONE,fullscan_vbr=0;
43 int show_techinfo=0,force_mode=0,quickscan=1;
44 int new_track=0,new_genre=0,firstfilearg;
45 id3tag new_tag;
46 char *print_format=NULL;
47 char error_msg[256];
48 unsigned int g,n;
49 int vbr_report=VBR_VARIABLE;
50 mp3info mp3;
51
52
53 new_tag.title[0]=new_tag.artist[0]=new_tag.album[0]=new_tag.year[0]=
54 new_tag.comment[0]=new_tag.track[0]=new_tag.genre[0]=1;
55 /* use something REALLY unlikely... -- so we could clear the tag... */
56
57 if (argc < 2 ) /* Only command is given. Short help */ {
58 printf("%s %s\n"\
59 "\n MP3Info comes with ABSOLUTELY NO WARRANTY. This is free software, and\n"\
60 " you are welcome to redistribute it under certain conditions.\n"\
61 " See the file 'LICENSE' for more information.\n"\
62 "\nUse 'mp3info -h' for a usage summary or see the mp3info man page for a\n"\
63 "complete description.\n",VERSION,COPYRIGHT);
64 return 0;
65 }
66
67
68
69 while ((c=getopt(argc,argv,"vhGidfxFt:a:l:y:c:n:g:p:r:"))!=-1) {
70
71 switch(c) {
72 case 'v': /* View mode is now automatic when no changes are
73 made to the ID3 tag. This switch is accepted
74 only for backward compatibility */
75 break;
76 case 'h':
77 display_help(); return 0;
78 break;
79 case 'G':
80 display_genres(alphagenreindex,typegenre); return 0;
81 break;
82 case 'i':
83 view_only=0;
84 interactive = 1;
85 break;
86 case 'd':
87 view_only=0;
88 delete_tag=1;
89 break;
90 case 'p':
91 print_format=optarg;
92 translate_escapes(print_format);
93 want_id3=0;
94 break;
95 case 'f':
96 force_mode=1;
97 break;
98 case 'x':
99 show_techinfo=1;
100 break;
101 case 't':
102 strncpy(new_tag.title,optarg,TEXT_FIELD_LEN);
103 view_only=0;
104 break;
105 case 'a':
106 strncpy(new_tag.artist,optarg,TEXT_FIELD_LEN);
107 view_only=0;
108 break;
109 case 'l':
110 strncpy(new_tag.album,optarg,TEXT_FIELD_LEN);
111 view_only=0;
112 break;
113 case 'y':
114 strncpy(new_tag.year,optarg,INT_FIELD_LEN);
115 view_only=0;
116 break;
117 case 'c':
118 strncpy(new_tag.comment,optarg,TEXT_FIELD_LEN);
119 view_only=0;
120 break;
121 case 'n':
122 n=atoi(optarg);
123 if(n <= 255) {
124 new_tag.track[0] = (unsigned char) n;
125 new_track=1;
126 view_only=0;
127 } else {
128 fprintf(stderr,"Error: '%s' is not a valid track number.\n",optarg);
129 fprintf(stderr,"Valid track numbers are integers from 0 to 255.\n");
130 fprintf(stderr,"Use a value of '0' to remove the track number field\n");
131 retcode |= 6;
132 return retcode;
133 }
134 break;
135 case 'g':
136 g=get_genre(optarg);
137 if(g <= 255) {
138 new_tag.genre[0] = (unsigned char) g;
139 new_genre=1;
140 view_only=0;
141 } else {
142 fprintf(stderr,"Error: '%s' is not a recognized genre name or number.\n",optarg);
143 fprintf(stderr,"Use the '-G' option to see a list of valid genre names and numbers\n");
144 retcode |= 6;
145 return retcode;
146 }
147 sscanf(optarg,"%u",&g);
148 break;
149 case 'r':
150 switch(optarg[0]) {
151 case 'a': vbr_report=VBR_AVERAGE; break;
152 case 'm': vbr_report=VBR_MEDIAN; break;
153 case 'v': vbr_report=VBR_VARIABLE; break;
154 default:
155 fprintf(stderr,"Error: %s is not a valid option to the VBR reporting switch (-r)\n",optarg);
156 fprintf(stderr,"Valid options are 'a', 'm' and 'v'. Run '%s -h' for more info.\n",argv[0]);
157 retcode |= 6;
158 return retcode;
159 }
160 break;
161 case 'F': quickscan=0; break;
162 }
163 }
164
165 if(!view_only)
166 scantype=SCAN_QUICK;
167
168 if(print_format) {
169 determine_tasks(print_format,&want_id3,&scantype,&fullscan_vbr,vbr_report);
170 } else if(view_only) {
171 determine_tasks(ID3_FORMAT_STRING,&want_id3,&scantype,&fullscan_vbr,vbr_report);
172 if(show_techinfo)
173 determine_tasks(TECH_FORMAT_STRING,&want_id3,&scantype,&fullscan_vbr,vbr_report);
174 }
175
176
177 if(!quickscan && (scantype == SCAN_QUICK))
178 scantype=SCAN_FULL;
179
180 firstfilearg=optind;
181
182 for(i=optind;i < argc; i++) { /* Iterate over all filenames */
183 file_open=0;
184 if (view_only == 1) {
185 if ( !( fp=fopen(argv[i],"rb") ) ) {
186 sprintf(error_msg,"Error opening MP3: %s",argv[i]);
187 perror(error_msg);
188 retcode |= 1;
189 } else {
190 file_open=1;
191 }
192 } else {
193 if ( !( fp=fopen(argv[i],"rb+") ) ) {
194 sprintf(error_msg,"Error opening MP3: %s",argv[i]);
195 perror(error_msg);
196 retcode |= 1;
197 } else {
198 file_open=1;
199 }
200 }
201
202 if(file_open == 1) {
203 memset(&mp3,0,sizeof(mp3info));
204 mp3.filename=argv[i];
205 mp3.file=fp;
206 get_mp3_info(&mp3,scantype,fullscan_vbr);
207
208 if((scantype != SCAN_NONE) && !mp3.header_isvalid && !force_mode) {
209 fprintf(stderr,"%s is corrupt or is not a standard MP3 file.\n",mp3.filename);
210 retcode |= 2;
211 }
212
213 if(view_only) {
214 if(want_id3 && !mp3.id3_isvalid)
215 fprintf(stderr,"%s does not have an ID3 1.x tag.\n",mp3.filename);
216
217 if(print_format) {
218 format_output(print_format,&mp3,vbr_report);
219 } else {
220
221 if(mp3.id3_isvalid || (show_techinfo && mp3.header_isvalid))
222 format_output(FILENAME_FORMAT_STRING,&mp3,vbr_report);
223
224 if(mp3.id3_isvalid)
225 format_output(ID3_FORMAT_STRING,&mp3,vbr_report);
226
227 if(show_techinfo && mp3.header_isvalid)
228 format_output(TECH_FORMAT_STRING,&mp3,vbr_report);
229
230 printf("\n");
231
232 }
233
234 } else if(mp3.header_isvalid || force_mode) {
235
236 if(new_tag.title[0]!=1) {
237 strncpy(mp3.id3.title,new_tag.title,TEXT_FIELD_LEN);
238 }
239
240 if(new_tag.artist[0]!=1) {
241 strncpy(mp3.id3.artist,new_tag.artist,TEXT_FIELD_LEN);
242 }
243
244 if(new_tag.album[0]!=1) {
245 strncpy(mp3.id3.album,new_tag.album,TEXT_FIELD_LEN);
246 }
247
248 if(new_tag.comment[0]!=1) {
249 strncpy(mp3.id3.comment,new_tag.comment,TEXT_FIELD_LEN);
250 }
251
252 if(new_track) {
253 mp3.id3.track[0]=new_tag.track[0];
254 if(new_tag.track[0] == '\0') {
255 pad(mp3.id3.comment,TEXT_FIELD_LEN);
256 }
257 }
258
259 if(new_tag.year[0]!=1) {
260 strncpy(mp3.id3.year,new_tag.year,INT_FIELD_LEN);
261 }
262
263 if(new_genre) {
264 mp3.id3.genre[0]=new_tag.genre[0];
265 }
266
267 if( interactive ) {
268 tagedit_curs(mp3.filename,i-firstfilearg+1,argc-firstfilearg,&(mp3.id3));
269 }
270
271
272
273 /* Finally! Get it done! */
274 if(!delete_tag) {
275 write_tag(&mp3);
276 }
277
278 } else {
279 fprintf(stderr,"Use the -f switch to add ID3 info to this file anyway.\n");
280 }
281
282 fclose(mp3.file);
283
284 if(delete_tag && mp3.id3_isvalid) {
285 truncate(mp3.filename,mp3.datasize);
286 }
287
288
289 }
290
291 }
292
293 if(optind == argc) {
294 fprintf(stderr,"No MP3 files specified!\n");
295 retcode |= 8;
296 }
297
298
299 return retcode;
300
301 }
302
303
304