]> gitweb.factorcode.org Git - factor.git/commitdiff
cuesheet: adding parser for cue files.
authorJohn Benediktsson <mrjbq7@gmail.com>
Thu, 21 Nov 2013 04:39:17 +0000 (20:39 -0800)
committerJohn Benediktsson <mrjbq7@gmail.com>
Thu, 21 Nov 2013 04:40:08 +0000 (20:40 -0800)
extra/cuesheet/authors.txt [new file with mode: 0644]
extra/cuesheet/cuesheet-tests.factor [new file with mode: 0644]
extra/cuesheet/cuesheet.factor [new file with mode: 0644]
extra/cuesheet/summary.txt [new file with mode: 0644]

diff --git a/extra/cuesheet/authors.txt b/extra/cuesheet/authors.txt
new file mode 100644 (file)
index 0000000..e091bb8
--- /dev/null
@@ -0,0 +1 @@
+John Benediktsson
diff --git a/extra/cuesheet/cuesheet-tests.factor b/extra/cuesheet/cuesheet-tests.factor
new file mode 100644 (file)
index 0000000..519c149
--- /dev/null
@@ -0,0 +1,118 @@
+USING: tools.test ;
+IN: cuesheet
+
+{
+    T{ cuesheet
+        { files
+            {
+                T{ file
+                    { name "Faithless - Live in Berlin.mp3" }
+                    { type "MP3" }
+                    { tracks
+                        {
+                            T{ track
+                                { number 1 }
+                                { datatype "AUDIO" }
+                                { title "Reverence" }
+                                { performer "Faithless" }
+                                { indices { T{ index f 1 "00:00:00" } } }
+                            }
+                            T{ track
+                                { number 2 }
+                                { datatype "AUDIO" }
+                                { title "She's My Baby" }
+                                { performer "Faithless" }
+                                { indices { T{ index f 1 "06:42:00" } } }
+                            }
+                            T{ track
+                                { number 3 }
+                                { datatype "AUDIO" }
+                                { title "Take the Long Way Home" }
+                                { performer "Faithless" }
+                                { indices { T{ index f 1 "10:54:00" } } }
+                            }
+                            T{ track
+                                { number 4 }
+                                { datatype "AUDIO" }
+                                { title "Insomnia" }
+                                { performer "Faithless" }
+                                { indices { T{ index f 1 "17:04:00" } } }
+                            }
+                            T{ track
+                                { number 5 }
+                                { datatype "AUDIO" }
+                                { title "Bring the Family Back" }
+                                { performer "Faithless" }
+                                { indices { T{ index f 1 "25:44:00" } } }
+                            }
+                            T{ track
+                                { number 6 }
+                                { datatype "AUDIO" }
+                                { title "Salva Mea" }
+                                { performer "Faithless" }
+                                { indices { T{ index f 1 "30:50:00" } } }
+                            }
+                            T{ track
+                                { number 7 }
+                                { datatype "AUDIO" }
+                                { title "Dirty Old Man" }
+                                { performer "Faithless" }
+                                { indices { T{ index f 1 "38:24:00" } } }
+                            }
+                            T{ track
+                                { number 8 }
+                                { datatype "AUDIO" }
+                                { title "God Is a DJ" }
+                                { performer "Faithless" }
+                                { indices { T{ index f 1 "42:35:00" } } }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        { remarks { "GENRE \"Electronica\"" "DATE \"1998\"" } }
+        { performer "Faithless" }
+        { title "Live in Berlin" }
+    }
+} [
+    """
+     REM GENRE "Electronica"
+     REM DATE "1998"
+     PERFORMER "Faithless"
+     TITLE "Live in Berlin"
+     FILE "Faithless - Live in Berlin.mp3" MP3
+       TRACK 01 AUDIO
+         TITLE "Reverence"
+         PERFORMER "Faithless"
+         INDEX 01 00:00:00
+       TRACK 02 AUDIO
+         TITLE "She's My Baby"
+         PERFORMER "Faithless"
+         INDEX 01 06:42:00
+       TRACK 03 AUDIO
+         TITLE "Take the Long Way Home"
+         PERFORMER "Faithless"
+         INDEX 01 10:54:00
+       TRACK 04 AUDIO
+         TITLE "Insomnia"
+         PERFORMER "Faithless"
+         INDEX 01 17:04:00
+       TRACK 05 AUDIO
+         TITLE "Bring the Family Back"
+         PERFORMER "Faithless"
+         INDEX 01 25:44:00
+       TRACK 06 AUDIO
+         TITLE "Salva Mea"
+         PERFORMER "Faithless"
+         INDEX 01 30:50:00
+       TRACK 07 AUDIO
+         TITLE "Dirty Old Man"
+         PERFORMER "Faithless"
+         INDEX 01 38:24:00
+       TRACK 08 AUDIO
+         TITLE "God Is a DJ"
+         PERFORMER "Faithless"
+         INDEX 01 42:35:00
+    """ string>cuesheet
+] unit-test
diff --git a/extra/cuesheet/cuesheet.factor b/extra/cuesheet/cuesheet.factor
new file mode 100644 (file)
index 0000000..4b85060
--- /dev/null
@@ -0,0 +1,136 @@
+! Copyright (C) 2013 John Benediktsson
+! See http://factorcode.org/license.txt for BSD license
+
+USING: accessors ascii combinators io io.encodings.utf8 io.files
+io.streams.string kernel math.parser sequences splitting ;
+
+IN: cuesheet
+
+TUPLE: cuesheet catalog cdtextfile files flags remarks performer
+songwriter title ;
+
+: <cuesheet> ( -- cuesheet )
+    f f f f f f f f cuesheet boa ;
+
+TUPLE: file name type tracks ;
+
+: <file> ( name type -- file )
+    f file boa ;
+
+TUPLE: track number datatype title performer songwriter pregap
+indices isrc postgap ;
+
+: <track> ( number datatype -- track )
+    f f f f f f f track boa ;
+
+TUPLE: index number duration ;
+
+C: <index> index
+
+ERROR: unknown-filetype filetype ;
+
+: check-filetype ( filetype -- filetype )
+    dup { "BINARY" "MOTOROLA" "AIFF" "WAVE" "MP3" } member?
+    [ unknown-filetype ] unless ;
+
+ERROR: unknown-flag flag ;
+
+: check-flag ( flag -- flag )
+    dup { "DCP" "4CH" "PRE" "SCMS" "DATA" } member?
+    [ unknown-flag ] unless ;
+
+: check-flags ( flags -- flags )
+    dup [ check-flag drop ] each ;
+
+ERROR: unknown-datatype datatype ;
+
+: check-datatype ( datatype -- datatype )
+    dup {
+        "AUDIO" "CDG" "MODE1/2048" "MODE1/2352" "MODE2/2336"
+        "MODE2/2352" "CDI/2336" "CDI/2352"
+    } member? [ unknown-datatype ] unless ;
+
+ERROR: unknown-syntax syntax ;
+
+<PRIVATE
+
+: trim-comments ( str -- str' )
+    dup [ CHAR: ; = ] find drop [ head ] when* ;
+
+: trim-quotes ( str -- str' )
+    [ CHAR: " = ] trim ;
+
+: last-track ( cuesheet -- cuesheet track )
+    dup files>> last tracks>> last ;
+
+: track-or-disc ( cuesheet -- cuesheet track/disc )
+    dup files>> [ dup ] [ last tracks>> last ] if-empty ;
+
+: parse-file ( cuesheet str -- cuesheet )
+    " " split1-last [ trim-quotes ] [ check-filetype ] bi*
+    <file> [ suffix ] curry change-files ;
+
+: parse-flags ( cuesheet str -- cuesheet )
+    check-flag [ suffix ] curry change-flags ;
+
+: parse-index ( cuesheet str -- cuesheet )
+    [ last-track ] [
+        " " split1 [ string>number ] dip <index>
+        [ suffix ] curry change-indices drop
+    ] bi* ;
+
+: parse-isrc ( cuesheet str -- cuesheet )
+    [ last-track ] [ >>isrc drop ] bi* ;
+
+: parse-performer ( cuesheet str -- cuesheet )
+    [ track-or-disc ] [ trim-quotes >>performer drop ] bi* ;
+
+: parse-postgap ( cuesheet str -- cuesheet )
+    [ last-track ] [ >>postgap drop ] bi* ;
+
+: parse-pregap ( cuesheet str -- cuesheet )
+    [ last-track ] [ >>pregap drop ] bi* ;
+
+: parse-remarks ( cuesheet str -- cuesheet )
+    [ suffix ] curry change-remarks ;
+
+: parse-songwriter ( cuesheet str -- cuesheet )
+    [ track-or-disc ] [ trim-quotes >>songwriter drop ] bi* ;
+
+: parse-title ( cuesheet str -- cuesheet )
+    [ track-or-disc ] [ trim-quotes >>title drop ] bi* ;
+
+: parse-track ( cuesheet str -- cuesheet )
+    [ dup files>> last ] [
+        " " split1 [ string>number ] [ check-datatype ] bi*
+    ] bi* <track> [ suffix ] curry change-tracks drop ;
+
+: parse-line ( cuesheet line -- cuesheet )
+    trim-comments [ blank? ] trim " " split1 swap {
+        { "CATALOG" [ >>catalog ] }
+        { "CDTEXTFILE" [ >>cdtextfile ] }
+        { "FILE" [ parse-file ] }
+        { "FLAGS" [ parse-flags ] }
+        { "INDEX" [ parse-index ] }
+        { "ISRC" [ parse-isrc ] }
+        { "PERFORMER" [ parse-performer ] }
+        { "POSTGAP" [ parse-postgap ] }
+        { "PREGAP" [ parse-pregap ] }
+        { "REM" [ parse-remarks ] }
+        { "SONGWRITER" [ parse-songwriter ] }
+        { "TITLE" [ parse-title ] }
+        { "TRACK" [ parse-track ] }
+        { "" [ drop ] }
+        [ unknown-syntax ]
+    } case ;
+
+PRIVATE>
+
+: read-cuesheet ( -- cuesheet )
+    <cuesheet> [ readln dup ] [ parse-line ] while drop ;
+
+: file>cuesheet ( path -- cuesheet )
+    utf8 [ read-cuesheet ] with-file-reader ;
+
+: string>cuesheet ( str -- cuesheet )
+    [ read-cuesheet ] with-string-reader ;
diff --git a/extra/cuesheet/summary.txt b/extra/cuesheet/summary.txt
new file mode 100644 (file)
index 0000000..6dcfca7
--- /dev/null
@@ -0,0 +1 @@
+Parsing cue sheet (cue files)