SiriusXM on Squeezebox Boom
![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
![[community profile]](https://www.dreamwidth.org/img/silk/identity/community.png)
This week I've been playing around with an old Squeezebox
Boom, and I've been reading through a
forum thread where - within the last few weeks -
people have been finding ways of playing SiriusXM channels on it.
The setup for Lyrion Music Server is fairly
well documented (although the name is fairly new); at the very
least, any awkwardness in the application is the early-2010s
awkwardness I grew up with, and not the new mobile touchscreen
awkwardness that makes me feel old.
After setting up LMS, I installed the "PlayHLS" plugin (which
actually plays audio on the server using ffmpeg and then streams
that to the radio). Then I downloaded a Python script (actually,
cloned the repo with Git) that hosts a web server and exposes HLS
URLs for each SiriusXM channel. https://github.com/PaulWebster/SiriusXM
is the one in the thread, and the "cookies" branch worked for me; there are other
forks of the same original repo out there, too, if there's
something you find it's missing.
My startup script looks like this:
#!/bin/sh
# Compile the code that translates the list of SiriusXM channels to an LMS favorites file
gcc -o /tmp/sxm_list_to_favorites /root/sxm_list_to_favorites.c
# Get the list of channels, parse it, and overwrite the list of favorites
python3 /root/SiriusXM/sxm.py -l EmailHere PasswordHere | /tmp/sxm_list_to_favorites > /var/lib/squeezeboxserver/prefs/favorites.opml
# Restart LMS
service lyrionmusicserver restart
# Start the proxy server for SXM channels
screen -d -m python3 /root/SiriusXM/sxm.py -p 8888 EmailHere PasswordHere
The file "sxm_list_to_favorites.c" is just a C application that
does some fairly ugly string processing (I don't know Python or
shell scripting very well):
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
char* findStart(char* buffer) {
while (buffer[0] == ' ') {
buffer++;
}
return buffer;
}
void trimEnd(char* buffer) {
for (char* ptr = buffer + strlen(buffer) - 1; ptr >= buffer; ptr--) {
if (*ptr == ' ')
*ptr = 0;
else
break;
}
}
int main()
{
printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<opml version=\"1.0\">\n <head title=\"Favorites\">\n <expansionState></expansionState>\n </head>\n <body>\n <outline icon=\"html/images/favorites.png\" text=\"SiriusXM\">\n");
char buffer[1024];
while (true) {
if (!fgets(buffer, sizeof buffer, stdin))
break;
char* id = 0;
char* num = 0;
char* name = 0;
char* curr = buffer;
char* pos = curr;
while (true) {
if (*pos == '|' && !id) {
*pos = 0;
id = curr;
curr = pos + 1;
}
else if (*pos == '|' && !num) {
*pos = 0;
num = curr;
curr = pos + 1;
}
else if (*pos == '\r' || *pos == '\n') {
*pos = 0;
name = curr;
break;
}
else if (*pos == '"') {
*pos = '\'';
}
else if (*pos == '&') {
*pos = '+';
}
pos++;
}
if (!id || !num || !name)
continue;
id = findStart(id);
num = findStart(num);
name = findStart(name);
trimEnd(id);
trimEnd(num);
trimEnd(name);
for (char* nPos = num; *nPos != 0; nPos++) {
if (*nPos < '0' || *nPos > '9') {
num = 0;
break;
}
}
if (!num) {
continue;
}
printf(" <outline URL=\"http://192.168.4.56:8888/%s.m3u8\" icon=\"html/images/radio.png\" text=\"[%s] %s\" type=\"audio\" />\n", id, num, name);
}
printf(" </outline>\n </body>\n</opml>\n");
}
This would be easier for me to do in C# or F#, and in the future,
I might do just that (either by compiling the C# or F# for Linux,
or by using Azure Functions if I have to).