initial push

This commit is contained in:
Sean Clarke 2021-10-06 00:15:32 -04:00
commit 654f3b26c2
20 changed files with 1601 additions and 0 deletions

19
Dockerfile Normal file
View File

@ -0,0 +1,19 @@
FROM ubuntu:latest
LABEL maintainer "me@seanland.ca"
RUN apt-get -y update; \
apt-get -y upgrade; \
apt-get install -y ices2 icecast2 sudo; \
apt-get clean;
COPY ./ices.xml /ices.xml
COPY ./start-icecast.sh /start-icecast.sh
COPY ./start-ices.sh /start-ices.sh
ADD ./etc /etc
EXPOSE 8000
VOLUME ["/config"]
CMD ["/start-icecast.sh"]

32
README.md Normal file
View File

@ -0,0 +1,32 @@
# One Container Radio
Using Ices2 and Icecast, the goal is to build a simple, single container deployment. One should be able to fill few parameters and direct the container to a music folder or share giving them a basic self hosted random music stream. (Reword)
__ Note: Usernames / Passwords are defaulted currently. Change them if you decide to use this...
__Warning: Work in progress, Docker experimenting. Please improve if you would like! Thanks :) __
## Usage ##
- Set the port
- Set the external share (only finds .oggs right now)
- Execute the command
- Navigate to 127.0.0.1:8080
- Enjoy your music
(Below is based on a local build)
```bash
docker run -p 8080:8000 -v d:/music:/media -t docker-one-container-radio:latest
```
## To Do ##
- [] Update parameters for username and passwords
- [] Add Customizations
- [] Update Readme
- [] Add Parameters
- [] Build Docker Compose (other forms to deploy)
- [] Modify exposed volumes for log access / addition information
## Influenced By: ##
The below repositories helped shape this repo; please check them out.
- https://github.com/moul/docker-icecast
- https://github.com/infiniteproject/icecast

View File

@ -0,0 +1,95 @@
<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" version = "1.0" >
<xsl:output omit-xml-declaration="no" method="xml" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" indent="yes" encoding="UTF-8" />
<xsl:template match = "/icestats" >
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Icecast Streaming Media Server</title>
<link rel="stylesheet" type="text/css" href="/style.css" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
</head>
<body>
<h1>Icecast2 Admin</h1>
<!--index header menu -->
<div id="menu">
<ul>
<li><a href="stats.xsl">Admin Home</a></li>
<li><a href="listmounts.xsl">Mountpoint List</a></li>
<li><a href="/status.xsl">Public Home</a></li>
</ul>
</div>
<!--end index header menu -->
<h2>Listener Stats</h2>
<xsl:for-each select="source">
<div class="roundbox">
<div class="mounthead">
<h3>Mountpoint <xsl:value-of select="@mount" /></h3>
<div class="right">
<xsl:choose>
<xsl:when test="authenticator">
<a class="auth" href="/auth.xsl">Login</a>
</xsl:when>
<xsl:otherwise>
<ul class="mountlist">
<li><a class="play" href="{@mount}.m3u">M3U</a></li>
<li><a class="play" href="{@mount}.xspf">XSPF</a></li>
<li><a class="play" href="{@mount}.vclt">VCLT</a></li>
</ul>
</xsl:otherwise>
</xsl:choose>
</div>
</div>
<div class="mountcont">
<ul class="nav">
<li class="active"><a href="listclients.xsl?mount={@mount}">List Clients</a></li>
<li><a href="moveclients.xsl?mount={@mount}">Move Listeners</a></li>
<li><a href="updatemetadata.xsl?mount={@mount}">Update Metadata</a></li>
<xsl:if test="authenticator">
<li><a href="manageauth.xsl?mount={@mount}">Manage Authentication</a></li>
</xsl:if>
<li><a href="killsource.xsl?mount={@mount}">Kill Source</a></li>
</ul>
<xsl:choose>
<xsl:when test="listener">
<div class="scrolltable">
<table class="colortable">
<thead>
<tr>
<td>IP</td>
<td>Sec. connected</td>
<td>User Agent</td>
<td>Action</td>
</tr>
</thead>
<tbody>
<xsl:variable name = "themount"><xsl:value-of select="@mount" /></xsl:variable>
<xsl:for-each select="listener">
<tr>
<td>
<xsl:value-of select="IP" />
<xsl:if test="username">
(<xsl:value-of select="username" />)
</xsl:if>
</td>
<td><xsl:value-of select="Connected" /></td>
<td><xsl:value-of select="UserAgent" /></td>
<td><a href="killclient.xsl?mount={$themount}&amp;id={ID}">Kick</a></td>
</tr>
</xsl:for-each>
</tbody>
</table>
</div>
</xsl:when>
<xsl:otherwise>
<p>No listeners connected</p>
</xsl:otherwise>
</xsl:choose>
</div>
</div>
</xsl:for-each>
<div id="footer">
Support icecast development at <a href="https://www.icecast.org/">www.icecast.org</a>
</div>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

View File

@ -0,0 +1,61 @@
<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" version = "1.0" >
<xsl:output omit-xml-declaration="no" method="xml" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" indent="yes" encoding="UTF-8" />
<xsl:template match = "/icestats" >
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Icecast Streaming Media Server</title>
<link rel="stylesheet" type="text/css" href="/style.css" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
</head>
<body>
<h1>Icecast2 Admin</h1>
<!--index header menu -->
<div id="menu">
<ul>
<li><a href="stats.xsl">Admin Home</a></li>
<li><a href="listmounts.xsl">Mountpoint List</a></li>
<li><a href="/status.xsl">Public Home</a></li>
</ul>
</div>
<!--end index header menu -->
<h2>Active Mountpoints</h2>
<xsl:for-each select="source">
<div class="roundbox">
<div class="mounthead">
<h3 class="mount">Mountpoint <xsl:value-of select="@mount" /></h3>
<div class="right">
<xsl:choose>
<xsl:when test="authenticator">
<a class="auth" href="/auth.xsl">Login</a>
</xsl:when>
<xsl:otherwise>
<ul class="mountlist">
<li><a class="play" href="{@mount}.m3u">M3U</a></li>
<li><a class="play" href="{@mount}.xspf">XSPF</a></li>
<li><a class="play" href="{@mount}.vclt">VCLT</a></li>
</ul>
</xsl:otherwise>
</xsl:choose>
</div>
</div>
<div class="mountcont">
<ul class="nav">
<li><a href="listclients.xsl?mount={@mount}">List Clients</a></li>
<li><a href="moveclients.xsl?mount={@mount}">Move Listeners</a></li>
<li><a href="updatemetadata.xsl?mount={@mount}">Update Metadata</a></li>
<xsl:if test="authenticator">
<li><a href="manageauth.xsl?mount={@mount}">Manage Authentication</a></li>
</xsl:if>
<li><a href="killsource.xsl?mount={@mount}">Kill Source</a></li>
</ul>
<p><xsl:value-of select="listeners" /> Listener(s)</p>
</div>
</div>
</xsl:for-each>
<div id="footer">
Support icecast development at <a href="https://www.icecast.org/">www.icecast.org</a>
</div>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

