1 /*
2  * mp3rename.c
3  *
4  * Sander Janssen      <janssen@rendo.dekooi.nl>
5  *
6  * This software is covered by the GNU public license,
7  * which should be in a file named LICENSE acompanying
8  * this.
9  *
10  */
11 
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <unistd.h>
15 #include <ctype.h>
16 #include <string.h>
17 #include <signal.h>
18 
19 void pad(char *string, int length);
20 void display_help();
21 void buildtag(char *buf, char *title, char *artist, char *album, char *year, char *comment, char *genre);
22 void set_filename(int argc,char *argv[]);
23 
main(int argc,char * argv[])24 int main(int argc, char *argv[])
25 {
26   FILE *fp;
27   int verbose = 0, forced = 0, burn = 0, info = 0, all = 0;
28   unsigned char sig[2];
29   char genre[1];
30   char input_char;
31   int i=0,plaatsen = 0;
32   int ch,p;
33   char filenamelook[100];
34   char str[100];
35 
36 
37   if (argc < 2 ) /* If nothing is given */
38   {
39     fprintf(stderr,"Mp3rename\n\nusage: [-vfhsbia] [file ...]\n\n");
40     return 0;
41   }
42 
43   /* Lets checkout the options */
44 
45   while ((ch = getopt(argc, argv, "vfhsbia")) != -1)
46     switch (ch)
47     {
48       case 'v':                      /* Verbose mode */
49         verbose = 1;
50         break;
51       case 'f':                      /* Always ask mode */
52         forced = 1;
53         break;
54       case 'h':                      /* Display the help */
55         display_help();
56         exit(1);
57       case 's':                      /* Set the default look */
58         set_filename(argc,argv);
59         exit(1);
60       case 'b':                      /* Burn modus cut of at 32 chars */
61         burn = 1;
62         break;
63       case 'i':                      /* Just the id3tag */
64 	info = 1;
65 	break;
66       case 'a':                      /* Ask everything */
67 	all = 1;
68 	break;
69       default:                       /* If wrong option is given */
70         fprintf(stderr,"Mp3rename\n\nusage: [-vfh] [file ...]\n\n");
71         exit(1);
72     }
73   argv += optind;
74 
75   if ( info == 1 && ( forced == 1 || verbose == 1))
76     {
77       printf("Info modus can not be used with other arguments.\n\n");
78       exit(1);
79     }
80   sprintf(str,"%s/.mp3rename",getenv("HOME")); /* Lets get the home dir */
81 
82   if ( !( fp=fopen(str,"r") ) ) /* if we don't find our config file */
83     {
84      sprintf(filenamelook,"(&a)-&t");
85      printf("Using default look, please use the -s option to set your own look\n");
86     }
87   else  /* found! */
88       fgets(filenamelook, 100, fp);
89 
90  if(burn != 1) /* If burn is on we will add the .mp3 later */
91   strcat(filenamelook,".mp3"); /* add .mp3 so that the filename will be complete */
92 
93 do {
94  char title[31]="", artist[31]="", album[31]="", year[5]="", comment[31]="", fbuf[4], newfilename[160]="",nieuw[150]="",dir[150]="",dirsource[200],fullline[228]="", burnname[29]="";
95   plaatsen = 0;
96 
97   if ( !( fp=fopen(*argv,"rb+") ) )    /* If the file doesn exist */
98   {
99      perror("Error opening file");
100      ++argv;                         /* Prepare for the next file */
101      continue;
102   }
103 
104   /* Lets check if we have a real mp3 file */
105 
106   fread(sig,sizeof(sig),1,fp);
107   sig[0] &= 0xff;
108   sig[1] &= 0xf0;
109   if(!((sig[0] == 0xff) && (sig[1] == 0xf0)))
110   {
111     fprintf(stderr,"%s is not an MP3 file!\n",*argv);
112     fclose(fp);
113     ++argv;
114     continue;
115   }
116 
117   /* Lets go to the beginning of the tag */
118    if ( fseek(fp, -128, SEEK_END ))
119    {
120      fclose(fp);
121      ++argv;
122      continue;
123    }
124 
125    /* Lets see if we already have a id3 tag */
126    fread(fbuf,1,3,fp); fbuf[3] = '\0';
127    if (!strcmp("TAG",fbuf) && !forced)
128    {
129      fseek(fp, -125, SEEK_END);
130      fread(title,1,30,fp); title[30] = '\0';
131      fread(artist,1,30,fp); artist[30] = '\0';
132      fread(album,1,30,fp); album[30] = '\0';
133      fread(year,1,4,fp); year[4] = '\0';
134      fread(comment,1,30,fp); comment[30] = '\0';
135      fread(genre,1,1,fp);
136      fseek(fp, -128, SEEK_END); /* back to the beginning of the tag */
137    }
138    else
139    {
140     if (!strcmp("TAG",fbuf) ) /* go to the position to append one */
141       {
142         if(forced)
143 	  {
144 	    fseek(fp, -125, SEEK_END);
145 	    fread(title,1,30,fp); title[30] = '\0';
146 	    fread(artist,1,30,fp); artist[30] = '\0';
147 	    fread(album,1,30,fp); album[30] = '\0';
148 	    fread(year,1,4,fp); year[4] = '\0';
149 	    fread(comment,1,30,fp); comment[30] = '\0';
150 	    fread(genre,1,1,fp);
151 	  }
152         fseek(fp, -128, SEEK_END);
153       }
154     else
155       fseek(fp, 0, SEEK_END);
156       if(verbose || forced)            /* Manual change of the name */
157       {
158         if(verbose)
159           printf("%s hasen't got a id3 tag. \n",*argv);
160         else
161           printf("%s:\n",*argv);
162         if(!all)
163 	  {
164 	    for( i=0 ; i!=(strlen(filenamelook)) ; i++)
165 	      {
166 		p = 0;
167 		if(filenamelook[i] == '&')
168 		  {
169 		    switch(filenamelook[i+1])
170 		      {
171 		        case 'a':
172 			  printf("Please enter the artist's name.\n");
173 			  do  /* Lets get the artist */
174 			    {
175 			      input_char = getchar();
176 			      if (input_char != '\n' && p == 0)
177 				strcpy(artist,"");
178 			      if (input_char != '\n' && input_char != EOF )
179 				sprintf(artist,"%s%c",artist,input_char);
180 			      p++;
181 			    } while (input_char != '\n');
182 			  i++;
183 			  break;
184 		        case 't':
185 			  printf("Please enter the title.\n");
186 			  do  /* Lets get the song title */
187 			    {
188 			      input_char = getchar();
189 			      if (input_char != '\n' && p == 0)
190 				strcpy(title,"");
191 			      if (input_char != '\n' && input_char != EOF)
192 				sprintf(title,"%s%c",title,input_char);
193 			      p++;
194 			    } while (input_char != '\n');
195 			  i++;
196 			  break;
197 		        case 'b':
198 			  printf("Please enter the album.\n");
199 			  do  /* Lets get the album */
200 			    {
201 			      input_char = getchar();
202 			      if (input_char != '\n' && p == 0)
203 				strcpy(album,"");
204 			      if (input_char != '\n' && input_char != EOF)
205 				sprintf(album,"%s%c",album,input_char);
206 			      p++;
207 			    } while (input_char != '\n');
208 			  i++;
209 			  break;
210 		        case 'y':
211 			  printf("Please enter the year.\n");
212 			  do  /* Lets get the year */
213 			    {
214 			      input_char = getchar();
215 			      if (input_char != '\n' && p == 0)
216 				strcpy(year,"");
217 			      if (input_char != '\n' && input_char != EOF)
218 				sprintf(year,"%s%c",year,input_char);
219 			      p++;
220 			    } while (input_char != '\n');
221 			  i++;
222 			  break;
223 		        default: /* the user has entered a character behind the & we don't know */
224 			  printf("Illegal char in config file please use the option '-s help' for more information");
225 			  exit(1);
226 		      }
227 		  }
228 	      }
229 	  }
230 	else
231 	  {
232 	    p = 0;
233 	    printf("Please enter the artist's name.\n");
234 	    do  /* Lets get the artist */
235 	      {
236 		input_char = getchar();
237 		if (input_char != '\n' && p == 0)
238 		  strcpy(artist,"");
239 		if (input_char != '\n' && input_char != EOF )
240 		  sprintf(artist,"%s%c",artist,input_char);
241 		p++;
242 	      } while (input_char != '\n');
243 	    p = 0;
244 	    printf("Please enter the title.\n");
245 	    do  /* Lets get the song title */
246 	      {
247 		input_char = getchar();
248 		if (input_char != '\n' && p == 0)
249 		  strcpy(title,"");
250 		if (input_char != '\n' && input_char != EOF)
251 		  sprintf(title,"%s%c",title,input_char);
252 		p++;
253 	      } while (input_char != '\n');
254 	    i++;
255 	    p = 0;
256 	    printf("Please enter the album.\n");
257 	    do  /* Lets get the album */
258 	      {
259 		input_char = getchar();
260 		if (input_char != '\n' && p == 0)
261 		  strcpy(album,"");
262 		if (input_char != '\n' && input_char != EOF)
263 		  sprintf(album,"%s%c",album,input_char);
264 		p++;
265 	      } while (input_char != '\n');
266 	    p = 0;
267 	    printf("Please enter the year.\n");
268 	    do  /* Lets get the year */
269 	      {
270 		input_char = getchar();
271 		if (input_char != '\n' && p == 0)
272 		  strcpy(year,"");
273 		if (input_char != '\n' && input_char != EOF)
274 		  sprintf(year,"%s%c",year,input_char);
275 		p++;
276 	      } while (input_char != '\n');
277 	  }
278         }
279       else   /* If we aren't in verbose or forced mode */
280         {
281           printf("%s hasen't got a id3 tag\n",*argv);
282           fclose(fp);
283           ++argv;
284           continue;
285         }
286 
287    }
288 
289   if(info == 1)
290     {
291       printf("Artist : %s\n",artist);
292       printf("Title : %s\n",title);
293       printf("Album : %s\n",album);
294       printf("Year : %s\n\n",year);
295       ++argv;
296       continue;
297     }
298 
299    /* Remove trailing spaces */
300   i=strlen(artist)-1;
301   while (i && artist[i]==' ')
302   {
303     artist[i]='\0';
304     i--;
305   }
306 
307   i=strlen(title)-1;
308   while (i && title[i]==' ')
309   {
310     title[i]='\0';
311     i--;
312   }
313   i=strlen(album)-1;
314   while (i && album[i]==' ')
315   {
316     album[i]='\0';
317     i--;
318   }
319   i=strlen(year)-1;
320   while (i && year[i]==' ')
321   {
322     year[i]='\0';
323     i--;
324   }
325 
326   /* We go through the filenamelook until we find a &x combination
327      then we replace the &x with album/title/year/artis            */
328   for( i=0 ; i!=(strlen(filenamelook)) ; i++)
329     {
330      if(filenamelook[i] == '&')
331        {
332          char tmp[100];
333          switch(filenamelook[i+1])
334 	  {
335 	     case 'a':
336                 sprintf(tmp,"%s%s",newfilename,artist);
337                 strcpy(newfilename,tmp);
338                 i++;
339                 break;
340              case 't':
341                 sprintf(tmp,"%s%s",newfilename,title);
342                 strcpy(newfilename,tmp);
343                 i++;
344                 break;
345              case 'b':
346                 sprintf(tmp,"%s%s",newfilename,album);
347                 strcpy(newfilename,tmp);
348                 i++;
349                 break;
350              case 'y':
351                 sprintf(tmp,"%s%s",newfilename,year);
352                 strcpy(newfilename,tmp);
353                 i++;
354                 break;
355              default:
356                 printf("Illegal char in config file please use the option '-s help' for more information\n");
357                 exit(1);
358 
359 	  }
360        }
361      else /* otherwise we just print the character in the filenamelook in the newfilename */
362        {
363       char tmp[100];
364       sprintf(tmp,"%s%c",newfilename,filenamelook[i]);
365       strcpy(newfilename,tmp);
366        }
367     }
368 
369   /* Lets find out what directory we are working in */
370 
371   sprintf(dirsource,"%s",*argv);
372   i=strlen(dirsource)+1;
373   while (i>-1)
374   {
375    if(dirsource[i] == '/')
376     plaatsen = 1;
377    if(plaatsen)
378     dir[i] = dirsource[i];
379    else
380     dir[i] = '\0';
381     i--;
382   }
383 
384   /* Build the new tag from the new names */
385 
386   buildtag(fullline,title,artist,album,year,comment,genre);
387   fwrite(fullline,1,128,fp);
388 
389   fclose(fp);
390 
391   /* Lets catch illegal characters */
392  for (i=0; i < strlen(newfilename); i++)
393   {
394     switch (newfilename[i])
395     {
396       case '<': newfilename[i] = '[';
397         break;
398       case '>': newfilename[i] = ']';
399         break;
400       case '|': newfilename[i] = '_';
401         break;
402       case '/': newfilename[i] = '-';
403         break;
404       case '\\': newfilename[i]= '-';
405         break;
406       case '*': newfilename[i] = '_';
407         break;
408       case '?': newfilename[i] = '_';
409         break;
410       case ':': newfilename[i] = ';';
411         break;
412       case '"': newfilename[i] = '-';
413         break;
414       default: break;
415     }
416   }
417 
418  /* Lets rename the file */
419   if(burn == 1) /* If burn is on the size */
420     {	        /* shouldn't be bigger than 32 chars including the .mp3 */
421       strncpy(burnname,newfilename,sizeof(burnname)-1);
422       sprintf(nieuw,"%s%s.mp3",dir,burnname);
423     }
424   else
425     {
426       sprintf(nieuw,"%s%s",dir,newfilename);
427     }
428   if(rename(*argv,nieuw))
429     printf("Error renaming %s\n",*argv);
430 
431   ++argv;   /* Prepare for the next */
432 
433 
434 } while (*argv);
435 
436 return 0;
437 }
438 
buildtag(char * buf,char * title,char * artist,char * album,char * year,char * comment,char * genre)439 void buildtag(char *buf, char *title, char *artist, char *album, char *year, char *comment, char *genre)
440 {
441 
442   strcpy(buf,"TAG");
443   pad(title,30);
444   strncat(buf,title,30);
445   pad(artist,30);
446   strncat(buf,artist,30);
447   pad(album,30);
448   strncat(buf,album,30);
449   pad(year,4);
450   strncat(buf,year,4);
451   pad(comment,30);
452   strncat(buf,comment,30);
453   strncat(buf,genre,1);
454 }
455 
pad(char * string,int length)456 void pad(char *string, int length)
457 {
458   int i;
459 
460   i=strlen(string);
461   while(i<length)
462   {
463     string[i] = ' ';
464     i++;
465   }
466 
467   string[i]='\0';
468 }
469 
display_help()470 void display_help()
471 {
472   printf("Mp3rename 0.6\n\n");
473   printf("Options:\n");
474   printf("\t-f\t Force non id3 rename.\n");
475   printf("\t-v\t Verbose mode.\n");
476   printf("\t-h\t Display this help message.\n");
477   printf("\t-b\t Limit the file size to 32 chars.\n");
478   printf("\t-i\t Only show the id3tags.\n");
479   printf("\t-a\t Ask everything for the id3tag.\n\n");
480   printf("\t-s\t Set the default filename look.\n");
481   printf("\t  \t for more help on this option: -s help\n\n");
482   printf("Sander Janssen <janssen@rendo.dekooi.nl>\n\n");
483 
484 }
set_filename(int argc,char * argv[])485 void set_filename(int argc,char *argv[])
486 {
487   FILE *fp;
488   char str[100];
489 
490  argv += 2;
491 
492  if(*argv == NULL)
493  {
494      printf("No config format given\n\r");
495      return;
496  }
497 
498  if(!strcmp(*argv,"help"))
499    {
500      printf("Mp3rename 0.6\n\n");
501      printf(" Use this option to set the default look of the file\n");
502      printf(" The information is saved in ~/.mp3rename\n");
503      printf(" You can use &t title, &b album, &y year and &a artist\n\n");
504      printf(" Example : mp3rename -s '(&a)-&t-&b'\n");
505      printf(" for (artist)-title-album.mp3\n\n");
506      return;
507    }
508   sprintf(str,"%s/.mp3rename",getenv("HOME"));
509 
510    if ( !( fp=fopen(str,"w") ) )
511     {
512      printf("Error opening config file\n\r");
513      return;
514     }
515 
516  if(!strcmp(*argv,""))
517  {
518      printf("No config format given\n\r");
519      return;
520  }
521  printf("Default is now set\n\n");
522 
523  fprintf(fp,*argv);
524  fclose(fp);
525 }
526 
527 
528 
529 
530