factor-work/flac/metadata/metadata.factor

173 lines
5.6 KiB
Factor
Raw Permalink Normal View History

2022-07-06 18:13:20 -04:00
USING: kernel math math.parser endian sequences pack io.streams.byte-array io.encodings.utf8 io.encodings.string io.encodings.binary io.encodings.ascii splitting assocs arrays byte-arrays accessors combinators ;
2021-06-06 12:53:59 -04:00
QUALIFIED: io
2022-07-06 18:13:20 -04:00
USING: flac.stream flac.format ;
2021-06-06 12:53:59 -04:00
IN: flac.metadata
2022-07-06 18:13:20 -04:00
<PRIVATE
2021-06-06 12:53:59 -04:00
ERROR: cuesheet-index-reserved-must-be-zero ;
: read-metadata-block-header ( -- header )
2023-06-16 21:35:43 -04:00
1 flac-read-uint 1 =
7 flac-read-uint <metadata-type>
24 flac-read-uint
2021-06-06 12:53:59 -04:00
metadata-block-header boa ;
: read-metadata-block-stream-info ( -- stream-info )
2023-06-16 21:35:43 -04:00
16 flac-read-uint
16 flac-read-uint
24 flac-read-uint
24 flac-read-uint
20 flac-read-uint
3 flac-read-uint 1 +
5 flac-read-uint 1 +
36 flac-read-uint
128 flac-read-uint 16 >be bytes>hex-string
2021-06-06 12:53:59 -04:00
stream-info boa ;
: read-metadata-block-seek-table ( length -- seek-table )
18 / <iota> [
drop
2023-06-16 21:35:43 -04:00
64 flac-read-uint
64 flac-read-uint
16 flac-read-uint
2021-06-06 12:53:59 -04:00
seek-point boa
] map
seek-table boa ;
: read-metadata-block-vorbis-comment ( length -- vorbis-comment )
! vorbis comments are in little endian...
drop
2023-06-16 21:35:43 -04:00
32 flac-read-uint 4 >le be> dup 8 * flac-read-uint swap >n-byte-array utf8 decode
32 flac-read-uint 4 >le be> <iota>
2021-06-06 12:53:59 -04:00
[
drop
2023-06-16 21:35:43 -04:00
32 flac-read-uint 4 >le be> dup 8 * flac-read-uint swap >n-byte-array utf8 decode
2021-06-06 12:53:59 -04:00
"=" split
] map
>alist vorbis-comment boa ;
: encode-vorbis-string ( str -- byte-array )
dup binary [ length 4 >le io:write utf8 encode io:write ] with-byte-writer ;
: encode-vorbis-comments ( assoc -- byte-array )
dup binary [
length 4 >le io:write
[ 2array "=" join encode-vorbis-string io:write ] assoc-each
] with-byte-writer ;
: encode-vorbis-comment ( vorbis-comment -- byte-array )
binary [
[ vendor-string>> encode-vorbis-string io:write ]
[ comments>> encode-vorbis-comments io:write ] bi
] with-byte-writer ;
: encode-padding ( padding -- byte-array )
length>> <byte-array> ;
: read-metadata-block-padding ( length -- padding )
2023-06-16 21:35:43 -04:00
dup 8 * flac-read-uint drop flac-padding boa ;
2021-06-06 12:53:59 -04:00
: read-metadata-block-application ( length -- application )
2023-06-16 21:35:43 -04:00
8 * flac-read-uint drop application new ;
2021-06-06 12:53:59 -04:00
: read-metadata-block-cuesheet ( length -- cuesheet )
2023-06-16 21:35:43 -04:00
dup [ 8 * flac-read-uint ] dip >be
2021-06-06 12:53:59 -04:00
binary
[
128 io:read ascii decode
8 io:read be>
259 io:read drop f
1 io:read be> <iota> [
drop
8 io:read be>
1 io:read be>
12 io:read ascii decode
21 io:read drop 0 <cuesheet-track-type> t
1 io:read <iota> [
drop
8 io:read be>
1 io:read be>
3 io:read be> = 0 [ cuesheet-index-reserved-must-be-zero ] unless
cuesheet-index boa
] map
cuesheet-track boa
] map
] with-byte-reader cuesheet boa ;
: read-metadata-block-picture ( length -- picture )
drop
2023-06-16 21:35:43 -04:00
32 flac-read-uint <picture-type>
32 flac-read-uint dup 8 * flac-read-uint swap >n-byte-array utf8 decode
32 flac-read-uint dup 8 * flac-read-uint swap >n-byte-array utf8 decode
32 flac-read-uint
32 flac-read-uint
32 flac-read-uint
32 flac-read-uint
32 flac-read-uint dup 8 * flac-read-uint swap >n-byte-array reverse
2021-06-06 12:53:59 -04:00
picture boa ;
2021-08-09 11:50:16 -04:00
: append-picture ( metadata picture -- metadata )
2022-08-22 23:23:23 -04:00
[ dup picture>> ] dip suffix >>picture ;
2021-08-09 11:50:16 -04:00
2021-06-06 12:53:59 -04:00
: read-metadata-block ( metadata length type -- metadata )
[
{
{ metadata-stream-info [ drop read-metadata-block-stream-info >>stream-info ] }
{ metadata-padding [ read-metadata-block-padding >>padding ] }
{ metadata-application [ read-metadata-block-application >>application ] }
{ metadata-seek-table [ read-metadata-block-seek-table >>seek-table ] }
{ metadata-vorbis-comment [ read-metadata-block-vorbis-comment >>vorbis-comment ] }
{ metadata-cuesheet [ read-metadata-block-cuesheet >>cuesheet ] }
2021-08-09 11:50:16 -04:00
{ metadata-picture [ read-metadata-block-picture append-picture ] }
2021-06-06 12:53:59 -04:00
} case
] with-big-endian ;
2022-07-06 18:13:20 -04:00
PRIVATE>
2021-06-06 12:53:59 -04:00
: read-flac-metadata ( -- metadata )
read/assert-flac-magic
metadata new
[
read-metadata-block-header
[ length>> ] [ type>> ] [ last?>> not ] tri
[ read-metadata-block ] dip
] loop ;
2023-06-16 21:35:43 -04:00
! : read-stream-info/seek-data ( -- stream-info )
! read/assert-flac-magic
! 32 flac-read-uint drop
! read-metadata-block-stream-info
! [ read-metadata-block-header [ length>> 8 * flac-seek ] [ last?>> not ] bi ] loop ;
2022-08-22 23:23:23 -04:00
2021-08-09 11:50:16 -04:00
: <flac-stream-info> ( filename -- stream-info )
[
read/assert-flac-magic
2023-06-16 21:35:43 -04:00
32 flac-read-uint drop
2021-08-09 11:50:16 -04:00
read-metadata-block-stream-info
] with-flac-file-reader ;
2022-08-22 23:23:23 -04:00
! TODO: write these
2022-07-06 18:13:20 -04:00
! : <flac-tags> ( filename -- tags )
! [
! read/assert-flac-magic
! [ read-metadata-block-header [ length>> ] [ type>> metadata-vorbis-comment = ] [ last?>> ] tri or ]
! [ flac-seek ] until [ read-metadata-block-vorbis-comment ] with-big-endian
! ] with-flac-file-reader ;
!
! : <flac-pictures> ( filename -- pictures )
! [
! read/assert-flac-magic
! [ read-metadata-block-header dup last?>> not ]
! [
! [ length>> ] [ type>> metadata-picture = ] bi
! [ read-metadata-block-picture ]
! [ flac-seek f ] if
! ] produce nip sift
! ] with-flac-file-reader ;
2021-08-09 11:50:16 -04:00
2021-06-06 12:53:59 -04:00
: <flac-metadata> ( filename -- metadata )
[ read-flac-metadata ] with-flac-file-reader ;