/*\r
- * FAPG 0.0 released under GPL\r
+ * FAPG 0.1 released under GPL\r
* http://royale.zerezo.com/fapg/\r
*/\r
\r
#include <stdlib.h>\r
#include <getopt.h>\r
#include <dirent.h>\r
+#include <sys/stat.h>\r
#include <sys/types.h>\r
#include <string.h>\r
#include <limits.h>\r
+#include <unistd.h>\r
+#include <ctype.h>\r
\r
#define MAX 10240\r
\r
\r
unsigned char artist[1024];\r
unsigned char title[1024];\r
-int time;\r
+int duration;\r
\r
unsigned char unix2dos[256]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,70,35,36,37,38,39,40,41,82,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,84,59,36,61,65,71,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,36,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,36,125,126,127,199,252,233,226,228,224,229,231,234,235,232,239,238,236,196,197,201,230,198,244,246,242,251,249,255,214,220,248,163,216,215,131,225,237,243,250,241,209,170,186,191,174,172,189,188,161,171,187,166,166,166,166,166,193,194,192,169,166,166,43,43,162,165,43,43,45,45,43,45,43,227,195,43,43,45,45,166,45,43,164,240,208,202,203,200,105,205,206,207,43,43,166,220,166,204,175,211,223,212,210,245,213,181,254,222,218,219,217,253,221,175,180,173,177,61,190,182,167,247,184,176,168,183,185,179,178,166,160};\r
\r
void usage()\r
{\r
- fprintf(stderr,"Usage >> fapg [-backslash] [-debug] [-format=m3u|pls|html] [-output=/path/to/file.m3u] [-prefix=/the/prefix] [-recursive] [-windows] /path/to/mp3/dir1 [/path/to/mp3/dir2 ...]\n");\r
+ fprintf(stderr,"Usage >> fapg [-b|--backslash] [-d|--debug] [-f|--format=m3u|pls|html] [-o|--output=/path/to/file.m3u] [-p|--prefix=/the/prefix] [-r|--recursive] [-w|--windows] /path/to/mp3/dir1 [/path/to/mp3/dir2 ...]\n");\r
exit(1);\r
}\r
\r
void parse_options(int argc,char **argv)\r
{\r
+ static char const short_options[]="bdf:o:p:rw";\r
static struct option long_options[]=\r
{\r
- {"backslash",no_argument,&separator,'\\'},\r
- {"debug",no_argument,&debug,1},\r
- {"format",required_argument,0,'f'},\r
- {"output",required_argument,0,'o'},\r
- {"prefix",required_argument,0,'p'},\r
- {"recursive",no_argument,&recursive,1},\r
- {"windows",no_argument,&windows,1}\r
+ {"backslash",no_argument,NULL,'b'},\r
+ {"debug",no_argument,NULL,'d'},\r
+ {"format",required_argument,NULL,'f'},\r
+ {"output",required_argument,NULL,'o'},\r
+ {"prefix",required_argument,NULL,'p'},\r
+ {"recursive",no_argument,NULL,'r'},\r
+ {"windows",no_argument,NULL,'w'}\r
};\r
int c;\r
int option_index=0;\r
- while ((c=getopt_long_only(argc,argv,"",long_options,&option_index))!=-1)\r
+ while ((c=getopt_long(argc,argv,short_options,long_options,&option_index))!=-1)\r
{\r
switch(c)\r
{\r
- case 0:\r
+ case 'b':\r
+ separator='\\';\r
+ break;\r
+ case 'd':\r
+ debug=1;\r
break;\r
case 'f':\r
if (strcmp(optarg,"m3u")==0) format=0; else\r
prefix=malloc(strlen(optarg)+1);\r
strcpy(prefix,optarg);\r
break;\r
+ case 'r':\r
+ recursive=1;\r
+ break;\r
+ case 'w':\r
+ windows=1;\r
+ break;\r
default:\r
usage();\r
}\r
size=(*c<<24)+(*(c+1)<<16)+(*(c+2)<<8)+(*(c+3));\r
if (size>lus) size=lus;\r
c+=4;\r
- if (version==2) while (c<buffer+size-5)\r
+ if (version==2) while (c<buffer+size-10)\r
{\r
int size=(*(c+3)<<16)+(*(c+4)<<8)+(*(c+5));\r
if (*c==0) break;\r
}\r
c+=size+6;\r
}\r
- if (version==3 || version==4) while (c<buffer+size-7)\r
+ if (version==3 || version==4) while (c<buffer+size-10)\r
{\r
int size=(*(c+4)<<24)+(*(c+5)<<16)+(*(c+6)<<8)+(*(c+7));\r
if (*c==0) break;\r
if (bitrate!=0)\r
{\r
fseek(fic,0,SEEK_END);\r
- time=(ftell(fic)+buffer-c)/125/bitrate;\r
+ duration=(ftell(fic)+buffer-c)/125/bitrate;\r
}\r
else\r
- time=0;\r
+ duration=0;\r
break;\r
}\r
c++;\r
{\r
c+=6;\r
samples=(*c)+(*(c+1)<<8)+(*(c+2)<<16)+(*(c+3)<<24);\r
- time=samples/sample_rate;\r
+ duration=samples/sample_rate;\r
}\r
\r
fclose(fic);\r
\r
void parse_directory(unsigned char *path)\r
{\r
- DIR *dirp;\r
- struct dirent *dp;\r
+ int i,n;\r
+ struct dirent **namelist;\r
unsigned char newpath[PATH_MAX];\r
unsigned char *c;\r
+ struct stat infos;\r
\r
void print_faketitle()\r
{\r
}\r
\r
if (debug) fprintf(stderr,"Debug >> parsing directory : %s\n",path);\r
- if ((dirp=opendir(path))==NULL) { fprintf(stderr,"Warning >> can't open directory : %s\n",path); return; }\r
- while ((dp=readdir(dirp))!=NULL)\r
+ if ((n=scandir(path,&namelist,0,alphasort))<0) { fprintf(stderr,"Warning >> can't open directory : %s\n",path); return; }\r
+ for (i=0;i<n;i++)\r
{\r
- sprintf(newpath,"%s/%s",path,dp->d_name);\r
- if (recursive && dp->d_type & DT_DIR && strcmp(dp->d_name,".")!=0 && strcmp(dp->d_name,"..")!=0)\r
- {\r
- parse_directory(newpath);\r
- }\r
- if (dp->d_type & DT_REG)\r
+ sprintf(newpath,"%s/%s",path,namelist[i]->d_name);\r
+ if (stat(newpath,&infos)!=0) { fprintf(stderr,"Warning >> can't stat file : %s\n",newpath); continue; }\r
+ if (recursive && S_ISDIR(infos.st_mode) && strcmp(namelist[i]->d_name,".")!=0 && strcmp(namelist[i]->d_name,"..")!=0) parse_directory(newpath);\r
+ if (S_ISREG(infos.st_mode))\r
{\r
unsigned char ext[5];\r
- int i;\r
- for (i=0;i<5;i++) ext[i]=tolower(dp->d_name[strlen(dp->d_name)-4+i]);\r
+ int j;\r
+ for (j=0;j<5;j++) ext[j]=tolower(namelist[i]->d_name[strlen(namelist[i]->d_name)-4+j]);\r
artist[0]='\0';\r
title[0]='\0';\r
- time=-2;\r
- if (strcmp(".mp3",ext)==0) { time=-1; parse_mp3(newpath); }\r
- if (strcmp(".ogg",ext)==0) { time=-1; parse_ogg(newpath); }\r
- if (strcmp(".wav",ext)==0) { time=-1; /* parse_wav(newpath); */ }\r
+ duration=-2;\r
+ if (strcmp(".mp3",ext)==0) { duration=-1; parse_mp3(newpath); }\r
+ if (strcmp(".ogg",ext)==0) { duration=-1; parse_ogg(newpath); }\r
+ if (strcmp(".wav",ext)==0) { duration=-1; /* parse_wav(newpath); */ }\r
\r
- if (time!=-2) /* is it an audio file ? */\r
+ if (duration!=-2) /* is it an audio file ? */\r
{\r
counter++;\r
switch (format)\r
{\r
case 0:\r
- if (time!=-1)\r
+ if (duration!=-1)\r
{\r
- printf("#EXTINF:%d,",time);\r
+ printf("#EXTINF:%d,",duration);\r
if (strlen(artist)==0 && strlen(title)==0) print_faketitle();\r
else printf("%s - %s",artist,title);\r
putchar('\n');\r
if (strlen(artist)==0 && strlen(title)==0) print_faketitle();\r
else printf("%s - %s",artist,title);\r
putchar('\n');\r
- if (time!=-1) printf("Length%d=%d\n",counter,time);\r
+ if (duration!=-1) printf("Length%d=%d\n",counter,duration);\r
break;\r
case 2:\r
printf("<tr><td>%d</td><td>%s</td><td>%s</td><td>",counter,artist,title);\r
- if (time==-1) printf("?"); else printf("%d",time);\r
+ if (duration==-1) printf("?"); else printf("%d:%s%d",duration/60,duration%60<10?"0":"",duration%60);\r
printf("</td></tr>\n");\r
break;\r
}\r
}\r
}\r
+ free(namelist[i]);\r
}\r
- closedir(dirp);\r
+ free(namelist);\r
}\r
\r
int main(int argc,char **argv)\r
printf("[playlist]\n");\r
break;\r
case 2:\r
- printf("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n\n<html>\n\n<head>\n<title>Playlist generated by FAPG 0.0</title>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\" />\n<link rel=\"stylesheet\" type=\"text/css\" href=\"fapg.css\" />\n</head>\n\n<body>\n\n<h1>Playlist</h1>\n\n<table>\n<tr><th>Entry</th><th>Artist</th><th>Title</th><th>Length</th></tr>\n");\r
+ printf("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n\n<html>\n\n<head>\n<title>Playlist generated by FAPG 0.1</title>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\" />\n<style type=\"text/css\">\n<!--\n\nbody,td,tr {\n font-family: Verdana, Arial, Helvetica, sans-serif;\n font-size: 12px;\n color: #000000;\n}\n\nbody {\n background: #ffffff;\n}\n\nth {\n text-align: center;\n background: #ffcccc;\n padding-left: 15px;\n padding-right: 15px;\n border: 1px #dd8888 solid;\n}\n\ntd {\n text-align: center;\n background: #eeeeee;\n padding-left: 15px;\n padding-right: 15px;\n border: 1px #cccccc solid;\n}\n\nh1 {\n font-size: 25px;\n}\n\np {\n font-size: 10px;\n}\n\na {\n color: #993333;\n text-decoration: none;\n}\n\na:hover {\n text-decoration: underline;\n}\n\n-->\n</style>\n</head>\n\n<body>\n\n<h1>Playlist</h1>\n\n<table>\n<tr><th>Entry</th><th>Artist</th><th>Title</th><th>Length</th></tr>\n");\r
break;\r
}\r
for (;optind<argc;optind++)\r
printf("NumberOfEntries=%d\nVersion=2\n",counter);\r
break;\r
case 2:\r
- printf("</table>\n\n<p>Playlist generated by <a href=\"http://royale.zerezo.com/fapg/\">FAPG 0.0</a></p>\n\n</body>\n\n</html>");\r
+ printf("</table>\n\n<p>Playlist generated by <a href=\"http://royale.zerezo.com/fapg/\">FAPG 0.1</a></p>\n\n</body>\n\n</html>");\r
break;\r
}\r
exit(0);\r