File indexing completed on 2024-05-12 17:26:00

0001 <?php
0002 /////////////////////////////////////////////////////////////////
0003 /// getID3() by James Heinrich <info@getid3.org>               //
0004 //  available at http://getid3.sourceforge.net                 //
0005 //            or http://www.getid3.org                         //
0006 //          also https://github.com/JamesHeinrich/getID3       //
0007 /////////////////////////////////////////////////////////////////
0008 // See readme.txt for more details                             //
0009 /////////////////////////////////////////////////////////////////
0010 //                                                             //
0011 // module.misc.cue.php                                         //
0012 // module for analyzing CUEsheet files                         //
0013 // dependencies: NONE                                          //
0014 //                                                             //
0015 /////////////////////////////////////////////////////////////////
0016 //                                                             //
0017 // Module originally written [2009-Mar-25] by                  //
0018 //      Nigel Barnes <ngbarnesØhotmail*com>                    //
0019 // Minor reformatting and similar small changes to integrate   //
0020 //   into getID3 by James Heinrich <info@getid3.org>           //
0021 //                                                            ///
0022 /////////////////////////////////////////////////////////////////
0023 
0024 /*
0025  * CueSheet parser by Nigel Barnes.
0026  *
0027  * This is a PHP conversion of CueSharp 0.5 by Wyatt O'Day (wyday.com/cuesharp)
0028  */
0029 
0030 /**
0031  * A CueSheet class used to open and parse cuesheets.
0032  *
0033  */
0034 class getid3_cue extends getid3_handler
0035 {
0036   public $cuesheet = array();
0037 
0038   public function Analyze() {
0039     $info = &$this->getid3->info;
0040 
0041     $info['fileformat'] = 'cue';
0042     $this->readCueSheetFilename($info['filenamepath']);
0043     $info['cue'] = $this->cuesheet;
0044     return true;
0045   }
0046 
0047 
0048 
0049   public function readCueSheetFilename($filename)
0050   {
0051     $filedata = file_get_contents($filename);
0052     return $this->readCueSheet($filedata);
0053   }
0054 
0055     /**
0056      * Parses a cue sheet file.
0057      *
0058      * @param $filedata
0059      *
0060      * @return array
0061      */
0062   public function readCueSheet(&$filedata)
0063   {
0064     $cue_lines = array();
0065     foreach (explode("\n", str_replace("\r", null, $filedata)) as $line)
0066     {
0067       if ( (strlen($line) > 0) && ($line[0] != '#'))
0068       {
0069         $cue_lines[] = trim($line);
0070       }
0071     }
0072     $this->parseCueSheet($cue_lines);
0073 
0074     return $this->cuesheet;
0075   }
0076 
0077   /**
0078   * Parses the cue sheet array.
0079   *
0080   * @param array $file - The cuesheet as an array of each line.
0081   */
0082   public function parseCueSheet($file)
0083   {
0084     //-1 means still global, all others are track specific
0085     $track_on = -1;
0086 
0087     for ($i=0; $i < count($file); $i++)
0088     {
0089       list($key) = explode(' ', strtolower($file[$i]), 2);
0090       switch ($key)
0091       {
0092         case 'catalog':
0093         case 'cdtextfile':
0094         case 'isrc':
0095         case 'performer':
0096         case 'songwriter':
0097         case 'title':
0098           $this->parseString($file[$i], $track_on);
0099           break;
0100         case 'file':
0101           $currentFile = $this->parseFile($file[$i]);
0102           break;
0103         case 'flags':
0104           $this->parseFlags($file[$i], $track_on);
0105           break;
0106         case 'index':
0107         case 'postgap':
0108         case 'pregap':
0109           $this->parseIndex($file[$i], $track_on);
0110           break;
0111         case 'rem':
0112           $this->parseComment($file[$i], $track_on);
0113           break;
0114         case 'track':
0115           $track_on++;
0116           $this->parseTrack($file[$i], $track_on);
0117           if (isset($currentFile)) // if there's a file
0118           {
0119             $this->cuesheet['tracks'][$track_on]['datafile'] = $currentFile;
0120           }
0121           break;
0122         default:
0123           //save discarded junk and place string[] with track it was found in
0124           $this->parseGarbage($file[$i], $track_on);
0125           break;
0126       }
0127     }
0128   }
0129 
0130   /**
0131   * Parses the REM command.
0132   *
0133   * @param string $line - The line in the cue file that contains the TRACK command.
0134   * @param integer $track_on - The track currently processing.
0135   */
0136   public function parseComment($line, $track_on)
0137   {
0138     $explodedline = explode(' ', $line, 3);
0139     $comment_REM  = (isset($explodedline[0]) ? $explodedline[0] : '');
0140     $comment_type = (isset($explodedline[1]) ? $explodedline[1] : '');
0141     $comment_data = (isset($explodedline[2]) ? $explodedline[2] : '');
0142     if (($comment_REM == 'REM') && $comment_type) {
0143       $comment_type  = strtolower($comment_type);
0144       $commment_data = trim($comment_data, ' "');
0145       if ($track_on != -1) {
0146         $this->cuesheet['tracks'][$track_on]['comments'][$comment_type][] = $comment_data;
0147       } else {
0148         $this->cuesheet['comments'][$comment_type][] = $comment_data;
0149       }
0150     }
0151   }
0152 
0153   /**
0154   * Parses the FILE command.
0155   *
0156   * @param string $line - The line in the cue file that contains the FILE command.
0157   * @return array - Array of FILENAME and TYPE of file..
0158   */
0159   public function parseFile($line)
0160   {
0161     $line =            substr($line, strpos($line, ' ') + 1);
0162     $type = strtolower(substr($line, strrpos($line, ' ')));
0163 
0164     //remove type
0165     $line = substr($line, 0, strrpos($line, ' ') - 1);
0166 
0167     //if quotes around it, remove them.
0168     $line = trim($line, '"');
0169 
0170     return array('filename'=>$line, 'type'=>$type);
0171   }
0172 
0173   /**
0174   * Parses the FLAG command.
0175   *
0176   * @param string $line - The line in the cue file that contains the TRACK command.
0177   * @param integer $track_on - The track currently processing.
0178   */
0179   public function parseFlags($line, $track_on)
0180   {
0181     if ($track_on != -1)
0182     {
0183       foreach (explode(' ', strtolower($line)) as $type)
0184       {
0185         switch ($type)
0186         {
0187           case 'flags':
0188             // first entry in this line
0189             $this->cuesheet['tracks'][$track_on]['flags'] = array(
0190               '4ch'  => false,
0191               'data' => false,
0192               'dcp'  => false,
0193               'pre'  => false,
0194               'scms' => false,
0195             );
0196             break;
0197           case 'data':
0198           case 'dcp':
0199           case '4ch':
0200           case 'pre':
0201           case 'scms':
0202             $this->cuesheet['tracks'][$track_on]['flags'][$type] = true;
0203             break;
0204           default:
0205             break;
0206         }
0207       }
0208     }
0209   }
0210 
0211   /**
0212   * Collect any unidentified data.
0213   *
0214   * @param string $line - The line in the cue file that contains the TRACK command.
0215   * @param integer $track_on - The track currently processing.
0216   */
0217   public function parseGarbage($line, $track_on)
0218   {
0219     if ( strlen($line) > 0 )
0220     {
0221       if ($track_on == -1)
0222       {
0223         $this->cuesheet['garbage'][] = $line;
0224       }
0225       else
0226       {
0227         $this->cuesheet['tracks'][$track_on]['garbage'][] = $line;
0228       }
0229     }
0230   }
0231 
0232   /**
0233   * Parses the INDEX command of a TRACK.
0234   *
0235   * @param string $line - The line in the cue file that contains the TRACK command.
0236   * @param integer $track_on - The track currently processing.
0237   */
0238   public function parseIndex($line, $track_on)
0239   {
0240     $type = strtolower(substr($line, 0, strpos($line, ' ')));
0241     $line =            substr($line, strpos($line, ' ') + 1);
0242 
0243     if ($type == 'index')
0244     {
0245       //read the index number
0246       $number = intval(substr($line, 0, strpos($line, ' ')));
0247       $line   =        substr($line, strpos($line, ' ') + 1);
0248     }
0249 
0250     //extract the minutes, seconds, and frames
0251     $explodedline = explode(':', $line);
0252     $minutes = (isset($explodedline[0]) ? $explodedline[0] : '');
0253     $seconds = (isset($explodedline[1]) ? $explodedline[1] : '');
0254     $frames  = (isset($explodedline[2]) ? $explodedline[2] : '');
0255 
0256     switch ($type) {
0257       case 'index':
0258         $this->cuesheet['tracks'][$track_on][$type][$number] = array('minutes'=>intval($minutes), 'seconds'=>intval($seconds), 'frames'=>intval($frames));
0259         break;
0260       case 'pregap':
0261       case 'postgap':
0262         $this->cuesheet['tracks'][$track_on][$type]          = array('minutes'=>intval($minutes), 'seconds'=>intval($seconds), 'frames'=>intval($frames));
0263         break;
0264     }
0265   }
0266 
0267   public function parseString($line, $track_on)
0268   {
0269     $category = strtolower(substr($line, 0, strpos($line, ' ')));
0270     $line     =            substr($line, strpos($line, ' ') + 1);
0271 
0272     //get rid of the quotes
0273     $line = trim($line, '"');
0274 
0275     switch ($category)
0276     {
0277       case 'catalog':
0278       case 'cdtextfile':
0279       case 'isrc':
0280       case 'performer':
0281       case 'songwriter':
0282       case 'title':
0283         if ($track_on == -1)
0284         {
0285           $this->cuesheet[$category] = $line;
0286         }
0287         else
0288         {
0289           $this->cuesheet['tracks'][$track_on][$category] = $line;
0290         }
0291         break;
0292       default:
0293         break;
0294     }
0295   }
0296 
0297   /**
0298   * Parses the TRACK command.
0299   *
0300   * @param string $line - The line in the cue file that contains the TRACK command.
0301   * @param integer $track_on - The track currently processing.
0302   */
0303   public function parseTrack($line, $track_on)
0304   {
0305     $line = substr($line, strpos($line, ' ') + 1);
0306     $track = ltrim(substr($line, 0, strpos($line, ' ')), '0');
0307 
0308     //find the data type.
0309     $datatype = strtolower(substr($line, strpos($line, ' ') + 1));
0310 
0311     $this->cuesheet['tracks'][$track_on] = array('track_number'=>$track, 'datatype'=>$datatype);
0312   }
0313 
0314 }
0315