An easy way to have a 24/7 audio stream of music.

Compare changes

Choose any two refs to compare.

+1
.env.example
··· 4 ICECAST_RELAY_PASSWORD=APasswordForRelaysIGuess 5 ICECAST_HOSTNAME=localhost 6 ICECAST_MAX_SOURCES=1 7 STREAM_NAME=Radio 8 STREAM_DESC=Our selection of music 9 STREAM_URL=https://google.com
··· 4 ICECAST_RELAY_PASSWORD=APasswordForRelaysIGuess 5 ICECAST_HOSTNAME=localhost 6 ICECAST_MAX_SOURCES=1 7 + ICECAST_CHARSET=UTF-8 8 STREAM_NAME=Radio 9 STREAM_DESC=Our selection of music 10 STREAM_URL=https://google.com
+2 -2
docker-compose.yml
··· 3 services: 4 icecast: 5 image: docker.io/mkody/icecast:latest 6 - restart: always 7 ports: 8 - "${ICECAST_PORT:-8000}:8000" 9 environment: ··· 19 20 liquidsoap: 21 image: docker.io/savonet/liquidsoap:v2.2.2 22 - restart: always 23 command: ["/script.liq"] 24 environment: 25 - ICECAST_SOURCE_PASSWORD
··· 3 services: 4 icecast: 5 image: docker.io/mkody/icecast:latest 6 + restart: unless-stopped 7 ports: 8 - "${ICECAST_PORT:-8000}:8000" 9 environment: ··· 19 20 liquidsoap: 21 image: docker.io/savonet/liquidsoap:v2.2.2 22 + restart: unless-stopped 23 command: ["/script.liq"] 24 environment: 25 - ICECAST_SOURCE_PASSWORD
+5
style-status.css
··· 131 margin-right: 0; 132 } 133 134 #footer { 135 border-top: 1px groove #ACACAC; 136 font-size: 80%;
··· 131 margin-right: 0; 132 } 133 134 + .audiooplayer .plyr__controls .plyr__controls__item.plyr__time { 135 + flex-grow: 1; 136 + text-align: left; 137 + } 138 + 139 #footer { 140 border-top: 1px groove #ACACAC; 141 font-size: 80%;
+12 -14
status.xsl
··· 78 let lastTitle = '' 79 // Store the current mount point 80 let currentMount = '' 81 - // Store the last notification 82 - let lastNotification = null 83 84 // On every audio element, create a new Plyr instance 85 document.querySelectorAll('div[data-mount]').forEach((e) => { ··· 141 142 // If we have permission, send a notification 143 if ('Notification' in window && Notification.permission === 'granted') { 144 - lastNotification = new Notification( 145 'RRM - Now Playing', 146 { 147 body: j.icestats.source.title, 148 icon: 'https://rita.moe/rita-icon.png', 149 renotify: true, 150 - requireInteraction: false, 151 tag: 'now-playing', 152 } 153 ) 154 } 155 } 156 } else { ··· 171 if ('Notification' in window && Notification.permission === 'default') { 172 Notification.requestPermission() 173 } 174 - 175 - document.addEventListener( 176 - 'visibilitychange', 177 - () => { 178 - // If the page is visible, close the last notification 179 - if (document.visibilityState === 'visible') { 180 - lastNotification?.close() 181 - } 182 - } 183 - ) 184 ]]> 185 </script> 186 </body>
··· 78 let lastTitle = '' 79 // Store the current mount point 80 let currentMount = '' 81 82 // On every audio element, create a new Plyr instance 83 document.querySelectorAll('div[data-mount]').forEach((e) => { ··· 139 140 // If we have permission, send a notification 141 if ('Notification' in window && Notification.permission === 'granted') { 142 + const lastNotification = new Notification( 143 'RRM - Now Playing', 144 { 145 body: j.icestats.source.title, 146 icon: 'https://rita.moe/rita-icon.png', 147 renotify: true, 148 + requireInteraction: true, 149 + silent: true, 150 tag: 'now-playing', 151 } 152 ) 153 + 154 + // Close the notification after 10 seconds, as renotify 155 + // isn't working perfectly when the track changes 156 + setTimeout( 157 + (_) => { 158 + lastNotification.close() 159 + }, 160 + 10000 161 + ) 162 } 163 } 164 } else { ··· 179 if ('Notification' in window && Notification.permission === 'default') { 180 Notification.requestPermission() 181 } 182 ]]> 183 </script> 184 </body>