Skip to content

Commit ee83bf9

Browse files
Update to use Lyrion Music Server
1 parent 18b969b commit ee83bf9

8 files changed

Lines changed: 48 additions & 45 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# AmpliPi Software Releases
22

33
# Future Release
4+
* System
5+
* Upgrade from Logitech Media Server 8.5.2 to Lyrion Music Server 9.0.3
46

57

68
# 0.4.11

amplipi/app.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -238,22 +238,22 @@ def shutdown():
238238
}
239239
)
240240
def lms_mode(ctrl: Api = Depends(get_ctrl)):
241-
""" Toggles Logitech Media Server mode on or off. """
241+
""" Toggles Lyrion Music Server mode on or off. """
242242
new_config: models.Status
243243
if ctrl.lms_mode:
244244
logging.info("turning LMS mode off...")
245245
try:
246246
os.remove(pathlib.Path(defaults.USER_CONFIG_DIR, "lms_mode"))
247247
except FileNotFoundError:
248248
pass
249-
Popen('sudo systemctl stop logitechmediaserver', shell=True)
250-
Popen('sudo systemctl disable logitechmediaserver', shell=True)
249+
Popen('sudo systemctl stop lyrionmusicserver', shell=True)
250+
Popen('sudo systemctl disable lyrionmusicserver', shell=True)
251251
new_config = models.Status(**defaults.default_config(is_streamer=ctrl.is_streamer, lms_mode=False))
252252
else:
253253
logging.info("turning LMS mode on...")
254254
pathlib.Path(defaults.USER_CONFIG_DIR, "lms_mode").touch()
255-
Popen('sudo systemctl start logitechmediaserver', shell=True)
256-
Popen('sudo systemctl enable logitechmediaserver', shell=True)
255+
Popen('sudo systemctl start lyrionmusicserver', shell=True)
256+
Popen('sudo systemctl enable lyrionmusicserver', shell=True)
257257
new_config = models.Status(**defaults.default_config(is_streamer=ctrl.is_streamer, lms_mode=True))
258258
load_config(new_config, ctrl)
259259

bin/arm64/find_lms_server

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version https://git-lfs.github.com/spec/v1
2+
oid sha256:97513b241d5189f92b47fc88b4906ce253e1d9e80db95bad19ca7c921157d4f8
3+
size 71472

docs/amplipi_api.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2680,7 +2680,7 @@ paths:
26802680
tags:
26812681
- config
26822682
summary: Lms Mode
2683-
description: Toggles Logitech Media Server mode on or off.
2683+
description: Toggles Lyrion Music Server mode on or off.
26842684
operationId: lms_mode_api_lms_mode_post
26852685
responses:
26862686
'200':

