+implementation module flac
+
+import StdEnv
+
+import Data.Error
+import Data.Func
+import Control.Monad => qualified join
+import System.FilePath
+import System._Pointer
+import System._Posix
+import Text
+
+import StdDebug
+
+NUM_COMMENT_OFFSET :== 32
+COMMENTS_OFFSET :== 40
+COMMENT_SIZE :== 16
+
+getTags :: FilePath !*World -> *(MaybeErrorString [(String, String)], !*World)
+getTags fp w
+ #! (mdp, w) = mallocSt 8 w
+ #! (ok, w) = FLAC__metadata_get_tags (packString fp) mdp w
+ | not ok
+ #! w = freeSt mdp w
+ = (Error "Error getting tags", w)
+ #! md = derefInt mdp
+ #! num_comments = readInt md NUM_COMMENT_OFFSET
+ #! comments = readInt md COMMENTS_OFFSET
+ #! comments = mapM (makeComment o derefString)
+ [readInt comments (COMMENT_SIZE*i+8)\\i<-[0..num_comments-1]]
+ #! w = FLAC__metadata_object_delete md w
+ #! w = freeSt mdp w
+ = (comments, w)
+where
+ makeComment :: !String -> MaybeErrorString (String, String)
+ makeComment s = case indexOf "=" s of
+ -1 = Error "No = in the tag"
+ i = Ok (s % (0, i-1), s % (i+1, size s))
+
+FLAC__metadata_get_tags :: !String !Pointer !*env -> (!Bool, !*env)
+FLAC__metadata_get_tags _ _ _ = code {
+ ccall FLAC__metadata_get_tags "sp:I:A"
+}
+
+FLAC__metadata_object_delete :: !Pointer !*env -> *env
+FLAC__metadata_object_delete _ _ = code {
+ ccall FLAC__metadata_object_delete "p:V:A"
+}
+
+Start w = getTags
+ "/mnt/data/music/Ahab/The Divinity of Oceans/01 Yet Another Raft of the Medusa (Pollard's Weakness).flac"
+ w