1 ! Copyright (C) 2013 John Benediktsson
2 ! See http://factorcode.org/license.txt for BSD license
4 USING: accessors ascii combinators io io.encodings.utf8 io.files
5 io.streams.string kernel math.parser sequences splitting ;
9 TUPLE: cuesheet catalog cdtextfile files flags remarks performer
12 : <cuesheet> ( -- cuesheet )
13 f f f f f f f f cuesheet boa ;
15 TUPLE: file name type tracks ;
17 : <file> ( name type -- file )
20 TUPLE: track number datatype title performer songwriter pregap
21 indices isrc postgap ;
23 : <track> ( number datatype -- track )
24 f f f f f f f track boa ;
26 TUPLE: index number duration ;
30 ERROR: unknown-filetype filetype ;
32 : check-filetype ( filetype -- filetype )
33 dup { "BINARY" "MOTOROLA" "AIFF" "WAVE" "MP3" } member?
34 [ throw-unknown-filetype ] unless ;
36 ERROR: unknown-flag flag ;
38 : check-flag ( flag -- flag )
39 dup { "DCP" "4CH" "PRE" "SCMS" "DATA" } member?
40 [ unknown-flag ] unless ;
42 : check-flags ( flags -- flags )
43 dup [ check-flag drop ] each ;
45 ERROR: unknown-datatype datatype ;
47 : check-datatype ( datatype -- datatype )
49 "AUDIO" "CDG" "MODE1/2048" "MODE1/2352" "MODE2/2336"
50 "MODE2/2352" "CDI/2336" "CDI/2352"
51 } member? [ unknown-datatype ] unless ;
53 ERROR: unknown-syntax syntax ;
57 : trim-comments ( str -- str' )
58 dup [ CHAR: ; = ] find drop [ head ] when* ;
60 : trim-quotes ( str -- str' )
63 : last-track ( cuesheet -- cuesheet track )
64 dup files>> last tracks>> last ;
66 : track-or-disc ( cuesheet -- cuesheet track/disc )
67 dup files>> [ dup ] [ last tracks>> last ] if-empty ;
69 : parse-file ( cuesheet str -- cuesheet )
70 " " split1-last [ trim-quotes ] [ check-filetype ] bi*
71 <file> [ suffix ] curry change-files ;
73 : parse-flags ( cuesheet str -- cuesheet )
74 check-flag [ suffix ] curry change-flags ;
76 : parse-index ( cuesheet str -- cuesheet )
78 " " split1 [ string>number ] dip <index>
79 [ suffix ] curry change-indices drop
82 : parse-isrc ( cuesheet str -- cuesheet )
83 [ last-track ] [ >>isrc drop ] bi* ;
85 : parse-performer ( cuesheet str -- cuesheet )
86 [ track-or-disc ] [ trim-quotes >>performer drop ] bi* ;
88 : parse-postgap ( cuesheet str -- cuesheet )
89 [ last-track ] [ >>postgap drop ] bi* ;
91 : parse-pregap ( cuesheet str -- cuesheet )
92 [ last-track ] [ >>pregap drop ] bi* ;
94 : parse-remarks ( cuesheet str -- cuesheet )
95 [ suffix ] curry change-remarks ;
97 : parse-songwriter ( cuesheet str -- cuesheet )
98 [ track-or-disc ] [ trim-quotes >>songwriter drop ] bi* ;
100 : parse-title ( cuesheet str -- cuesheet )
101 [ track-or-disc ] [ trim-quotes >>title drop ] bi* ;
103 : parse-track ( cuesheet str -- cuesheet )
104 [ dup files>> last ] [
105 " " split1 [ string>number ] [ check-datatype ] bi*
106 ] bi* <track> [ suffix ] curry change-tracks drop ;
108 : parse-line ( cuesheet line -- cuesheet )
109 trim-comments [ blank? ] trim " " split1 swap {
110 { "CATALOG" [ >>catalog ] }
111 { "CDTEXTFILE" [ >>cdtextfile ] }
112 { "FILE" [ parse-file ] }
113 { "FLAGS" [ parse-flags ] }
114 { "INDEX" [ parse-index ] }
115 { "ISRC" [ parse-isrc ] }
116 { "PERFORMER" [ parse-performer ] }
117 { "POSTGAP" [ parse-postgap ] }
118 { "PREGAP" [ parse-pregap ] }
119 { "REM" [ parse-remarks ] }
120 { "SONGWRITER" [ parse-songwriter ] }
121 { "TITLE" [ parse-title ] }
122 { "TRACK" [ parse-track ] }
129 : read-cuesheet ( -- cuesheet )
130 <cuesheet> [ readln dup ] [ parse-line ] while drop ;
132 : file>cuesheet ( path -- cuesheet )
133 utf8 [ read-cuesheet ] with-file-reader ;
135 : string>cuesheet ( str -- cuesheet )
136 [ read-cuesheet ] with-string-reader ;