From aaef11add4fb30b977c7989dd237aa9baf71cea6 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Thu, 27 Feb 2014 18:38:02 +0000 Subject: [PATCH] * VRFS-1047 - broadcasts can be listened to (but very raw). VRFS-1257 - adding back in listen_in page for admin only --- ruby/Gemfile | 1 + ruby/lib/jam_ruby/models/icecast_mount.rb | 4 +- .../assets/javascripts/feed_item_session.js | 23 ++- .../javascripts/jquery.listenbroadcast.js | 162 ++++++++++++++++++ web/app/assets/javascripts/session.js | 2 +- web/app/assets/javascripts/utils.js | 1 - web/app/assets/javascripts/web/web.js | 1 + .../stylesheets/client/sidebar.css.scss | 3 + web/app/controllers/spikes_controller.rb | 4 + web/app/helpers/feeds_helper.rb | 11 ++ web/app/views/clients/_session.html.erb | 2 +- web/app/views/clients/_sidebar.html.erb | 2 +- web/app/views/users/_feed_item.html.haml | 1 - .../views/users/_feed_music_session.html.haml | 27 ++- web/app/views/users/_feed_recording.html.haml | 12 +- web/config/routes.rb | 5 +- web/spec/features/welcome_spec.rb | 44 ++++- 17 files changed, 283 insertions(+), 22 deletions(-) create mode 100644 web/app/assets/javascripts/jquery.listenbroadcast.js diff --git a/ruby/Gemfile b/ruby/Gemfile index 47bababdd..4856141b3 100644 --- a/ruby/Gemfile +++ b/ruby/Gemfile @@ -41,6 +41,7 @@ gem 'resque-failed-job-mailer' #, :path => "/Users/seth/workspace/resque_failed_ gem 'resque-lonely_job', '~> 1.0.0' gem 'oj' gem 'builder' +gem 'fog' group :test do gem 'simplecov', '~> 0.7.1' diff --git a/ruby/lib/jam_ruby/models/icecast_mount.rb b/ruby/lib/jam_ruby/models/icecast_mount.rb index bf3d5b393..cfa3424a2 100644 --- a/ruby/lib/jam_ruby/models/icecast_mount.rb +++ b/ruby/lib/jam_ruby/models/icecast_mount.rb @@ -110,7 +110,7 @@ module JamRuby def listener_add with_lock do - sourced_needs_changing_at = Time.now if listeners == 0 + self.sourced_needs_changing_at = Time.now if listeners == 0 # this is completely unsafe without that 'with_lock' statement above self.listeners = self.listeners + 1 @@ -126,7 +126,7 @@ module JamRuby end with_lock do - sourced_needs_changing_at = Time.now if listeners == 1 + self.sourced_needs_changing_at = Time.now if listeners == 1 # this is completely unsafe without that 'with_lock' statement above self.listeners = self.listeners - 1 diff --git a/web/app/assets/javascripts/feed_item_session.js b/web/app/assets/javascripts/feed_item_session.js index 9c544d1f8..63d49750a 100644 --- a/web/app/assets/javascripts/feed_item_session.js +++ b/web/app/assets/javascripts/feed_item_session.js @@ -8,12 +8,31 @@ var $feedItem = $parentElement; var $description = $('.description', $feedItem) var $musicians = $('.musician-detail', $feedItem) + var $controls = $('.session-controls', $feedItem); + var playing = false; + var toggledOpen = false; - var toggledOpen = false; if(!$feedItem.is('.feed-entry')) { throw "$parentElement must be a .feed-entry" } + function togglePlay() { + if(playing) { + var img = $('.play-icon', $(this)); + img.attr('src', '/assets/content/icon_playbutton.png'); + $controls.trigger('pause.listenBroadcast'); + } + else { + var img = $('.play-icon', $(this)); + img.attr('src', '/assets/content/icon_pausebutton.png'); + $controls.trigger('play.listenBroadcast'); + } + + playing = !playing; + + return false; + } + function toggleDetails() { if(toggledOpen) { @@ -39,11 +58,13 @@ function events() { $('.details', $feedItem).click(toggleDetails); $('.details-arrow', $feedItem).click(toggleDetails); + $('.play-button', $feedItem).click(togglePlay); } function initialize() { $('.timeago', $feedItem).timeago(); $('.dotdotdot', $feedItem).dotdotdot(); + $controls.listenBroadcast(); context.JK.prettyPrintElements($('time.duration', $feedItem)); context.JK.setInstrumentAssetPath($('.instrument-icon', $feedItem)); diff --git a/web/app/assets/javascripts/jquery.listenbroadcast.js b/web/app/assets/javascripts/jquery.listenbroadcast.js new file mode 100644 index 000000000..c7a19f0ac --- /dev/null +++ b/web/app/assets/javascripts/jquery.listenbroadcast.js @@ -0,0 +1,162 @@ +(function(context, $) { + + "use strict"; + + context.JK = context.JK || {}; + + // the purpose of this code is to simply the interaction between user and server + // it provides methods to call on user events (primarily play/pause), and will fire + // events (such as 'stream_gone'). This element does nothing with UI; only fires events for you to handle + + // $parentElement: the parent element needs to contain one audio element; this will take control of it. + // pass in music_session as a 'data-music-session' attribute on the $parentElement + + // this will also interact with any REST APIs needed to + context.JK.ListenBroadcast = function($parentElement, options){ + + var logger = context.JK.logger; + var rest = context.JK.Rest(); + var $parent = $parentElement; + var $audio = null; + var audioDomElement = null; + var musicSessionId = null; + var isPlaying = false; // tracks if the stream is actually playing + + function play(e) { + if(e) { + e.preventDefault(); + e.stopPropagation(); + } + + if(!audioDomElement) throw "no audio element supplied; the user should not be able to attempt a play" + + audioDomElement.play(); + } + + function pause(e) { + if(e) { + e.preventDefault(); + e.stopPropagation(); + } + + if (!audioDomElement) throw "no audio element supplied; the user should not be able to attempt a pause" + + audioDomElement.pause(); + } + + function onPlay() { + logger.debug("onplay", arguments); + + isPlaying = true; + } + + function onPlaying() { + logger.debug("onplaying", arguments); + + + isPlaying = true; + } + + function onPause() { + logger.debug("onpause", arguments); + + isPlaying = false; + } + + function onError() { + logger.debug("onerror", arguments); + } + + function onEnded() { + logger.debug("onended", arguments); + } + + function onEmptied() { + logger.debug("onemptied", arguments); + } + + function onAbort() { + logger.debug("onabort", arguments); + } + + function onStalled() { + logger.debug("onstalled", arguments); + + // fires in Chrome on page load + } + + function onSuspend() { + logger.debug("onsuspend", arguments); + + // fires in FF on page load + } + + function onTimeUpdate() { + //logger.debug("ontimeupdate", arguments); + } + + function onProgress() { + //logger.debug("onprogress", arguments); + } + + function initialize() { + + musicSessionId = $parent.attr('data-music-session'); + if(!musicSessionId) throw "data-music-session must be specified on $parentElement"; + + $audio = $('audio', $parent); + + if($audio.length == 0) { + logger.debug("listen_broadcast: no audio element. deactivating") + return; + } + if($audio.length > 1) { + throw "more than one