2019-05-21 11:05:53 +02:00
|
|
|
import Dates
|
|
|
|
ms2string(m::Dates.DateTime) = Dates.format(m, Dates.dateformat"YYYY-mm-ddTHH:MM:SS")
|
|
|
|
|
2019-05-17 20:22:01 +02:00
|
|
|
import Base.push!
|
|
|
|
|
2019-05-21 11:05:53 +02:00
|
|
|
# Try to fix missing mime types
|
|
|
|
Mux.mimetypes["alac"] = "audio/x-m4a"
|
|
|
|
Mux.mimetypes["m4a"] = "audio/x-m4a"
|
|
|
|
|
2019-05-17 20:22:01 +02:00
|
|
|
function push!(root::XMLElement, p::Playlist)
|
|
|
|
playlistXML = new_child(root, "playlist")
|
|
|
|
set_attributes(playlistXML, [
|
|
|
|
("id", p.uuid),
|
|
|
|
("name", p.name),
|
|
|
|
("comment", p.comment),
|
|
|
|
("owner", p.owner),
|
|
|
|
("public", string(p.public)),
|
|
|
|
("songCount", string(length(p.songs))),
|
2019-05-19 18:28:43 +02:00
|
|
|
("duration", reduce(+, p.songs, init = 0.0) |> floor |> Int |> string),
|
2019-05-21 11:05:53 +02:00
|
|
|
("created", ms2string(p.created)),
|
2019-05-17 20:22:01 +02:00
|
|
|
("coverArt", p.cover),
|
|
|
|
])
|
|
|
|
playlistXML
|
|
|
|
end
|
|
|
|
|
|
|
|
function append!(root::XMLElement, p::Playlist)
|
|
|
|
playlistXML = push!(root, p)
|
2019-05-19 22:24:18 +02:00
|
|
|
# Allowed users
|
|
|
|
for al in p.allowed
|
2019-05-21 11:05:53 +02:00
|
|
|
set_content(new_child(playlistXML, "allowedUser"), al)
|
2019-05-19 22:24:18 +02:00
|
|
|
end
|
2019-05-17 20:22:01 +02:00
|
|
|
for song in p.songs
|
|
|
|
entry = new_child(playlistXML, "entry")
|
|
|
|
set_attributes(entry, props(song))
|
2019-05-19 22:24:18 +02:00
|
|
|
set_attribute(entry, "artist", Beets.artist(song).name)
|
2019-05-17 20:22:01 +02:00
|
|
|
end
|
|
|
|
playlistXML
|
|
|
|
end
|
|
|
|
|
|
|
|
push!(p::Playlist, s::Song) = push!(p.songs, s)
|
|
|
|
|
|
|
|
function push!(root::XMLElement, album::Beets.Album)
|
|
|
|
albumXML = new_child(root, "album")
|
|
|
|
set_attributes(albumXML, [
|
|
|
|
("id", album.uuid),
|
2019-05-19 18:28:43 +02:00
|
|
|
("name", album.title),
|
2019-05-17 20:22:01 +02:00
|
|
|
("coverArt", album.uuid),
|
|
|
|
("songCount", string(length(album.songs))),
|
2019-05-21 11:05:53 +02:00
|
|
|
("created", ms2string(album.added)),
|
2019-05-19 18:28:43 +02:00
|
|
|
("duration", string(sum([t.length for t in album.songs]) |> floor |> Int)),
|
|
|
|
("artist", album.artist.name),
|
|
|
|
("artistId", album.artist.uuid)
|
2019-05-17 20:22:01 +02:00
|
|
|
])
|
|
|
|
albumXML
|
|
|
|
end
|
|
|
|
|
2019-05-21 15:13:08 +02:00
|
|
|
import Base.sort
|
|
|
|
sort(ss::Vector{Beets.Song}) = sort(ss, by = x -> x.track)
|
|
|
|
|
2019-05-19 18:28:43 +02:00
|
|
|
function append!(root::XMLElement, a::Beets.Album)
|
|
|
|
albumXML = push!(root, a)
|
2019-05-21 15:13:08 +02:00
|
|
|
for song in sort(a.songs)
|
2019-05-19 18:28:43 +02:00
|
|
|
songXML = push!(albumXML, song)
|
|
|
|
set_attributes(songXML, [
|
|
|
|
("album", a.title),
|
|
|
|
("parent", a.artist.uuid), # Not clear
|
|
|
|
("artist", a.artist.name),
|
|
|
|
("coverArt", a.uuid),
|
|
|
|
("albumId", a.uuid),
|
|
|
|
("artistId", a.artist.uuid),
|
|
|
|
])
|
|
|
|
end
|
|
|
|
albumXML
|
|
|
|
end
|
|
|
|
|
2019-05-17 20:22:01 +02:00
|
|
|
function push!(root::XMLElement, artist::Beets.Artist)
|
|
|
|
artistXML = new_child(root, "artist")
|
|
|
|
set_attributes(artistXML, [
|
|
|
|
("id", artist.uuid),
|
|
|
|
("name", artist.name),
|
|
|
|
("coverArt", artist.uuid),
|
2019-05-19 22:24:18 +02:00
|
|
|
("albumCount", Beets.album(artist) |> length |> string)
|
2019-05-17 20:22:01 +02:00
|
|
|
])
|
|
|
|
artistXML
|
|
|
|
end
|
|
|
|
|
2019-05-19 18:28:43 +02:00
|
|
|
function push!(root::XMLElement, song::Beets.Song)
|
|
|
|
songXML = new_child(root, "song")
|
|
|
|
suffix = lowercase(song.format)
|
2019-05-21 11:05:53 +02:00
|
|
|
mime = suffix in keys(Mux.mimetypes) ? Mux.mimetypes[suffix] : suffix
|
2019-05-19 18:28:43 +02:00
|
|
|
set_attributes(songXML, [
|
|
|
|
("id", song.uuid),
|
|
|
|
("title", song.title),
|
|
|
|
("isDir", "false"),
|
2019-05-21 11:05:53 +02:00
|
|
|
("created", ms2string(song.added)),
|
2019-05-19 18:28:43 +02:00
|
|
|
("duration", string(floor(song.length) |> Int)),
|
|
|
|
("bitrate", string(song.bitrate)),
|
|
|
|
("size", string(filesize(song.path))),
|
|
|
|
("suffix", suffix),
|
2019-05-21 11:05:53 +02:00
|
|
|
("contentType", mime),
|
2019-05-19 18:28:43 +02:00
|
|
|
("isVideo", "false"),
|
|
|
|
("path", relpath(song.path, Beets.musicdir())),
|
|
|
|
("type", "music")
|
|
|
|
])
|
|
|
|
songXML
|
|
|
|
end
|
|
|
|
|
2019-05-17 20:22:01 +02:00
|
|
|
function push!(root::XMLElement, song_album::Tuple{Beets.Song,Beets.Album})
|
|
|
|
songXML = new_child(root, "song")
|
|
|
|
song, album = song_album
|
2019-05-19 18:28:43 +02:00
|
|
|
suffix = lowercase(song.format)
|
2019-05-21 11:05:53 +02:00
|
|
|
mime = suffix in keys(Mux.mimetypes) ? Mux.mimetypes[suffix] : suffix
|
2019-05-17 20:22:01 +02:00
|
|
|
set_attributes(songXML, [
|
|
|
|
("id", song.uuid),
|
2019-05-19 18:28:43 +02:00
|
|
|
("parent", album.artist.uuid), # Not clear
|
2019-05-17 20:22:01 +02:00
|
|
|
("title", song.title),
|
|
|
|
("album", album.title),
|
|
|
|
("artist", album.artist.name),
|
|
|
|
("isDir", "false"),
|
|
|
|
("coverArt", album.uuid),
|
2019-05-21 11:05:53 +02:00
|
|
|
("created", ms2string(album.added)),
|
2019-05-17 20:22:01 +02:00
|
|
|
("duration", string(floor(song.length) |> Int)),
|
|
|
|
("bitrate", string(song.bitrate)),
|
|
|
|
("size", string(filesize(song.path))),
|
2019-05-19 18:28:43 +02:00
|
|
|
("suffix", suffix),
|
2019-05-21 11:05:53 +02:00
|
|
|
("contentType", mime),
|
2019-05-17 20:22:01 +02:00
|
|
|
("isVideo", "false"),
|
|
|
|
("path", relpath(song.path, Beets.musicdir())),
|
|
|
|
("albumId", album.uuid),
|
|
|
|
("artistId", album.artist.uuid),
|
|
|
|
("type", "music")
|
|
|
|
])
|
|
|
|
root
|
|
|
|
end
|
|
|
|
|
|
|
|
function props(song::Song)
|
2019-05-19 18:28:43 +02:00
|
|
|
suffix = lowercase(song.format)
|
2019-05-21 11:05:53 +02:00
|
|
|
mime = suffix in keys(Mux.mimetypes) ? Mux.mimetypes[suffix] : suffix
|
2019-05-17 20:22:01 +02:00
|
|
|
[
|
|
|
|
("id", song.uuid),
|
|
|
|
# ("parent", album.artist.uuid), # Not clear
|
|
|
|
("title", song.title),
|
|
|
|
("album", song.title),
|
|
|
|
# ("artist", song.album.artist.name),
|
|
|
|
("isDir", "false"),
|
|
|
|
("coverArt", song.uuid),
|
2019-05-21 11:05:53 +02:00
|
|
|
("created", ms2string(song.added)),
|
2019-05-17 20:22:01 +02:00
|
|
|
("duration", string(floor(song.length) |> Int)),
|
|
|
|
("bitrate", string(song.bitrate)),
|
|
|
|
("size", string(filesize(song.path))),
|
2019-05-19 18:28:43 +02:00
|
|
|
("suffix", suffix),
|
2019-05-21 11:05:53 +02:00
|
|
|
("contentType", mime), # mpeg
|
2019-05-17 20:22:01 +02:00
|
|
|
("isVideo", "false"),
|
|
|
|
("path", relpath(song.path, Beets.musicdir())),
|
2019-05-21 15:13:08 +02:00
|
|
|
#("albumId", song.album.uuid),
|
|
|
|
#("artistId", song.album.artist.uuid),
|
2019-05-17 20:22:01 +02:00
|
|
|
("type", "music")
|
|
|
|
]
|
|
|
|
end
|
|
|
|
|
2019-05-21 15:13:08 +02:00
|
|
|
|
2019-05-17 20:22:01 +02:00
|
|
|
function push!(root::XMLElement, songs::Vector{Tuple{Beets.Song,Beets.Album}})
|
|
|
|
for (song, album) in songs
|
|
|
|
songXML = new_child(root, "song")
|
|
|
|
set_attributes(songXML, props(song))
|
2019-05-21 15:13:08 +02:00
|
|
|
set_attribute(songXML, "artistId", album.artist.uuid)
|
|
|
|
set_attribute(songXML, "albumId", album.uuid)
|
2019-05-17 20:22:01 +02:00
|
|
|
end
|
|
|
|
root
|
|
|
|
end
|
|
|
|
|
|
|
|
function push!(root::XMLElement, user::User)
|
|
|
|
userXML = new_child(root, "user")
|
|
|
|
set_attributes(userXML,
|
|
|
|
[
|
|
|
|
("username", user.name)
|
|
|
|
("email", user.email)
|
|
|
|
("adminRole", string(user.admin))
|
|
|
|
("scrobblingEnabled", "false")
|
|
|
|
("settingsRole", string(user.settings))
|
|
|
|
("downloadRole", string(user.download))
|
|
|
|
("uploadRole", string(user.upload))
|
|
|
|
("playlistRole", string(user.playlist))
|
|
|
|
("coverArtRole", string(user.cover))
|
|
|
|
("commentRole", string(user.comment))
|
|
|
|
("podcastRole", "false")
|
|
|
|
("streamRole", string(user.stream))
|
|
|
|
("jukeboxRole", "false")
|
|
|
|
("shareRole", string(user.share))
|
|
|
|
])
|
|
|
|
end
|