Merge branch 'develop' of bitbucket.org:jamkazam/jam-cloud into develop

This commit is contained in:
Scott Comer 2014-03-04 18:48:42 -06:00
commit 87b6654f28
10 changed files with 132 additions and 38 deletions

View File

@ -35,7 +35,7 @@ class JamRuby::Promotional < ActiveRecord::Base
end
def self.active(max_count=10)
rel = self.where(:aasm_state => ACTIVE_STATE)
rel = self.where(:aasm_state => ACTIVE_STATE).where('latest_id IS NOT NULL')
if 0 < (mc = max_count.to_i)
rel = rel.limit(mc)
end

View File

@ -78,14 +78,21 @@
checkServer()
.done(function(response) {
audioDomElement.play();
retryAttempts = 0;
if(!response.mount) {
transition(PlayStateSessionOver);
destroy();
}
else {
audioDomElement.play();
transition(PlayStateInitializing);
retryAttempts = 0;
// keep this after transition, because any transition clears this timer
waitForBufferingTimeout = setTimeout(noBuffer, WAIT_FOR_BUFFER_TIMEOUT);
transition(PlayStateInitializing);
// keep this after transition, because any transition clears this timer
waitForBufferingTimeout = setTimeout(noBuffer, WAIT_FOR_BUFFER_TIMEOUT);
}
})
}
@ -132,7 +139,7 @@
$audio.append(originalSource);
audioDomElement = $audio.get(0);
audioBind();
logger.debug("recreated audio element ")
logger.log("recreated audio element ")
}
function clearBufferTimeout() {
@ -143,7 +150,7 @@
}
function transition(newState) {
logger.debug("transitioning from " + playState + " to " + newState);
logger.log("transitioning from " + playState + " to " + newState);
playState = newState;
@ -156,6 +163,7 @@
playState == PlayStateSessionOver ||
playState == PlayStateNetworkError ||
playState == PlayStateServerError ) {
$audio.unbind('canplay');
context.JK.ListenBroadcastCurrentlyPlaying = null;
}
@ -165,7 +173,7 @@
function noBuffer() {
if(retryAttempts >= RETRY_ATTEMPTS) {
logger.debug("never received indication of buffering or playing");
logger.log("never received indication of buffering or playing");
transition(PlayStateFailedStart);
}
else {
@ -173,20 +181,38 @@
clearBufferTimeout();
// tell audio to stop/start, in attempt to retry
//audioDomElement.pause();
audioDomElement.load();
audioDomElement.play();
checkServer()
.done(function(response) {
transition(PlayStateRetrying);
if(!response.mount) {
transition(PlayStateSessionOver);
destroy();
}
else {
// tell audio to stop/start, in attempt to retry
//audioDomElement.pause();
audioDomElement.load();
if(needsCanPlayGuard()) {
$audio.bind('canplay', function() {
audioDomElement.play();
})
}
else {
audioDomElement.play();
}
transition(PlayStateRetrying);
waitForBufferingTimeout = setTimeout(noBuffer, WAIT_FOR_BUFFER_TIMEOUT);
}
})
waitForBufferingTimeout = setTimeout(noBuffer, WAIT_FOR_BUFFER_TIMEOUT);
}
}
function isNoisyEvent(eventName) {
if(playState == PlayStateNone) {
console.log("ignoring: " + eventName)
logger.log("ignoring: " + eventName)
return true;
}
@ -199,21 +225,26 @@
function onPlaying() {
if(isNoisyEvent('playing')) return;
logger.debug("playing", arguments);
logger.log("playing", arguments);
transition(PlayStatePlaying);
}
function onPause() {
if(isNoisyEvent('pause')) return;
logger.debug("pause", arguments);
logger.log("pause", arguments);
if(treatPauseLikeEnd()) {
transition(PlayStateEnded);
return;
};
transition(PlayStateStalled);
}
function onError() {
if(isNoisyEvent('error')) return;
logger.debug("error", arguments);
logger.log("error", arguments);
if(playState == PlayStatePlaying || playState == PlayStateStalled) {
transition(PlayStateFailedPlaying);
@ -225,29 +256,31 @@
function onEnded() {
if(isNoisyEvent('ended')) return;
logger.debug("ended", arguments);
logger.log("ended", arguments);
transition(PlayStateEnded);
}
function onEmptied() {
if(isNoisyEvent('emptied')) return;
logger.debug("emptied", arguments);
logger.log("emptied", arguments);
}
function onAbort() {
if(isNoisyEvent('abort')) return;
logger.debug("abort", arguments);
logger.log("abort", arguments);
}
function onStalled() {
if(isNoisyEvent('stalled')) return;
logger.debug("stalled", arguments);
logger.log("stalled", arguments);
if(arguments[0].target !== audioDomElement) {
logger.debug("ignoring stalled msg for non-active audio element")
logger.log("ignoring stalled msg for non-active audio element")
return;
}
if(ignoreStalls()) return;
// fires in Chrome on page load
if(playState == PlayStateBuffering || playState == PlayStatePlaying) {
@ -257,15 +290,17 @@
function onSuspend() {
if(isNoisyEvent('suspend')) return;
logger.debug("onsuspend", arguments);
logger.log("onsuspend", arguments);
// fires in FF on page load
if(ignoreSuspend()) return;
transition(PlayStateStalled);
}
function onTimeUpdate() {
//logger.debug("ontimeupdate", arguments);
//logger.log("ontimeupdate", arguments);
}
function onProgress() {
@ -368,6 +403,38 @@
}
}
function treatPauseLikeEnd() {
// never see a pause event until the session is over, in the rich client
return playState == PlayStatePlaying && navigator.userAgent.toLowerCase().indexOf('jamkazam') > -1;
}
function ignoreSuspend() {
// client always does a 'suspend' after playing. bleh
return playState == PlayStatePlaying && navigator.userAgent.toLowerCase().indexOf('jamkazam') > -1;
}
function ignoreStalls() {
return false;
}
function needsCanPlayGuard() {
var ua = navigator.userAgent.toLowerCase();
if (ua.indexOf('safari') != -1) {
if (ua.indexOf('chrome') > -1) {
} else {
if (ua.indexOf('ipad') > -1 || ua.indexOf('iphone') > -1) {
return false; // not sure yet which way this should go
}
return true;
}
}
else if(ua.indexOf('jamkazam') > -1) {
return true;
}
return false;
}
function audioBind() {
$audio.bind('play', onPlay);
$audio.bind('playing', onPlaying);
@ -380,8 +447,8 @@
$audio.bind('stalled', onStalled);
//$audio.bind('timeupdate', onTimeUpdate);
$audio.bind('progress', onProgress);
}
function initialize() {
musicSessionId = $parent.attr('data-music-session');
@ -394,7 +461,7 @@
$audio = $('audio', $parent);
if($audio.length == 0) {
logger.debug("listen_broadcast: no audio element. deactivating")
logger.log("listen_broadcast: no audio element. deactivating")
return;
}
if($audio.length > 1) {

View File

@ -11,8 +11,10 @@
text-align: center;
@include border_box_sizing;
height: 36px;
}
.recording-controls {
margin-top: 15px;
padding: 3px 5px 3px 10px;
@ -35,6 +37,10 @@
.play-button {
outline: 0;
// the following 3 properties were to make safari on iOS not wrap text after the .play-button float:left was preferred
position:absolute;
left:5px;
top:7px;
}
&.no-mount{

View File

@ -27,8 +27,9 @@ class ApiIcecastController < ApiController
remote_ip = params[:ip]
remote_user_agent = params[:agent]
mount = IcecastMount.find_by_name!(@mount_id)
mount.listener_add
mount = IcecastMount.find_by_name(@mount_id)
mount.listener_add if mount
render text: '', :status => :ok
end
@ -39,8 +40,8 @@ class ApiIcecastController < ApiController
pass = params[:pass]
duration = params[:duration] # seconds connected to the listen stream
mount = IcecastMount.find_by_name!(@mount_id)
mount.listener_remove
mount = IcecastMount.find_by_name(@mount_id)
mount.listener_remove if mount
render text: '', :status => :ok
end

View File

@ -3,6 +3,14 @@ object @music_session
if !current_user
# there should be more data returned, but we need to think very carefully about what data is public for a music session
attributes :id
# only show mount info if fan_access is public. Eventually we'll also need to show this in other scenarios, like if invited
child({:mount => :mount}, :if => lambda { |music_session| music_session.fan_access}) {
attributes :id, :name, :sourced, :listeners, :bitrate, :subtype, :url
node(:mime_type) { |mount| mount.resolve_string(:mime_type) }
node(:bitrate) { |mount| mount.resolve_string(:bitrate) }
node(:subtype) { |mount| mount.resolve_string(:subtype) }
}
else
attributes :id, :description, :musician_access, :approval_required, :fan_access, :fan_chat, :band_id, :user_id, :claimed_recording_initiator_id, :track_changes_counter

View File

@ -22,7 +22,7 @@
- if feed_item.has_mount?
%audio{preload: 'none'}
%source{src: feed_item.music_session.mount.url, type: feed_item.music_session.mount.resolve_string(:mime_type)}
.session-status
%span.session-status
= session_text(feed_item)
/ current playback time
= session_duration(feed_item, class: 'session-duration tick-duration recording-current', 'data-created-at' => feed_item.created_at.to_i)

View File

@ -10,7 +10,9 @@ unless $rails_rake_task
:port => APP_CONFIG.websocket_gateway_port,
:emwebsocket_debug => APP_CONFIG.websocket_gateway_internal_debug,
:connect_time_stale => APP_CONFIG.websocket_gateway_connect_time_stale,
:connect_time_expire => APP_CONFIG.websocket_gateway_connect_time_expire)
:connect_time_expire => APP_CONFIG.websocket_gateway_connect_time_expire,
:rabbitmq_host => APP_CONFIG.rabbitmq_host,
:rabbitmq_port => APP_CONFIG.rabbitmq_port)
end
end
end

View File

@ -48,4 +48,6 @@ Object.send(:remove_const, :Rails) # this is to 'fool' new relic into not thinki
Server.new.run(:port => config["port"],
:emwebsocket_debug => config["emwebsocket_debug"],
:connect_time_stale => config["connect_time_stale"],
:connect_time_expire => config["connect_time_expire"])
:connect_time_expire => config["connect_time_expire"],
:rabbitmq_host => config['rabbitmq_host'],
:rabbitmq_port => config['rabbitmq_port'])

View File

@ -6,14 +6,20 @@ development:
port: 6767
verbose: true
emwebsocket_debug: false
rabbitmq_host: localhost
rabbitmq_port: 5672
<<: *defaults
test:
port: 6769
verbose: true
rabbitmq_host: localhost
rabbitmq_port: 5672
<<: *defaults
production:
port: 6767
verbose: false
verbose: false
rabbitmq_host: localhost
rabbitmq_port: 5672
<<: *defaults

View File

@ -17,8 +17,10 @@ module JamWebsockets
port = options[:port]
connect_time_stale = options[:connect_time_stale].to_i
connect_time_expire = options[:connect_time_expire].to_i
rabbitmq_host = options[:rabbitmq_host]
rabbitmq_port = options[:rabbitmq_port].to_i
@log.info "starting server #{host}:#{port} with staleness_time=#{connect_time_stale}; reconnect time = #{connect_time_expire}"
@log.info "starting server #{host}:#{port} staleness_time=#{connect_time_stale}; reconnect time = #{connect_time_expire}, rabbitmq=#{rabbitmq_host}:#{rabbitmq_port}"
EventMachine.error_handler{|e|
@log.error "unhandled error #{e}"
@ -26,7 +28,7 @@ module JamWebsockets
}
EventMachine.run do
@router.start(connect_time_stale) do
@router.start(connect_time_stale, host: rabbitmq_host, port: rabbitmq_port) do
# take stale off the expire limit because the call to stale will
# touch the updated_at column, adding an extra stale limit to the expire time limit
# expire_time = connect_time_expire > connect_time_stale ? connect_time_expire - connect_time_stale : connect_time_expire