module.misc.cue.php 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  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.misc.cue.php //
  11. // module for analyzing CUEsheet files //
  12. // dependencies: NONE //
  13. // //
  14. /////////////////////////////////////////////////////////////////
  15. // //
  16. // Module originally written [2009-Mar-25] by //
  17. // Nigel Barnes <ngbarnesØhotmail*com> //
  18. // Minor reformatting and similar small changes to integrate //
  19. // into getID3 by James Heinrich <info@getid3.org> //
  20. // ///
  21. /////////////////////////////////////////////////////////////////
  22. /*
  23. * CueSheet parser by Nigel Barnes.
  24. *
  25. * This is a PHP conversion of CueSharp 0.5 by Wyatt O'Day (wyday.com/cuesharp)
  26. */
  27. /**
  28. * A CueSheet class used to open and parse cuesheets.
  29. *
  30. */
  31. class getid3_cue extends getid3_handler
  32. {
  33. var $cuesheet = array();
  34. function Analyze() {
  35. $info = &$this->getid3->info;
  36. $info['fileformat'] = 'cue';
  37. $this->readCueSheetFilename($info['filenamepath']);
  38. $info['cue'] = $this->cuesheet;
  39. return true;
  40. }
  41. function readCueSheetFilename($filename)
  42. {
  43. $filedata = file_get_contents($filename);
  44. return $this->readCueSheet($filedata);
  45. }
  46. /**
  47. * Parses a cue sheet file.
  48. *
  49. * @param string $filename - The filename for the cue sheet to open.
  50. */
  51. function readCueSheet(&$filedata)
  52. {
  53. $cue_lines = array();
  54. foreach (explode("\n", str_replace("\r", null, $filedata)) as $line)
  55. {
  56. if ( (strlen($line) > 0) && ($line[0] != '#'))
  57. {
  58. $cue_lines[] = trim($line);
  59. }
  60. }
  61. $this->parseCueSheet($cue_lines);
  62. return $this->cuesheet;
  63. }
  64. /**
  65. * Parses the cue sheet array.
  66. *
  67. * @param array $file - The cuesheet as an array of each line.
  68. */
  69. function parseCueSheet($file)
  70. {
  71. //-1 means still global, all others are track specific
  72. $track_on = -1;
  73. for ($i=0; $i < count($file); $i++)
  74. {
  75. list($key) = explode(' ', strtolower($file[$i]), 2);
  76. switch ($key)
  77. {
  78. case 'catalog':
  79. case 'cdtextfile':
  80. case 'isrc':
  81. case 'performer':
  82. case 'songwriter':
  83. case 'title':
  84. $this->parseString($file[$i], $track_on);
  85. break;
  86. case 'file':
  87. $currentFile = $this->parseFile($file[$i]);
  88. break;
  89. case 'flags':
  90. $this->parseFlags($file[$i], $track_on);
  91. break;
  92. case 'index':
  93. case 'postgap':
  94. case 'pregap':
  95. $this->parseIndex($file[$i], $track_on);
  96. break;
  97. case 'rem':
  98. $this->parseComment($file[$i], $track_on);
  99. break;
  100. case 'track':
  101. $track_on++;
  102. $this->parseTrack($file[$i], $track_on);
  103. if (isset($currentFile)) // if there's a file
  104. {
  105. $this->cuesheet['tracks'][$track_on]['datafile'] = $currentFile;
  106. }
  107. break;
  108. default:
  109. //save discarded junk and place string[] with track it was found in
  110. $this->parseGarbage($file[$i], $track_on);
  111. break;
  112. }
  113. }
  114. }
  115. /**
  116. * Parses the REM command.
  117. *
  118. * @param string $line - The line in the cue file that contains the TRACK command.
  119. * @param integer $track_on - The track currently processing.
  120. */
  121. function parseComment($line, $track_on)
  122. {
  123. $explodedline = explode(' ', $line, 3);
  124. $comment_REM = (isset($explodedline[0]) ? $explodedline[0] : '');
  125. $comment_type = (isset($explodedline[1]) ? $explodedline[1] : '');
  126. $comment_data = (isset($explodedline[2]) ? $explodedline[2] : '');
  127. if (($comment_REM == 'REM') && $comment_type) {
  128. $comment_type = strtolower($comment_type);
  129. $commment_data = trim($comment_data, ' "');
  130. if ($track_on != -1) {
  131. $this->cuesheet['tracks'][$track_on]['comments'][$comment_type][] = $comment_data;
  132. } else {
  133. $this->cuesheet['comments'][$comment_type][] = $comment_data;
  134. }
  135. }
  136. }
  137. /**
  138. * Parses the FILE command.
  139. *
  140. * @param string $line - The line in the cue file that contains the FILE command.
  141. * @return array - Array of FILENAME and TYPE of file..
  142. */
  143. function parseFile($line)
  144. {
  145. $line = substr($line, strpos($line, ' ') + 1);
  146. $type = strtolower(substr($line, strrpos($line, ' ')));
  147. //remove type
  148. $line = substr($line, 0, strrpos($line, ' ') - 1);
  149. //if quotes around it, remove them.
  150. $line = trim($line, '"');
  151. return array('filename'=>$line, 'type'=>$type);
  152. }
  153. /**
  154. * Parses the FLAG command.
  155. *
  156. * @param string $line - The line in the cue file that contains the TRACK command.
  157. * @param integer $track_on - The track currently processing.
  158. */
  159. function parseFlags($line, $track_on)
  160. {
  161. if ($track_on != -1)
  162. {
  163. foreach (explode(' ', strtolower($line)) as $type)
  164. {
  165. switch ($type)
  166. {
  167. case 'flags':
  168. // first entry in this line
  169. $this->cuesheet['tracks'][$track_on]['flags'] = array(
  170. '4ch' => false,
  171. 'data' => false,
  172. 'dcp' => false,
  173. 'pre' => false,
  174. 'scms' => false,
  175. );
  176. break;
  177. case 'data':
  178. case 'dcp':
  179. case '4ch':
  180. case 'pre':
  181. case 'scms':
  182. $this->cuesheet['tracks'][$track_on]['flags'][$type] = true;
  183. break;
  184. default:
  185. break;
  186. }
  187. }
  188. }
  189. }
  190. /**
  191. * Collect any unidentified data.
  192. *
  193. * @param string $line - The line in the cue file that contains the TRACK command.
  194. * @param integer $track_on - The track currently processing.
  195. */
  196. function parseGarbage($line, $track_on)
  197. {
  198. if ( strlen($line) > 0 )
  199. {
  200. if ($track_on == -1)
  201. {
  202. $this->cuesheet['garbage'][] = $line;
  203. }
  204. else
  205. {
  206. $this->cuesheet['tracks'][$track_on]['garbage'][] = $line;
  207. }
  208. }
  209. }
  210. /**
  211. * Parses the INDEX command of a TRACK.
  212. *
  213. * @param string $line - The line in the cue file that contains the TRACK command.
  214. * @param integer $track_on - The track currently processing.
  215. */
  216. function parseIndex($line, $track_on)
  217. {
  218. $type = strtolower(substr($line, 0, strpos($line, ' ')));
  219. $line = substr($line, strpos($line, ' ') + 1);
  220. if ($type == 'index')
  221. {
  222. //read the index number
  223. $number = intval(substr($line, 0, strpos($line, ' ')));
  224. $line = substr($line, strpos($line, ' ') + 1);
  225. }
  226. //extract the minutes, seconds, and frames
  227. $explodedline = explode(':', $line);
  228. $minutes = (isset($explodedline[0]) ? $explodedline[0] : '');
  229. $seconds = (isset($explodedline[1]) ? $explodedline[1] : '');
  230. $frames = (isset($explodedline[2]) ? $explodedline[2] : '');
  231. switch ($type) {
  232. case 'index':
  233. $this->cuesheet['tracks'][$track_on][$type][$number] = array('minutes'=>intval($minutes), 'seconds'=>intval($seconds), 'frames'=>intval($frames));
  234. break;
  235. case 'pregap':
  236. case 'postgap':
  237. $this->cuesheet['tracks'][$track_on][$type] = array('minutes'=>intval($minutes), 'seconds'=>intval($seconds), 'frames'=>intval($frames));
  238. break;
  239. }
  240. }
  241. function parseString($line, $track_on)
  242. {
  243. $category = strtolower(substr($line, 0, strpos($line, ' ')));
  244. $line = substr($line, strpos($line, ' ') + 1);
  245. //get rid of the quotes
  246. $line = trim($line, '"');
  247. switch ($category)
  248. {
  249. case 'catalog':
  250. case 'cdtextfile':
  251. case 'isrc':
  252. case 'performer':
  253. case 'songwriter':
  254. case 'title':
  255. if ($track_on == -1)
  256. {
  257. $this->cuesheet[$category] = $line;
  258. }
  259. else
  260. {
  261. $this->cuesheet['tracks'][$track_on][$category] = $line;
  262. }
  263. break;
  264. default:
  265. break;
  266. }
  267. }
  268. /**
  269. * Parses the TRACK command.
  270. *
  271. * @param string $line - The line in the cue file that contains the TRACK command.
  272. * @param integer $track_on - The track currently processing.
  273. */
  274. function parseTrack($line, $track_on)
  275. {
  276. $line = substr($line, strpos($line, ' ') + 1);
  277. $track = ltrim(substr($line, 0, strpos($line, ' ')), '0');
  278. //find the data type.
  279. $datatype = strtolower(substr($line, strpos($line, ' ') + 1));
  280. $this->cuesheet['tracks'][$track_on] = array('track_number'=>$track, 'datatype'=>$datatype);
  281. }
  282. }
  283. ?>