View File

@ -0,0 +1,91 @@
<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" version = "1.0" >
<xsl:output omit-xml-declaration="no" method="xml" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" indent="yes" encoding="UTF-8" />
<xsl:template match = "/icestats" >
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Icecast Streaming Media Server</title>
<link rel="stylesheet" type="text/css" href="/style.css" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
</head>
<body>
<h1>Icecast2 Admin</h1>
<!--index header menu -->
<div id="menu">
<ul>
<li><a href="stats.xsl">Admin Home</a></li>
<li><a href="listmounts.xsl">Mountpoint List</a></li>
<li><a href="/status.xsl">Public Home</a></li>
</ul>
</div>
<!--end index header menu -->
<h2>Manage Authentication</h2>
<xsl:if test="iceresponse">
<div class="roundbox">
<h3>Message</h3>
<xsl:for-each select="iceresponse">
<xsl:value-of select="message" /><br />
</xsl:for-each>
</div>
</xsl:if>
<xsl:for-each select="source">
<div class="roundbox">
<h3>Mountpoint <xsl:value-of select="@mount" />
<xsl:if test="server_name">
<small><xsl:value-of select="server_name" /></small>
</xsl:if>
</h3>
<ul class="nav">
<li><a href="listclients.xsl?mount={@mount}">List Clients</a></li>
<li><a href="moveclients.xsl?mount={@mount}">Move Listeners</a></li>
<li><a href="updatemetadata.xsl?mount={@mount}">Update Metadata</a></li>
<li><a href="manageauth.xsl?mount={@mount}">Manage Authentication</a></li>
<li><a href="killsource.xsl?mount={@mount}">Kill Source</a></li>
</ul>
<xsl:if test="User">
<table class="colortable">
<thead>
<tr>
<td>User</td>
<td>Action</td>
</tr>
</thead>
<tbody>
<xsl:variable name="themount"><xsl:value-of select="@mount" /></xsl:variable>
<xsl:for-each select="User">
<tr>
<td>
<xsl:value-of select="username" />
</td>
<td>
<a href="manageauth.xsl?mount={$themount}&amp;username={username}&amp;action=delete">Delete</a>
</td>
</tr>
</xsl:for-each>
</tbody>
</table>
</xsl:if>
<form class="alignedform" method="get" action="/admin/manageauth.xsl">
<fieldset>
<legend>Add new user</legend>
<p>
<label for="username">Username:</label>
<input type="text" id="username" name="username"/>
</p>
<p>
<label for="password">Password:</label>
<input type="password" id="password" name="password"/>
</p>
<input type="hidden" name="mount" value="{@mount}"/>
<input type="hidden" name="action" value="add"/>
<input type="Submit" value="Add"/>
</fieldset>
</form>
</div>
</xsl:for-each>
<div id="footer">
Support icecast development at <a href="https://www.icecast.org/">www.icecast.org</a>
</div>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

View File

@ -0,0 +1,39 @@
<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" version = "1.0" >
<xsl:output omit-xml-declaration="no" method="xml" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" indent="yes" encoding="UTF-8" />
<xsl:template match = "/icestats" >
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Icecast Streaming Media Server</title>
<link rel="stylesheet" type="text/css" href="/style.css" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
</head>
<body>
<h1>Icecast2 Admin</h1>
<!--index header menu -->
<div id="menu">
<ul>
<li><a href="stats.xsl">Admin Home</a></li>
<li><a href="listmounts.xsl">Mountpoint List</a></li>
<li><a href="/status.xsl">Public Home</a></li>
</ul>
</div>
<!--end index header menu -->
<xsl:variable name = "currentmount" ><xsl:value-of select="current_source" /></xsl:variable>
<h2>Moving listeners from <xsl:value-of select="current_source" /></h2>
<div class="roundbox">
<h3>Move to which mountpoint?</h3>
<xsl:for-each select="source">
<p>
Move from <code><xsl:copy-of select="$currentmount" /></code> to <code><xsl:value-of select="@mount" /></code><br />
<xsl:value-of select="listeners" /> listeners<br />
<a href="moveclients.xsl?mount={$currentmount}&amp;destination={@mount}">Move clients</a>
</p>
</xsl:for-each>
</div>
<div id="footer">
Support icecast development at <a href="https://www.icecast.org/">www.icecast.org</a>
</div>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

View File

@ -0,0 +1,35 @@
<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" version = "1.0" >
<xsl:output omit-xml-declaration="no" method="xml" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" indent="yes" encoding="UTF-8" />
<xsl:template match = "/iceresponse" >
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Icecast Streaming Media Server</title>
<link rel="stylesheet" type="text/css" href="/style.css" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
</head>
<body>
<h1>Icecast2 Admin</h1>
<!--index header menu -->
<div id="menu">
<ul>
<li><a href="stats.xsl">Admin Home</a></li>
<li><a href="listmounts.xsl">Mountpoint List</a></li>
<li><a href="/status.xsl">Public Home</a></li>
</ul>
</div>
<!--end index header menu -->
<h2>Icecast Server Response</h2>
<xsl:for-each select="/iceresponse">
<div class="roundbox">
<h3>Response</h3>
<p>Message: <xsl:value-of select="message" /></p>
<p>Return Code: <xsl:value-of select="return" /></p>
</div>
</xsl:for-each>
<div id="footer">
Support icecast development at <a href="https://www.icecast.org/">www.icecast.org</a>
</div>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

