An easy way to have a 24/7 audio stream of music.
1<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 2 <xsl:output method="html" 3 doctype-system="about:legacy-compat" 4 encoding="UTF-8" /> 5 <xsl:template match="/icestats"> 6 <html xmlns="http://www.w3.org/1999/xhtml"> 7 <head> 8 <meta charset="utf-8" /> 9 <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" /> 10 <title>Radio Rita.moe</title> 11 <link rel="icon" href="https://rita.moe/rita-icon.png" /> 12 <link rel="stylesheet" type="text/css" href="style-status.css" /> 13 <link rel="stylesheet" href="https://cdn.plyr.io/3.7.8/plyr.css" /> 14 <script src="https://cdn.plyr.io/3.7.8/plyr.polyfilled.js"></script> 15 </head> 16 <body> 17 <div class="content"> 18 <h1 id="header">Radio Rita.moe</h1> 19 <!--mount point stats--> 20 <xsl:for-each select="source"> 21 <xsl:choose> 22 <xsl:when test="listeners"> 23 <div class="roundbox" data-mount="{@mount}"> 24 <div class="mounthead"> 25 <h3 class="mount"> 26 <xsl:value-of select="server_name" /> 27 <small>(<xsl:value-of select="@mount" />)</small> 28 </h3> 29 <div class="right"> 30 <xsl:choose> 31 <xsl:when test="authenticator"> 32 <a class="auth" href="/auth.xsl">Login</a> 33 </xsl:when> 34 <xsl:otherwise> 35 <ul class="mountlist"> 36 <li> 37 <a class="play" href="{@mount}.m3u">M3U</a> 38 </li> 39 </ul> 40 </xsl:otherwise> 41 </xsl:choose> 42 </div> 43 </div> 44 <div class="mountcont"> 45 <xsl:if test="server_type"> 46 <div class="audioplayer"> 47 <audio controls="controls" preload="none"> 48 <source src="{@mount}" type="{server_type}" /> 49 </audio> 50 </div> 51 </xsl:if> 52 <div class="playing"> 53 <xsl:if test="artist"> 54 <xsl:value-of select="artist" /> 55 - 56 </xsl:if> 57 <xsl:value-of select="title" /> 58 </div> 59 <div class="search"> 60 <a href="/" onclick="ss('{@mount}'); return false;">(search youtube)</a> 61 </div> 62 </div> 63 </div> 64 </xsl:when> 65 <xsl:otherwise> 66 <h3> 67 <xsl:value-of select="@mount" /> 68 - Not Connected 69 </h3> 70 </xsl:otherwise> 71 </xsl:choose> 72 </xsl:for-each> 73 <div id="footer"> 74 Powered by <a href="https://www.icecast.org">Icecast</a> 75 and <a href="https://www.liquidsoap.info">Liquidsoap</a>. 76 </div> 77 </div> 78 <script type="text/javascript"> 79<![CDATA[ 80 function ss (mount) { 81 let title = document.querySelector('[data-mount="' + mount + '"] .playing').innerHTML 82 let se = document.querySelector('[data-mount="' + mount + '"] .search a') 83 se.innerHTML = 'Please wait...' 84 fetch('https://www.googleapis.com/youtube/v3/search?part=snippet&maxResults=1&safeSearch=none&type=video&videoCategoryId=10&key=AIzaSyB0PbGfWP_AwEXx7_DypkJiB0qIjHxedi0&q=' + encodeURIComponent(title)) 85 .then(r => r.json()) 86 .then(j => { 87 se.innerHTML = '(search youtube)' 88 if (j.items.length > 0) { 89 window.open('https://www.youtube.com/watch?v=' + j.items[0].id.videoId, '_blank') 90 } 91 }) 92 } 93 94 function s () { 95 document.querySelectorAll('div[data-mount]').forEach(e => { 96 fetch('https://radio.rita.moe/status-json.xsl?mount=' + e.dataset.mount) 97 .then(r => r.json()) 98 .then(j => { 99 setTimeout(_ => { 100 e.querySelector('.playing').innerHTML = j.icestats.source.title 101 }, 5000) 102 }) 103 }) 104 } 105 106 setInterval(s, 3000) 107 108 document.querySelectorAll('audio').forEach(e => { 109 new Plyr(e, { 110 controls: ['play', 'current-time', 'mute', 'volume'], 111 invertTime: false, 112 toggleInvert: false 113 }) 114 }) 115]]> 116 </script> 117 </body> 118 </html> 119 </xsl:template> 120</xsl:stylesheet> 121