version 0.1 v0.1
authorAntoine Jacquet <royale@zerezo.com>
Sat, 4 Oct 2003 22:00:00 +0000 (00:00 +0200)
committerAntoine Jacquet <royale@zerezo.com>
Sat, 4 Oct 2003 22:00:00 +0000 (00:00 +0200)
* initial release

Makefile
README
fapg.c

index 0b26a2d..7dbdd60 100755 (executable)
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,6 @@
 PRE = /usr/local
 BIN = $(PRE)/bin
-PIX = $(PRE)/share/irssistats/pix
-DOC = $(PRE)/doc/irssistats
-MAN = $(PRE)/man/man1
+DOC = $(PRE)/doc/fapg
 
 fapg:fapg.c
        gcc -o fapg fapg.c
@@ -11,12 +9,10 @@ clean:
        rm -f fapg
 
 install:fapg
-       mkdir -p $(BIN) $(PIX) $(DOC) $(MAN)
+       mkdir -p $(BIN) $(DOC)
        cp -f fapg $(BIN)
        cp -f COPYING README $(DOC)
-       cp -f fapg.1 $(MAN)
 
 uninstall:
        rm -f $(BIN)/fapg
        rm -rf $(DOC)
-       rm -f $(MAN)/fapg.1
diff --git a/README b/README
index ca5ce57..4913345 100755 (executable)
--- a/README
+++ b/README
@@ -1,13 +1,23 @@
-FAPG 0.0 (Fast Audio Playlist Generator)
+FAPG 0.1 (Fast Audio Playlist Generator)
 site: http://royale.zerezo.com/fapg/
 mail: royale@zerezo.com
 
-This is a pre-released version for testing purpose only !
+install:
+make
+make install
 
-TODO :
-  - fapg.css
-  - define best "size" for MAX constant...
-  - XML export ? format (DTD) ?
-  - SQL export ? INSERT INTO playlist VALUES (counter,artist,title,time) ?
-  - TXT export ? format ?
-  - support MP3 specials headers (extended & unsynchronisation)...
\ No newline at end of file
+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 ...]
+- backslash : replace the '/' with '\' in Unix path. 
+- debug : display useful messages if the program fails ;) 
+- format : choose which format of playlist you want to generate (default is m3u). 
+- output : choose the name of the playlist file to generate (default behavior is to display on standart output). 
+- prefix : replace the Unix path with another string (useful to give a Samba path for example). 
+- recursive : recursively read the subdirectories. 
+- windows : replace all Unix characters with Windows characters... 
+
+links :
+http://geek.scorpiorising.ca/scripts.html
+http://id3lib.sourceforge.net/
+http://id3.org/
+http://www.xiph.org/ogg/vorbis/docs.html
\ No newline at end of file
diff --git a/fapg.c b/fapg.c
index eaa8ac3..4dc2cc1 100755 (executable)
--- a/fapg.c
+++ b/fapg.c
@@ -1,5 +1,5 @@
 /*\r
- * FAPG 0.0 released under GPL\r
+ * FAPG 0.1 released under GPL\r
  * http://royale.zerezo.com/fapg/\r
  */\r
 \r
@@ -7,9 +7,12 @@
 #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
@@ -26,35 +29,40 @@ int counter=0;
 \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
@@ -70,6 +78,12 @@ void parse_options(int argc,char **argv)
         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
@@ -110,7 +124,7 @@ void parse_mp3(unsigned char *file)
     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
@@ -126,7 +140,7 @@ void parse_mp3(unsigned char *file)
       }\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
@@ -162,10 +176,10 @@ void parse_mp3(unsigned char *file)
       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
@@ -244,7 +258,7 @@ void parse_ogg(unsigned char *file)
   {\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
@@ -252,10 +266,11 @@ void parse_ogg(unsigned char *file)
 \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
@@ -275,35 +290,33 @@ void parse_directory(unsigned char *path)
   }\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
@@ -319,18 +332,19 @@ void parse_directory(unsigned char *path)
             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
@@ -346,7 +360,7 @@ int main(int argc,char **argv)
       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
@@ -360,7 +374,7 @@ int main(int argc,char **argv)
       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