View File

@ -0,0 +1,100 @@
<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" version = "1.0" >
<xsl:output omit-xml-declaration="no" method="xml" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" indent="yes" encoding="UTF-8" />
<xsl:template match = "/icestats" >
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Icecast Streaming Media Server</title>
<link rel="stylesheet" type="text/css" href="/style.css" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
</head>
<body>
<h1>Icecast2 Admin</h1>
<!--index header menu -->
<div id="menu">
<ul>
<li><a href="stats.xsl">Admin Home</a></li>
<li><a href="listmounts.xsl">Mountpoint List</a></li>
<li><a href="/status.xsl">Public Home</a></li>
</ul>
</div>
<!--end index header menu -->
<!--global server stats-->
<div class="roundbox">
<h3>Global Server Stats</h3>
<table class="yellowkeys">
<tbody>
<xsl:for-each select="/icestats">
<xsl:for-each select="*">
<xsl:if test = "name()!='source'">
<tr>
<td><xsl:value-of select="name()" /></td>
<td><xsl:value-of select="." /></td>
</tr>
</xsl:if>
</xsl:for-each>
</xsl:for-each>
</tbody>
</table>
</div>
<!--end global server stats-->
<!--mount point stats-->
<xsl:for-each select="source">
<xsl:if test = "listeners!=''">
<div class="roundbox">
<div class="mounthead">
<h3 class="mount">Mountpoint <xsl:value-of select="@mount" /></h3>
<div class="right">
<xsl:choose>
<xsl:when test="authenticator">
<a class="auth" href="/auth.xsl">Login</a>
</xsl:when>
<xsl:otherwise>
<ul class="mountlist">
<li><a class="play" href="{@mount}.m3u">M3U</a></li>
<li><a class="play" href="{@mount}.xspf">XSPF</a></li>
<li><a class="play" href="{@mount}.vclt">VCLT</a></li>
</ul>
</xsl:otherwise>
</xsl:choose>
</div>
</div>
<div class="mountcont">
<ul class="nav">
<li><a href="listclients.xsl?mount={@mount}">List Clients</a></li>
<li><a href="moveclients.xsl?mount={@mount}">Move Listeners</a></li>
<li><a href="updatemetadata.xsl?mount={@mount}">Update Metadata</a></li>
<xsl:if test="authenticator">
<li><a href="manageauth.xsl?mount={@mount}">Manage Authentication</a></li>
</xsl:if>
<li><a href="killsource.xsl?mount={@mount}">Kill Source</a></li>
</ul>
<xsl:if test="server_type and ((server_type = 'application/ogg') or (server_type = 'audio/ogg'))">
<div class="audioplayer">
<audio controls="controls" preload="none">
<source src="{@mount}" type="{server_type}" />
</audio>
</div>
</xsl:if>
<table class="yellowkeys">
<tbody>
<xsl:for-each select="*">
<tr>
<td><xsl:value-of select="name()" /></td>
<td><xsl:value-of select="." /></td>
</tr>
</xsl:for-each>
</tbody>
</table>
</div>
</div>
</xsl:if>
</xsl:for-each>
<!--end mount point stats-->
<div id="footer">
Support icecast development at <a href="https://www.icecast.org/">www.icecast.org</a>
</div>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

View File

@ -0,0 +1,49 @@
<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" version = "1.0">
<xsl:output omit-xml-declaration="no" method="xml" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" indent="yes" encoding="UTF-8" />
<xsl:template match = "/icestats">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Icecast Streaming Media Server</title>
<link rel="stylesheet" type="text/css" href="/style.css" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
</head>
<body>
<h1>Icecast2 Admin</h1>
<!--index header menu -->
<div id="menu">
<ul>
<li><a href="stats.xsl">Admin Home</a></li>
<li><a href="listmounts.xsl">Mountpoint List</a></li>
<li><a href="/status.xsl">Public Home</a></li>
</ul>
</div>
<!--end index header menu -->
<h2>Update Metadata</h2>
<xsl:for-each select="source">
<div class="roundbox">
<h3>Mountpoint <xsl:value-of select="@mount" />
<xsl:if test="server_name">
<small><xsl:value-of select="server_name" /></small>
</xsl:if>
</h3>
<form class="alignedform" method="get" action="/admin/metadata.xsl">
<p>
<label for="song">Metadata:</label>
<input type="text" id="song" name="song"/>
</p>
<p>
<input type="submit" value="Update"/>
<input type="hidden" name="mount" value="{@mount}"/>
<input type="hidden" name="mode" value="updinfo"/>
<input type="hidden" name="charset" value="UTF-8"/>
</p>
</form>
</div>
</xsl:for-each>
<div id="footer">
Support icecast development at <a href="https://www.icecast.org/">www.icecast.org</a>
</div>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

View File

@ -0,0 +1,54 @@
<!--
VCLT xslt stylesheet for Icecast 2.3.2 and above
based on XSPF xslt stylesheet.
Copyright (C) 2007 Thomas B. Ruecker, <thomas@ruecker.fi>
Copyright (C) 2011 Philipp Schafft, <lion@lion.leolix.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the
Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
-->
<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" version = "1.0" >
<xsl:output omit-xml-declaration="yes" media-type="audio/x-vclt"
method="text" indent="no" encoding="UTF-8" />
<xsl:template match = "/icestats" >
<xsl:for-each select="source">STREAMURL=<xsl:value-of select="listenurl" />
<xsl:if test="artist"><xsl:text>
</xsl:text>ARTIST=<xsl:value-of select="artist" /></xsl:if>
<xsl:if test="title"><xsl:text>
</xsl:text>TITLE=<xsl:value-of select="title" /></xsl:if>
<xsl:if test="server_name"><xsl:text>
</xsl:text>SERVER_NAME=<xsl:value-of select="server_name" /></xsl:if>
<xsl:if test="server_description"><xsl:text>
</xsl:text>DESCRIPTION=<xsl:value-of select="server_description" /></xsl:if>
SIGNALINFO=<xsl:choose>
<xsl:when test="server_type = 'application/ogg'">
<xsl:choose>
<xsl:when test="subtype = 'Vorbis'">codec:ogg_vorbis</xsl:when>
<!-- More codecs should be added here, however I don't know how to find out about the codec.
At the moment we just guess that application/ogg is a Ogg bitstream with some undefined
codec. Everything else is undefined.
-->
<xsl:otherwise>codec:ogg_general</xsl:otherwise>
</xsl:choose>
</xsl:when>
</xsl:choose><xsl:text>
</xsl:text>
<xsl:if test="genre">GENRE=<xsl:value-of select="genre" /></xsl:if>
==
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

