blob: bd7f0a044213a569511efd9b11e9874149058eee (
plain) (
tree)
|
|
open Angstrom
(**
We only care about tags in the intersection of those known
by MPD and ListenBrainz. They are (LB <-> MPD)
+ artist_name <-> artist, performer, composer
+ track_name <-> title
+ tracknumber <-> track
+ artist_mbids <-> musicbrainz_artistid
+ release_mbid <-> musicbrainz_albumid
+ recording_mbid <-> musicbrainz_trackid
MPD may return multiple entries for each tag.
See https://picard-docs.musicbrainz.org/downloads/MusicBrainz_Picard_Tag_Map.html
for the correspondence between LB and MPD tag names.
*)
type currentsong = {
artist: string list;
performer: string list;
composer: string list;
title: string option;
track: int option;
musicbrainz_albumid: string option;
musicbrainz_artistid: string list;
musicbrainz_trackid: string option;
}
exception ParseError of string
let parse_string p s =
match Angstrom.parse_string ~consume:All (p >>= return) s with
| Ok parsed -> parsed
| Error m -> raise (ParseError m)
let take_till_eol =
let is_eol = function
| '\n' | '\r' -> true
| _ -> false in
take_till is_eol <* end_of_line
let is_whitespace = function
| ' ' | '\t' -> true
| _ -> false
let skip_spaces = skip_while is_whitespace
let currentsong_parser : currentsong Angstrom.t =
let open Angstrom in
fix (fun currentsong ->
lift2 (fun artist current -> { current with artist = artist :: current.artist })
(string "Artist:" *> skip_spaces *> take_till_eol)
currentsong
<|> lift2 (fun performer current -> { current with performer = performer :: current.performer })
(string "Performer:" *> skip_spaces *> take_till_eol)
currentsong
<|> lift2 (fun composer current -> { current with composer = composer :: current.composer })
(string "Composer:" *> skip_spaces *> take_till_eol)
currentsong
<|> lift2 (fun title current -> { current with title = Some title })
(string "Title:" *> skip_spaces *> take_till_eol)
currentsong
<|> lift2 (fun track current -> { current with track = Some (int_of_string track) })
(string "Track:" *> skip_spaces *> take_till_eol)
currentsong
<|> lift2 (fun albumid current -> { current with musicbrainz_albumid = Some albumid })
(string "MUSICBRAINZ_ALBUMID:" *> skip_spaces *> take_till_eol)
currentsong
<|> lift2 (fun artistid current ->
{ current with musicbrainz_artistid = artistid :: current.musicbrainz_artistid })
(string "MUSICBRAINZ_ARTISTID:" *> skip_spaces *> take_till_eol)
currentsong
<|> lift2 (fun trackid current -> { current with musicbrainz_trackid = Some trackid })
(string "MUSICBRAINZ_TRACKID:" *> skip_spaces *> take_till_eol)
currentsong
<|> ((string "OK") *> return {
artist = [];
performer = [];
composer = [];
title = None;
track = None;
musicbrainz_albumid = None;
musicbrainz_artistid = [];
musicbrainz_trackid = None;
})
<|> (take_till_eol *> currentsong))
<?> "currentsong"
|