* VRFS-1047 - broadcasts can be listened to (but very raw). VRFS-1257 - adding back in listen_in page for admin only
This commit is contained in:
parent
7c99c44eaf
commit
aaef11add4
|
|
@ -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'
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
||||
|
|
|
|||
|
|
@ -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 <audio> element found";
|
||||
}
|
||||
|
||||
|
||||
audioDomElement = $audio.get(0);
|
||||
|
||||
function getAllEvents(element) {
|
||||
var result = [];
|
||||
for (var key in element) {
|
||||
if (key.indexOf('on') === 0) {
|
||||
result.push(key);
|
||||
}
|
||||
}
|
||||
return result.join(' ');
|
||||
}
|
||||
|
||||
console.log("ALL events names: " + getAllEvents(audioDomElement))
|
||||
$audio.bind(getAllEvents(audioDomElement), function(e) { console.log("ALL EVENT:", arguments) });
|
||||
|
||||
$audio.bind('*', function() {alert('works')});
|
||||
$audio.bind('play', onPlay);
|
||||
$audio.bind('playing', onPlaying);
|
||||
$audio.bind('error', onError);
|
||||
$audio.bind('emptied', onEmptied);
|
||||
$audio.bind('abort', onAbort);
|
||||
$audio.bind('ended', onEnded);
|
||||
$audio.bind('pause', onPause);
|
||||
$audio.bind('suspend', onSuspend);
|
||||
$audio.bind('stalled', onStalled);
|
||||
$audio.bind('timeupdate', onTimeUpdate);
|
||||
$audio.bind('progress', onProgress);
|
||||
$audio.bind('load', function() { console.log("load", arguments)})
|
||||
|
||||
$parent.bind('play.listenBroadcast', play);
|
||||
$parent.bind('pause.listenBroadcast', pause);
|
||||
}
|
||||
|
||||
initialize();
|
||||
|
||||
this.play = play;
|
||||
this.pause = pause;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
$.fn.listenBroadcast = function(options) {
|
||||
new context.JK.ListenBroadcast(this, options);
|
||||
}
|
||||
})(window, jQuery);
|
||||
|
|
@ -31,7 +31,7 @@
|
|||
var playbackControls = null;
|
||||
var promptLeave = false;
|
||||
|
||||
var rest = JK.Rest();
|
||||
var rest = context.JK.Rest();
|
||||
|
||||
var RENDER_SESSION_DELAY = 750; // When I need to render a session, I have to wait a bit for the mixers to be there.
|
||||
|
||||
|
|
|
|||
|
|
@ -294,7 +294,6 @@
|
|||
if(!$element.is('img')) { throw "expected to receive an <img> in setInstrumentAssetPath" }
|
||||
|
||||
var instrument = $element.attr('instrument-id');
|
||||
if(!instrument) { throw "expect there to be an instrument defined in setInstrumentAssetPath" }
|
||||
|
||||
$element.attr('src', context.JK.getInstrumentIcon24(instrument))
|
||||
})
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
//= require jquery.mousewheel-3.1.9
|
||||
//= require jquery.timeago
|
||||
//= require jquery.dotdotdot
|
||||
//= require jquery.listenbroadcast
|
||||
//= require AAA_Log
|
||||
//= require AAC_underscore
|
||||
//= require globals
|
||||
|
|
|
|||
|
|
@ -122,6 +122,9 @@
|
|||
float:left;
|
||||
font-size:18px;
|
||||
margin-top:12px;
|
||||
|
||||
.friend-name-label {
|
||||
}
|
||||
}
|
||||
|
||||
li .friend-status {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,10 @@ class SpikesController < ApplicationController
|
|||
|
||||
def listen_in
|
||||
|
||||
if !current_user.admin
|
||||
raise PermissionError "must be administrator"
|
||||
end
|
||||
|
||||
#as_musician = false is the critical search criteria for sessions to list correctly
|
||||
@music_sessions = MusicSession.index(current_user, as_musician: false)
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,13 @@ module FeedsHelper
|
|||
music_session_history.description
|
||||
end
|
||||
|
||||
# grabs 1st genre
|
||||
def session_genre(music_session_history)
|
||||
genres_array = music_session_history.genres.nil? ? [] : music_session_history.genres.split(MusicSessionHistory::SEPARATOR)
|
||||
genre = genres_array.length > 0 ? Genre.find_by_id(genres_array[0]) : nil
|
||||
genre.nil? ? '' : genre.description
|
||||
end
|
||||
|
||||
def recording_artist_name(recording)
|
||||
(recording.band.nil? ? nil : recording.band.name) || recording.candidate_claimed_recording.user.name
|
||||
end
|
||||
|
|
@ -39,4 +46,8 @@ module FeedsHelper
|
|||
recording.candidate_claimed_recording.description
|
||||
end
|
||||
|
||||
def recording_genre(recording)
|
||||
recording.candidate_claimed_recording.genre.description
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@
|
|||
<img src="{avatar}"/>
|
||||
</div>
|
||||
<div class="track-instrument {preMasteredClass}">
|
||||
<img src="/assets/{instrumentIcon}" width="45" height="45"/>
|
||||
<img src="{instrumentIcon}" width="45" height="45"/>
|
||||
</div>
|
||||
<div class="track-gain" mixer-id="{mixerId}"></div>
|
||||
<!--
|
||||
|
|
|
|||
|
|
@ -173,7 +173,7 @@
|
|||
<li class="{cssClass}">
|
||||
<div class="avatar-small" user-id="{userId}" hoveraction="{hoverAction}"><img src="{avatar_url}" /></div>
|
||||
<div class="friend-name" user-id="{userId}" hoveraction="{hoverAction}">
|
||||
{userName}<br/>
|
||||
<span class="friend-name-label">{userName}</span><br/>
|
||||
<span class="friend-status">
|
||||
{status} {extra_info}
|
||||
</span>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
= puts "feedededededeedde #{feed_item.inspect}"
|
||||
- if feed_item.music_session_history
|
||||
= render :partial => "feed_music_session", locals: { feed_item: feed_item.music_session_history }
|
||||
- else
|
||||
|
|
|
|||
|
|
@ -15,26 +15,33 @@
|
|||
/ timeline and controls
|
||||
.right.w40
|
||||
/ recording play controls
|
||||
.session-controls{class: (feed_item.is_over? ? 'ended' : 'inprogress')}
|
||||
.session-controls{ class: (feed_item.is_over? ? 'ended' : 'inprogress'), 'data-music-session' => feed_item.id }
|
||||
/ session status
|
||||
%a.left.play-button{href:'#'}
|
||||
= image_tag 'content/icon_playbutton.png', width:20, height:20
|
||||
= image_tag 'content/icon_playbutton.png', width:20, height:20, class:'play-icon'
|
||||
- if feed_item.music_session && feed_item.music_session.mount
|
||||
%audio{preload: 'none'}
|
||||
%source{src: feed_item.music_session.mount.url, type: feed_item.music_session.mount.resolve_string(:mime_type)}
|
||||
.session-status
|
||||
= feed_item.is_over? ? 'SESSION ENDED' : 'SESSION IN PROGRESS'
|
||||
/ current playback time
|
||||
= session_duration(feed_item, class: 'recording-current')
|
||||
/ end recording play controls
|
||||
/ genre and social
|
||||
.left.small Pop
|
||||
.left.small
|
||||
= session_genre(feed_item)
|
||||
.right.small.feed-details
|
||||
%span.play-count
|
||||
%span.plays 80
|
||||
%span.plays
|
||||
= feed_item.play_count
|
||||
= image_tag 'content/icon_arrow.png', :height => "12", :width => "7"
|
||||
%span.comment-count
|
||||
%span.comments 12
|
||||
%span.comments
|
||||
= feed_item.comment_count
|
||||
= image_tag 'content/icon_comment.png', :height => "12", :width => "13"
|
||||
%span.like-count
|
||||
%span.likes 35
|
||||
%span.likes
|
||||
= feed_item.like_count
|
||||
= image_tag 'content/icon_like.png', :height => "12", :width => "12"
|
||||
%a.details{:href => "#"} Details
|
||||
%a.details-arrow.arrow-down-orange{:href => "#"}
|
||||
|
|
@ -53,8 +60,12 @@
|
|||
= "#{user.first_name} #{user.last_name}"
|
||||
%td
|
||||
.nowrap
|
||||
- user.total_instruments.split('|').uniq.each do |instrument_id|
|
||||
%img.instrument-icon{'instrument-id' =>instrument_id, height:24, width:24}
|
||||
- if user.total_instruments
|
||||
- user.total_instruments.split('|').uniq.each do |instrument_id|
|
||||
%img.instrument-icon{'instrument-id' =>instrument_id, height:24, width:24}
|
||||
- else
|
||||
%img.instrument-icon{'instrument-id' =>'default', height:24, width:24}
|
||||
|
||||
|
||||
%br{:clear => "all"}/
|
||||
%br/
|
||||
|
|
@ -37,16 +37,20 @@
|
|||
1:23
|
||||
/ end recording play controls
|
||||
/ genre and social
|
||||
.left.small Blues
|
||||
.left.small
|
||||
= recording_genre(feed_item)
|
||||
.right.small.feed-details
|
||||
%span.play-count
|
||||
%span.plays 80
|
||||
%span.plays
|
||||
= feed_item.play_count
|
||||
= image_tag 'content/icon_arrow.png', :height => "12", :width => "7"
|
||||
%span.comment-count
|
||||
%span.comments 12
|
||||
%span.comments
|
||||
= feed_item.comment_count
|
||||
= image_tag 'content/icon_comment.png', :height => "12", :width => "13"
|
||||
%span.like-count
|
||||
%span.likes 35
|
||||
%span.likes
|
||||
= feed_item.like_count
|
||||
= image_tag 'content/icon_like.png', :height => "12", :width => "12"
|
||||
%a.details{:href => "#"} Details
|
||||
%a.details-arrow.arrow-down-orange{:href => "#"}
|
||||
|
|
|
|||
|
|
@ -60,6 +60,10 @@ SampleApp::Application.routes.draw do
|
|||
|
||||
match '/gmail_contacts', to: 'gmail#gmail_contacts'
|
||||
|
||||
|
||||
# temporarily allow for debugging
|
||||
match '/listen_in', to: 'spikes#listen_in'
|
||||
|
||||
# embed resque-web if this is development mode
|
||||
if Rails.env == "development"
|
||||
require 'resque/server'
|
||||
|
|
@ -69,7 +73,6 @@ SampleApp::Application.routes.draw do
|
|||
|
||||
# route to spike controller (proof-of-concepts)
|
||||
match '/facebook_invite', to: 'spikes#facebook_invite'
|
||||
match '/listen_in', to: 'spikes#listen_in'
|
||||
|
||||
# junk pages
|
||||
match '/help', to: 'static_pages#help'
|
||||
|
|
|
|||
|
|
@ -11,6 +11,10 @@ describe "Welcome", :js => true, :type => :feature, :capybara_feature => true d
|
|||
end
|
||||
|
||||
before(:each) do
|
||||
Feed.delete_all
|
||||
MusicSessionHistory.delete_all
|
||||
Recording.delete_all
|
||||
|
||||
page.driver.headers = { 'User-Agent' => ' JamKazam ' }
|
||||
visit "/"
|
||||
find('h1', text: 'Play music together over the Internet as if in the same room')
|
||||
|
|
@ -148,13 +152,51 @@ describe "Welcome", :js => true, :type => :feature, :capybara_feature => true d
|
|||
end
|
||||
|
||||
describe "feed" do
|
||||
it "typical feed" do
|
||||
|
||||
it "data" do
|
||||
claimedRecording1 = FactoryGirl.create(:claimed_recording)
|
||||
musicSessionHistory1 = claimedRecording1.recording.music_session.music_session_history
|
||||
|
||||
visit "/"
|
||||
find('h1', text: 'Play music together over the Internet as if in the same room')
|
||||
find('.feed-entry.music-session-history-entry .description', text: musicSessionHistory1.description)
|
||||
find('.feed-entry.music-session-history-entry .session-status', text: 'SESSION IN PROGRESS')
|
||||
find('.feed-entry.music-session-history-entry .session-controls.inprogress', text: 'SESSION IN PROGRESS')
|
||||
find('.feed-entry.music-session-history-entry .artist', text: musicSessionHistory1.user.name)
|
||||
should_not have_selector('.feed-entry.music-session-history-entry .musician-detail')
|
||||
|
||||
find('.feed-entry.recording-entry .name', text: claimedRecording1.name)
|
||||
find('.feed-entry.recording-entry .description', text: claimedRecording1.description)
|
||||
find('.feed-entry.recording-entry .title', text: 'RECORDING')
|
||||
find('.feed-entry.recording-entry .artist', text: claimedRecording1.user.name)
|
||||
should_not have_selector('.feed-entry.recording-entry .musician-detail')
|
||||
|
||||
# try to hide the recording
|
||||
claimedRecording1.is_public = false
|
||||
claimedRecording1.save!
|
||||
|
||||
visit "/"
|
||||
find('h1', text: 'Play music together over the Internet as if in the same room')
|
||||
find('.feed-entry.music-session-history-entry .description', text: musicSessionHistory1.description)
|
||||
should_not have_selector('.feed-entry.recording-entry')
|
||||
|
||||
# try to mess with the music session history by removing all user histories (which makes it a bit invalid)
|
||||
# but we really don't want the front page to ever crash if we can help it
|
||||
musicSessionHistory1.music_session_user_histories.delete_all
|
||||
musicSessionHistory1.reload
|
||||
musicSessionHistory1.music_session_user_histories.length.should == 0
|
||||
|
||||
visit "/"
|
||||
find('h1', text: 'Play music together over the Internet as if in the same room')
|
||||
find('.feed-entry.music-session-history-entry .description', text: musicSessionHistory1.description)
|
||||
|
||||
# try to hide the music session
|
||||
musicSessionHistory1.fan_access = false
|
||||
musicSessionHistory1.save!
|
||||
|
||||
visit "/"
|
||||
find('h1', text: 'Play music together over the Internet as if in the same room')
|
||||
should_not have_selector('.feed-entry.music-session-history-entry')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in New Issue