Files
Iris/src/js/services/mopidy/middleware.js

144 lines
5.0 KiB
JavaScript
Raw Normal View History

import Mopidy from 'mopidy'
import actions from './actions'
const MopidyMiddleware = (function(){
// container for the actual Mopidy socket
var socket = null;
// handle all manner of socket messages
const handleMessage = (ws, store, type, data) => {
switch( type ){
case 'state:online':
store.dispatch({ type: 'MOPIDY_CONNECTED' });
instruct( ws, store, 'playback.getState' );
instruct( ws, store, 'playback.getVolume' );
instruct( ws, store, 'tracklist.getConsume' );
instruct( ws, store, 'tracklist.getRandom' );
instruct( ws, store, 'tracklist.getRepeat' );
instruct( ws, store, 'tracklist.getTlTracks' );
instruct( ws, store, 'playback.getCurrentTlTrack' );
break;
case 'state:offline':
store.dispatch({ type: 'MOPIDY_DISCONNECTED' });
break;
case 'event:tracklistChanged':
instruct( ws, store, 'tracklist.getTlTracks' );
break;
//case 'event:trackPlaybackEnded':
case 'event:playbackStateChanged':
case 'event:trackPlaybackStarted':
instruct( ws, store, 'playback.getState' );
instruct( ws, store, 'playback.getCurrentTlTrack' );
break;
case 'event:volumeChanged':
store.dispatch({ type: 'MOPIDY_Volume', data: data.volume });
break;
case 'event:optionsChanged':
instruct( ws, store, 'tracklist.getConsume' );
instruct( ws, store, 'tracklist.getRandom' );
instruct( ws, store, 'tracklist.getRepeat' );
break;
default:
//console.log( 'MopidyService: Unhandled message', type, message );
}
}
/**
* Call something with Mopidy
*
* Sends request to Mopidy server, and updates our local storage on return
* @param object ws = Mopidy class that wraps a Websocket
* @param string model = which Mopidy model (playback, tracklist, etc)
* @param string property = TlTracks, Consume, etc
* @param string value (optional) = value of the property to pass
**/
const instruct = ( ws, store, call, value = false ) => {
var callParts = call.split('.');
var model = callParts[0];
var method = callParts[1];
var property = method;
property = property.replace('get','');
property = property.replace('set','');
// if we have a value, we need to include in our payload
if( value ){
ws[model][method]( value )
.then(
response => store.dispatch({ type: 'MOPIDY_'+property, model: model, data: response }),
error => console.error( error )
);
// no value, so omit the payload
}else{
ws[model][method]()
.then(
response => store.dispatch({ type: 'MOPIDY_'+property, model: model, data: response }),
error => console.error( error )
);
}
}
/**
* Middleware
*
* This behaves like an action interceptor. We listen for specific actions
* and handle special functionality. If the action is not in our switch, then
* it just proceeds to the next middleware, or default functionality
**/
return store => next => action => {
switch(action.type) {
case 'MOPIDY_CONNECT':
if(socket != null) socket.close();
store.dispatch({ type: 'MOPIDY_CONNECTING' });
2016-10-18 08:56:53 +13:00
var state = store.getState();
socket = new Mopidy({
2016-10-18 08:56:53 +13:00
webSocketUrl: 'ws://'+state.mopidy.host+':'+state.mopidy.port+'/mopidy/ws',
callingConvention: 'by-position-or-by-name'
});
socket.on( (type, data) => handleMessage( socket, store, type, data ) );
break;
case 'MOPIDY_DISCONNECT':
if(socket != null) socket.close();
socket = null;
store.dispatch({ type: 'MOPIDY_DISCONNECTED' });
break;
// send an instruction to the websocket
case 'MOPIDY_INSTRUCT':
case 'MOPIDY_CHANGE_TRACK':
case 'MOPIDY_REMOVE_TRACKS':
instruct( socket, store, action.call, action.value )
break;
2016-10-18 08:56:53 +13:00
case 'MOPIDY_SET_CONFIG':
next(action);
localStorage.setItem('mopidy', JSON.stringify({ host: action.host, port: action.port }));
break;
// This action is irrelevant to us, pass it on to the next middleware
default:
return next(action);
}
}
})();
export default MopidyMiddleware