Fix duration/progress parsing.
parent
0356616566
commit
7825744006
|
@ -4,17 +4,18 @@
|
|||
|
||||
metadata_api_hostname = environment.get(default="icedream-bitwave", "METADATA_API_HOSTNAME")
|
||||
|
||||
def http_export_meta(%argsof(json.stringify), m) =
|
||||
j = json()
|
||||
list.iter((fun (v) -> j.add(fst(v), (snd(v):string))), m)
|
||||
json.stringify(%argsof(json.stringify), j)
|
||||
end
|
||||
def setup_harbor_metadata_api(~metadata_api_port=21338, ~id="", s) =
|
||||
# HACK - work around https://github.com/savonet/liquidsoap/issues/2996
|
||||
id = if id != "" then id else s.id() end
|
||||
|
||||
def setup_harbor_metadata_api(~metadata_api_port=21338, s) =
|
||||
id = s.id()
|
||||
s = drop_metadata(s) # stream metadata wipes out own data
|
||||
s = insert_metadata(s)
|
||||
|
||||
# holder for dynamic meta (things we don't want to go out over icecast
|
||||
# because they change a LOT like duration)
|
||||
dynamic_duration = ref(null())
|
||||
dynamic_progress = ref(null())
|
||||
|
||||
# Handler for fetching metadata
|
||||
def on_http_get_metadata(request) =
|
||||
http_version = request.http_version
|
||||
|
@ -36,7 +37,19 @@ def setup_harbor_metadata_api(~metadata_api_port=21338, s) =
|
|||
|
||||
# data = metadata.json.stringify(compact=true, m)
|
||||
m = metadata.cover.remove(m)
|
||||
data = http_export_meta(compact=true, m)
|
||||
|
||||
j = json()
|
||||
list.iter((fun (v) -> j.add(fst(v), (snd(v):string))), m)
|
||||
|
||||
# add dynamic metadata
|
||||
if null.defined(dynamic_duration()) then
|
||||
j.add("duration", null.get(dynamic_duration()))
|
||||
end
|
||||
if null.defined(dynamic_progress()) then
|
||||
j.add("progress", null.get(dynamic_progress()))
|
||||
end
|
||||
|
||||
data = json.stringify(compact=true, j)
|
||||
|
||||
http.response(http_version=http_version, status_code=200, headers=[
|
||||
("access-control-allow-origin","*"),
|
||||
|
@ -81,42 +94,78 @@ def setup_harbor_metadata_api(~metadata_api_port=21338, s) =
|
|||
# Handler for receiving metadata
|
||||
def on_http_metadata(request) =
|
||||
http_version = request.http_version
|
||||
data = request.data()
|
||||
raw_data = request.body()
|
||||
headers = request.headers
|
||||
|
||||
let json.parse (data : {
|
||||
data: [(string * string)] as json.object
|
||||
}) = data
|
||||
# log.info("New data for #{id}: #{data}")
|
||||
|
||||
m = data.data
|
||||
let json.parse ({
|
||||
data = {
|
||||
duration,
|
||||
progress,
|
||||
},
|
||||
} : {
|
||||
data: {
|
||||
duration: int?,
|
||||
progress: int?,
|
||||
}
|
||||
}) = raw_data
|
||||
let json.parse ({
|
||||
data
|
||||
} : {
|
||||
data: [(string * string?)] as json.object
|
||||
}) = raw_data
|
||||
m = data
|
||||
|
||||
# TODO - we remove cover art for now as it disturbs REKT, this needs fixing
|
||||
# m = metadata.cover.remove(m)
|
||||
|
||||
new_track = if list.assoc.mem("new_track", m) then bool_of_string(string_of(list.assoc("new_track", m))) else false end
|
||||
|
||||
# merge old metadata except for the ones we expect to change
|
||||
# old artist and title
|
||||
oldm = s.last_metadata() ?? []
|
||||
oldm = if list.assoc.mem("artist", oldm) then list.assoc.remove("artist", oldm) else oldm end
|
||||
oldm = if list.assoc.mem("title", oldm) then list.assoc.remove("title", oldm) else oldm end
|
||||
oldm = if list.assoc.mem("album", oldm) then list.assoc.remove("album", oldm) else oldm end
|
||||
oldm = if list.assoc.mem("publisher", oldm) then list.assoc.remove("publisher", oldm) else oldm end
|
||||
oldm = if list.assoc.mem("genre", oldm) then list.assoc.remove("genre", oldm) else oldm end
|
||||
oldm = if list.assoc.mem("date", oldm) then list.assoc.remove("date", oldm) else oldm end
|
||||
oldm = if list.assoc.mem("tracknumber", oldm) then list.assoc.remove("tracknumber", oldm) else oldm end
|
||||
oldm = if list.assoc.mem("comment", oldm) then list.assoc.remove("comment", oldm) else oldm end
|
||||
oldm = if list.assoc.mem("track", oldm) then list.assoc.remove("track", oldm) else oldm end
|
||||
oldm = if list.assoc.mem("year", oldm) then list.assoc.remove("year", oldm) else oldm end
|
||||
oldm = if list.assoc.mem("dj", oldm) then list.assoc.remove("dj", oldm) else oldm end
|
||||
oldm = if list.assoc.mem("next", oldm) then list.assoc.remove("next", oldm) else oldm end
|
||||
oldm = if list.assoc.mem("apic", oldm) then list.assoc.remove("apic", oldm) else oldm end
|
||||
oldm = if list.assoc.mem("metadata_block_picture", oldm) then list.assoc.remove("metadata_block_picture", oldm) else oldm end
|
||||
oldm = if list.assoc.mem("coverart", oldm) then list.assoc.remove("coverart", oldm) else oldm end
|
||||
oldm = if list.assoc.mem("cover_url", oldm) then list.assoc.remove("cover_url", oldm) else oldm end
|
||||
m = list.append(oldm ?? [], m)
|
||||
old_artist = if list.assoc.mem("artist", oldm) then oldm["artist"] else "" end
|
||||
old_title = if list.assoc.mem("title", oldm) then oldm["title"] else "" end
|
||||
new_artist = if list.assoc.mem("artist", m) then list.assoc("artist", m) ?? "" else "" end
|
||||
new_title = if list.assoc.mem("title", m) then list.assoc("title", m) ?? "" else "" end
|
||||
|
||||
# set metadata on stream
|
||||
s.insert_metadata(new_track=new_track, m)
|
||||
if old_artist != new_artist or old_title != new_title then
|
||||
# filter dynamic metadata
|
||||
m = if list.assoc.mem("progress", m) then list.assoc.remove("progress", m) else m end
|
||||
m = if list.assoc.mem("duration", m) then list.assoc.remove("duration", m) else m end
|
||||
|
||||
# TODO - we remove cover art for now as it disturbs REKT, this needs fixing
|
||||
# m = metadata.cover.remove(m)
|
||||
|
||||
new_track = if list.assoc.mem("new_track", m) then bool_of_string(string_of(list.assoc("new_track", m))) else false end
|
||||
|
||||
# merge old metadata except for the ones we expect to change
|
||||
oldm = if list.assoc.mem("artist", oldm) then list.assoc.remove("artist", oldm) else oldm end
|
||||
oldm = if list.assoc.mem("title", oldm) then list.assoc.remove("title", oldm) else oldm end
|
||||
oldm = if list.assoc.mem("album", oldm) then list.assoc.remove("album", oldm) else oldm end
|
||||
oldm = if list.assoc.mem("publisher", oldm) then list.assoc.remove("publisher", oldm) else oldm end
|
||||
oldm = if list.assoc.mem("genre", oldm) then list.assoc.remove("genre", oldm) else oldm end
|
||||
oldm = if list.assoc.mem("date", oldm) then list.assoc.remove("date", oldm) else oldm end
|
||||
oldm = if list.assoc.mem("tracknumber", oldm) then list.assoc.remove("tracknumber", oldm) else oldm end
|
||||
oldm = if list.assoc.mem("comment", oldm) then list.assoc.remove("comment", oldm) else oldm end
|
||||
oldm = if list.assoc.mem("track", oldm) then list.assoc.remove("track", oldm) else oldm end
|
||||
oldm = if list.assoc.mem("year", oldm) then list.assoc.remove("year", oldm) else oldm end
|
||||
oldm = if list.assoc.mem("dj", oldm) then list.assoc.remove("dj", oldm) else oldm end
|
||||
oldm = if list.assoc.mem("next", oldm) then list.assoc.remove("next", oldm) else oldm end
|
||||
oldm = if list.assoc.mem("apic", oldm) then list.assoc.remove("apic", oldm) else oldm end
|
||||
oldm = if list.assoc.mem("metadata_block_picture", oldm) then list.assoc.remove("metadata_block_picture", oldm) else oldm end
|
||||
oldm = if list.assoc.mem("coverart", oldm) then list.assoc.remove("coverart", oldm) else oldm end
|
||||
oldm = if list.assoc.mem("cover_url", oldm) then list.assoc.remove("cover_url", oldm) else oldm end
|
||||
m = list.append(oldm ?? [], m)
|
||||
|
||||
# set metadata on stream
|
||||
m = list.assoc.filter(fun (_, v) -> null.defined(v), m)
|
||||
m = list.map(fun (v) -> (fst(v), null.get(snd(v))), m)
|
||||
log.info("New metadata for #{id}: #{json.stringify(m)}")
|
||||
s.insert_metadata(new_track=new_track, m)
|
||||
else
|
||||
log.info("No new metadata for #{id}")
|
||||
end
|
||||
|
||||
# set new dynamic meta
|
||||
log.info("Updating dynamic meta for #{id}")
|
||||
dynamic_duration.set(duration)
|
||||
dynamic_progress.set(progress)
|
||||
|
||||
http.response(http_version=http_version, status_code=200, headers=[
|
||||
("allow","POST"),
|
||||
|
@ -125,7 +174,7 @@ def setup_harbor_metadata_api(~metadata_api_port=21338, s) =
|
|||
("access-control-allow-methods","GET,POST"),
|
||||
("access-control-allow-headers","Origin,X-Requested-With,Content-Type,Accept,Authorization,access-control-allow-headers,access-control-allow-origin"),
|
||||
("content-type","application/json"),
|
||||
], data=json.stringify(data))
|
||||
], data=raw_data)
|
||||
end
|
||||
|
||||
# Just in case we use a browser to send data to this (for example while emulating Tuna)
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"image"
|
||||
"image/jpeg"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
|
@ -16,7 +17,6 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"image/jpeg"
|
||||
_ "image/jpeg"
|
||||
_ "image/png"
|
||||
|
||||
|
@ -42,6 +42,8 @@ type liquidsoapMetadata struct {
|
|||
Title string `json:"title"`
|
||||
Publisher string `json:"publisher,omitempty"`
|
||||
Year string `json:"year,omitempty"`
|
||||
Duration uint64 `json:"duration,omitempty"`
|
||||
Progress uint64 `json:"progress,omitempty"`
|
||||
}
|
||||
|
||||
func (lm *liquidsoapMetadata) SetCover(r io.Reader, compressToJPEG bool) (err error) {
|
||||
|
@ -147,9 +149,12 @@ func main() {
|
|||
tunaData := new(tuna.TunaData)
|
||||
if err = json.NewDecoder(resp.Body).Decode(tunaData); err == nil {
|
||||
// skip empty or same metadata
|
||||
differentDataReceived := oldTunaData == nil ||
|
||||
differentSongReceived := oldTunaData == nil ||
|
||||
oldTunaData.Title != tunaData.Title ||
|
||||
len(oldTunaData.Artists) != len(tunaData.Artists)
|
||||
differentDataReceived := differentSongReceived ||
|
||||
oldTunaData.Progress != tunaData.Progress ||
|
||||
oldTunaData.Duration != tunaData.Duration
|
||||
if !differentDataReceived {
|
||||
for i, artist := range oldTunaData.Artists {
|
||||
differentDataReceived = differentDataReceived || artist != tunaData.Artists[i]
|
||||
|
@ -161,6 +166,8 @@ func main() {
|
|||
CoverURL: tunaData.CoverURL,
|
||||
Publisher: tunaData.Label,
|
||||
Title: tunaData.Title,
|
||||
Duration: tunaData.Duration,
|
||||
Progress: tunaData.Progress,
|
||||
}
|
||||
|
||||
if tunaData.Year > 0 {
|
||||
|
@ -168,28 +175,30 @@ func main() {
|
|||
}
|
||||
|
||||
// transfer cover to liquidsoap metadata
|
||||
if coverURL, err := url.Parse(tunaData.CoverURL); err == nil {
|
||||
if strings.EqualFold(coverURL.Scheme, "http") ||
|
||||
strings.EqualFold(coverURL.Scheme, "https") {
|
||||
log.Println("Downloading cover:", tunaData.CoverURL)
|
||||
resp, err := http.Get(tunaData.CoverURL)
|
||||
if err == nil {
|
||||
err = liquidsoapMetadata.SetCover(resp.Body, true)
|
||||
resp.Body.Close()
|
||||
if err != nil {
|
||||
log.Println("WARNING: Failed to transfer cover to liquidsoap metadata, skipping:", err.Error())
|
||||
if differentSongReceived {
|
||||
if coverURL, err := url.Parse(tunaData.CoverURL); err == nil {
|
||||
if strings.EqualFold(coverURL.Scheme, "http") ||
|
||||
strings.EqualFold(coverURL.Scheme, "https") {
|
||||
log.Println("Downloading cover:", tunaData.CoverURL)
|
||||
resp, err := http.Get(tunaData.CoverURL)
|
||||
if err == nil {
|
||||
err = liquidsoapMetadata.SetCover(resp.Body, true)
|
||||
resp.Body.Close()
|
||||
if err != nil {
|
||||
log.Println("WARNING: Failed to transfer cover to liquidsoap metadata, skipping:", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// remove reference to localhost/127.*.*.*
|
||||
localhost := coverURL.Host == "localhost" || strings.HasSuffix(coverURL.Host, ".localhost")
|
||||
if !localhost {
|
||||
if ip := net.ParseIP(coverURL.Host); ip != nil {
|
||||
localhost = ip[0] == 127
|
||||
// remove reference to localhost/127.*.*.*
|
||||
localhost := coverURL.Host == "localhost" || strings.HasSuffix(coverURL.Host, ".localhost")
|
||||
if !localhost {
|
||||
if ip := net.ParseIP(coverURL.Host); ip != nil {
|
||||
localhost = ip[0] == 127
|
||||
}
|
||||
}
|
||||
if localhost {
|
||||
liquidsoapMetadata.CoverURL = ""
|
||||
}
|
||||
}
|
||||
if localhost {
|
||||
liquidsoapMetadata.CoverURL = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue