From e190e97a01d7d55de4620dc656d9cde3ec1bbedb Mon Sep 17 00:00:00 2001 From: Dan Barber Date: Fri, 6 Dec 2013 13:46:58 +0000 Subject: [PATCH] Realtime updates via Server-Sent Events. --- assets/js/application.js | 7 +++++++ assets/js/controls/transport.js | 5 +---- models/mpd_connection.rb | 2 +- mpd_client.rb | 27 ++++++++++++++++++++++----- 4 files changed, 31 insertions(+), 10 deletions(-) diff --git a/assets/js/application.js b/assets/js/application.js index 839d7fb..41f9f02 100644 --- a/assets/js/application.js +++ b/assets/js/application.js @@ -11,12 +11,19 @@ $(document).ready(function() { status: status }), + events: new EventSource('/api/stream'), + queue: new Queue('#queue', { queueSongs: queueSongs, status: status }) }; + mpdClient.events.onmessage = function(e) { + newStatus = JSON.parse(e.data); + status.attr(newStatus); + } + status.bind('change', function(event, attr, how, newVal, oldVal) { if (attr == 'song') { mpdClient.queueSongs.updatePlaying(oldVal, newVal); diff --git a/assets/js/controls/transport.js b/assets/js/controls/transport.js index 8dcd534..ab707e7 100644 --- a/assets/js/controls/transport.js +++ b/assets/js/controls/transport.js @@ -13,10 +13,7 @@ var Transport = can.Control.extend({ var self = this; can.ajax({ url: '/api/control/' + command, - type: 'PUT', - success: function(status) { - self.updateStatus(status); - } + type: 'PUT' }); }, diff --git a/models/mpd_connection.rb b/models/mpd_connection.rb index d361a38..b1f37fb 100644 --- a/models/mpd_connection.rb +++ b/models/mpd_connection.rb @@ -1,6 +1,6 @@ class MPDConnection def self.mpd - @mpd ||= MPD.new + @mpd ||= MPD.new('localhost', 6600, { callbacks: true }) @mpd.connect unless @mpd.connected? @mpd end diff --git a/mpd_client.rb b/mpd_client.rb index 565c7dd..7919581 100644 --- a/mpd_client.rb +++ b/mpd_client.rb @@ -15,6 +15,8 @@ require './models/song' class MPDClient < Sinatra::Base + set server: 'thin', connections: [] + set :assets_precompile, %w(app.js app.css *.png *.jpg *.svg *.eot *.ttf *.woff) set :assets_prefix, 'assets' register Sinatra::AssetPipeline @@ -25,21 +27,34 @@ class MPDClient < Sinatra::Base erb :index end - namespace '/api' do + def self.send_status + status = JSON MPDConnection.status + settings.connections.each { |out| out << "data: #{status}\n\n" } + end - before do - content_type 'application/json' - end + MPDConnection.mpd.on(:song) { |song| send_status } + MPDConnection.mpd.on(:state) { |state| send_status } + + namespace '/api' do get '/status' do JSON MPDConnection.status end + get '/stream', provides: 'text/event-stream' do + stream :keep_open do |out| + settings.connections << out + out.callback { settings.connections.delete(out) } + end + end + get '/albums' do + content_type 'application/json' JSON Album.all.map(&:to_h) end get '/artists/:artist' do + content_type 'application/json' JSON Album.by_artist(CGI.unescape(params[:artist])).sort.map(&:to_h) end @@ -52,23 +67,25 @@ class MPDClient < Sinatra::Base #end get '/artists' do + content_type 'application/json' JSON Artist.all.map(&:to_h) end get '/queue' do + content_type 'application/json' JSON({ data: Song.queue.map(&:to_h) }) end put '/control/:action' do if Control.controls.include?(params[:action].to_sym) Control.send(params[:action]) - JSON MPDConnection.status else not_found end end put '/control/volume/:value' do + content_type 'application/json' Control.volume(params[:value]) end