View File

@ -0,0 +1,73 @@
<!--
XSPF xslt stylesheet for Icecast and above
Copyright (C) 2007 Thomas B. Ruecker, <thomas@ruecker.fi>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the
Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
-->
<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" version = "1.0" >
<xsl:output omit-xml-declaration="no" media-type="application/xspf+xml"
method="xml" indent="yes" encoding="UTF-8" />
<xsl:template match = "/icestats" >
<playlist version="1" xmlns="http://xspf.org/ns/0/">
<title><xsl:value-of select="server" /></title>
<creator><xsl:value-of select="server" /></creator>
<trackList >
<!-- end of "header" -->
<xsl:for-each select="source">
<track>
<location><xsl:value-of select="listenurl" /></location>
<xsl:if test="artist"><creator><xsl:value-of select="artist" /></creator></xsl:if>
<title><xsl:value-of select="title" /></title>
<!-- The <xsl:text>\n</xsl:text> elements in the following part are used
to enforce linebreaks this format seems to be expected by clients -->
<annotation>
<xsl:if test="server_name">Stream Title: <xsl:value-of select="server_name" /><xsl:text>
</xsl:text></xsl:if>
<xsl:if test="server_description">Stream Description: <xsl:value-of select="server_description" /></xsl:if>
Content Type:<xsl:value-of select="server_type" /><xsl:text>
</xsl:text>
<xsl:if test="bitrate">Bitrate: <xsl:value-of select="bitrate" /><xsl:text>
</xsl:text></xsl:if>
<xsl:if test="quality">Quality: <xsl:value-of select="quality" /><xsl:text>
</xsl:text></xsl:if>
<xsl:if test="video_quality">Video Quality: <xsl:value-of select="video_quality" /><xsl:text>
</xsl:text></xsl:if>
<xsl:if test="frame_size">Framesize: <xsl:value-of select="frame_size" /><xsl:text>
</xsl:text></xsl:if>
<xsl:if test="frame_rate">Framerate: <xsl:value-of select="frame_rate" /><xsl:text>
</xsl:text></xsl:if>
<xsl:if test="listeners">Current Listeners: <xsl:value-of select="listeners" /><xsl:text>
</xsl:text></xsl:if>
<xsl:if test="listener_peak">Peak Listeners: <xsl:value-of select="listener_peak" /><xsl:text>
</xsl:text></xsl:if>
<xsl:if test="genre">Stream Genre: <xsl:value-of select="genre" /></xsl:if>
</annotation>
<xsl:if test="server_url"><info><xsl:value-of select="server_url" /></info></xsl:if>
</track>
</xsl:for-each>
</trackList>
</playlist>
</xsl:template>
</xsl:stylesheet>

244
etc/icecast2/icecast.xml Normal file
View File

