[ Index ]

WordPress Cross Reference

title

Body

[close]

/wp-includes/ID3/ -> module.tag.id3v1.php (source)

   1  <?php
   2  /////////////////////////////////////////////////////////////////
   3  /// getID3() by James Heinrich <info@getid3.org>               //
   4  //  available at http://getid3.sourceforge.net                 //
   5  //            or http://www.getid3.org                         //
   6  /////////////////////////////////////////////////////////////////
   7  // See readme.txt for more details                             //
   8  /////////////////////////////////////////////////////////////////
   9  //                                                             //
  10  // module.tag.id3v1.php                                        //
  11  // module for analyzing ID3v1 tags                             //
  12  // dependencies: NONE                                          //
  13  //                                                            ///
  14  /////////////////////////////////////////////////////////////////
  15  
  16  
  17  class getid3_id3v1 extends getid3_handler
  18  {
  19  
  20  	public function Analyze() {
  21          $info = &$this->getid3->info;
  22  
  23          if (!getid3_lib::intValueSupported($info['filesize'])) {
  24              $info['warning'][] = 'Unable to check for ID3v1 because file is larger than '.round(PHP_INT_MAX / 1073741824).'GB';
  25              return false;
  26          }
  27  
  28          fseek($this->getid3->fp, -256, SEEK_END);
  29          $preid3v1 = fread($this->getid3->fp, 128);
  30          $id3v1tag = fread($this->getid3->fp, 128);
  31  
  32          if (substr($id3v1tag, 0, 3) == 'TAG') {
  33  
  34              $info['avdataend'] = $info['filesize'] - 128;
  35  
  36              $ParsedID3v1['title']   = $this->cutfield(substr($id3v1tag,   3, 30));
  37              $ParsedID3v1['artist']  = $this->cutfield(substr($id3v1tag,  33, 30));
  38              $ParsedID3v1['album']   = $this->cutfield(substr($id3v1tag,  63, 30));
  39              $ParsedID3v1['year']    = $this->cutfield(substr($id3v1tag,  93,  4));
  40              $ParsedID3v1['comment'] =                 substr($id3v1tag,  97, 30);  // can't remove nulls yet, track detection depends on them
  41              $ParsedID3v1['genreid'] =             ord(substr($id3v1tag, 127,  1));
  42  
  43              // If second-last byte of comment field is null and last byte of comment field is non-null
  44              // then this is ID3v1.1 and the comment field is 28 bytes long and the 30th byte is the track number
  45              if (($id3v1tag{125} === "\x00") && ($id3v1tag{126} !== "\x00")) {
  46                  $ParsedID3v1['track']   = ord(substr($ParsedID3v1['comment'], 29,  1));
  47                  $ParsedID3v1['comment'] =     substr($ParsedID3v1['comment'],  0, 28);
  48              }
  49              $ParsedID3v1['comment'] = $this->cutfield($ParsedID3v1['comment']);
  50  
  51              $ParsedID3v1['genre'] = $this->LookupGenreName($ParsedID3v1['genreid']);
  52              if (!empty($ParsedID3v1['genre'])) {
  53                  unset($ParsedID3v1['genreid']);
  54              }
  55              if (isset($ParsedID3v1['genre']) && (empty($ParsedID3v1['genre']) || ($ParsedID3v1['genre'] == 'Unknown'))) {
  56                  unset($ParsedID3v1['genre']);
  57              }
  58  
  59              foreach ($ParsedID3v1 as $key => $value) {
  60                  $ParsedID3v1['comments'][$key][0] = $value;
  61              }
  62  
  63              // ID3v1 data is supposed to be padded with NULL characters, but some taggers pad with spaces
  64              $GoodFormatID3v1tag = $this->GenerateID3v1Tag(
  65                                              $ParsedID3v1['title'],
  66                                              $ParsedID3v1['artist'],
  67                                              $ParsedID3v1['album'],
  68                                              $ParsedID3v1['year'],
  69                                              (isset($ParsedID3v1['genre']) ? $this->LookupGenreID($ParsedID3v1['genre']) : false),
  70                                              $ParsedID3v1['comment'],
  71                                              (!empty($ParsedID3v1['track']) ? $ParsedID3v1['track'] : ''));
  72              $ParsedID3v1['padding_valid'] = true;
  73              if ($id3v1tag !== $GoodFormatID3v1tag) {
  74                  $ParsedID3v1['padding_valid'] = false;
  75                  $info['warning'][] = 'Some ID3v1 fields do not use NULL characters for padding';
  76              }
  77  
  78              $ParsedID3v1['tag_offset_end']   = $info['filesize'];
  79              $ParsedID3v1['tag_offset_start'] = $ParsedID3v1['tag_offset_end'] - 128;
  80  
  81              $info['id3v1'] = $ParsedID3v1;
  82          }
  83  
  84          if (substr($preid3v1, 0, 3) == 'TAG') {
  85              // The way iTunes handles tags is, well, brain-damaged.
  86              // It completely ignores v1 if ID3v2 is present.
  87              // This goes as far as adding a new v1 tag *even if there already is one*
  88  
  89              // A suspected double-ID3v1 tag has been detected, but it could be that
  90              // the "TAG" identifier is a legitimate part of an APE or Lyrics3 tag
  91              if (substr($preid3v1, 96, 8) == 'APETAGEX') {
  92                  // an APE tag footer was found before the last ID3v1, assume false "TAG" synch
  93              } elseif (substr($preid3v1, 119, 6) == 'LYRICS') {
  94                  // a Lyrics3 tag footer was found before the last ID3v1, assume false "TAG" synch
  95              } else {
  96                  // APE and Lyrics3 footers not found - assume double ID3v1
  97                  $info['warning'][] = 'Duplicate ID3v1 tag detected - this has been known to happen with iTunes';
  98                  $info['avdataend'] -= 128;
  99              }
 100          }
 101  
 102          return true;
 103      }
 104  
 105  	public static function cutfield($str) {
 106          return trim(substr($str, 0, strcspn($str, "\x00")));
 107      }
 108  
 109  	public static function ArrayOfGenres($allowSCMPXextended=false) {
 110          static $GenreLookup = array(
 111              0    => 'Blues',
 112              1    => 'Classic Rock',
 113              2    => 'Country',
 114              3    => 'Dance',
 115              4    => 'Disco',
 116              5    => 'Funk',
 117              6    => 'Grunge',
 118              7    => 'Hip-Hop',
 119              8    => 'Jazz',
 120              9    => 'Metal',
 121              10   => 'New Age',
 122              11   => 'Oldies',
 123              12   => 'Other',
 124              13   => 'Pop',
 125              14   => 'R&B',
 126              15   => 'Rap',
 127              16   => 'Reggae',
 128              17   => 'Rock',
 129              18   => 'Techno',
 130              19   => 'Industrial',
 131              20   => 'Alternative',
 132              21   => 'Ska',
 133              22   => 'Death Metal',
 134              23   => 'Pranks',
 135              24   => 'Soundtrack',
 136              25   => 'Euro-Techno',
 137              26   => 'Ambient',
 138              27   => 'Trip-Hop',
 139              28   => 'Vocal',
 140              29   => 'Jazz+Funk',
 141              30   => 'Fusion',
 142              31   => 'Trance',
 143              32   => 'Classical',
 144              33   => 'Instrumental',
 145              34   => 'Acid',
 146              35   => 'House',
 147              36   => 'Game',
 148              37   => 'Sound Clip',
 149              38   => 'Gospel',
 150              39   => 'Noise',
 151              40   => 'Alt. Rock',
 152              41   => 'Bass',
 153              42   => 'Soul',
 154              43   => 'Punk',
 155              44   => 'Space',
 156              45   => 'Meditative',
 157              46   => 'Instrumental Pop',
 158              47   => 'Instrumental Rock',
 159              48   => 'Ethnic',
 160              49   => 'Gothic',
 161              50   => 'Darkwave',
 162              51   => 'Techno-Industrial',
 163              52   => 'Electronic',
 164              53   => 'Pop-Folk',
 165              54   => 'Eurodance',
 166              55   => 'Dream',
 167              56   => 'Southern Rock',
 168              57   => 'Comedy',
 169              58   => 'Cult',
 170              59   => 'Gangsta Rap',
 171              60   => 'Top 40',
 172              61   => 'Christian Rap',
 173              62   => 'Pop/Funk',
 174              63   => 'Jungle',
 175              64   => 'Native American',
 176              65   => 'Cabaret',
 177              66   => 'New Wave',
 178              67   => 'Psychedelic',
 179              68   => 'Rave',
 180              69   => 'Showtunes',
 181              70   => 'Trailer',
 182              71   => 'Lo-Fi',
 183              72   => 'Tribal',
 184              73   => 'Acid Punk',
 185              74   => 'Acid Jazz',
 186              75   => 'Polka',
 187              76   => 'Retro',
 188              77   => 'Musical',
 189              78   => 'Rock & Roll',
 190              79   => 'Hard Rock',
 191              80   => 'Folk',
 192              81   => 'Folk/Rock',
 193              82   => 'National Folk',
 194              83   => 'Swing',
 195              84   => 'Fast-Fusion',
 196              85   => 'Bebob',
 197              86   => 'Latin',
 198              87   => 'Revival',
 199              88   => 'Celtic',
 200              89   => 'Bluegrass',
 201              90   => 'Avantgarde',
 202              91   => 'Gothic Rock',
 203              92   => 'Progressive Rock',
 204              93   => 'Psychedelic Rock',
 205              94   => 'Symphonic Rock',
 206              95   => 'Slow Rock',
 207              96   => 'Big Band',
 208              97   => 'Chorus',
 209              98   => 'Easy Listening',
 210              99   => 'Acoustic',
 211              100  => 'Humour',
 212              101  => 'Speech',
 213              102  => 'Chanson',
 214              103  => 'Opera',
 215              104  => 'Chamber Music',
 216              105  => 'Sonata',
 217              106  => 'Symphony',
 218              107  => 'Booty Bass',
 219              108  => 'Primus',
 220              109  => 'Porn Groove',
 221              110  => 'Satire',
 222              111  => 'Slow Jam',
 223              112  => 'Club',
 224              113  => 'Tango',
 225              114  => 'Samba',
 226              115  => 'Folklore',
 227              116  => 'Ballad',
 228              117  => 'Power Ballad',
 229              118  => 'Rhythmic Soul',
 230              119  => 'Freestyle',
 231              120  => 'Duet',
 232              121  => 'Punk Rock',
 233              122  => 'Drum Solo',
 234              123  => 'A Cappella',
 235              124  => 'Euro-House',
 236              125  => 'Dance Hall',
 237              126  => 'Goa',
 238              127  => 'Drum & Bass',
 239              128  => 'Club-House',
 240              129  => 'Hardcore',
 241              130  => 'Terror',
 242              131  => 'Indie',
 243              132  => 'BritPop',
 244              133  => 'Negerpunk',
 245              134  => 'Polsk Punk',
 246              135  => 'Beat',
 247              136  => 'Christian Gangsta Rap',
 248              137  => 'Heavy Metal',
 249              138  => 'Black Metal',
 250              139  => 'Crossover',
 251              140  => 'Contemporary Christian',
 252              141  => 'Christian Rock',
 253              142  => 'Merengue',
 254              143  => 'Salsa',
 255              144  => 'Thrash Metal',
 256              145  => 'Anime',
 257              146  => 'JPop',
 258              147  => 'Synthpop',
 259  
 260              255  => 'Unknown',
 261  
 262              'CR' => 'Cover',
 263              'RX' => 'Remix'
 264          );
 265  
 266          static $GenreLookupSCMPX = array();
 267          if ($allowSCMPXextended && empty($GenreLookupSCMPX)) {
 268              $GenreLookupSCMPX = $GenreLookup;
 269              // http://www.geocities.co.jp/SiliconValley-Oakland/3664/alittle.html#GenreExtended
 270              // Extended ID3v1 genres invented by SCMPX
 271              // Note that 255 "Japanese Anime" conflicts with standard "Unknown"
 272              $GenreLookupSCMPX[240] = 'Sacred';
 273              $GenreLookupSCMPX[241] = 'Northern Europe';
 274              $GenreLookupSCMPX[242] = 'Irish & Scottish';
 275              $GenreLookupSCMPX[243] = 'Scotland';
 276              $GenreLookupSCMPX[244] = 'Ethnic Europe';
 277              $GenreLookupSCMPX[245] = 'Enka';
 278              $GenreLookupSCMPX[246] = 'Children\'s Song';
 279              $GenreLookupSCMPX[247] = 'Japanese Sky';
 280              $GenreLookupSCMPX[248] = 'Japanese Heavy Rock';
 281              $GenreLookupSCMPX[249] = 'Japanese Doom Rock';
 282              $GenreLookupSCMPX[250] = 'Japanese J-POP';
 283              $GenreLookupSCMPX[251] = 'Japanese Seiyu';
 284              $GenreLookupSCMPX[252] = 'Japanese Ambient Techno';
 285              $GenreLookupSCMPX[253] = 'Japanese Moemoe';
 286              $GenreLookupSCMPX[254] = 'Japanese Tokusatsu';
 287              //$GenreLookupSCMPX[255] = 'Japanese Anime';
 288          }
 289  
 290          return ($allowSCMPXextended ? $GenreLookupSCMPX : $GenreLookup);
 291      }
 292  
 293  	public static function LookupGenreName($genreid, $allowSCMPXextended=true) {
 294          switch ($genreid) {
 295              case 'RX':
 296              case 'CR':
 297                  break;
 298              default:
 299                  if (!is_numeric($genreid)) {
 300                      return false;
 301                  }
 302                  $genreid = intval($genreid); // to handle 3 or '3' or '03'
 303                  break;
 304          }
 305          $GenreLookup = self::ArrayOfGenres($allowSCMPXextended);
 306          return (isset($GenreLookup[$genreid]) ? $GenreLookup[$genreid] : false);
 307      }
 308  
 309  	public static function LookupGenreID($genre, $allowSCMPXextended=false) {
 310          $GenreLookup = self::ArrayOfGenres($allowSCMPXextended);
 311          $LowerCaseNoSpaceSearchTerm = strtolower(str_replace(' ', '', $genre));
 312          foreach ($GenreLookup as $key => $value) {
 313              if (strtolower(str_replace(' ', '', $value)) == $LowerCaseNoSpaceSearchTerm) {
 314                  return $key;
 315              }
 316          }
 317          return false;
 318      }
 319  
 320  	public static function StandardiseID3v1GenreName($OriginalGenre) {
 321          if (($GenreID = self::LookupGenreID($OriginalGenre)) !== false) {
 322              return self::LookupGenreName($GenreID);
 323          }
 324          return $OriginalGenre;
 325      }
 326  
 327  	public static function GenerateID3v1Tag($title, $artist, $album, $year, $genreid, $comment, $track='') {
 328          $ID3v1Tag  = 'TAG';
 329          $ID3v1Tag .= str_pad(trim(substr($title,  0, 30)), 30, "\x00", STR_PAD_RIGHT);
 330          $ID3v1Tag .= str_pad(trim(substr($artist, 0, 30)), 30, "\x00", STR_PAD_RIGHT);
 331          $ID3v1Tag .= str_pad(trim(substr($album,  0, 30)), 30, "\x00", STR_PAD_RIGHT);
 332          $ID3v1Tag .= str_pad(trim(substr($year,   0,  4)),  4, "\x00", STR_PAD_LEFT);
 333          if (!empty($track) && ($track > 0) && ($track <= 255)) {
 334              $ID3v1Tag .= str_pad(trim(substr($comment, 0, 28)), 28, "\x00", STR_PAD_RIGHT);
 335              $ID3v1Tag .= "\x00";
 336              if (gettype($track) == 'string') {
 337                  $track = (int) $track;
 338              }
 339              $ID3v1Tag .= chr($track);
 340          } else {
 341              $ID3v1Tag .= str_pad(trim(substr($comment, 0, 30)), 30, "\x00", STR_PAD_RIGHT);
 342          }
 343          if (($genreid < 0) || ($genreid > 147)) {
 344              $genreid = 255; // 'unknown' genre
 345          }
 346          switch (gettype($genreid)) {
 347              case 'string':
 348              case 'integer':
 349                  $ID3v1Tag .= chr(intval($genreid));
 350                  break;
 351              default:
 352                  $ID3v1Tag .= chr(255); // 'unknown' genre
 353                  break;
 354          }
 355  
 356          return $ID3v1Tag;
 357      }
 358  
 359  }


Generated: Tue Mar 25 01:41:18 2014 WordPress honlapkészítés: online1.hu