Removing Icecast; Adding Snapcast websocket streaming (from SnapWeb); Adding new snapcast broadcast events, fixes #612

This commit is contained in:
James Barnsley
2020-10-02 22:28:03 +13:00
parent 446a0c9917
commit 555d7e717a
19 changed files with 995 additions and 1242 deletions

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

@ -106,7 +106,7 @@
// Release details
// These are automatically injected to built HTML
var build = "1601538533";
var build = "1601627320";
var version = "3.52.4";
// Construct the script tag

View File

@ -153,42 +153,8 @@ class OutputControl extends React.Component {
);
}
localStreaming() {
const {
http_streaming_enabled,
http_streaming_volume,
http_streaming_mute,
coreActions,
} = this.props;
if (!http_streaming_enabled) return null;
return (
<div className="output-control__item outputs__item--icecast">
<div className="output-control__item__name">
Local browser
</div>
<div className="output-control__item__controls">
<MuteControl
className="output-control__item__mute"
noTooltip
mute={http_streaming_mute}
onMuteChange={(mute) => coreActions.set({ http_streaming_mute: mute })}
/>
<VolumeControl
className="output-control__item__volume"
volume={http_streaming_volume}
mute={http_streaming_mute}
onVolumeChange={(percent) => coreActions.set({ http_streaming_volume: percent })}
/>
</div>
</div>
);
}
renderOutputs() {
const snapcastGroups = this.snapcastGroups();
const localStreaming = this.localStreaming();
const commands = this.commands();
if (!snapcastGroups && !localStreaming && !commands) {
@ -220,7 +186,7 @@ class OutputControl extends React.Component {
}
// No customisable outputs
if (!this.props.http_streaming_enabled && !this.props.snapcast_enabled && !this.props.pusher_commands) {
if (!this.props.snapcast_enabled && !this.props.pusher_commands) {
return (
<span className="output-control disabled">
<button className="control speakers"><Icon name="speaker" /></button>
@ -235,10 +201,7 @@ class OutputControl extends React.Component {
}
}
const mapStateToProps = (state, ownProps) => ({
http_streaming_enabled: state.core.http_streaming_enabled,
http_streaming_volume: parseInt(state.core.http_streaming_volume) || 50,
http_streaming_mute: state.core.http_streaming_mute,
const mapStateToProps = (state) => ({
pusher_connected: state.pusher.connected,
snapcast_enabled: (state.pusher.config ? state.pusher.config.snapcast_enabled : null),
show_disconnected_clients: (state.ui.snapcast_show_disconnected_clients !== undefined ? state.ui.snapcast_show_disconnected_clients : false),

View File

@ -278,47 +278,6 @@ class Services extends React.Component {
);
}
renderIcecast() {
const { core, coreActions } = this.props;
return (
<div>
<div className="field checkbox">
<div className="name">
<I18n path="settings.services.icecast.enable.label" />
</div>
<div className="input">
<label>
<input
type="checkbox"
name="ssl"
checked={core.http_streaming_enabled}
onChange={() => coreActions.set({ http_streaming_enabled: !core.http_streaming_enabled })}
/>
<span className="label">
<I18n path="settings.services.icecast.enable.description" />
</span>
</label>
</div>
</div>
<label className="field">
<div className="name">
<I18n path="settings.services.icecast.location.label" />
</div>
<div className="input">
<TextField
onChange={(value) => coreActions.set({ http_streaming_url: value })}
value={core.http_streaming_url}
autosave
/>
<div className="description">
<I18n path="settings.services.icecast.location.description" />
</div>
</div>
</label>
</div>
);
}
renderMenu() {
if (this.props.spotify.me && this.props.core.users[this.props.spotify.me.uri]) {
var spotify_icon = <Thumbnail className="menu-item__thumbnail" circle size="small" images={this.props.core.users[this.props.spotify.me.uri].images} />;
@ -415,23 +374,6 @@ class Services extends React.Component {
)}
</div>
</Link>
<Link history={this.props.history} className="menu-item menu-item--icecast" activeClassName="menu-item--active" to="/settings/services/icecast" scrollTo="#services-menu">
<div className="menu-item__inner">
<Icon className="menu-item__icon" name="wifi_tethering" />
<div className="menu-item__title">
<I18n path="services.icecast.title" />
</div>
{this.props.core.http_streaming_enabled ? (
<span className="status green-text">
<I18n path="settings.services.enabled" />
</span>
) : (
<span className="status mid_grey-text">
<I18n path="settings.services.disabled" />
</span>
)}
</div>
</Link>
</div>
</div>
);
@ -446,8 +388,6 @@ class Services extends React.Component {
return <div className="sub-tabs__content">{this.renderLastfm()}</div>;
case 'genius':
return <div className="sub-tabs__content">{this.renderGenius()}</div>;
case 'icecast':
return <div className="sub-tabs__content">{this.renderIcecast()}</div>;
case 'snapcast':
return <div className="sub-tabs__content">{<Snapcast match={this.props.match} />}</div>;
default:
@ -465,7 +405,7 @@ class Services extends React.Component {
}
}
const mapStateToProps = (state, ownProps) => state;
const mapStateToProps = (state) => state;
const mapDispatchToProps = (dispatch) => ({
coreActions: bindActionCreators(coreActions, dispatch),

File diff suppressed because it is too large Load Diff

View File

@ -72,7 +72,7 @@ const SnapcastClients = ({ actions, group, clients, groups }) => {
</div>
<div className="input">
<LatencyControl
max="150"
max="500"
value={client.latency}
onChange={(value) => actions.setClientLatency(client.id, parseInt(value))}
/>

View File

@ -9,31 +9,79 @@ class Stream extends React.Component {
constructor(props) {
super(props);
console.log(props);
if (props.enabled && props.streaming_enabled) {
this.snapstream = new SnapStream('192.168.1.201', 1780);
this.start();
}
}
start = () => {
const {
host,
port,
ssl,
username,
} = this.props;
if (this.snapstream) {
this.snapstream.play();
} else {
const protocol = (ssl ? 'wss' : 'ws');
console.log(protocol, host, port, username);
this.snapstream = new SnapStream(protocol, host, port, 'Iris');
}
}
stop = () => {
if (this.snapstream) {
this.snapstream.stop();
this.snapstream = null;
}
}
componentDidUpdate = () => {
const { enabled, streaming_enabled } = this.props;
componentDidUpdate = ({
streaming_enabled: prevStreamingEnabled,
}) => {
const {
enabled,
streaming_enabled,
} = this.props;
if (enabled && streaming_enabled && !this.snapstream) {
this.snapstream = new SnapStream('192.168.1.201', 1780);
if (!prevStreamingEnabled && enabled && streaming_enabled) {
this.start();
}
if ((!enabled || !streaming_enabled) && this.snapstream) {
this.snapstream = null;
if (!enabled || !streaming_enabled) {
this.stop();
}
}
render = () => null;
}
const mapStateToProps = (state) => ({
enabled: state.snapcast.enabled,
streaming_enabled: state.snapcast.streaming_enabled,
});
const mapStateToProps = (state) => {
const {
snapcast: {
enabled,
streaming_enabled,
host,
port,
ssl,
},
pusher: {
username,
},
} = state;
return {
enabled,
streaming_enabled,
host,
port,
ssl,
username,
};
};
const mapDispatchToProps = (dispatch) => ({
coreActions: bindActionCreators(coreActions, dispatch),

View File

@ -118,8 +118,6 @@ services:
want_lyrics: 'Wollen Sie Liedtexte? Genius autorisieren in '
google:
title: Google
icecast:
title: Icecast
lastfm:
title: LastFM
love: Liebe es
@ -385,13 +383,6 @@ settings:
locale:
title: Sprache
description: ISO 639 Sprachcode in Kleinbuchstaben und ein großgeschriebener ISO 3166-1 alpha-2 Ländercode, verbunden mit einem Unterstrich (z.B. 'de_DE')
icecast:
enable:
label: Aktivieren
description: Audio an diesen Browser streamen
location:
label: Standort
description: Die vollständige URL zu Ihrem Stream-Endpunkt
user:
title: Benutzer
title_window: '%{name} (Benutzer)'

View File

@ -130,8 +130,6 @@ services:
want_lyrics: 'Want track lyrics? Authorize Genius in '
google:
title: Google
icecast:
title: Icecast
lastfm:
title: LastFM
love: Love
@ -415,13 +413,6 @@ settings:
locale:
title: Locale
description: Lowercase ISO 639 language code and an uppercase ISO 3166-1 alpha-2 country code, joined by an underscore (eg 'en_NZ')
icecast:
enable:
label: Enable
description: Stream audio to this browser
location:
label: Location
description: The full URL to your stream endpoint
user:
title: User
title_window: '%{name} (user)'

View File

@ -129,8 +129,6 @@ services:
want_lyrics: 'Vous voulez les paroles ? Autorisez Genius sous '
google:
title: Google
icecast:
title: Icecast
lastfm:
title: LastFM
love: Aimer
@ -408,13 +406,6 @@ settings:
locale:
title: Locale
description: Code de langage ISO 639 en minuscules et code de pays ISO 3166-1 alpha-2 en majucule, séparés par un tiret bas (par exemple 'fr_FR')
icecast:
enable:
label: Activer
description: Envoyer le flux audio sur ce navigateur
location:
label: Adresse
description: URL du flux audio
user:
title: Utilisateur
title_window: '%{name} (utilisateur)'

View File

@ -125,8 +125,6 @@ services:
want_lyrics: 'Wil je songteksten? Geef Genius toestemming in '
google:
title: Google
icecast:
title: Icecast
lastfm:
title: LastFM
love: Leuk
@ -391,13 +389,6 @@ settings:
locale:
title: Taal
description: Een ISO 639 taalcode in kleine letters en een ISO 3166-1 alpha-2 landcode in hoofdletters, verbonden met een liggend streepje (bv 'nl_NL' of 'nl_BE')
icecast:
enable:
label: Actief
description: Stream audio naar deze browser
location:
label: Locatie
description: De volledige URL naar het stream-eindpunt
user:
title: Gebruiker
title_window: '%{name} (gebruiker)'

9
src/js/locale/sv.yaml Normal file → Executable file
View File

@ -129,8 +129,6 @@ services:
want_lyrics: 'Vill du ha låttext? auktorisera Genius i '
google:
title: Google
icecast:
title: Icecast
lastfm:
title: LastFM
love: Love
@ -410,13 +408,6 @@ settings:
locale:
title: Språk
description: Gemen ISO 639 språkkod och en versal ISO 3166-1 alpha-2 landskod, tillsammans med ett understreck (ex 'sv_SE')
icecast:
enable:
label: Aktivera
description: Spela ljud till denna webbläsare
location:
label: Location
description: The full URL to your stream endpoint
user:
title: Användare
title_window: '%{name} (user)'

View File

@ -151,14 +151,6 @@ export function calculateGroupVolume(id, clients) {
};
}
/**
* Record loaders
*
* We've got a loaded record, now we just need to plug it in to our state and stores.
* */
export function serverLoaded(server) {
return {
type: 'SNAPCAST_SERVER_LOADED',

View File

@ -96,8 +96,14 @@ const SnapcastMiddleware = (function () {
store.dispatch(snapcastActions.groupLoaded(message.params));
break;
case 'Group.OnNameChanged':
store.dispatch(snapcastActions.groupLoaded(message.params));
break;
case 'Server.OnUpdate':
store.dispatch(snapcastActions.serverLoaded(message.param));
store.dispatch(snapcastActions.serverLoaded(message.params.server.server));
store.dispatch(snapcastActions.groupsLoaded(message.params.server.groups, true));
store.dispatch(snapcastActions.streamsLoaded(message.params.server.streams, true));
break;
default:
@ -330,24 +336,23 @@ const SnapcastMiddleware = (function () {
next(action);
break;
case 'SNAPCAST_CLIENTS_LOADED':
var clients_index = { ...snapcast.clients };
var clients_loaded = [];
case 'SNAPCAST_CLIENTS_LOADED': {
const nextClients = action.flush ? {} : { ...snapcast.clients };
for (const raw_client of action.clients) {
var client = formatClient(raw_client);
if (clients_index[client.id]) {
client = { ...clients_index[client.id], ...client };
}
clients_loaded.push(client);
const client = formatClient(raw_client);
nextClients[client.id] = {
...nextClients[client.id],
...client,
};
}
action.clients = clients_loaded;
next(action);
next({
...action,
clients: nextClients,
});
break;
}
case 'SNAPCAST_SET_CLIENT_NAME':
var client = snapcast.clients[action.id];

View File

@ -17,16 +17,7 @@ export default function reducer(snapcast = {}, action) {
return { ...snapcast, server: action.server };
case 'SNAPCAST_CLIENTS_LOADED':
if (action.flush) {
var clients = {};
} else {
var clients = { ...snapcast.clients };
}
for (const client of action.clients) {
clients[client.id] = client;
}
return { ...snapcast, clients };
return { ...snapcast, clients: action.clients };
case 'SNAPCAST_GROUPS_LOADED':
if (action.flush) {

View File

@ -712,7 +712,7 @@ const formatClient = function (data) {
if (data.volume.percent) {
client.volume = data.volume.percent;
}
if (data.volume.muted) {
if (data.volume.muted !== undefined) {
client.mute = data.volume.muted;
}
}

View File

@ -496,6 +496,10 @@ const iconFromKeyword = (name) => {
icon: 'smartphone',
words: ['phone', 'mobile']
},
{
icon: 'web',
words: ['web', 'browser', 'iris']
},
];
for (let item of iconWords) {
for (let word of item.words) {