@ -0,0 +1,244 @@
<icecast>
<!-- location and admin are two arbitrary strings that are e.g. visible
on the server info page of the icecast web interface
(server_version.xsl). -->
<location>Earth</location>
<admin>your@email.com</admin>
<!-- IMPORTANT!
Especially for inexperienced users:
Start out by ONLY changing all passwords and restarting Icecast.
For detailed setup instructions please refer to the documentation.
It's also available here: http://icecast.org/docs/
-->
<limits>
<clients>100</clients>
<sources>2</sources>
<queue-size>524288</queue-size>
<client-timeout>30</client-timeout>
<header-timeout>15</header-timeout>
<source-timeout>10</source-timeout>
<!-- If enabled, this will provide a burst of data when a client
first connects, thereby significantly reducing the startup
time for listeners that do substantial buffering. However,
it also significantly increases latency between the source
client and listening client. For low-latency setups, you
might want to disable this. -->
<burst-on-connect>1</burst-on-connect>
<!-- same as burst-on-connect, but this allows for being more
specific on how much to burst. Most people won't need to
change from the default 64k. Applies to all mountpoints -->
<burst-size>65535</burst-size>
</limits>
<authentication>
<!-- Sources log in with username 'source' -->
<source-password>password</source-password>
<!-- Relays log in with username 'relay' -->
<relay-password>password</relay-password>
<!-- Admin logs in with the username given below -->
<admin-user>admin</admin-user>
<admin-password>password</admin-password>
</authentication>
<!-- set the mountpoint for a shoutcast source to use, the default if not
specified is /stream but you can change it here if an alternative is
wanted or an extension is required
<shoutcast-mount>/live.nsv</shoutcast-mount>
-->
<!-- Uncomment this if you want directory listings -->
<!--
<directory>
<yp-url-timeout>15</yp-url-timeout>
<yp-url>http://dir.xiph.org/cgi-bin/yp-cgi</yp-url>
</directory>
-->
<!-- This is the hostname other people will use to connect to your server.
It affects mainly the urls generated by Icecast for playlists and yp
listings. You MUST configure it properly for YP listings to work!
-->
<hostname>localhost</hostname>
<!-- You may have multiple <listen-socket> elements -->
<listen-socket>
<port>8000</port>
<!-- <bind-address>127.0.0.1</bind-address> -->
<!-- <shoutcast-mount>/stream</shoutcast-mount> -->
</listen-socket>
<!--
<listen-socket>
<port>8080</port>
</listen-socket>
-->
<!--
<listen-socket>
<port>8443</port>
<ssl>1</ssl>
</listen-socket>
-->
<!-- Global header settings
Headers defined here will be returned for every HTTP request to Icecast.
The ACAO header makes Icecast public content/API by default
This will make streams easier embeddable (some HTML5 functionality needs it).
Also it allows direct access to e.g. /status-json.xsl from other sites.
If you don't want this, comment out the following line or read up on CORS.
-->
<http-headers>
<header name="Access-Control-Allow-Origin" value="*" />
</http-headers>
<!-- Relaying
You don't need this if you only have one server.
Please refer to the documentation for a detailed explanation.
-->
<!--<master-server>127.0.0.1</master-server>-->
<!--<master-server-port>8001</master-server-port>-->
<!--<master-update-interval>120</master-update-interval>-->
<!--<master-password>hackme</master-password>-->
<!-- setting this makes all relays on-demand unless overridden, this is
useful for master relays which do not have <relay> definitions here.
The default is 0 -->
<!--<relays-on-demand>1</relays-on-demand>-->
<!--
<relay>
<server>127.0.0.1</server>
<port>8080</port>
<mount>/example.ogg</mount>
<local-mount>/different.ogg</local-mount>
<on-demand>0</on-demand>
<relay-shoutcast-metadata>0</relay-shoutcast-metadata>
</relay>
-->
<!-- Mountpoints
Only define <mount> sections if you want to use advanced options,
like alternative usernames or passwords
-->
<!-- Default settings for all mounts that don't have a specific <mount type="normal">.
-->
<!--
<mount type="default">
<public>0</public>
<intro>/server-wide-intro.ogg</intro>
<max-listener-duration>3600</max-listener-duration>
<authentication type="url">
<option name="mount_add" value="http://auth.example.org/stream_start.php"/>
</authentication>
<http-headers>
<header name="foo" value="bar" />
</http-headers>
</mount>
-->
<!-- Normal mounts -->
<!--
<mount type="normal">
<mount-name>/example-complex.ogg</mount-name>
<username>othersource</username>
<password>hackmemore</password>
<max-listeners>1</max-listeners>
<dump-file>/tmp/dump-example1.ogg</dump-file>
<burst-size>65536</burst-size>
<fallback-mount>/example2.ogg</fallback-mount>
<fallback-override>1</fallback-override>
<fallback-when-full>1</fallback-when-full>
<intro>/example_intro.ogg</intro>
<hidden>1</hidden>
<public>1</public>
<authentication type="htpasswd">
<option name="filename" value="myauth"/>
<option name="allow_duplicate_users" value="0"/>
</authentication>
<http-headers>
<header name="Access-Control-Allow-Origin" value="http://webplayer.example.org" />
<header name="baz" value="quux" />
</http-headers>
<on-connect>/home/icecast/bin/stream-start</on-connect>
<on-disconnect>/home/icecast/bin/stream-stop</on-disconnect>
</mount>
-->
<!--
<mount type="normal">
<mount-name>/auth_example.ogg</mount-name>
<authentication type="url">
<option name="mount_add" value="http://myauthserver.net/notify_mount.php"/>
<option name="mount_remove" value="http://myauthserver.net/notify_mount.php"/>
<option name="listener_add" value="http://myauthserver.net/notify_listener.php"/>
<option name="listener_remove" value="http://myauthserver.net/notify_listener.php"/>
<option name="headers" value="x-pragma,x-token"/>
<option name="header_prefix" value="ClientHeader."/>
</authentication>
</mount>
-->
<fileserve>1</fileserve>
<paths>
<!-- basedir is only used if chroot is enabled -->
<basedir>/usr/share/icecast2</basedir>
<!-- Note that if <chroot> is turned on below, these paths must both
be relative to the new root, not the original root -->
<logdir>/var/log/icecast2</logdir>
<webroot>/usr/share/icecast2/web</webroot>
<adminroot>/usr/share/icecast2/admin</adminroot>
<!-- <pidfile>/usr/share/icecast2/icecast.pid</pidfile> -->
<!-- Aliases: treat requests for 'source' path as being for 'dest' path
May be made specific to a port or bound address using the "port"
and "bind-address" attributes.
-->
<!--
<alias source="/foo" destination="/bar"/>
-->
<!-- Aliases: can also be used for simple redirections as well,
this example will redirect all requests for http://server:port/ to
the status page
-->
<alias source="/" destination="/status.xsl"/>
<!-- The certificate file needs to contain both public and private part.
Both should be PEM encoded.
<ssl-certificate>/usr/share/icecast2/icecast.pem</ssl-certificate>
-->
</paths>
<logging>
<accesslog>access.log</accesslog>
<errorlog>error.log</errorlog>
<!-- <playlistlog>playlist.log</playlistlog> -->
<loglevel>3</loglevel> <!-- 4 Debug, 3 Info, 2 Warn, 1 Error -->
<logsize>10000</logsize> <!-- Max size of a logfile -->
<!-- If logarchive is enabled (1), then when logsize is reached
the logfile will be moved to [error|access|playlist].log.DATESTAMP,
otherwise it will be moved to [error|access|playlist].log.old.
Default is non-archive mode (i.e. overwrite)
-->
<!-- <logarchive>1</logarchive> -->
</logging>
<security>
<chroot>0</chroot>
<!--
<changeowner>
<user>nobody</user>
<group>nogroup</group>
</changeowner>
-->
</security>
</icecast>

59
etc/icecast2/web/auth.xsl Normal file
View File

