Little improvements

This commit is contained in:
Přemysl Eric Janouch 2016-10-25 00:21:26 +02:00 committed by Přemysl Janouch
parent 92dbdedf0c
commit a50f35aac3
Signed by: p
GPG Key ID: A0420B94F92B9493
2 changed files with 28 additions and 29 deletions

View File

@ -1,5 +1,4 @@
Copyright (c) 2016, Přemysl Janouch <p.janouch@gmail.com> Copyright (c) 2016 - 2017, Přemysl Janouch <p.janouch@gmail.com>
All rights reserved.
Permission to use, copy, modify, and/or distribute this software for any Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above

View File

@ -26,11 +26,13 @@ type meta struct {
func getMeta(name string) (*meta, error) { func getMeta(name string) (*meta, error) {
const metaBaseURI = "http://polling.bbc.co.uk/radio/nhppolling/" const metaBaseURI = "http://polling.bbc.co.uk/radio/nhppolling/"
resp, err := http.Get(metaBaseURI + name) resp, err := http.Get(metaBaseURI + name)
if resp != nil {
defer resp.Body.Close()
}
if err != nil { if err != nil {
return nil, err return nil, err
} }
b, err := ioutil.ReadAll(resp.Body) b, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
if len(b) < 2 { if len(b) < 2 {
// There needs to be an enclosing () pair // There needs to be an enclosing () pair
return nil, errors.New("invalid metadata response") return nil, errors.New("invalid metadata response")
@ -38,19 +40,19 @@ func getMeta(name string) (*meta, error) {
// TODO: also retrieve richtracks/is_now_playing, see example file // TODO: also retrieve richtracks/is_now_playing, see example file
type broadcast struct { type broadcast struct {
Title string `json:"title"` // Title of the broadcast Title string // Title of the broadcast
Percentage int `json:"percentage"` // How far we're in Percentage int // How far we're in
} }
var v struct { var v struct {
Packages struct { Packages struct {
OnAir struct { OnAir struct {
Broadcasts []broadcast `json:"broadcasts"` Broadcasts []broadcast
BroadcastNowIndex uint `json:"broadcastNowIndex"` BroadcastNowIndex uint
} `json:"on-air"` } `json:"on-air"`
} `json:"packages"` }
Timeouts struct { Timeouts struct {
PollingTimeout uint `json:"polling_timeout"` PollingTimeout uint `json:"polling_timeout"`
} `json:"timeouts"` }
} }
err = json.Unmarshal(b[1:len(b)-1], &v) err = json.Unmarshal(b[1:len(b)-1], &v)
if err != nil { if err != nil {
@ -69,11 +71,13 @@ func getMeta(name string) (*meta, error) {
// Resolve an M3U8 playlist to the first link that seems to be playable // Resolve an M3U8 playlist to the first link that seems to be playable
func resolveM3U8(target string) (out []string, err error) { func resolveM3U8(target string) (out []string, err error) {
resp, err := http.Get(target) resp, err := http.Get(target)
if resp != nil {
defer resp.Body.Close()
}
if err != nil { if err != nil {
return nil, err return nil, err
} }
b, err := ioutil.ReadAll(resp.Body) b, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
if !utf8.Valid(b) { if !utf8.Valid(b) {
return nil, errors.New("invalid UTF-8") return nil, errors.New("invalid UTF-8")
} }
@ -97,6 +101,8 @@ func resolveM3U8(target string) (out []string, err error) {
} }
func metaProc(ctx context.Context, name string, out chan<- string) { func metaProc(ctx context.Context, name string, out chan<- string) {
defer close(out)
var current, last string var current, last string
var interval time.Duration var interval time.Duration
for { for {
@ -108,10 +114,14 @@ func metaProc(ctx context.Context, name string, out chan<- string) {
current = meta.title current = meta.title
interval = time.Duration(meta.timeout) interval = time.Duration(meta.timeout)
} }
// TODO: select on the send? Can't close it in the main proc.
// Also see https://blog.golang.org/pipelines
if current != last { if current != last {
out <- current // TODO: see https://blog.golang.org/pipelines
// find out if we can do this better
select {
case out <- current:
case <-ctx.Done():
return
}
last = current last = current
} }
@ -211,29 +221,19 @@ func proxy(w http.ResponseWriter, req *http.Request) {
}() }()
var queuedMeta []byte var queuedMeta []byte
makeMetaChunk := func() []byte {
meta := queuedMeta
queuedMeta = nil
for len(meta)%16 != 0 {
meta = append(meta, 0)
}
if len(meta) > 16*255 {
meta = meta[:16*255]
}
chunk := []byte{byte(len(meta) / 16)}
return append(chunk, meta...)
}
for { for {
select { select {
case title := <-metaChan: case title := <-metaChan:
queuedMeta = []byte(fmt.Sprintf("StreamTitle='%s'", title)) queuedMeta = []byte(fmt.Sprintf("StreamTitle='%s'", title))
case chunk, connected := <-chunkChan: case chunk, ok := <-chunkChan:
if !connected { if !ok {
return return
} }
if wantMeta { if wantMeta {
chunk = append(chunk, makeMetaChunk()...) var meta [1 + 16*255]byte
meta[0] = byte((copy(meta[1:], queuedMeta) + 15) / 16)
chunk = append(chunk, meta[:1+int(meta[0])*16]...)
queuedMeta = nil
} }
if _, err := bufrw.Write(chunk); err != nil { if _, err := bufrw.Write(chunk); err != nil {
return return