Skip to content

Commit 6d38211

Browse files
committed
Add snapcast support for client & server
1 parent f1e47c4 commit 6d38211

File tree

4 files changed

+128
-20
lines changed

4 files changed

+128
-20
lines changed

assets/jquery-3.5.1.min.js

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cgi-bin/applyConfig.php

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
<?php
22
require(__DIR__ . "/config.php");
33

4+
// 23 == 0dB capture gain
5+
`amixer cset name='Capture Volume' 23`;
6+
47
if ($config['CONFIG_AIRPLAY_ACTIVE'])
58
{
69
`systemctl start shairport-sync`;
@@ -28,19 +31,47 @@
2831
`systemctl stop librespot`;
2932
}
3033

34+
if ($config['CONFIG_LINEIN_STREAM_ACTIVE'])
35+
{
36+
`systemctl start snapserver`;
37+
}
38+
else
39+
{
40+
`systemctl stop snapserver`;
41+
}
42+
43+
if ($config['CONFIG_SNAPCAST_CLIENT_ACTIVE'])
44+
{
45+
$snapclient_config = 'START_SNAPCLIENT=true' . "\n" .
46+
'SNAPCLIENT_OPTS="-h ' . escapeshellarg($config['CONFIG_SNAPCAST_CLIENT_HOST']) . '"' . "\n";
47+
$snapclient_config_path = "/etc/default/snapclient";
48+
if (file_get_contents($snapclient_config_path) != $snapclient_config)
49+
{
50+
file_put_contents($snapclient_config_path, $snapclient_config);
51+
`systemctl restart snapclient`;
52+
}
53+
else
54+
{
55+
`systemctl start snapclient`;
56+
}
57+
}
58+
else
59+
{
60+
`systemctl stop snapclient`;
61+
}
3162

3263
$wpaconf = 'ctrl_interface=/var/run/wpa_supplicant
3364
#ap_scan=1
3465
3566
network={
36-
ssid="'. $config['CONFIG_WIFI_SSID'] .'"
37-
scan_ssid=1
38-
key_mgmt=WPA-PSK
39-
psk="'. $config['CONFIG_WIFI_PSK'] .'"
67+
ssid="'. $config['CONFIG_WIFI_SSID'] .'"
68+
scan_ssid=1
69+
key_mgmt=WPA-PSK
70+
psk="'. $config['CONFIG_WIFI_PSK'] .'"
4071
}
4172
';
4273

