     ] output>array sift ;
 
 : seq>synchsafe ( seq -- n )
-    0 [ [ 7 shift ] dip bitor ] reduce ; inline
+    0 [ [ 7 shift ] dip bitor ] reduce ;
 
 : synchsafe>seq ( n -- seq )
     dup 1+ log2 1+ 7 / ceiling
-    [ [ -7 shift ] keep HEX: 7f bitand  ] replicate nip reverse ; inline
+    [ [ -7 shift ] keep HEX: 7f bitand  ] replicate nip reverse ;
 
 : filter-text-data ( data -- filtered )
-    [ printable? ] filter ; inline
+    [ printable? ] filter ;
 
 : valid-tag? ( id -- ? )
-    [ { [ digit? ] [ LETTER? ] } 1|| ] all? ; inline
+    [ { [ digit? ] [ LETTER? ] } 1|| ] all? ;
 
 : read-frame-data ( frame seq -- frame data )
-    [ 10 over size>> 10 + ] dip <slice> filter-text-data ; inline
+    [ 10 over size>> 10 + ] dip <slice> filter-text-data ;
 
 : decode-text ( string -- string' )
     dup 2 short head
     { { HEX: ff HEX: fe } { HEX: fe HEX: ff } } member?
-    utf16 ascii ? decode ; inline
+    utf16 ascii ? decode ;
 
 : (read-frame) ( seq -- frame )
     [ <frame> ] dip

            swap >>data
    ] [
        2drop f
    ] if ; inline

: id3v1>frames ( id3v1 -- seq )
    [

PRIVATE>

: mp3>id3 ( path -- id3/f )
    dup file-info size>> 0 <= [ drop f ] [ (mp3>id3) ] if ;

: find-id3-frame ( id3 name -- obj/f )
    swap frames>> at* [ data>> ] when ;

: title ( id3 -- string/f ) "TIT2" find-id3-frame ;

: artist ( id3 -- string/f ) "TPE1" find-id3-frame ;

: album ( id3 -- string/f ) "TALB" find-id3-frame ;

: year ( id3 -- string/f ) "TYER" find-id3-frame ;

: comment ( id3 -- string/f ) "COMM" find-id3-frame ;

: genre ( id3 -- string/f )
    "TCON" find-id3-frame parse-genre ;

: find-mp3s ( path -- seq )
    [ >lower ".mp3" tail? ] find-all-files ;

: mp3-paths>id3s ( seq -- seq' )
    [ dup mp3>id3 ] { } map>assoc ;

: parse-mp3-directory ( path -- seq )
    find-mp3s mp3-paths>id3s ;