@ -0,0 +1,59 @@
<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" version = "1.0" >
<xsl:output omit-xml-declaration="no" method="xml" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" indent="yes" encoding="UTF-8" />
<xsl:template match = "/icestats" >
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Icecast Streaming Media Server</title>
<link rel="stylesheet" type="text/css" href="style.css" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
</head>
<body>
<h1 id="header">Icecast2 Status</h1>
<!--index header menu -->
<div id="menu">
<ul>
<li><a href="admin/">Administration</a></li>
<li><a href="status.xsl">Server Status</a></li>
<li><a href="server_version.xsl">Version</a></li>
</ul>
</div>
<!--end index header menu -->
<h2>Authorization Page</h2>
<xsl:for-each select="source">
<xsl:choose>
<xsl:when test="listeners">
<xsl:if test="authenticator">
<div class="roundbox">
<h3 class="mount">
Mount Point <xsl:value-of select="@mount" />
<xsl:if test="server_name">
<small><xsl:value-of select="server_name" /></small>
</xsl:if>
</h3>
<form class="alignedform" method="get" action="/admin/buildm3u">
<p>
<label for="name">Username: </label>
<input id="name" name="username" type="text" />
</p>
<p>
<label for="password">Password: </label>
<input id="password" name="password" type="password" />
</p>
<input type="hidden" name="mount" value="{@mount}" />
<input type="submit" value="Login" />
</form>
</div>
</xsl:if>
</xsl:when>
<xsl:otherwise>
<h3><xsl:value-of select="@mount" /> - Not Connected</h3>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
<div id="footer">
Support icecast development at <a href="https://www.icecast.org/">www.icecast.org</a>
</div>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

View File

@ -0,0 +1,73 @@
<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" version = "1.0">
<xsl:output omit-xml-declaration="no" method="xml" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" indent="yes" encoding="UTF-8" />
<xsl:template match = "/icestats">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Icecast Streaming Media Server</title>
<link rel="stylesheet" type="text/css" href="style.css" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
</head>
<body>
<h1 id="header">Server Information</h1>
<!--index header menu -->
<div id="menu">
<ul>
<li><a href="admin/">Administration</a></li>
<li><a href="status.xsl">Server Status</a></li>
<li><a href="server_version.xsl">Version</a></li>
</ul>
</div>
<!--end index header menu -->
<div class="roundbox">
<h3>Server Information</h3>
<table class="yellowkeys">
<tbody>
<xsl:for-each select="/icestats">
<tr>
<td>Location</td>
<td><xsl:value-of select="location" /></td>
</tr>
<tr>
<td>Admin</td>
<td><xsl:value-of select="admin" /></td>
</tr>
<tr>
<td>Host</td>
<td><xsl:value-of select="host" /></td>
</tr>
<tr>
<td>Version</td>
<td><xsl:value-of select="server_id" /></td>
</tr>
</xsl:for-each>
<tr>
<td>Download</td>
<td><a href="https://icecast.org/download/">icecast.org</a></td>
</tr>
<tr>
<td>Source code</td>
<td><a href="https://icecast.org/download/#git">icecast.org/download/#git</a></td>
</tr>
<tr>
<td>Documentation</td>
<td><a href="https://icecast.org/docs/">icecast.org/docs</a></td>
</tr>
<tr>
<td>Stream Directory</td>
<td><a href="http://dir.xiph.org/index.php">dir.xiph.org</a></td>
</tr>
<tr>
<td>Community</td>
<td><a href="https://icecast.org/contact/">icecast.org/contact</a></td>
</tr>
</tbody>
</table>
</div>
<div id="footer">
Support icecast development at <a href="https://www.icecast.org/">www.icecast.org</a>
</div>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

View File

@ -0,0 +1,24 @@
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:import href="xml2json.xslt"/>
<xsl:output indent="no" omit-xml-declaration="yes" method="text" encoding="UTF-8" media-type="application/json"/>
<xsl:strip-space elements="*"/>
<!-- override imported transform variable to enable output -->
<xsl:variable name="output">true</xsl:variable>
<!-- hide certain nodes from all sources -->
<xsl:template match="icestats/source/max_listeners"><xsl:if test="not(following-sibling::*)">"dummy":null}</xsl:if></xsl:template>
<xsl:template match="icestats/source/public"><xsl:if test="not(following-sibling::*)">"dummy":null}</xsl:if></xsl:template>
<xsl:template match="icestats/source/source_ip"><xsl:if test="not(following-sibling::*)">"dummy":null}</xsl:if></xsl:template>
<xsl:template match="icestats/source/slow_listeners"><xsl:if test="not(following-sibling::*)">"dummy":null}</xsl:if></xsl:template>
<xsl:template match="icestats/source/*[contains(name(), 'total_bytes')]"><xsl:if test="not(following-sibling::*)">"dummy":null}</xsl:if></xsl:template>
<xsl:template match="icestats/source/user_agent" ><xsl:if test="not(following-sibling::*)">"dummy":null}</xsl:if></xsl:template>
<!-- hide certain global nodes -->
<xsl:template match="icestats/sources"><xsl:if test="not(following-sibling::*)">"dummy":null}</xsl:if></xsl:template>
<xsl:template match="icestats/clients"><xsl:if test="not(following-sibling::*)">"dummy":null}</xsl:if></xsl:template>
<xsl:template match="icestats/stats"><xsl:if test="not(following-sibling::*)">"dummy":null}</xsl:if></xsl:template>
<xsl:template match="icestats/listeners"><xsl:if test="not(following-sibling::*)">"dummy":null}</xsl:if></xsl:template>
<xsl:template match="node()[contains(name(), 'connections')]"><xsl:if test="not(following-sibling::*)">"dummy":null}</xsl:if></xsl:template>
</xsl:stylesheet>

167
etc/icecast2/web/status.xsl Normal file
View File

