Snapcast fully operational
This commit is contained in:
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@ -100,7 +100,7 @@
|
||||
|
||||
// Release details
|
||||
// These are automatically injected to built HTML
|
||||
var build = "1571860001";
|
||||
var build = "1571990280";
|
||||
var version = "3.41.2";
|
||||
|
||||
// Construct the script tag
|
||||
|
||||
@ -94,6 +94,9 @@ export class App extends React.Component {
|
||||
// Fire up our services
|
||||
this.props.mopidyActions.connect();
|
||||
this.props.pusherActions.connect();
|
||||
if (this.props.snapcast_enabled) {
|
||||
this.props.snapcastActions.connect();
|
||||
}
|
||||
this.props.coreActions.getBroadcasts();
|
||||
|
||||
// Check for url-parsed configuration values
|
||||
@ -358,6 +361,7 @@ const mapStateToProps = (state, ownProps) => ({
|
||||
initial_setup_complete: state.ui.initial_setup_complete,
|
||||
slim_mode: state.ui.slim_mode,
|
||||
mopidy_connected: state.mopidy.connected,
|
||||
snapcast_enabled: state.snapcast.enabled,
|
||||
spotify_authorized: state.spotify.authorization,
|
||||
sidebar_open: state.ui.sidebar_open,
|
||||
dragging: state.ui.dragger && state.ui.dragger.active,
|
||||
|
||||
@ -72,26 +72,26 @@ class OutputControl extends React.Component {
|
||||
snapcast_clients = (
|
||||
<div>
|
||||
{
|
||||
clients.map((client) => (
|
||||
<div className="output-control__item outputs__item--snapcast" key={client.id}>
|
||||
<div className="output-control__item__name">
|
||||
{client.name}
|
||||
</div>
|
||||
<div className="output-control__item__controls">
|
||||
<MuteControl
|
||||
className="output-control__item__mute"
|
||||
noTooltip
|
||||
mute={client.mute}
|
||||
onMuteChange={(mute) => this.props.snapcastActions.setClientMute(client.id, mute)}
|
||||
/>
|
||||
<VolumeControl
|
||||
className="output-control__item__volume"
|
||||
volume={client.volume}
|
||||
mute={client.mute}
|
||||
onVolumeChange={(percent) => this.props.snapcastActions.setClientVolume(client.id, percent)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
clients.map(client => (
|
||||
<div className="output-control__item outputs__item--snapcast" key={client.id}>
|
||||
<div className="output-control__item__name">
|
||||
{client.name}
|
||||
</div>
|
||||
<div className="output-control__item__controls">
|
||||
<MuteControl
|
||||
className="output-control__item__mute"
|
||||
noTooltip
|
||||
mute={client.mute}
|
||||
onMuteChange={(mute) => this.props.snapcastActions.setClientMute(client.id, mute)}
|
||||
/>
|
||||
<VolumeControl
|
||||
className="output-control__item__volume"
|
||||
volume={client.volume}
|
||||
mute={client.mute}
|
||||
onVolumeChange={(percent) => this.props.snapcastActions.setClientVolume(client.id, percent)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
|
||||
@ -359,7 +359,15 @@ class Services extends React.Component {
|
||||
<div className="menu-item__title">
|
||||
Snapcast
|
||||
</div>
|
||||
{this.props.pusher.config.snapcast_enabled ? <span className="status green-text">Enabled</span> : <span className="status mid_grey-text">Disabled</span>}
|
||||
{!this.props.snapcast.enabled && (
|
||||
<span className="status mid_grey-text">Disabled</span>
|
||||
)}
|
||||
{this.props.snapcast.enabled && !this.props.snapcast.connected && (
|
||||
<span className="status red-text">Disconnected</span>
|
||||
)}
|
||||
{this.props.snapcast.enabled && this.props.snapcast.connected && (
|
||||
<span className="status green-text">Connected</span>
|
||||
)}
|
||||
</div>
|
||||
</Link>
|
||||
<Link history={this.props.history} className="menu-item menu-item--icecast" activeClassName="menu-item--active" to="/settings/icecast" scrollTo="#services-menu">
|
||||
|
||||
@ -64,7 +64,7 @@ class Snapcast extends React.Component {
|
||||
if (!clients || clients.length <= 0) {
|
||||
return (
|
||||
<div className="text mid_grey-text">
|
||||
No clients
|
||||
No clients
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -72,116 +72,121 @@ class Snapcast extends React.Component {
|
||||
return (
|
||||
<div className="list snapcast__clients">
|
||||
{
|
||||
clients.map((client) => {
|
||||
let class_name = 'list__item list__item--no-interaction snapcast__client';
|
||||
if (client.connected) {
|
||||
class_name += ' snapcast__client--connected';
|
||||
} else {
|
||||
class_name += ' snapcast__client--disconnected';
|
||||
}
|
||||
clients.map((client) => {
|
||||
let class_name = 'list__item list__item--no-interaction snapcast__client';
|
||||
if (client.connected) {
|
||||
class_name += ' snapcast__client--connected';
|
||||
} else {
|
||||
class_name += ' snapcast__client--disconnected';
|
||||
}
|
||||
|
||||
if (this.state.clients_expanded.includes(client.id)) {
|
||||
return (
|
||||
<div className={`${class_name} snapcast__client--expanded`} key={client.id}>
|
||||
<div className="snapcast__client__header" onClick={(e) => this.toggleClientExpanded(client.id)}>
|
||||
{client.name}
|
||||
<div className="snapcast__client__header__icons">
|
||||
{!client.connected ? <Icon name="power_off" className="disconnected" /> : null}
|
||||
<Icon name="expand_less" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="snapcast__client__details">
|
||||
<label className="field">
|
||||
<div className="name">
|
||||
Name
|
||||
</div>
|
||||
<div className="input">
|
||||
<TextField
|
||||
onChange={(value) => actions.setClientName(client.id, value)}
|
||||
value={client.name}
|
||||
/>
|
||||
</div>
|
||||
</label>
|
||||
<label className="field dropdown">
|
||||
<div className="name">
|
||||
Group
|
||||
</div>
|
||||
<div className="input">
|
||||
<select onChange={(e) => actions.setClientGroup(client.id, e.target.value)} value={group.id}>
|
||||
{
|
||||
groups.map((group) => (
|
||||
<option value={group.id} key={group.id}>
|
||||
{group.name ? group.name : `Group ${group.id.substring(0, 3)}`}
|
||||
</option>
|
||||
))
|
||||
}
|
||||
<option value={group.id}>
|
||||
New group
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</label>
|
||||
<div className="snapcast__client__volume field">
|
||||
<div className="name">
|
||||
Volume
|
||||
</div>
|
||||
<div className="input">
|
||||
<MuteControl
|
||||
className="snapcast__client__mute-control"
|
||||
mute={client.mute}
|
||||
onMuteChange={(mute) => actions.setClientMute(client.id, mute)}
|
||||
/>
|
||||
<VolumeControl
|
||||
className="snapcast__client__volume-control"
|
||||
volume={client.volume}
|
||||
onVolumeChange={(percent) => actions.setClientVolume(client.id, percent)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="snapcast__client__latency field">
|
||||
<div className="name">
|
||||
Latency
|
||||
</div>
|
||||
<div className="input">
|
||||
<LatencyControl
|
||||
max="150"
|
||||
value={client.latency}
|
||||
onChange={(value) => actions.setClientLatency(client.id, parseInt(value))}
|
||||
/>
|
||||
<TextField
|
||||
className="tiny"
|
||||
type="number"
|
||||
onChange={(value) => actions.setClientLatency(client.id, parseInt(value))}
|
||||
value={String(client.latency)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div className={`${class_name} snapcast__client--collapsed`} key={client.id}>
|
||||
<div className="snapcast__client__header" onClick={(e) => this.toggleClientExpanded(client.id)}>
|
||||
{client.name}
|
||||
<div className="snapcast__client__header__icons">
|
||||
{!client.connected ? <Icon name="power_off" className="disconnected" /> : null}
|
||||
<Icon name="expand_more" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})
|
||||
}
|
||||
if (this.state.clients_expanded.includes(client.id)) {
|
||||
return (
|
||||
<div className={`${class_name} snapcast__client--expanded`} key={client.id}>
|
||||
<div className="snapcast__client__header" onClick={(e) => this.toggleClientExpanded(client.id)}>
|
||||
{client.name}
|
||||
<div className="snapcast__client__header__icons">
|
||||
{!client.connected ? <Icon name="power_off" className="disconnected" /> : null}
|
||||
<Icon name="expand_less" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="snapcast__client__details">
|
||||
<label className="field">
|
||||
<div className="name">
|
||||
Name
|
||||
</div>
|
||||
<div className="input">
|
||||
<TextField
|
||||
onChange={(value) => actions.setClientName(client.id, value)}
|
||||
value={client.name}
|
||||
/>
|
||||
</div>
|
||||
</label>
|
||||
<label className="field dropdown">
|
||||
<div className="name">
|
||||
Group
|
||||
</div>
|
||||
<div className="input">
|
||||
<select onChange={(e) => actions.setClientGroup(client.id, e.target.value)} value={group.id}>
|
||||
{
|
||||
groups.map((group) => (
|
||||
<option value={group.id} key={group.id}>
|
||||
{group.name ? group.name : `Group ${group.id.substring(0, 3)}`}
|
||||
</option>
|
||||
))
|
||||
}
|
||||
<option value={group.id}>
|
||||
New group
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</label>
|
||||
<div className="snapcast__client__volume field">
|
||||
<div className="name">
|
||||
Volume
|
||||
</div>
|
||||
<div className="input">
|
||||
<MuteControl
|
||||
className="snapcast__client__mute-control"
|
||||
mute={client.mute}
|
||||
onMuteChange={(mute) => actions.setClientMute(client.id, mute)}
|
||||
/>
|
||||
<VolumeControl
|
||||
className="snapcast__client__volume-control"
|
||||
volume={client.volume}
|
||||
onVolumeChange={(percent) => actions.setClientVolume(client.id, percent)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="snapcast__client__latency field">
|
||||
<div className="name">
|
||||
Latency
|
||||
</div>
|
||||
<div className="input">
|
||||
<LatencyControl
|
||||
max="150"
|
||||
value={client.latency}
|
||||
onChange={(value) => actions.setClientLatency(client.id, parseInt(value))}
|
||||
/>
|
||||
<TextField
|
||||
className="tiny"
|
||||
type="number"
|
||||
onChange={(value) => actions.setClientLatency(client.id, parseInt(value))}
|
||||
value={String(client.latency)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div className={`${class_name} snapcast__client--collapsed`} key={client.id}>
|
||||
<div className="snapcast__client__header" onClick={(e) => this.toggleClientExpanded(client.id)}>
|
||||
{client.name}
|
||||
<div className="snapcast__client__header__icons">
|
||||
{!client.connected ? <Icon name="power_off" className="disconnected" /> : null}
|
||||
<Icon name="expand_more" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
enabled,
|
||||
snapcastActions: actions,
|
||||
uiActions,
|
||||
snapcast: {
|
||||
host,
|
||||
port,
|
||||
enabled,
|
||||
connected,
|
||||
},
|
||||
} = this.props;
|
||||
|
||||
const streams = [];
|
||||
@ -202,13 +207,14 @@ class Snapcast extends React.Component {
|
||||
<div className="snapcast">
|
||||
|
||||
<div className="field checkbox">
|
||||
<div className="name">Enabled</div>
|
||||
<div className="input">
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
name="enabled"
|
||||
checked={enabled}
|
||||
onChange={() => actions.setEnabled(!enabled)}
|
||||
onChange={() => actions.set({ enabled: !enabled })}
|
||||
/>
|
||||
<span className="label">
|
||||
Enabled
|
||||
@ -222,93 +228,107 @@ class Snapcast extends React.Component {
|
||||
onChange={() => uiActions.set({ snapcast_show_disconnected_clients: !this.props.show_disconnected_clients })}
|
||||
/>
|
||||
<span className="label">
|
||||
Show disconnected clients
|
||||
Show disconnected clients
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="field">
|
||||
<div className="name">Host</div>
|
||||
<div className="input">
|
||||
<TextField
|
||||
value={host}
|
||||
onChange={value => actions.set({ host: value })}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="field">
|
||||
<div className="name">Port</div>
|
||||
<div className="input">
|
||||
<TextField
|
||||
value={port}
|
||||
onChange={value => actions.set({ port: value })}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="snapcast__groups">
|
||||
{
|
||||
groups.map((group) => {
|
||||
group = helpers.collate(group, { clients: this.props.clients });
|
||||
groups.map((group) => {
|
||||
group = helpers.collate(group, { clients: this.props.clients });
|
||||
|
||||
// Average our clients' volume for an overall group volume
|
||||
let group_volume = 0;
|
||||
for (let i = 0; i < group.clients.length; i++) {
|
||||
const client = group.clients[i];
|
||||
group_volume += client.volume;
|
||||
}
|
||||
group_volume /= group.clients.length;
|
||||
// Average our clients' volume for an overall group volume
|
||||
let group_volume = 0;
|
||||
for (let i = 0; i < group.clients.length; i++) {
|
||||
const client = group.clients[i];
|
||||
group_volume += client.volume;
|
||||
}
|
||||
group_volume /= group.clients.length;
|
||||
|
||||
return (
|
||||
<div className="snapcast__group" key={group.id}>
|
||||
<div className="field">
|
||||
<div className="name">
|
||||
Name
|
||||
</div>
|
||||
<div className="input">
|
||||
<div className="text">
|
||||
{group.name}
|
||||
{' '}
|
||||
|
||||
<span className="mid_grey-text">
|
||||
(
|
||||
{group.id}
|
||||
)
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="field dropdown">
|
||||
<div className="name">
|
||||
Stream
|
||||
</div>
|
||||
<div className="input">
|
||||
<select onChange={(e) => actions.setGroupStream(group.id, e.target.value)} value={group.stream_id}>
|
||||
{
|
||||
streams.map((stream) => (
|
||||
<option value={stream.id} key={stream.id}>
|
||||
{stream.id}
|
||||
{' '}
|
||||
(
|
||||
{stream.status}
|
||||
)
|
||||
</option>
|
||||
))
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div className="field">
|
||||
<div className="name">
|
||||
Volume
|
||||
</div>
|
||||
<div className="input">
|
||||
<MuteControl
|
||||
className="snapcast__group__mute-control"
|
||||
mute={group.muted}
|
||||
onMuteChange={(mute) => actions.setGroupMute(group.id, mute)}
|
||||
/>
|
||||
<VolumeControl
|
||||
className="snapcast__group__volume-control"
|
||||
volume={group_volume}
|
||||
onVolumeChange={(percent, old_percent) => actions.setGroupVolume(group.id, percent, old_percent)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="field">
|
||||
<div className="name">
|
||||
Clients
|
||||
</div>
|
||||
<div className="input">
|
||||
{this.renderClientsList(group, groups)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})
|
||||
}
|
||||
return (
|
||||
<div className="snapcast__group" key={group.id}>
|
||||
<div className="field text">
|
||||
<div className="name">
|
||||
Name
|
||||
</div>
|
||||
<div className="input">
|
||||
<TextField
|
||||
value={group.name}
|
||||
onChange={value => actions.setGroupName(group.id, value)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="field dropdown">
|
||||
<div className="name">
|
||||
Stream
|
||||
</div>
|
||||
<div className="input">
|
||||
<select onChange={(e) => actions.setGroupStream(group.id, e.target.value)} value={group.stream_id}>
|
||||
{
|
||||
streams.map((stream) => (
|
||||
<option value={stream.id} key={stream.id}>
|
||||
{stream.id}
|
||||
{' '}
|
||||
(
|
||||
{stream.status}
|
||||
)
|
||||
</option>
|
||||
))
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div className="field">
|
||||
<div className="name">
|
||||
Volume
|
||||
</div>
|
||||
<div className="input">
|
||||
<MuteControl
|
||||
className="snapcast__group__mute-control"
|
||||
mute={group.muted}
|
||||
onMuteChange={(mute) => actions.setGroupMute(group.id, mute)}
|
||||
/>
|
||||
<VolumeControl
|
||||
className="snapcast__group__volume-control"
|
||||
volume={group_volume}
|
||||
onVolumeChange={(percent, old_percent) => actions.setGroupVolume(group.id, percent, old_percent)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="field">
|
||||
<div className="name">
|
||||
Clients
|
||||
</div>
|
||||
<div className="input">
|
||||
{this.renderClientsList(group, groups)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@ -316,8 +336,7 @@ class Snapcast extends React.Component {
|
||||
}
|
||||
|
||||
const mapStateToProps = (state, ownProps) => ({
|
||||
enabled: state.snapcast.enabled,
|
||||
connected: state.snapcast.connected,
|
||||
snapcast: state.snapcast,
|
||||
show_disconnected_clients: (
|
||||
state.ui.snapcast_show_disconnected_clients !== undefined
|
||||
? state.ui.snapcast_show_disconnected_clients
|
||||
|
||||
@ -243,18 +243,18 @@ export const digestMopidyImages = function (mopidy, images) {
|
||||
};
|
||||
|
||||
|
||||
export const generateGuid = function (type = 'numeric') {
|
||||
export const generateGuid = function (type = 'numeric', length = 12) {
|
||||
// numeric
|
||||
if (type == 'numeric') {
|
||||
const date = new Date().valueOf().toString();
|
||||
const random_number = Math.floor((Math.random() * 100)).toString();
|
||||
return parseInt(date + random_number);
|
||||
}
|
||||
const format = 'xxxxxxxxxx';
|
||||
const format = 'x'.repeat(length);
|
||||
return format.replace(/[xy]/g, (c) => {
|
||||
const r = Math.random() * 16 | 0; const
|
||||
v = c == 'x' ? r : (r & 0x3 | 0x8);
|
||||
return v.toString(16);
|
||||
return v.toString(length);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
|
||||
const helpers = require('../../helpers.js');
|
||||
|
||||
const localstorageMiddleware = (function () {
|
||||
const localstorageMiddleware = (function () {
|
||||
/**
|
||||
* The actual middleware inteceptor
|
||||
* */
|
||||
return (store) => (next) => (action) => {
|
||||
return (store) => (next) => (action) => {
|
||||
// proceed as normal first
|
||||
// this way, any reducers and middleware do their thing BEFORE we store our new state
|
||||
next(action);
|
||||
@ -14,7 +14,7 @@ const localstorageMiddleware = (function () {
|
||||
window._store = store;
|
||||
|
||||
// if debug enabled
|
||||
if (store.getState().ui.log_actions) {
|
||||
if (store.getState().ui.log_actions) {
|
||||
const ignored_actions = [
|
||||
'START_LOADING',
|
||||
'STOP_LOADING',
|
||||
@ -26,7 +26,7 @@ const localstorageMiddleware = (function () {
|
||||
}
|
||||
}
|
||||
|
||||
switch (action.type) {
|
||||
switch (action.type) {
|
||||
case 'PUSHER_CONNECTED':
|
||||
helpers.setStorage(
|
||||
'pusher',
|
||||
@ -236,6 +236,13 @@ const localstorageMiddleware = (function () {
|
||||
);
|
||||
break;
|
||||
|
||||
case 'SNAPCAST_SET':
|
||||
helpers.setStorage(
|
||||
'snapcast',
|
||||
action.data,
|
||||
);
|
||||
break;
|
||||
|
||||
case 'SNAPCAST_COMMANDS_UPDATED':
|
||||
helpers.setStorage(
|
||||
'snapcast',
|
||||
@ -290,7 +297,7 @@ const localstorageMiddleware = (function () {
|
||||
break;
|
||||
*/
|
||||
}
|
||||
};
|
||||
};
|
||||
}());
|
||||
|
||||
export default localstorageMiddleware;
|
||||
|
||||
@ -159,11 +159,6 @@ const PusherMiddleware = (function () {
|
||||
store.dispatch(uiActions.createNotification({ type: 'bad', content: message.params.message, description: message.params.description }));
|
||||
break;
|
||||
}
|
||||
|
||||
// Pass snapcast events to the Snapcast service
|
||||
if (message.method.startsWith('snapcast_')) {
|
||||
store.dispatch(snapcastActions.eventReceived(message));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
|
||||
export function setEnabled(enabled) {
|
||||
export function set(data) {
|
||||
return {
|
||||
type: 'SNAPCAST_SET_ENABLED',
|
||||
enabled,
|
||||
type: 'SNAPCAST_SET',
|
||||
data,
|
||||
};
|
||||
}
|
||||
|
||||
@ -18,6 +18,23 @@ export function disconnect() {
|
||||
};
|
||||
}
|
||||
|
||||
export function request(method, params = null, response_callback = null, error_callback = null) {
|
||||
return {
|
||||
type: 'SNAPCAST_REQUEST',
|
||||
method,
|
||||
params,
|
||||
response_callback,
|
||||
error_callback,
|
||||
};
|
||||
}
|
||||
|
||||
export function debug(message = null) {
|
||||
return {
|
||||
type: 'SNAPCAST_DEBUG',
|
||||
message,
|
||||
};
|
||||
}
|
||||
|
||||
export function getServer() {
|
||||
return {
|
||||
type: 'SNAPCAST_GET_SERVER',
|
||||
@ -71,6 +88,14 @@ export function deleteClient(id) {
|
||||
};
|
||||
}
|
||||
|
||||
export function setGroupName(id, name) {
|
||||
return {
|
||||
type: 'SNAPCAST_SET_GROUP_NAME',
|
||||
id,
|
||||
name,
|
||||
};
|
||||
}
|
||||
|
||||
export function setGroupStream(id, stream_id) {
|
||||
return {
|
||||
type: 'SNAPCAST_SET_GROUP_STREAM',
|
||||
@ -96,14 +121,6 @@ export function setGroupVolume(id, percent, old_percent = 0) {
|
||||
};
|
||||
}
|
||||
|
||||
export function eventReceived(message) {
|
||||
return {
|
||||
type: 'SNAPCAST_EVENT_RECEIVED',
|
||||
method: message.method,
|
||||
params: message.params,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Record loaders
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
|
||||
import ReactGA from 'react-ga';
|
||||
import { sha256 } from 'js-sha256';
|
||||
|
||||
const helpers = require('../../helpers');
|
||||
const coreActions = require('../core/actions');
|
||||
@ -63,8 +64,66 @@ const SnapcastMiddleware = (function () {
|
||||
));
|
||||
} else {
|
||||
switch (message.method) {
|
||||
case 'connection_added':
|
||||
store.dispatch(pusherActions.connectionAdded(message.params.connection));
|
||||
case 'Client.OnConnect':
|
||||
store.dispatch(snapcastActions.clientLoaded(
|
||||
{
|
||||
id: message.params.client.id,
|
||||
name: message.params.client.name,
|
||||
volume: message.params.client.config.volume.percent,
|
||||
mute: message.params.client.config.volume.muted,
|
||||
connected: message.params.client.connected,
|
||||
},
|
||||
));
|
||||
break;
|
||||
|
||||
case 'Client.OnDisconnect':
|
||||
store.dispatch(snapcastActions.clientLoaded(
|
||||
{
|
||||
id: message.params.client.id,
|
||||
connected: message.params.client.connected,
|
||||
},
|
||||
));
|
||||
break;
|
||||
|
||||
case 'Client.OnVolumeChanged':
|
||||
store.dispatch(snapcastActions.clientLoaded(
|
||||
{
|
||||
id: message.params.id,
|
||||
mute: message.params.volume.muted,
|
||||
volume: message.params.volume.percent,
|
||||
},
|
||||
));
|
||||
break;
|
||||
|
||||
case 'Client.OnLatencyChanged':
|
||||
store.dispatch(snapcastActions.clientLoaded(
|
||||
{
|
||||
id: message.params.id,
|
||||
latency: message.params.latency,
|
||||
},
|
||||
));
|
||||
break;
|
||||
|
||||
case 'Client.OnNameChanged':
|
||||
store.dispatch(snapcastActions.clientLoaded(
|
||||
{
|
||||
id: message.params.id,
|
||||
name: message.params.name,
|
||||
},
|
||||
));
|
||||
break;
|
||||
|
||||
case 'Group.OnMute':
|
||||
store.dispatch(snapcastActions.groupLoaded(
|
||||
{
|
||||
id: message.params.id,
|
||||
mute: message.params.mute,
|
||||
},
|
||||
));
|
||||
break;
|
||||
|
||||
case 'Server.OnUpdate':
|
||||
store.dispatch(snapcastActions.serverLoaded(message.param));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -72,7 +131,7 @@ const SnapcastMiddleware = (function () {
|
||||
};
|
||||
|
||||
const request = (store, method, params = null) => new Promise((resolve, reject) => {
|
||||
const id = helpers.generateGuid();
|
||||
const id = helpers.generateGuid(8);
|
||||
const message = {
|
||||
jsonrpc: '2.0',
|
||||
id,
|
||||
@ -82,7 +141,7 @@ const SnapcastMiddleware = (function () {
|
||||
message.params = params;
|
||||
}
|
||||
|
||||
if (store.getState().ui.log_pusher) {
|
||||
if (store.getState().ui.log_snapcast) {
|
||||
console.log('Snapcast log (outgoing)', message);
|
||||
}
|
||||
|
||||
@ -121,14 +180,46 @@ const SnapcastMiddleware = (function () {
|
||||
}
|
||||
|
||||
store.dispatch({ type: 'SNAPCAST_CONNECTING' });
|
||||
|
||||
var state = store.getState();
|
||||
|
||||
socket = new Mopidy({
|
||||
webSocketUrl: `ws${window.location.protocol === 'https:' ? 's' : ''}://${state.snapcast.host}:${state.snapcast.port}/jsonrpc/`,
|
||||
callingConvention: 'by-position-or-by-name',
|
||||
});
|
||||
socket = new WebSocket(
|
||||
`ws${window.location.protocol === 'https:' ? 's' : ''}://${state.snapcast.host}:${state.snapcast.port}/jsonrpc`,
|
||||
);
|
||||
|
||||
socket.on((type, data) => handleMessage(socket, store, type, data));
|
||||
socket.onopen = () => {
|
||||
store.dispatch({
|
||||
type: 'SNAPCAST_CONNECTED',
|
||||
});
|
||||
};
|
||||
|
||||
socket.onclose = (e) => {
|
||||
store.dispatch({
|
||||
type: 'SNAPCAST_DISCONNECTED',
|
||||
});
|
||||
|
||||
// attempt to reconnect every 5 seconds
|
||||
if (state.snapcast.enabled) {
|
||||
setTimeout(() => {
|
||||
store.dispatch(snapcastActions.connect());
|
||||
}, 5000);
|
||||
}
|
||||
};
|
||||
|
||||
socket.onerror = (e) => {
|
||||
if (socket.readyState == 1) {
|
||||
store.dispatch(coreActions.handleException(
|
||||
'Snapcast websocket error',
|
||||
e,
|
||||
e.type,
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
socket.onmessage = (message) => {
|
||||
var message = JSON.parse(message.data);
|
||||
handleMessage(socket, store, message);
|
||||
};
|
||||
break;
|
||||
|
||||
case 'SNAPCAST_CONNECTED':
|
||||
@ -137,6 +228,7 @@ const SnapcastMiddleware = (function () {
|
||||
ReactGA.event({ category: 'Snapcast', action: 'Connected', label: hashed_hostname });
|
||||
}
|
||||
store.dispatch(uiActions.createNotification({ content: 'Snapcast connected' }));
|
||||
store.dispatch(snapcastActions.getServer());
|
||||
next(action);
|
||||
break;
|
||||
|
||||
@ -152,39 +244,59 @@ const SnapcastMiddleware = (function () {
|
||||
break;
|
||||
|
||||
case 'SNAPCAST_DEBUG':
|
||||
request(socket, store, action.call, action.value)
|
||||
.then((response) => {
|
||||
store.dispatch({ type: 'DEBUG', response });
|
||||
});
|
||||
request(store, action.message.method, action.message.data)
|
||||
.then(
|
||||
(response) => {
|
||||
store.dispatch({ type: 'DEBUG', response });
|
||||
},
|
||||
(error) => {
|
||||
store.dispatch(coreActions.handleException(
|
||||
'Could not debug',
|
||||
error,
|
||||
error.message,
|
||||
));
|
||||
},
|
||||
);
|
||||
break;
|
||||
|
||||
case 'SNAPCAST_REQUEST':
|
||||
request(store, action.method, action.params)
|
||||
.then(
|
||||
(response) => {
|
||||
if (action.response_callback) {
|
||||
action.response_callback.call(this, response);
|
||||
}
|
||||
},
|
||||
(error) => {
|
||||
if (action.error_callback) {
|
||||
action.error_callback.call(this, error);
|
||||
} else {
|
||||
store.dispatch(coreActions.handleException(
|
||||
'Snapcast request failed',
|
||||
error,
|
||||
action.method,
|
||||
action,
|
||||
));
|
||||
}
|
||||
},
|
||||
);
|
||||
break;
|
||||
|
||||
case 'SNAPCAST_GET_SERVER':
|
||||
request(
|
||||
store,
|
||||
{
|
||||
method: 'Server.GetStatus',
|
||||
},
|
||||
(response) => {
|
||||
store.dispatch(snapcastActions.serverLoaded(response.server));
|
||||
},
|
||||
(error) => {
|
||||
store.dispatch(coreActions.handleException(
|
||||
'Could not get server',
|
||||
error,
|
||||
));
|
||||
},
|
||||
);
|
||||
break;
|
||||
|
||||
case 'SNAPCAST_SERVER_LOADED':
|
||||
store.dispatch(snapcastActions.groupsLoaded(action.server.groups, true));
|
||||
store.dispatch(snapcastActions.streamsLoaded(action.server.streams, true));
|
||||
|
||||
// Snapcast double-nests the server object
|
||||
action.server = action.server.server;
|
||||
|
||||
next(action);
|
||||
request(store, 'Server.GetStatus')
|
||||
.then(
|
||||
(response) => {
|
||||
store.dispatch(snapcastActions.serverLoaded(response.server.server, true));
|
||||
store.dispatch(snapcastActions.groupsLoaded(response.server.groups, true));
|
||||
store.dispatch(snapcastActions.streamsLoaded(response.server.streams, true));
|
||||
},
|
||||
(error) => {
|
||||
store.dispatch(coreActions.handleException(
|
||||
'Could not get Snapcast server',
|
||||
error,
|
||||
));
|
||||
},
|
||||
);
|
||||
break;
|
||||
|
||||
case 'SNAPCAST_GROUPS_LOADED':
|
||||
@ -237,127 +349,110 @@ const SnapcastMiddleware = (function () {
|
||||
|
||||
case 'SNAPCAST_SET_CLIENT_NAME':
|
||||
var client = snapcast.clients[action.id];
|
||||
var data = {
|
||||
method: 'Client.SetName',
|
||||
params: {
|
||||
id: action.id,
|
||||
name: action.name,
|
||||
},
|
||||
var params = {
|
||||
id: action.id,
|
||||
name: action.name,
|
||||
};
|
||||
|
||||
request(
|
||||
store,
|
||||
data,
|
||||
(response) => {
|
||||
store.dispatch(snapcastActions.clientLoaded(
|
||||
{
|
||||
id: action.id,
|
||||
name: response.name,
|
||||
},
|
||||
));
|
||||
},
|
||||
);
|
||||
request(store, 'Client.SetName', params)
|
||||
.then(
|
||||
response => {
|
||||
store.dispatch(snapcastActions.clientLoaded(
|
||||
{
|
||||
id: action.id,
|
||||
name: response.name,
|
||||
},
|
||||
));
|
||||
},
|
||||
);
|
||||
break;
|
||||
|
||||
case 'SNAPCAST_SET_CLIENT_MUTE':
|
||||
var client = store.getState().snapcast.clients[action.id];
|
||||
var data = {
|
||||
method: 'Client.SetVolume',
|
||||
params: {
|
||||
id: action.id,
|
||||
volume: {
|
||||
muted: action.mute,
|
||||
percent: client.volume,
|
||||
},
|
||||
var params = {
|
||||
id: action.id,
|
||||
volume: {
|
||||
muted: action.mute,
|
||||
percent: client.volume,
|
||||
},
|
||||
};
|
||||
|
||||
request(
|
||||
store,
|
||||
data,
|
||||
(response) => {
|
||||
store.dispatch(snapcastActions.clientLoaded(
|
||||
{
|
||||
id: action.id,
|
||||
volume: response.volume.percent,
|
||||
mute: response.volume.muted,
|
||||
},
|
||||
));
|
||||
},
|
||||
(error) => {
|
||||
store.dispatch(coreActions.handleException(
|
||||
'Error',
|
||||
error,
|
||||
error.message,
|
||||
));
|
||||
},
|
||||
);
|
||||
request(store, 'Client.SetVolume', params)
|
||||
.then(
|
||||
response => {
|
||||
store.dispatch(snapcastActions.clientLoaded(
|
||||
{
|
||||
id: action.id,
|
||||
volume: response.volume.percent,
|
||||
mute: response.volume.muted,
|
||||
},
|
||||
));
|
||||
},
|
||||
error => {
|
||||
store.dispatch(coreActions.handleException(
|
||||
'Error',
|
||||
error,
|
||||
error.message,
|
||||
));
|
||||
},
|
||||
);
|
||||
break;
|
||||
|
||||
case 'SNAPCAST_SET_CLIENT_VOLUME':
|
||||
var client = snapcast.clients[action.id];
|
||||
|
||||
var data = {
|
||||
method: 'Client.SetVolume',
|
||||
params: {
|
||||
id: action.id,
|
||||
volume: {
|
||||
muted: client.mute,
|
||||
percent: action.volume,
|
||||
},
|
||||
var params = {
|
||||
id: action.id,
|
||||
volume: {
|
||||
muted: client.mute,
|
||||
percent: action.volume,
|
||||
},
|
||||
};
|
||||
|
||||
request(
|
||||
store,
|
||||
data,
|
||||
(response) => {
|
||||
store.dispatch(snapcastActions.clientLoaded(
|
||||
{
|
||||
id: action.id,
|
||||
volume: response.volume.percent,
|
||||
},
|
||||
));
|
||||
},
|
||||
(error) => {
|
||||
store.dispatch(coreActions.handleException(
|
||||
'Error',
|
||||
error,
|
||||
error.message,
|
||||
));
|
||||
},
|
||||
);
|
||||
request(store, 'Client.SetVolume', params)
|
||||
.then(
|
||||
response => {
|
||||
store.dispatch(snapcastActions.clientLoaded(
|
||||
{
|
||||
id: action.id,
|
||||
volume: response.volume.percent,
|
||||
},
|
||||
));
|
||||
},
|
||||
(error) => {
|
||||
store.dispatch(coreActions.handleException(
|
||||
'Error',
|
||||
error,
|
||||
error.message,
|
||||
));
|
||||
}
|
||||
);
|
||||
break;
|
||||
|
||||
case 'SNAPCAST_SET_CLIENT_LATENCY':
|
||||
var client = store.getState().snapcast.clients[action.id];
|
||||
var data = {
|
||||
method: 'Client.SetLatency',
|
||||
params: {
|
||||
id: action.id,
|
||||
latency: action.latency,
|
||||
},
|
||||
var params = {
|
||||
id: action.id,
|
||||
latency: action.latency,
|
||||
};
|
||||
|
||||
request(
|
||||
store,
|
||||
data,
|
||||
(response) => {
|
||||
store.dispatch(snapcastActions.clientLoaded(
|
||||
{
|
||||
id: action.id,
|
||||
latency: response.latency,
|
||||
},
|
||||
));
|
||||
},
|
||||
(error) => {
|
||||
store.dispatch(coreActions.handleException(
|
||||
'Error',
|
||||
error,
|
||||
error.message,
|
||||
));
|
||||
},
|
||||
);
|
||||
request(store, 'Client.SetLatency', params)
|
||||
.then(
|
||||
response => {
|
||||
store.dispatch(snapcastActions.clientLoaded(
|
||||
{
|
||||
id: action.id,
|
||||
latency: response.latency,
|
||||
},
|
||||
));
|
||||
},
|
||||
error => {
|
||||
store.dispatch(coreActions.handleException(
|
||||
'Error',
|
||||
error,
|
||||
error.message,
|
||||
));
|
||||
},
|
||||
);
|
||||
break;
|
||||
|
||||
case 'SNAPCAST_SET_CLIENT_GROUP':
|
||||
@ -375,117 +470,121 @@ const SnapcastMiddleware = (function () {
|
||||
clients_ids.splice(clients_ids_index, 1);
|
||||
}
|
||||
|
||||
var data = {
|
||||
method: 'Group.SetClients',
|
||||
params: {
|
||||
id: action.group_id,
|
||||
clients: clients_ids,
|
||||
},
|
||||
var params = {
|
||||
id: action.group_id,
|
||||
clients: clients_ids,
|
||||
};
|
||||
|
||||
request(
|
||||
store,
|
||||
data,
|
||||
(response) => {
|
||||
store.dispatch(snapcastActions.serverLoaded(response.server));
|
||||
},
|
||||
(error) => {
|
||||
store.dispatch(coreActions.handleException(
|
||||
'Error',
|
||||
error,
|
||||
error.message,
|
||||
));
|
||||
},
|
||||
);
|
||||
request(store, 'Group.SetClients', params)
|
||||
.then(
|
||||
response => {
|
||||
store.dispatch(snapcastActions.serverLoaded(response.server));
|
||||
},
|
||||
error => {
|
||||
store.dispatch(coreActions.handleException(
|
||||
'Error',
|
||||
error,
|
||||
error.message,
|
||||
));
|
||||
},
|
||||
);
|
||||
break;
|
||||
|
||||
case 'SNAPCAST_DELETE_CLIENT':
|
||||
var data = {
|
||||
method: 'Server.DeleteClient',
|
||||
params: {
|
||||
id: action.id,
|
||||
},
|
||||
var params = {
|
||||
id: action.id,
|
||||
};
|
||||
|
||||
request(
|
||||
store,
|
||||
data,
|
||||
(response) => {
|
||||
store.dispatch({
|
||||
type: 'SNAPCAST_CLIENT_REMOVED',
|
||||
key: action.data.params.id,
|
||||
});
|
||||
},
|
||||
(error) => {
|
||||
store.dispatch(coreActions.handleException(
|
||||
'Error',
|
||||
error,
|
||||
error.message,
|
||||
));
|
||||
},
|
||||
);
|
||||
request(store, 'Server.DeleteClient', params)
|
||||
.then(
|
||||
response => {
|
||||
store.dispatch({
|
||||
type: 'SNAPCAST_CLIENT_REMOVED',
|
||||
key: action.data.params.id,
|
||||
});
|
||||
},
|
||||
error => {
|
||||
store.dispatch(coreActions.handleException(
|
||||
'Error',
|
||||
error,
|
||||
error.message,
|
||||
));
|
||||
},
|
||||
);
|
||||
break;
|
||||
|
||||
case 'SNAPCAST_SET_GROUP_NAME':
|
||||
var group = snapcast.groups[action.id];
|
||||
var params = {
|
||||
id: action.id,
|
||||
name: action.name,
|
||||
};
|
||||
|
||||
request(store, 'Group.SetName', params)
|
||||
.then(
|
||||
response => {
|
||||
store.dispatch(snapcastActions.groupLoaded(
|
||||
{
|
||||
id: action.id,
|
||||
name: response.name,
|
||||
},
|
||||
));
|
||||
},
|
||||
);
|
||||
break;
|
||||
|
||||
case 'SNAPCAST_SET_GROUP_STREAM':
|
||||
var group = store.getState().snapcast.groups[action.id];
|
||||
var data = {
|
||||
method: 'Group.SetStream',
|
||||
params: {
|
||||
id: action.id,
|
||||
stream_id: action.stream_id,
|
||||
},
|
||||
var params = {
|
||||
id: action.id,
|
||||
stream_id: action.stream_id,
|
||||
};
|
||||
|
||||
request(
|
||||
store,
|
||||
data,
|
||||
(response) => {
|
||||
store.dispatch(snapcastActions.groupLoaded(
|
||||
{
|
||||
id: action.id,
|
||||
stream_id: action.stream_id,
|
||||
},
|
||||
));
|
||||
},
|
||||
(error) => {
|
||||
store.dispatch(coreActions.handleException(
|
||||
'Could not change stream',
|
||||
error,
|
||||
error.message,
|
||||
));
|
||||
},
|
||||
);
|
||||
request(store, 'Group.SetStream', params)
|
||||
.then(
|
||||
response => {
|
||||
store.dispatch(snapcastActions.groupLoaded(
|
||||
{
|
||||
id: action.id,
|
||||
stream_id: action.stream_id,
|
||||
},
|
||||
));
|
||||
},
|
||||
error => {
|
||||
store.dispatch(coreActions.handleException(
|
||||
'Could not change stream',
|
||||
error,
|
||||
error.message,
|
||||
));
|
||||
},
|
||||
);
|
||||
break;
|
||||
|
||||
case 'SNAPCAST_SET_GROUP_MUTE':
|
||||
var group = store.getState().snapcast.groups[action.id];
|
||||
var data = {
|
||||
method: 'Group.SetMute',
|
||||
params: {
|
||||
id: action.id,
|
||||
mute: action.mute,
|
||||
},
|
||||
var params = {
|
||||
id: action.id,
|
||||
mute: action.mute,
|
||||
};
|
||||
|
||||
request(
|
||||
store,
|
||||
data,
|
||||
(response) => {
|
||||
store.dispatch(snapcastActions.groupLoaded(
|
||||
{
|
||||
id: action.id,
|
||||
muted: response.mute,
|
||||
},
|
||||
));
|
||||
},
|
||||
(error) => {
|
||||
store.dispatch(coreActions.handleException(
|
||||
'Could not toggle mute',
|
||||
error,
|
||||
error.message,
|
||||
));
|
||||
},
|
||||
);
|
||||
request(store, 'Group.SetMute', params)
|
||||
.then(
|
||||
response => {
|
||||
store.dispatch(snapcastActions.groupLoaded(
|
||||
{
|
||||
id: action.id,
|
||||
muted: response.mute,
|
||||
},
|
||||
));
|
||||
},
|
||||
error => {
|
||||
store.dispatch(coreActions.handleException(
|
||||
'Could not toggle mute',
|
||||
error,
|
||||
error.message,
|
||||
));
|
||||
},
|
||||
);
|
||||
break;
|
||||
|
||||
case 'SNAPCAST_SET_GROUP_VOLUME':
|
||||
@ -522,78 +621,7 @@ const SnapcastMiddleware = (function () {
|
||||
store.dispatch(snapcastActions.setClientVolume(client_to_update.id, volume));
|
||||
}
|
||||
break;
|
||||
|
||||
case 'SNAPCAST_EVENT_RECEIVED':
|
||||
|
||||
// Drop the prefix
|
||||
action.method = action.method.replace('snapcast_', '');
|
||||
|
||||
switch (action.method) {
|
||||
case 'Client.OnConnect':
|
||||
store.dispatch(snapcastActions.clientLoaded(
|
||||
{
|
||||
id: action.params.client.id,
|
||||
name: action.params.client.name,
|
||||
volume: action.params.client.volume.percent,
|
||||
mute: action.params.client.volume.muted,
|
||||
connected: action.params.client.connected,
|
||||
},
|
||||
));
|
||||
break;
|
||||
|
||||
case 'Client.OnDisconnect':
|
||||
store.dispatch(snapcastActions.clientLoaded(
|
||||
{
|
||||
id: action.params.client.id,
|
||||
connected: action.params.client.connected,
|
||||
},
|
||||
));
|
||||
break;
|
||||
|
||||
case 'Client.OnVolumeChanged':
|
||||
store.dispatch(snapcastActions.clientLoaded(
|
||||
{
|
||||
id: action.params.id,
|
||||
mute: action.params.volume.muted,
|
||||
volume: action.params.volume.percent,
|
||||
},
|
||||
));
|
||||
break;
|
||||
|
||||
case 'Client.OnLatencyChanged':
|
||||
store.dispatch(snapcastActions.clientLoaded(
|
||||
{
|
||||
id: action.params.id,
|
||||
latency: action.params.latency,
|
||||
},
|
||||
));
|
||||
break;
|
||||
|
||||
case 'Client.OnNameChanged':
|
||||
store.dispatch(snapcastActions.clientLoaded(
|
||||
{
|
||||
id: action.params.id,
|
||||
name: action.params.name,
|
||||
},
|
||||
));
|
||||
break;
|
||||
|
||||
case 'Group.OnMute':
|
||||
store.dispatch(snapcastActions.groupLoaded(
|
||||
{
|
||||
id: action.params.id,
|
||||
mute: action.params.mute,
|
||||
},
|
||||
));
|
||||
break;
|
||||
|
||||
case 'Server.OnUpdate':
|
||||
store.dispatch(snapcastActions.serverLoaded(action.params));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
// This action is irrelevant to us, pass it on to the next middleware
|
||||
|
||||
default:
|
||||
return next(action);
|
||||
}
|
||||
|
||||
@ -1,9 +1,17 @@
|
||||
|
||||
export default function reducer(snapcast = {}, action) {
|
||||
console.log(action);
|
||||
switch (action.type) {
|
||||
case 'SNAPCAST_SET_ENABLED':
|
||||
return { ...snapcast, enabled: action.enabled };
|
||||
case 'SNAPCAST_SET':
|
||||
return { ...snapcast, ...action.data };
|
||||
|
||||
case 'SNAPCAST_CONNECTED':
|
||||
return { ...snapcast, connected: true, connecting: false };
|
||||
|
||||
case 'SNAPCAST_CONNECTING':
|
||||
return { ...snapcast, connecting: true, connected: false };
|
||||
|
||||
case 'SNAPCAST_DISCONNECTED':
|
||||
return { ...snapcast, connected: false, connecting: false };
|
||||
|
||||
case 'SNAPCAST_SERVER_LOADED':
|
||||
return { ...snapcast, server: action.server };
|
||||
|
||||
@ -13,6 +13,7 @@ import * as uiActions from '../services/ui/actions';
|
||||
import * as pusherActions from '../services/pusher/actions';
|
||||
import * as mopidyActions from '../services/mopidy/actions';
|
||||
import * as spotifyActions from '../services/spotify/actions';
|
||||
import * as snapcastActions from '../services/snapcast/actions';
|
||||
|
||||
class Debug extends React.Component {
|
||||
constructor(props) {
|
||||
@ -21,6 +22,7 @@ class Debug extends React.Component {
|
||||
mopidy_call: 'playlists.asList',
|
||||
mopidy_data: '{}',
|
||||
pusher_data: '{"method":"get_config"}',
|
||||
snapcast_data: '{"method":"Server.GetStatus"}',
|
||||
access_token: this.props.access_token,
|
||||
toggling_test_mode: false,
|
||||
};
|
||||
@ -40,6 +42,11 @@ class Debug extends React.Component {
|
||||
this.props.pusherActions.debug(JSON.parse(this.state.pusher_data));
|
||||
}
|
||||
|
||||
callSnapcast(e) {
|
||||
e.preventDefault();
|
||||
this.props.snapcastActions.debug(JSON.parse(this.state.snapcast_data));
|
||||
}
|
||||
|
||||
toggleTestMode(e) {
|
||||
this.setState({ toggling_test_mode: true });
|
||||
this.props.uiActions.set({ test_mode: !this.props.test_mode });
|
||||
@ -216,6 +223,25 @@ Back
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<h4 className="underline">Snapcast</h4>
|
||||
<form onSubmit={(e) => this.callSnapcast(e)}>
|
||||
<label className="field">
|
||||
<div className="name">Data</div>
|
||||
<div className="input">
|
||||
<textarea
|
||||
onChange={(e) => this.setState({ snapcast_data: e.target.value })}
|
||||
value={this.state.snapcast_data}
|
||||
/>
|
||||
</div>
|
||||
</label>
|
||||
<div className="field">
|
||||
<div className="name" />
|
||||
<div className="input">
|
||||
<button type="submit" className="button button--default">Send</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<h4 className="underline">Response</h4>
|
||||
<pre>
|
||||
{ this.props.debug_response ? JSON.stringify(this.props.debug_response, null, 2) : null }
|
||||
@ -244,6 +270,7 @@ const mapDispatchToProps = (dispatch) => ({
|
||||
pusherActions: bindActionCreators(pusherActions, dispatch),
|
||||
mopidyActions: bindActionCreators(mopidyActions, dispatch),
|
||||
spotifyActions: bindActionCreators(spotifyActions, dispatch),
|
||||
snapcastActions: bindActionCreators(snapcastActions, dispatch),
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(Debug);
|
||||
|
||||
Reference in New Issue
Block a user