43-
$wpaconfPath = "/etc/wpa_supplicant/wpa_supplicant-wlan0.conf";
74+
$wpaconfPath = "/etc/wpa_supplicant/wpa_supplicant-wlan0.conf";
4475
if (file_get_contents($wpaconfPath) != $wpaconf)
4576
{
4677
file_put_contents($wpaconfPath, $wpaconf);
@@ -72,6 +103,14 @@
72103
{
73104
`systemctl restart librespot`;
74105
}
106+
if ($config['CONFIG_SNAPCAST_CLIENT_ACTIVE'])
107+
{
108+
`systemctl restart snapclient`;
109+
}
110+
if ($config['CONFIG_LINEIN_STREAM_ACTIVE'])
111+
{
112+
`systemctl restart snapserver`;
113+
}
75114

76115
$restarted_services = true;
77116

cgi-bin/ottercast

Lines changed: 80 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,10 @@ if (isset($_POST['ssid']))
2323
$new_config .= "CONFIG_PULSEAUDIO_ACTIVE=" . escapeshellarg($_POST['pulseaudio'] == 'active' ? '1' : '0') . "\n";
2424
$new_config .= "CONFIG_PULSEAUDIO_LATENCY=" . escapeshellarg($config['CONFIG_PULSEAUDIO_LATENCY']) . "\n";
2525
$new_config .= "CONFIG_LIBRESPOT_ACTIVE=" . escapeshellarg($_POST['librespot'] == 'active' ? '1' : '0') . "\n";
26+
$new_config .= "CONFIG_SNAPCAST_CLIENT_ACTIVE=" . escapeshellarg($_POST['snapclient'] == 'active' ? '1' : '0') . "\n";
27+
$new_config .= "CONFIG_SNAPCAST_CLIENT_HOST=" . escapeshellarg($_POST['snapclienthost']) . "\n";
2628

2729
$new_config .= "CONFIG_LINEIN_STREAM_ACTIVE=" . escapeshellarg($_POST['linein'] == 'active' ? '1' : '0') . "\n";
28-
$new_config .= "CONFIG_LINEIN_STREAM_TARGET=" . escapeshellarg($_POST['lineintarget']) . "\n";
2930

3031

3132
file_put_contents("/mnt/config.sh", $new_config);
@@ -118,14 +119,45 @@ $loadavg = $loadavg[0] . ", " . $loadavg[1] . ", " . $loadavg[2];
118119
-ms-user-select: none;
119120
margin-right: 20px;
120121
}
122+
123+
label.form-check-label {
124+
user-drag: none;
125+
user-select: none;
126+
-moz-user-select: none;
127+
-webkit-user-drag: none;
128+
-webkit-user-select: none;
129+
-ms-user-select: none;
130+
}
131+
132+
.bd-callout {
133+
padding: 1.25rem;
134+
/* margin-top: 1.25rem; */
135+
margin-bottom: 1.25rem;
136+
border: 1px solid #e9ecef;
137+
border-left-width: .25rem;
138+
border-radius: .25rem;
139+
background-color: #ffffff;
140+
}
141+
.bd-callout-info {
142+
border-left-color: #5bc0de !important;
143+
}
144+
145+
.bd-callout-warning {
146+
border-left-color: #f0ad4e
147+
}
148+
149+
.bd-callout-danger {
150+
border-left-color: #d9534f
151+
}
152+
121153
</style>
122154

123155

124156
<!-- Custom styles for this template -->
125157
<link href="assets/form-validation.css" rel="stylesheet">
126158
</head>
127159
<body class="bg-light">
128-
160+
129161
<header class="d-flex flex-column flex-md-row align-items-center p-3 px-md-4 mb-3 bg-body border-bottom shadow-sm">
130162
<div class="mx-auto">
131163
<a href="/cgi-bin/ottercast" class="text-decoration-none text-reset">
@@ -204,7 +236,7 @@ $loadavg = $loadavg[0] . ", " . $loadavg[1] . ", " . $loadavg[2];
204236
</ul>
205237
</div>
206238
<div class="col-md-7 col-lg-8">
207-
<form class="needs-validation" novalidate action="/cgi-bin/ottercast" method="POST">
239+
<form class="needs-validation" novalidate action="/cgi-bin/ottercast" method="POST" id="settingsform">
208240
<div class="col-12">
209241
<label for="hostname" class="form-label">Display name</label>
210242
<input type="text" class="form-control" name="hostname" id="hostname" placeholder="OtterCast Bathroom" value="<?php echo htmlspecialchars($config["CONFIG_DISPLAY_NAME"]); ?>" pattern="[A-Za-z0-9\-]{3,50}" required>
@@ -255,22 +287,28 @@ $loadavg = $loadavg[0] . ", " . $loadavg[1] . ", " . $loadavg[2];
255287
<label class="form-check-label" for="librespot">Spotify Connect (librespot)</label>
256288
</div>
257289

290+
<div class="form-check">
291+
<input type="checkbox" class="form-check-input" name="snapclient" id="snapclient" value="active" <?php if ($config["CONFIG_SNAPCAST_CLIENT_ACTIVE"]) echo "checked"; ?>>
292+
<label class="form-check-label" for="snapclient">Snapcast Client</label>
293+
</div>
294+
<div class="col-12 bd-callout bd-callout-info" id="snapclienthostdiv">
295+
<label for="snapclienthost" class="form-label">Snapcast Server (IP/hostname)</label>
296+
<input type="text" class="form-control" name="snapclienthost" id="snapclienthost" placeholder="ottercast2.local" value="<?php echo htmlspecialchars($config["CONFIG_SNAPCAST_CLIENT_HOST"]); ?>">
297+
<div class="invalid-feedback">
298+
Please enter a valid hostname or IP address.
299+
</div>
300+
</div>
301+
258302
<hr class="my-4">
259303

