Preliminary radio
This commit is contained in:
@ -51,6 +51,33 @@ class IrisFrontend(pykka.ThreadingActor, CoreListener):
|
||||
|
||||
# get a fresh spotify authentication token and store for future use
|
||||
# self.refresh_spotify_token()
|
||||
|
||||
|
||||
##
|
||||
# Get a new spotify authentication token for server-side use
|
||||
#
|
||||
# Uses the Client Credentials Flow, so is invisible to the user. We need this token for
|
||||
# any backend spotify requests (we don't tap in to Mopidy-Spotify, yet). Also used for
|
||||
# passing token to frontend for javascript requests without use of the Authorization Code Flow.
|
||||
##
|
||||
def refresh_spotify_token( self ):
|
||||
|
||||
url = 'https://accounts.spotify.com/api/token'
|
||||
authorization = 'YTg3ZmI0ZGJlZDMwNDc1YjhjZWMzODUyM2RmZjUzZTI6ZDdjODlkMDc1M2VmNDA2OGJiYTE2NzhjNmNmMjZlZDY='
|
||||
|
||||
headers = {'Authorization' : 'Basic ' + authorization}
|
||||
data = {'grant_type': 'client_credentials'}
|
||||
data_encoded = urllib.urlencode( data )
|
||||
req = urllib2.Request(url, data_encoded, headers)
|
||||
|
||||
try:
|
||||
response = urllib2.urlopen(req, timeout=30).read()
|
||||
response_dict = json.loads(response)
|
||||
self.spotify_token = response_dict
|
||||
return response_dict
|
||||
except urllib2.HTTPError as e:
|
||||
return e
|
||||
|
||||
|
||||
##
|
||||
# Listen for core events, and update our frontend as required
|
||||
|
||||
@ -194,7 +194,7 @@ class PusherWebsocketHandler(tornado.websocket.WebSocketHandler):
|
||||
send_message(
|
||||
self.connectionid,
|
||||
'response',
|
||||
messageJson['action'],
|
||||
'radio_started',
|
||||
messageJson['message_id'],
|
||||
{ 'radio': radio }
|
||||
)
|
||||
|
||||
@ -12,7 +12,7 @@ const localstorageMiddleware = (function(){
|
||||
|
||||
// append our state to a global variable. This gives us access to debug the store at any point
|
||||
window._store = store
|
||||
//console.log(action)
|
||||
console.log(action)
|
||||
|
||||
switch( action.type ){
|
||||
|
||||
|
||||
@ -43,6 +43,19 @@ export function instruct( message_type, data = null ){
|
||||
}
|
||||
}
|
||||
|
||||
export function startRadio( uris ){
|
||||
return {
|
||||
type: 'PUSHER_START_RADIO',
|
||||
uris: uris
|
||||
}
|
||||
}
|
||||
|
||||
export function stopRadio( uris ){
|
||||
return {
|
||||
type: 'PUSHER_STOP_RADIO'
|
||||
}
|
||||
}
|
||||
|
||||
export function debug( call, data = null ){
|
||||
return {
|
||||
type: 'PUSHER_DEBUG',
|
||||
|
||||
@ -63,6 +63,7 @@ const PusherMiddleware = (function(){
|
||||
socket.onopen = () => {
|
||||
store.dispatch({ type: 'PUSHER_CONNECTED', connection: connection });
|
||||
store.dispatch({ type: 'PUSHER_SET_USERNAME', username: connection.username });
|
||||
makeRequest({ action: 'get_radio' });
|
||||
};
|
||||
|
||||
socket.onmessage = (message) => {
|
||||
@ -149,7 +150,7 @@ const PusherMiddleware = (function(){
|
||||
|
||||
// make it so
|
||||
var notification = new notification( title, options );
|
||||
break;
|
||||
break
|
||||
|
||||
case 'PUSHER_SEND_AUTHORIZATION':
|
||||
if( window.confirm('Spotify authorization for user '+action.data.me.id+' received. Do you want to import?') ){
|
||||
@ -165,6 +166,29 @@ const PusherMiddleware = (function(){
|
||||
}
|
||||
break
|
||||
|
||||
case 'PUSHER_START_RADIO':
|
||||
|
||||
var data = {
|
||||
action: 'start_radio',
|
||||
seed_artists: [],
|
||||
seed_genres: [],
|
||||
seed_tracks: []
|
||||
}
|
||||
|
||||
for( var i = 0; i < action.uris.length; i++){
|
||||
switch( helpers.uriType( action.uris[i] ) ){
|
||||
case 'artist':
|
||||
data.seed_artists.push( action.uris[i] );
|
||||
break;
|
||||
case 'track':
|
||||
data.seed_tracks.push( action.uris[i] );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
makeRequest( data )
|
||||
break
|
||||
|
||||
// This action is irrelevant to us, pass it on to the next middleware
|
||||
default:
|
||||
return next(action);
|
||||
|
||||
@ -117,6 +117,10 @@ export default function reducer(ui = {}, action){
|
||||
case 'FOLLOWING_LOADING':
|
||||
return Object.assign({}, ui, { following_loading: true })
|
||||
|
||||
case 'PUSHER_RADIO':
|
||||
case 'PUSHER_START_RADIO':
|
||||
return Object.assign({}, ui, { radio: action.data })
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -16,7 +16,9 @@ import FollowButton from '../components/FollowButton'
|
||||
import SidebarToggleButton from '../components/SidebarToggleButton'
|
||||
|
||||
import * as helpers from '../helpers'
|
||||
import * as uiActions from '../services/ui/actions'
|
||||
import * as mopidyActions from '../services/mopidy/actions'
|
||||
import * as pusherActions from '../services/pusher/actions'
|
||||
import * as lastfmActions from '../services/lastfm/actions'
|
||||
import * as spotifyActions from '../services/spotify/actions'
|
||||
|
||||
@ -67,7 +69,9 @@ class Artist extends React.Component{
|
||||
}
|
||||
|
||||
play(){
|
||||
alert('Yet to be implemented')
|
||||
if (!this.props.artist.uri) return
|
||||
this.props.uiActions.createNotification('Starting radio...')
|
||||
this.props.pusherActions.startRadio([this.props.artist.uri])
|
||||
}
|
||||
|
||||
renderSubViewMenu(){
|
||||
@ -204,7 +208,9 @@ const mapStateToProps = (state, ownProps) => {
|
||||
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
return {
|
||||
uiActions: bindActionCreators(uiActions, dispatch),
|
||||
mopidyActions: bindActionCreators(mopidyActions, dispatch),
|
||||
pusherActions: bindActionCreators(pusherActions, dispatch),
|
||||
lastfmActions: bindActionCreators(lastfmActions, dispatch),
|
||||
spotifyActions: bindActionCreators(spotifyActions, dispatch)
|
||||
}
|
||||
|
||||
@ -41,6 +41,17 @@ class Queue extends React.Component{
|
||||
this.props.mopidyActions.reorderTracklist( indexes, index )
|
||||
}
|
||||
|
||||
renderRadio(){
|
||||
if (!this.props.radio) return null
|
||||
|
||||
return (
|
||||
<div className="radio">
|
||||
Playing radio
|
||||
<button onClick={ e => this.props.pusherActions.instruct('stop_radio') }>Stop radio</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
render(){
|
||||
return (
|
||||
<div className="view queue-view">
|
||||
@ -49,6 +60,8 @@ class Queue extends React.Component{
|
||||
|
||||
<FullPlayer />
|
||||
|
||||
{ this.renderRadio() }
|
||||
|
||||
<section className="list-wrapper">
|
||||
<TrackList
|
||||
show_source_icon={true}
|
||||
@ -74,6 +87,7 @@ class Queue extends React.Component{
|
||||
|
||||
const mapStateToProps = (state, ownProps) => {
|
||||
return {
|
||||
radio: state.ui.radio,
|
||||
current_tracklist: state.ui.current_tracklist
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user