scripts/configure.py

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -249,17 +249,15 @@
249249
]
250250
},
251251
'lms': {
252-
'apt': ['libcrypt-openssl-rsa-perl', 'libio-socket-ssl-perl', 'libopusfile0'],
252+
'apt': ['libcrypt-openssl-rsa-perl', 'libio-socket-ssl-perl', 'libopusfile0', 'squeezelite'],
253253
'copy': [{'from': 'bin/ARCH/find_lms_server', 'to': 'streams/find_lms_server'}],
254254
'script': [
255-
'if [ ! $(dpkg-query --show --showformat=\'${Status}\' logitechmediaserver | grep -q installed) ]; then '
256-
' wget -nv https://storage.googleapis.com/amplipi-deb/pool/main/l/logitechmediaserver/logitechmediaserver_8.5.2_all.deb -O /tmp/logitechmediaserver_8.5.2.deb',
257-
' sudo dpkg -i /tmp/logitechmediaserver_8.5.2.deb',
258-
' if [ ! -e /home/pi/.config/amplipi/lms_mode ] ; then sudo systemctl disable logitechmediaserver; fi',
259-
' if [ ! -e /home/pi/.config/amplipi/lms_mode ] ; then sudo systemctl stop logitechmediaserver; fi',
255+
'if [ ! $(dpkg-query --show --showformat=\'${Status}\' lyrionmusicserver | grep -q installed) ]; then '
256+
' wget -nv https://downloads.lms-community.org/LyrionMusicServer_v9.0.3/lyrionmusicserver_9.0.3_arm.deb -O /tmp/lyrionmusicserver_9.0.3.deb',
257+
' sudo dpkg -i /tmp/lyrionmusicserver_9.0.3.deb',
258+
' if [ ! -e /home/pi/.config/amplipi/lms_mode ] ; then sudo systemctl disable lyrionmusicserver; fi',
259+
' if [ ! -e /home/pi/.config/amplipi/lms_mode ] ; then sudo systemctl stop lyrionmusicserver; fi',
260260
'fi',
261-
'wget -nv https://storage.googleapis.com/amplipi-deb/pool/main/s/squeezelite/squeezelite_2.0.0-1488+git20240509.0e85ddf-1.1_armhf.deb -O /tmp/squeezelite_2.0.0-1488+git20240509.0e85ddf-1.1_armhf.deb',
262-
'sudo dpkg -i /tmp/squeezelite_2.0.0-1488+git20240509.0e85ddf-1.1_armhf.deb',
263261
'sudo systemctl stop squeezelite',
264262
'sudo systemctl disable squeezelite',
265263

scripts/edit_media_directories.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@
1111

1212

1313
def check_lms_mode():
14-
try:
15-
status_output = subprocess.check_output('systemctl is-active logitechmediaserver', shell=True).decode().strip()
16-
return status_output == 'active'
17-
except subprocess.CalledProcessError:
18-
return False
14+
try:
15+
status_output = subprocess.check_output('systemctl is-active lyrionmusicserver', shell=True).decode().strip()
16+
return status_output == 'active'
17+
except subprocess.CalledProcessError:
18+
return False
1919

2020

2121
def get_usb_drives(logger: logging.Logger):

streams/find_lms_server.c

Lines changed: 21 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
*
1111
*/
1212

13+
/* from https://github.com/ralph-irving/squeezelite/blob/master/tools/find_servers.c */
1314
#include <assert.h>
1415
#include <ctype.h>
1516
#include <signal.h>
@@ -60,7 +61,7 @@
6061
#define packC(ptr, off, v) \
6162
{ ptr[off] = v & 0xFF; }
6263
#define packA4(ptr, off, v) \
63-
{ strncpy((char *)(&ptr[off]), v, 4); }
64+
{ strncpy((char*)(&ptr[off]), v, 4); }
6465

6566
#define unpackN4(ptr, off) \
6667
((ptr[off] << 24) | (ptr[off + 1] << 16) | (ptr[off + 2] << 8) | ptr[off + 3])
@@ -74,18 +75,18 @@
7475
#define DISCOVERY_PKTSIZE 1516
7576
#define SLIMPROTO_DISCOVERY "eNAME\0JSON\0"
7677

77-
int slimproto_discover(char *server_addr, int server_addr_len, int port,
78-
unsigned int *jsonport, bool scan) {
78+
int slimproto_discover(char* server_addr, int server_addr_len, int port, unsigned int* jsonport,
79+
bool scan) {
7980
int sockfd;
8081
int try;
81-
char *packet;
82+
char* packet;
8283
int pktlen;
8384
int pktidx;
84-
char *t;
85+
char* t;
8586
unsigned int l;
86-
char *v;
87-
char *server_name;
88-
char *server_json;
87+
char* v;
88+
char* server_name;
89+
char* server_json;
8990
struct pollfd pollfd;
9091
struct sockaddr_in sendaddr;
9192
struct sockaddr_in recvaddr;
@@ -117,8 +118,8 @@ int slimproto_discover(char *server_addr, int server_addr_len, int port,
117118
pollfd.fd = sockfd;
118119
pollfd.events = POLLIN;
119120

120-
if ((setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, (const void *)&broadcast,
121-
sizeof broadcast)) == -1) {
121+
if ((setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, (const void*)&broadcast, sizeof broadcast)) ==
122+
-1) {
122123
perror("setsockopt - SO_BROADCAST");
123124
return -1;
124125
}
@@ -128,7 +129,7 @@ int slimproto_discover(char *server_addr, int server_addr_len, int port,
128129
sendaddr.sin_addr.s_addr = INADDR_ANY;
129130
memset(sendaddr.sin_zero, '\0', sizeof sendaddr.sin_zero);
130131

131-
if (bind(sockfd, (struct sockaddr *)&sendaddr, sizeof sendaddr) == -1) {
132+
if (bind(sockfd, (struct sockaddr*)&sendaddr, sizeof sendaddr) == -1) {
132133
perror("bind");
133134
return -1;
134135
}
@@ -152,7 +153,7 @@ int slimproto_discover(char *server_addr, int server_addr_len, int port,
152153

153154
for (try = 0; try < 5; try++) {
154155
if (sendto(sockfd, SLIMPROTO_DISCOVERY, sizeof(SLIMPROTO_DISCOVERY), 0,
155-
(struct sockaddr *)&recvaddr, sizeof(recvaddr)) == -1) {
156+
(struct sockaddr*)&recvaddr, sizeof(recvaddr)) == -1) {
156157
CLOSESOCKET(sockfd);
157158
perror("sendto");
158159
return -1;
@@ -165,7 +166,7 @@ int slimproto_discover(char *server_addr, int server_addr_len, int port,
165166
memset(packet, 0, sizeof(packet));
166167

167168
pktlen = recvfrom(sockfd, packet, DISCOVERY_PKTSIZE, MSG_DONTWAIT,
168-
(struct sockaddr *)&sendaddr, &sockaddr_len);
169+
(struct sockaddr*)&sendaddr, &sockaddr_len);
169170

170171
if (pktlen == -1)
171172
continue;
@@ -198,17 +199,14 @@ int slimproto_discover(char *server_addr, int server_addr_len, int port,
198199
server_json[l] = '\0';
199200
}
200201

201-
VDEBUGF("slimproto_discover: key: %s len: %d value: %s pktidx: %d\n", t,
202-
l, v, pktidx);
202+
VDEBUGF("slimproto_discover: key: %s len: %d value: %s pktidx: %d\n", t, l, v, pktidx);
203203
}
204204

205-
inet_ntop(AF_INET, &sendaddr.sin_addr.s_addr, server_addr,
206-
server_addr_len);
205+
inet_ntop(AF_INET, &sendaddr.sin_addr.s_addr, server_addr, server_addr_len);
207206

208207
*jsonport = (unsigned int)strtoul(server_json, NULL, 10);
209208

210-
DEBUGF("slimproto_discover: discovered %s:%u (%s)\n", server_name,
211-
*jsonport, server_addr);
209+
DEBUGF("slimproto_discover: discovered %s:%u (%s)\n", server_name, *jsonport, server_addr);
212210

213211
serveraddr_len = strlen(server_addr);
214212

@@ -271,7 +269,7 @@ static void license(void) {
271269
"https://github.com/ralph-irving/squeezelite\n");
272270
}
273271

274-
int main(int argc, char **argv) {
272+
int main(int argc, char** argv) {
275273
char slimserver_address[256] = "127.0.0.1";
276274
int port = 3483;
277275
unsigned int json;
@@ -283,11 +281,10 @@ int main(int argc, char **argv) {
283281
}
284282

285283
/* Scan */
286-
len = slimproto_discover(slimserver_address, sizeof(slimserver_address), port,
287-
&json, true);
284+
len = slimproto_discover(slimserver_address, sizeof(slimserver_address), port, &json, true);
288285

289-
VDEBUGF("main: slimproto_discover_scan: address:%s len:%d json:%u\n",
290-
slimserver_address, len, json);
286+
VDEBUGF("main: slimproto_discover_scan: address:%s len:%d json:%u\n", slimserver_address, len,
287+
json);
291288

292289
return 0;
293290
}

streams/lms_metadata.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ def save_file(self, folder):
5050

5151

5252
class LMSMetadataReader:
53-
"""A class for getting metadata from a Logitech Media Server."""
53+
"""A class for getting metadata from a Lyrion Music Server."""
5454

5555
# meta_ref is probably an unneccessary variable to pass as an arg since it's obscured from the user, but we can eventually make it an optional setting for the user
5656
def __init__(self, name: str, vsrc: int, server: Optional[str] = None, port: Optional[int] = 9000, meta_ref: Optional[int] = 2):
@@ -167,15 +167,18 @@ def connect(self):
167167
find_lms_server = "bin/x64/find_lms_server"
168168
elif machine == "armv7l":
169169
find_lms_server = "bin/arm/find_lms_server"
170+
elif machine == "aarch64":
171+
find_lms_server = "bin/arm64/find_lms_server"
170172
else:
171173
self.meta.artist = "Unsupported CPU architecture for LMS MetaData"
172174
self.meta.album = "Please set 'server' in LMS config to an IP"
173175
self.meta.track = "or contact AmpliPi Support:support@micro-nova.com"
174176
self.logger.warning("LMS metadata reader has detected an unsupported chipset")
175177
self.logger.warning("Aborting LMS metadata search")
176178
break
179+
find_lms_server = "bin/arm64/find_lms_server"
177180

178-
# Much faster method of connecting to the metadata server using code from: https://github.com/ralph-irving/squeezelite/blob/master/tools/find_server.c
181+
# Much faster method of connecting to the metadata server using code from: https://github.com/ralph-irving/squeezelite/blob/master/tools/find_servers.c
179182
# faster relative to the original method, using NMAP to go door to door (ip to ip) and ask if self.name is home
180183
ip_find = subprocess.run([find_lms_server], check=True, capture_output=True, text=True)
181184
ip_output = ip_find.stdout.splitlines()

0 commit comments

Comments
 (0)