260-
<h4 class="mb-3">Line-In Streaming</h4>
261-
<div class="mb-2 small">OtterCast is able to stream the Line-In port directly to another OtterCast or networked PulseAudio device.
262-
Make sure "PulseAudio Sink" protocol is active on the receiver and set the correct target hostname. Avahi/mDNS can be used with the ".local" suffix.</div>
304+
<h4 class="mb-3">Line-In Streaming (Snapcast Server)</h4>
305+
<div class="mb-2 small bd-callout bd-callout-info">OtterCast is able to stream the Line-In port directly to another OtterCast or <a href="https://github.com/badaix/snapcast/" target="_blank">Snapcast Client</a>.<br>
306+
Make sure "Snapcast Client" protocol is active on the receiver. <br>Avahi/mDNS can be used with the ".local" suffix.</div>
263307
<div class="form-check">
264308
<input type="checkbox" class="form-check-input mb-3" name="linein" id="linein" value="active" <?php if ($config["CONFIG_LINEIN_STREAM_ACTIVE"]) echo "checked"; ?>>
265-
<label class="form-check-label" for="linein">Streaming active</label>
309+
<label class="form-check-label" for="linein">Streaming server active</label>
266310
</div>
267-
<div class="col-12">
268-
<label for="ssid" class="form-label">Target (IP/hostname)</label>
269-
<input type="text" class="form-control" name="lineintarget" id="lineintarget" placeholder="ottercast2.local" value="<?php echo htmlspecialchars($config["CONFIG_LINEIN_STREAM_TARGET"]); ?>">
270-
<div class="invalid-feedback">
271-
Please enter a valid hostname or IP address.
272-
</div>
273-
</div>
311+
274312

275313
<hr class="my-4">
276314

@@ -290,7 +328,35 @@ $loadavg = $loadavg[0] . ", " . $loadavg[1] . ", " . $loadavg[2];
290328
</footer>
291329
</div>
292330

331+
<script
332+
src="assets/jquery-3.5.1.min.js"
333+
integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0="
334+
></script>
293335
<script src="assets/bootstrap.bundle.min.js"></script>
294336
<script src="assets/form-validation.js"></script>
337+
338+
<script type="text/javascript">
339+
function eval_snapclient_checkbox()
340+
{
341+
var snapclienthostdiv = $('#snapclienthostdiv');
342+
if($('#snapclient').is(':checked'))
343+
{
344+
snapclienthostdiv.show();
345+
snapclienthostdiv.find('input').attr('required', true);
346+
} else {
347+
snapclienthostdiv.hide();
348+
snapclienthostdiv.find('input').attr('required', false);
349+
}
350+
}
351+
352+
$(function()
353+
{
354+
var snapclienthostdiv = $('#snapclienthostdiv');
355+
snapclienthostdiv.hide();
356+
357+
$('#snapclient').on('change', eval_snapclient_checkbox);
358+
eval_snapclient_checkbox();
359+
});
360+
</script>
295361
</body>
296362
</html>

example_config.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ CONFIG_AIRPLAY_ACTIVE='1'
55
CONFIG_PULSEAUDIO_ACTIVE='1'
66
CONFIG_PULSEAUDIO_LATENCY='8'
77
CONFIG_LIBRESPOT_ACTIVE='1'
8+
CONFIG_SNAPCAST_CLIENT_ACTIVE='0'
9+
CONFIG_SNAPCAST_CLIENT_HOST=''
810
CONFIG_LINEIN_STREAM_ACTIVE='0'
9-
CONFIG_LINEIN_STREAM_TARGET=''

0 commit comments

Comments
 (0)