From 2cd16c553309990f63484181137d35c47c6de5ea Mon Sep 17 00:00:00 2001 From: ale <ale@incal.net> Date: Mon, 11 Nov 2013 01:02:43 +0000 Subject: [PATCH] add a XSL template to render icecast status in a parsable format, with code to read it --- debian/radioai.xsl | 19 ++++++++++++++ debian/rules | 4 +++ node/icecast.go | 64 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+) create mode 100644 debian/radioai.xsl diff --git a/debian/radioai.xsl b/debian/radioai.xsl new file mode 100644 index 00000000..9e547458 --- /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 56d20c0d..d0541f82 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 843024fe..4a1c28ae 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) +} -- GitLab