From 5f14f73322d3304b9818d06d1af64b6c44725f5a Mon Sep 17 00:00:00 2001 From: Seth Call Date: Fri, 2 Jan 2015 15:29:31 -0600 Subject: [PATCH] * some more fixes for broadcasting - VRFS-2523 --- .../javascripts/jquery.listenbroadcast.js | 152 +++++++++--------- web/app/assets/javascripts/sessionList.js | 3 +- web/app/assets/javascripts/web/sessions.js | 13 +- .../stylesheets/web/recordings.css.scss | 4 +- web/app/views/music_sessions/show.html.erb | 2 +- 5 files changed, 91 insertions(+), 83 deletions(-) diff --git a/web/app/assets/javascripts/jquery.listenbroadcast.js b/web/app/assets/javascripts/jquery.listenbroadcast.js index 66c20d850..95c806af2 100644 --- a/web/app/assets/javascripts/jquery.listenbroadcast.js +++ b/web/app/assets/javascripts/jquery.listenbroadcast.js @@ -33,6 +33,7 @@ context.JK.ListenBroadcast = function($parentElement, options){ var WAIT_FOR_BUFFER_TIMEOUT = 5000; + var WAIT_FOR_PLAYING_TIMEOUT = 7000; var RETRY_ATTEMPTS = 5; // we try 4 times, so the user will wait up until RETRY_ATTEMPTS * WAIT_FOR_BUFFER_TIMEOUTS var logger = context.JK.logger; @@ -42,6 +43,7 @@ var audioDomElement = null; var musicSessionId = null; var waitForBufferingTimeout = null; + var waitForPlayingTimeout = null; var fanAccess = null; var audioSrc = null; var audioType = null; @@ -49,6 +51,7 @@ var self = this; var mountInfo = null; var $mountState = null; + var sessionInfo = null; // stored so we can access .mount, mostly var lazyAudioInit = options && options.lazyAudioInit; var hoverOptions = (options && options.hoverOptions) ? options.hoverOptions : {} var $detailHelper = options && options.detailHelper; @@ -77,21 +80,7 @@ e.stopPropagation(); } - if(lazyAudioInit) { - if($audio.length == 0) { - $audio = - $('') - $parent.append($audio) - audioDomElement = $audio.get(0); - audioBind(); - } - } - - if(destroyed) return; - - if(!audioDomElement) throw "no audio element supplied; the user should not be able to attempt a play" + //if(destroyed) return; if(context.JK.ListenBroadcastCurrentlyPlaying) { context.JK.ListenBroadcastCurrentlyPlaying.forcedPause(); @@ -102,20 +91,33 @@ checkServer() .done(function(response) { - if(!response.mount) { + if(!sessionInfo.mount) { transition(PlayStateSessionOver); destroy(); } else { - audioDomElement.play(); + recreateAudioElement(); - retryAttempts = 0; + audioDomElement.load(); - transition(PlayStateInitializing); + retryAttempts = 0; + + transition(PlayStateInitializing); + + // keep this after transition, because any transition clears this timer + waitForBufferingTimeout = setTimeout(noBuffer, WAIT_FOR_BUFFER_TIMEOUT); + logger.debug("setting buffering timeout"); + rest.addPlayablePlay(musicSessionId, 'JamRuby::MusicSession', null, context.JK.currentUserId); + + if(needsCanPlayGuard()) { + $audio.bind('canplay', function() { + audioDomElement.play(); + }) + } + else { + audioDomElement.play(); + } - // keep this after transition, because any transition clears this timer - waitForBufferingTimeout = setTimeout(noBuffer, WAIT_FOR_BUFFER_TIMEOUT); - rest.addPlayablePlay(musicSessionId, 'JamRuby::MusicSession', null, context.JK.currentUserId); } }) } @@ -131,9 +133,7 @@ e.stopPropagation(); } - if(destroyed) return; - - if(!lazyAudioInit && !audioDomElement) throw "no audio element supplied; the user should not be able to attempt a pause" + //if(destroyed) return; transition(PlayStateNone); @@ -141,12 +141,13 @@ } function destroy() { - if(!destroyed) { - $audio.remove(); - $audio = null; - audioDomElement = null; - destroyed = true; - } + // if(!destroyed) { + //$audio.remove(); + //$audio = null; + //audioDomElement = null; + recreateAudioElement() + // destroyed = true; + //} } function onScreenChanged(e, data) { @@ -155,36 +156,49 @@ } } + function createAudioElementHtml() { + if (sessionInfo == null) throw "no session info"; + if (sessionInfo.mount == null) throw "no session mount info"; + + $audio = + $('') + $parent.append($audio) + audioDomElement = $audio.get(0); + audioBind(); + + } + // this is the only way to make audio stop buffering after the user hits pause function recreateAudioElement() { // jeez: http://stackoverflow.com/questions/4071872/html5-video-force-abort-of-buffering/13302599#13302599 - var originalSource = $audio.html() - audioDomElement.pause(); - audioDomElement.src = ''; - audioDomElement.load(); - var $parent = $audio.parent(); + if(audioDomElement) { + audioDomElement.pause(); + audioDomElement.src = ''; + audioDomElement.load(); + } $audio.remove(); - $audio = $('') - $audio.append(originalSource); - var $sources = $audio.find('source') - $.each($sources, function(i, source) { - var $source = $(source); - var bustedSource = cacheBustedSrc($source.attr('data-audio-src')) - $source.attr('src', bustedSource) - }) - $parent.append($audio); - audioDomElement = $audio.get(0); - audioBind(); + createAudioElementHtml(); logger.log("recreated audio element ") } function clearBufferTimeout() { if(waitForBufferingTimeout) { + logger.debug("clearing buffering timeout"); clearTimeout (waitForBufferingTimeout); waitForBufferingTimeout = null; } } + function clearPlayingTimeout() { + if(waitForPlayingTimeout) { + logger.debug("clearing playing timeout"); + clearTimeout (waitForPlayingTimeout); + waitForPlayingTimeout = null; + } + } + function transition(newState) { logger.log("transitioning from " + playState + " to " + newState); @@ -192,8 +206,15 @@ if(newState != PlayStateStalled) { clearBufferTimeout(); + clearPlayingTimeout(); } + if(newState == PlayStateBuffering) { + // give some time after buffering is seen to let play start + waitForPlayingTimeout = setTimeout(noPlay, WAIT_FOR_PLAYING_TIMEOUT) + } + + if( playState == PlayStateNone || playState == PlayStateEnded || playState == PlayStateFailedStart || @@ -208,6 +229,9 @@ triggerStateChange(); } + function noPlay() { + noBuffer(); + } function noBuffer() { waitForBufferingTimeout = null; @@ -224,7 +248,7 @@ checkServer() .done(function(response) { - if(!response.mount) { + if(!sessionInfo.mount) { transition(PlayStateSessionOver); destroy(); } @@ -353,6 +377,10 @@ function checkServer() { return rest.getSession(musicSessionId) + .done(function(response) { + console.log("assigning sessionInfo") + sessionInfo = response; + }) .fail(function(jqXHR) { if(jqXHR.status == 404 || jqXHR.status == 403) { transition(PlayStateSessionOver); @@ -454,7 +482,7 @@ if(refresh) { checkServer() .done(function(response) { - if(!response.mount) { + if(!sessionInfo.mount) { transition(PlayStateSessionOver); destroy(); }}) @@ -649,7 +677,7 @@ function openBubble() { checkServer().done(function(response) { - var mountId = response.mount ? response.mount.id : null + var mountId = sessionInfo.mount ? sessionInfo.mount.id : null if(mountId) { rest.getMount({id: mountId}) @@ -705,7 +733,6 @@ function initialize() { - musicSessionId = $parent.attr('data-music-session'); if(!musicSessionId) throw "data-music-session must be specified on $parentElement"; @@ -713,14 +740,6 @@ if(fanAccess === null) throw 'fan-access must be specified in $parentElement'; fanAccess = $parent.attr('fan-access') === 'true' // coerce to boolean - if(lazyAudioInit) { - // save the original src element (without any cache bust) - audioSrc = $parent.attr('data-audio-src'); - if(audioSrc === null) throw 'data-audio-src must be specified in $parentElement'; - audioType = $parent.attr('data-audio-type'); - if(audioType === null) throw 'data-audio-type must be specified in $parentElement'; - } - bindHoverDetail(); $audio = $('audio', $parent); @@ -733,21 +752,6 @@ throw "more than one