@ -0,0 +1,167 @@
<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" version = "1.0">
<xsl:output omit-xml-declaration="no" method="xml" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" indent="yes" encoding="UTF-8" />
<xsl:template match = "/icestats">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Icecast Streaming Media Server</title>
<link rel="stylesheet" type="text/css" href="style.css" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
</head>
<body>
<h1 id="header">Icecast2 Status</h1>
<!--index header menu -->
<div id="menu">
<ul>
<li><a href="admin/">Administration</a></li>
<li><a href="status.xsl">Server Status</a></li>
<li><a href="server_version.xsl">Version</a></li>
</ul>
</div>
<!--end index header menu -->
<xsl:text disable-output-escaping="yes">
&lt;!-- WARNING:
DO NOT ATTEMPT TO PARSE ICECAST HTML OUTPUT!
The web interface may change completely between releases.
If you have a need for automatic processing of server data,
please read the appropriate documentation. Latest docs:
https://icecast.org/docs/icecast-latest/icecast2_stats.html
-->
</xsl:text>
<!--mount point stats-->
<xsl:for-each select="source">
<xsl:choose>
<xsl:when test="listeners">
<div class="roundbox">
<div class="mounthead">
<h3 class="mount">Mount Point <xsl:value-of select="@mount" /></h3>
<div class="right">
<xsl:choose>
<xsl:when test="authenticator">
<a class="auth" href="/auth.xsl">Login</a>
</xsl:when>
<xsl:otherwise>
<ul class="mountlist">
<li><a class="play" href="{@mount}.m3u">M3U</a></li>
<li><a class="play" href="{@mount}.xspf">XSPF</a></li>
<!-- <li><a class="play" href="{@mount}.vclt">VCLT</a></li> -->
</ul>
</xsl:otherwise>
</xsl:choose>
</div>
</div>
<div class="mountcont">
<xsl:if test="server_type and ((server_type = 'application/ogg') or (server_type = 'audio/ogg'))">
<div class="audioplayer">
<audio controls="controls" preload="none">
<source src="{@mount}" type="{server_type}" />
</audio>
</div>
</xsl:if>
<table class="yellowkeys">
<tbody>
<xsl:if test="server_name">
<tr>
<td>Stream Name:</td>
<td><xsl:value-of select="server_name" /></td>
</tr>
</xsl:if>
<xsl:if test="server_description">
<tr>
<td>Stream Description:</td>
<td><xsl:value-of select="server_description" /></td>
</tr>
</xsl:if>
<xsl:if test="server_type">
<tr>
<td>Content Type:</td>
<td><xsl:value-of select="server_type" /></td>
</tr>
</xsl:if>
<xsl:if test="stream_start">
<tr>
<td>Stream started:</td>
<td class="streamstats"><xsl:value-of select="stream_start" /></td>
</tr>
</xsl:if>
<xsl:if test="bitrate">
<tr>
<td>Bitrate:</td>
<td class="streamstats"><xsl:value-of select="bitrate" /></td>
</tr>
</xsl:if>
<xsl:if test="quality">
<tr>
<td>Quality:</td>
<td class="streamstats"><xsl:value-of select="quality" /></td>
</tr>
</xsl:if>
<xsl:if test="video_quality">
<tr>
<td>Video Quality:</td>
<td class="streamstats"><xsl:value-of select="video_quality" /></td>
</tr>
</xsl:if>
<xsl:if test="frame_size">
<tr>
<td>Framesize:</td>
<td class="streamstats"><xsl:value-of select="frame_size" /></td>
</tr>
</xsl:if>
<xsl:if test="frame_rate">
<tr>
<td>Framerate:</td>
<td class="streamstats"><xsl:value-of select="frame_rate" /></td>
</tr>
</xsl:if>
<xsl:if test="listeners">
<tr>
<td>Listeners (current):</td>
<td class="streamstats"><xsl:value-of select="listeners" /></td>
</tr>
</xsl:if>
<xsl:if test="listener_peak">
<tr>
<td>Listeners (peak):</td>
<td class="streamstats"><xsl:value-of select="listener_peak" /></td>
</tr>
</xsl:if>
<xsl:if test="genre">
<tr>
<td>Genre:</td>
<td class="streamstats"><xsl:value-of select="genre" /></td>
</tr>
</xsl:if>
<xsl:if test="server_url">
<tr>
<td>Stream URL:</td>
<td class="streamstats">
<a href="{server_url}"><xsl:value-of select="server_url" /></a>
</td>
</tr>
</xsl:if>
<tr>
<td>Currently playing:</td>
<td class="streamstats">
<xsl:if test="artist">
<xsl:value-of select="artist" /> -
</xsl:if>
<xsl:value-of select="title" />
</td>
</tr>
</tbody>
</table>
</div>
</div>
</xsl:when>
<xsl:otherwise>
<h3><xsl:value-of select="@mount" /> - Not Connected</h3>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
<div id="footer">
Support icecast development at <a href="https://www.icecast.org/">www.icecast.org</a>
</div>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

274
etc/icecast2/web/style.css Normal file
View File

