libextractor

GNU libextractor
Log | Files | Refs | Submodules | README | LICENSE

analyze.pike (4621B)


      1 #! /usr/bin/env pike
      2 #pike 7.5
      3 
      4 //
      5 // A small program that analyses ID3v1/ID3v1.1 tags and
      6 // displays its findings.
      7 // Copyright (c) 2003 Martin Nilsson
      8 //
      9 
     10 #if !constant(ADT.Struct)
     11 #error This Pike is too old for this application.
     12 #endif
     13 
     14 // The structure of an ID3v1 tag.
     15 class ID3_1 {
     16   inherit ADT.Struct;
     17   //  Item head = Chars(3);
     18   Item title = Chars(30);
     19   Item artist = Chars(30);
     20   Item album = Chars(30);
     21   Item year = Chars(4);
     22   Item comment = Chars(30);
     23   Item genre = Byte();
     24 }
     25 
     26 // The structure of an ID3v1.1 tag.
     27 class ID3_11 {
     28   inherit ADT.Struct;
     29   //  Item head = Chars(3);
     30   Item title = Chars(30);
     31   Item artist = Chars(30);
     32   Item album = Chars(30);
     33   Item year = Chars(4);
     34   Item comment = Chars(28);
     35   Item null = Byte();
     36   Item track = Byte();
     37   Item genre = Byte();
     38 }
     39 
     40 array(string) id3_genres = ({
     41   "Blues", // 0
     42   "Classic Rock",
     43   "Country",
     44   "Dance",
     45   "Disco",
     46   "Funk",
     47   "Grunge",
     48   "Hip-Hop",
     49   "Jazz",
     50   "Metal",
     51   "New Age",
     52   "Oldies",
     53   "Other",
     54   "Pop",
     55   "R&B",
     56   "Rap",
     57   "Reggae",
     58   "Rock",
     59   "Techno",
     60   "Industrial",
     61   "Alternative",
     62   "Ska",
     63   "Death Metal",
     64   "Pranks",
     65   "Soundtrack",
     66   "Euro-Techno",
     67   "Ambient",
     68   "Trip-Hop",
     69   "Vocal",
     70   "Jazz+Funk",
     71   "Fusion",
     72   "Trance",
     73   "Classical",
     74   "Instrumental",
     75   "Acid",
     76   "House",
     77   "Game",
     78   "Sound Clip",
     79   "Gospel",
     80   "Noise",
     81   "AlternRock",
     82   "Bass",
     83   "Soul",
     84   "Punk",
     85   "Space",
     86   "Meditative",
     87   "Instrumental Pop",
     88   "Instrumental Rock",
     89   "Ethnic",
     90   "Gothic",
     91   "Darkwave",
     92   "Techno-Industrial",
     93   "Electronic",
     94   "Pop-Folk",
     95   "Eurodance",
     96   "Dream",
     97   "Southern Rock",
     98   "Comedy",
     99   "Cult",
    100   "Gangsta",
    101   "Top 40",
    102   "Christian Rap",
    103   "Pop/Funk",
    104   "Jungle",
    105   "Native American",
    106   "Cabaret",
    107   "New Wave",
    108   "Psychadelic",
    109   "Rave",
    110   "Showtunes",
    111   "Trailer",
    112   "Lo-Fi",
    113   "Tribal",
    114   "Acid Punk",
    115   "Acid Jazz",
    116   "Polka",
    117   "Retro",
    118   "Musical",
    119   "Rock & Roll",
    120   "Hard Rock", // 79
    121   "Folk",
    122   "Folk-Rock",
    123   "National Folk",
    124   "Swing",
    125   "Fast Fusion",
    126   "Bebob",
    127   "Latin",
    128   "Revival",
    129   "Celtic",
    130   "Bluegrass",
    131   "Avantgarde",
    132   "Gothic Rock",
    133   "Progressive Rock",
    134   "Psychedelic Rock",
    135   "Symphonic Rock",
    136   "Slow Rock",
    137   "Big Band",
    138   "Chorus",
    139   "Easy Listening",
    140   "Acoustic",
    141   "Humour",
    142   "Speech",
    143   "Chanson",
    144   "Opera",
    145   "Chamber Music",
    146   "Sonata",
    147   "Symphony",
    148   "Booty Bass",
    149   "Primus",
    150   "Porn Groove",
    151   "Satire",
    152   "Slow Jam",
    153   "Club",
    154   "Tango",
    155   "Samba",
    156   "Folklore",
    157   "Ballad",
    158   "Power Ballad",
    159   "Rhythmic Soul",
    160   "Freestyle",
    161   "Duet",
    162   "Punk Rock",
    163   "Drum Solo",
    164   "A capella",
    165   "Euro-House",
    166   "Dance Hall", // 125
    167   "Goa",
    168   "Drum & Bass",
    169   "Club-House",
    170   "Hardcore",
    171   "Terror",
    172   "Indie",
    173   "BritPop",
    174   "Negerpunk",
    175   "Polsk Punk",
    176   "Beat",
    177   "Christian",
    178   "Heavy Metal",
    179   "Black Metal",
    180   "Crossover",
    181   "Contemporary",
    182   "Christian Rock",
    183   "Merengue",
    184   "Salsa",
    185   "Thrash Metal",
    186   "Anime",
    187   "JPop",
    188   "Synthpop",
    189 });
    190 
    191 string genre(int i) {
    192   if( i>=sizeof(id3_genres) ) return "Not defined";
    193   return "\""+id3_genres[i]+"\"";
    194 }
    195 
    196 int(0..1) exitcode;
    197 
    198 // Test an ID3 field.
    199 void handle_str(string what, string s) {
    200   // Strip trailing zero
    201   if(s[-1]==0) {
    202     sscanf(reverse(s), "%*[\0]%s", s);
    203     s=reverse(s);
    204   }
    205   string str=s;
    206   sscanf(str, "%s\0", str);
    207   write("%-11s: %O\n", what, str);
    208   if(has_value(s,0)) {
    209     write("%13sString contains illegal zero character(s).\n","");
    210     exitcode = 1;
    211   }
    212   catch {
    213     if(utf8_to_string(s)!=s)
    214       write("%13sString can be UTF-8 decoded.\n","");
    215   };
    216 }
    217 
    218 void main(int num, array(string) args) {
    219   if(num!=2) {
    220     werror("Usage: analyse.pike <file>\n");
    221     exit(1);
    222   }
    223 
    224   Stdio.File f = Stdio.File(args[-1]);
    225   if(!f) {
    226     werror("Couldn't find file %O.\n", args[-1]);
    227     exit(2);
    228   }
    229   if(f->stat()->size < 128) {
    230     werror("File too small to hold an ID3v1 tag.\n");
    231     exit(3);
    232   }
    233 
    234   f->seek(-128);
    235   if(f->read(3)!="TAG") {
    236     werror("File contains no ID3 tag.\n");
    237     exit(4);
    238   }
    239 
    240   string data = f->read();
    241   object tag;
    242   if(data[-3]==0 && data[-2]!=0) {
    243     write("Tag version: 1.1\n");
    244     tag = ID3_11(data);
    245   }
    246   else {
    247     write("Tag version: 1.0\n");
    248     tag = ID3_1(data);
    249   }
    250 
    251   handle_str("Title",tag->title);
    252   handle_str("Artist",tag->artist);
    253   handle_str("Album",tag->album);
    254   handle_str("Year",tag->year);
    255   string y=tag->year;
    256   sscanf(y, "%[0-9]", y);
    257   if( sizeof(y)!=4 ) {
    258     write("%13sMalformed year field data.\n","");
    259     exitcode = 1;
    260   }
    261   write("%-11s: %d (%s)\n", "Genre", tag->genre, genre(tag->genre));
    262   handle_str("Comment",tag->comment);
    263   if(tag->track)
    264     write("%-11s: %d\n", "Track", tag->track);
    265 
    266   if(exitcode)
    267     exit(5);
    268 }