Using snapcast stream params for control_url; SSL explicit for Snapcast connection, fixes #775

This commit is contained in:
James Barnsley
2021-10-23 13:46:55 +13:00
parent 35b95306db
commit 6110ef8457
11 changed files with 202 additions and 80 deletions

View File

@ -1192,11 +1192,7 @@ class IrisCore(pykka.ThreadingActor):
##
async def update_snapcast_meta(self, *args, **kwargs):
track = self.core.playback.get_current_track().get()
# Append our server details, so Iris UI can switch to this Mopidy instance
# This isn't a great way of doing this, but it works for now.
meta = {
"control_url": self.config["iris"]["control_url"],
}
meta = {}
if track:
# Convert the Track to JSON, but to make it a response-ready JSON we need to load it.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -115,7 +115,7 @@
// Release details
// These are automatically injected to built HTML
var build = "1634632497";
var build = "1634948692";
var version = "3.59.1";
// Construct the script tag

View File

@ -21,30 +21,31 @@ const Header = ({ stream, server }) => {
const dispatch = useDispatch();
const {
id,
meta,
meta: {
name,
artists,
images: rawImages,
} = {},
status,
uri: {
path,
scheme,
query: {
control_url,
} = {},
},
} = stream || {};
let {
control_url,
images,
name,
artists,
} = meta || {};
const controlURL = meta?.control_url ? new URL(meta.control_url) : null;
const controlURL = control_url ? new URL(control_url) : null;
const controlServer = controlURL ? {
url: meta.control_url,
url: control_url,
ssl: controlURL.protocol === 'https:',
host: controlURL.hostname,
port: controlURL.port || (controlURL.protocol === 'https:' ? '443' : '80'),
} : null;
const images = rawImages ? formatImages(digestMopidyImages(controlServer, rawImages)) : null;
const current_server_id = useSelector((state) => state.mopidy.current_server);
const current_server = useSelector((state) => state.mopidy.servers[current_server_id]);
const isCurrentServer = control_url === current_server.url;
const isControlSwitchable = controlServer && !isCurrentServer;
if (images) images = formatImages(digestMopidyImages(controlServer, images));
const onClick = () => {
if (isControlSwitchable) {
@ -71,13 +72,13 @@ const Header = ({ stream, server }) => {
{control_url && <div className="tooltip__content">{control_url}</div>}
</h5>
<ul className="details">
<li>{name || path}</li>
<li>{name || scheme}</li>
{artists && <li><LinksSentence items={artists} type="artist" nolinks /></li>}
</ul>
</div>
</div>
);
}
};
const Group = ({
group: {
@ -160,9 +161,9 @@ const Outputs = () => {
groups,
};
return (
<div className="output-control__stream">
<div className="output-control__stream" key={`stream_${id}`}>
<Header stream={stream} />
{groups.map((group) => <Group group={group} /> )}
{groups.map((group) => <Group group={group} key={`group_${group.id}`} />)}
</div>
);
})}

View File

@ -9,7 +9,6 @@ import { Button } from './Button';
import * as mopidyActions from '../services/mopidy/actions';
import { iconFromKeyword } from '../util/helpers';
import { I18n } from '../locale';
import { decodeUri, encodeUri } from '../util/format';
const Server = () => {
const { id } = useParams();
@ -84,6 +83,11 @@ const Server = () => {
<I18n path="settings.servers.encryption.description" />
</span>
</span>
{!server.ssl && window.location.protocol === 'https:' && (
<span className="red-text">
<I18n path="settings.servers.encryption.incompatible" />
</span>
)}
</label>
</div>
</div>

View File

@ -19,6 +19,7 @@ const Snapcast = (props) => {
snapcast: {
host,
port,
ssl,
enabled,
streaming_enabled,
connected,
@ -30,10 +31,11 @@ const Snapcast = (props) => {
snapcast_enabled = false,
snapcast_host = 'localhost',
snapcast_port = '1780',
snapcast_ssl = false,
} = config || {};
actions.setEnabled(snapcast_enabled);
actions.setConnection({ host: snapcast_host, port: snapcast_port });
actions.setConnection({ host: snapcast_host, port: snapcast_port, ssl: snapcast_ssl });
}
return (
@ -111,6 +113,34 @@ const Snapcast = (props) => {
</div>
</div>
<div className="field checkbox">
<div className="name">
<I18n path="snapcast.encryption.label" />
</div>
<div className="input">
<label>
<input
type="checkbox"
name="ssl"
value={ssl}
checked={ssl}
onChange={() => actions.setConnection({ ssl: !ssl })}
/>
<span className="label tooltip">
<I18n path="snapcast.encryption.sublabel" />
<span className="tooltip__content">
<I18n path="snapcast.encryption.description" />
</span>
</span>
{!ssl && window.location.protocol === 'https:' && (
<span className="red-text">
<I18n path="snapcast.encryption.incompatible" />
</span>
)}
</label>
</div>
</div>
{connected && enabled && <SnapcastGroups match={match} history={history} />}
</div>
);

View File

@ -217,6 +217,11 @@ snapcast:
latency: Latency
stream: Stream
volume: Volume
encryption:
label: Encryption
sublabel: Use SSL
description: Requires a SSL proxy
incompatible: ' (required when connecting from a HTTPS browser session)'
authentication:
popup_blocked: Popup blocked. Please allow popups and try again.
failed: Authorization failed. %{origin} is not the configured authorization_url.
@ -438,6 +443,7 @@ settings:
label: Encryption
sublabel: Use SSL
description: Requires a SSL proxy
incompatible: ' (required when connecting from a HTTPS browser session)'
switch: Switch to this server
reconnect: Reconnect
services:

View File

@ -167,9 +167,9 @@ const SnapcastMiddleware = (function () {
clearTimeout(reconnectTimer);
store.dispatch({ type: 'SNAPCAST_CONNECTING' });
const { host, port, ssl } = store.getState().snapcast;
socket = new WebSocket(
`ws${window.location.protocol === 'https:' ? 's' : ''}://${store.getState().snapcast.host}:${store.getState().snapcast.port}/jsonrpc`,
`ws${ssl ? 's' : ''}://${host}:${port}/jsonrpc`,
);
socket.onopen = () => {

View File

@ -106,6 +106,7 @@ let initialState = {
connected: false,
host: 'localhost',
port: '1780',
ssl: false,
streams: {},
groups: {},
clients: {},