diff --git a/debian/radioai.xsl b/debian/radioai.xsl new file mode 100644 index 0000000000000000000000000000000000000000..9e5474588991d60c62694d0b22474082b6c899a4 --- /dev/null +++ b/debian/radioai.xsl @@ -0,0 +1,19 @@ +<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" version = "1.0" > +<xsl:template match = "/icestats" > + +<config> + +<xsl:for-each select="source"> + <mount> + <title><xsl:value-of select="@mount" /></title> + <name><xsl:value-of select="name" /></name> + <listeners><xsl:value-of select="listeners" /></listeners> + <bitrate><xsl:value-of select="bitrate" /></bitrate> + <url><xsl:value-of select="url" /></url> + </mount> +</xsl:for-each> + +</config> + +</xsl:template> +</xsl:stylesheet> diff --git a/debian/rules b/debian/rules index 56d20c0dafe794cbfe8cc90a3694c397d09e7c03..d0541f8278ece4116c1ab0774f8c60bc7409c7fa 100755 --- a/debian/rules +++ b/debian/rules @@ -63,3 +63,7 @@ override_dh_install: chmod 0755 $(SVCDIR)/$$f/log/run ; \ done) + # Icecast2 status XSL template. + install -d -m 755 -o root -g root $(DESTDIR)/usr/share/icecast2/web + install -m 644 -o root -g root $(CURDIR)/debian/radioai.xsl \ + $(DESTDIR)/usr/share/icecast2/web/radioai.xsl diff --git a/node/icecast.go b/node/icecast.go index 843024feba4487bc01e3abb6b8d746aceacd1a57..4a1c28ae2b0c8a6d521f308c95baab706769fd98 100644 --- a/node/icecast.go +++ b/node/icecast.go @@ -1,15 +1,38 @@ package node import ( + "encoding/xml" + "io" + "net/http" "os" "os/exec" + "time" ) +var ( + statusPageUrl = "http://localhost:8000/radioai.xsl" +) + +type icecastStatusMount struct { + Title string `xml:"title"` + Name string `xml:"name"` + Url string `xml:"url"` + Listeners int `xml:"listeners"` + BitRate int `xml:"bitrate"` +} + +type IcecastStatus struct { + XMLName xml.Name `xml:"config"` + Mounts []icecastStatusMount +} + type IcecastController struct { PublicIp string ConfigFile string InitScript string config *icecastConfig + status *IcecastStatus + stop chan bool } func NewIcecastController(publicIp string) *IcecastController { @@ -18,6 +41,7 @@ func NewIcecastController(publicIp string) *IcecastController { ConfigFile: "/etc/icecast2/icecast.conf", InitScript: "/etc/init.d/icecast2", config: newIcecastConfig(publicIp), + stop: make(chan bool, 1), } } @@ -44,3 +68,43 @@ func (ic *IcecastController) Update(conf *ClusterConfig, isMaster bool, masterAd return ic.reload() } + +func (ic *IcecastController) statusUpdater() { + t := time.NewTicker(3 * time.Second) + for { + select { + case <-t.C: + if status, err := ic.fetchStatus(); err == nil { + ic.status = status + } + case <-ic.stop: + return + } + } +} + +func (ic *IcecastController) fetchStatus() (*IcecastStatus, error) { + resp, err := http.Get(statusPageUrl) + if err != nil { + return nil, err + } + defer resp.Body.Close() + return ic.parseStatusPage(resp.Body) +} + +func (ic *IcecastController) parseStatusPage(input io.Reader) (*IcecastStatus, error) { + var status IcecastStatus + if err := xml.NewDecoder(input).Decode(&status); err != nil { + return nil, err + } + + return &status, nil +} + +func (ic *IcecastController) Run() { + go ic.statusUpdater() +} + +func (ic *IcecastController) Stop() { + close(ic.stop) +}