@ -0,0 +1,274 @@
html {
margin: 0;
padding: 0;
background-color: #000;
}
body {
padding: 0 25px 0 50px;
background-color: #000;
font-family: Verdana, sans-serif;
text-decoration: none;
color: #fff;
}
a {
color: #f8ef64;
text-decoration: none;
border-bottom: 1px dotted #f8ef64;
}
a:hover {
color: #f8ef64;
text-decoration: none;
border-bottom: 1px solid #f8ef64;
}
h1 {
font-family: Verdana, sans-serif;
text-decoration: none;
font-weight: bold;
font-size: 3em;
color: #fff;
margin-top: 3px;
}
h3 {
margin: 0px;
padding: 0px;
font-family: Verdana, sans-serif;
font-weight: bold;
font-size: 110%;
color: #f8ef64;
}
h1#header{
padding: 10px 0px 10px 80px;
background: transparent url(/icecast.png) no-repeat scroll left center;
}
h3 small {
color: #fff;
font-size: 70%;
padding-left: 15px;
}
form.alignedform label {
text-align: right;
display: inline-block;
vertical-align: middle;
width: 10em;
margin: 0 1em 0 0;
}
form.alignedform input {
display: inline-block;
vertical-align: middle;
border: 1px solid #f8ef64;
background-color: #333;
color: #f8ef64;
padding: 5px;
}
#menu {
border-top: 3px solid #7B96C6;
border-bottom: 3px solid #7B96C6;
text-align: center;
margin-bottom: 35px;
}
#menu ul {
margin: 0;
padding: 0;
list-style: none;
display: inline-block;
vertical-align: middle;
}
#menu ul li {
float: left;
padding-left: 25px;
padding-right: 25px;
}
#menu ul li a {
font-family: Verdana, sans-serif;
text-decoration: none;
color: #fff;
font-size: 18px;
border: none;
}
#menu ul li a:hover {
color: #f8ef64;
}
.roundbox {
width: 90%;
background-color: #656565;
border-radius: 10px;
padding: 15px 20px;
margin-bottom: 35px;
}
.roundbox h3 {
margin-bottom: 10px;
border-bottom: 1px groove #ACACAC;
}
.roundbox table.yellowkeys tr td:last-child {
color: #f8ef64;
}
table.colortable {
border-collapse: collapse;
padding: 20px 0 20px 0;
margin: 0 auto;
}
table.colortable td {
border: 1px solid #000;
text-align: center;
padding: 5px;
}
table.colortable thead tr td {
color: #656565;
background: #f8ef64;
border-color: white;
}
.roundbox table.yellowkeys tr td {
padding: 5px 5px 0 0;
word-wrap: break-word;
word-break: break-all;
}
.right {
float: right;
}
.mounthead h3 {
float: left;
margin-bottom: 0px;
border-bottom: none;
}
.mountcont {
border-top: 1px groove #ACACAC;
clear: both;
}
ul.mountlist {
margin: 0;
padding: 0;
list-style: none;
text-align: right;
}
.mountlist li {
display: inline;
}
a.play {
padding-left: 22px;
margin-left: 25px;
border: none;
background: transparent url(/tunein.png) no-repeat scroll left center;
background-size: auto 100%;
}
a.auth {
padding-left: 22px;
margin-left: 25px;
border: none;
background: transparent url(/key.png) no-repeat scroll left top;
background-size: auto 100%;
}
/* Admin navigation */
ul.nav {
margin: 0;
padding: 5px 0 10px 0;
clear: both;
list-style: none;
text-align: center;
}
ul.nav li {
display: inline;
}
ul.nav li a {
border: none;
display: inline-block;
padding: .2em .7em;
margin-top: .2em;
background-color: #333;
white-space: nowrap;
}
ul.nav li a:hover {
color: #fff;
}
/* Footer */
#footer {
border-top: 1px groove #ACACAC;
margin-top: 20px;
font-size: 80%;
}
@media (max-width: 800px) {
body {
padding: 0;
}
.roundbox {
width: auto;
border-radius: 0;
}
.roundbox table.yellowkeys tr td {
display: block;
padding: 5px 5px 0 0;
}
.roundbox table.yellowkeys tr td:last-child {
margin-bottom: 5px;
margin-left: 5px;
}
.scrolltable {
overflow: auto;
}
}
@media (max-width: 320px) {
ul.nav, #menu ul {
display: block;
}
ul.nav li, #menu ul li {
float: none;
}
ul.nav li a, #menu ul li a {
display: block;
}
ul.nav li + li, #menu ul li + li {
border-top: 1px solid #ACACAC;
}
a.play {
margin-left: 15px;
}
}

100
ices.xml Normal file
View File

@ -0,0 +1,100 @@
<?xml version="1.0"?>
<ices>
<!-- run in background -->
<background>0</background>
<!-- where logs, etc go. -->
<logpath>/var/log/ices</logpath>
<logfile>ices.log</logfile>
<!-- 1=error,2=warn,3=info,4=debug -->
<loglevel>1</loglevel>
<!-- set this to 1 to log to the console instead of to the file above -->
<consolelog>0</consolelog>
<!-- optional filename to write process id to -->
<!-- <pidfile>/home/ices/ices.pid</pidfile> -->
<stream>
<!-- metadata used for stream listing (not currently used) -->
<metadata>
<name>One Container Radio</name>
<genre>Your Music</genre>
<description>You are playing your music with one deployed container!</description>
</metadata>
<!-- input module
The module used here is the playlist module - it has
'submodules' for different types of playlist. There are
two currently implemented, 'basic', which is a simple
file-based playlist, and 'script' which invokes a command
to returns a filename to start playing. -->
<input>
<module>playlist</module>
<param name="type">basic</param>
<param name="file">playlist.txt</param>
<!-- random play -->
<param name="random">1</param>
<!-- if the playlist get updated that start at the beginning -->
<param name="restart-after-reread">0</param>
<!-- if set to 1 , plays once through, then exits. -->
<param name="once">0</param>
</input>
<!-- Stream instance
You may have one or more instances here. This allows you to
send the same input data to one or more servers (or to different
mountpoints on the same server). Each of them can have different
parameters. This is primarily useful for a) relaying to multiple
independent servers, and b) encoding/reencoding to multiple
bitrates.
If one instance fails (for example, the associated server goes
down, etc), the others will continue to function correctly.
This example defines two instances as two mountpoints on the
same server. -->
<instance>
<!-- Server details:
You define hostname and port for the server here, along with
the source password and mountpoint. -->
<hostname>localhost</hostname>
<port>8000</port>
<password>password</password>
<mount>/radio.ogg</mount>
<!-- Reconnect parameters:
When something goes wrong (e.g. the server crashes, or the
network drops) and ices disconnects from the server, these
control how often it tries to reconnect, and how many times
it tries to reconnect. Delay is in seconds.
If you set reconnectattempts to -1, it will continue
indefinately. Suggest setting reconnectdelay to a large value
if you do this.
-->
<reconnectdelay>2</reconnectdelay>
<reconnectattempts>5</reconnectattempts>
<!-- maxqueuelength:
This describes how long the internal data queues may be. This
basically lets you control how much data gets buffered before
ices decides it can't send to the server fast enough, and
either shuts down or flushes the queue (dropping the data)
and continues.
For advanced users only.
-->
<maxqueuelength>80</maxqueuelength>
<!-- Live encoding/reencoding:
Currrently, the parameters given here for encoding MUST
match the input data for channels and sample rate. That
restriction will be relaxed in the future.
Remove this section if you don't want your files getting reencoded.
-->
<encode>
<nominal-bitrate>64000</nominal-bitrate> <!-- bps. e.g. 64000 for 64 kbps -->
<samplerate>44100</samplerate>
<channels>2</channels>
</encode>
</instance>
</stream>
</ices>

5
start-icecast.sh Normal file
View File

@ -0,0 +1,5 @@
#!/bin/bash
sudo -Eu icecast2 icecast2 -n -c /etc/icecast2/icecast.xml &
bash ./start-ices.sh

7
start-ices.sh Normal file
View File

@ -0,0 +1,7 @@
#!/bin/bash
sudo mkdir -p /var/log/ices
sudo touch /var/log/ices/ices.log
find /media -type f -name "*.ogg" > /playlist.txt
sudo ices2 /ices.xml