From 9876c00a7ac95c2782dc03e97c93470328f00f86 Mon Sep 17 00:00:00 2001 From: Seth Call Date: Fri, 19 Dec 2014 14:00:49 -0600 Subject: [PATCH] * VRFS-2456 - add listen function to find session page, and update of join/rsvp icons --- ruby/lib/jam_ruby/lib/subscription_message.rb | 4 +- ruby/lib/jam_ruby/models/icecast_mount.rb | 8 +- .../jam_ruby/models/icecast_mount_spec.rb | 4 +- web/app/assets/images/content/join-icon.jpg | Bin 0 -> 1407 bytes web/app/assets/images/content/listen-icon.jpg | Bin 0 -> 8688 bytes web/app/assets/images/content/pause-icon.jpg | Bin 0 -> 8249 bytes web/app/assets/images/content/rsvp-icon.jpg | Bin 0 -> 8651 bytes web/app/assets/javascripts/globals.js | 3 +- .../javascripts/jquery.listenbroadcast.js | 138 ++++++++++++------ web/app/assets/javascripts/layout.js | 2 + web/app/assets/javascripts/sessionList.js | 85 ++++++++++- web/app/assets/javascripts/utils.js | 5 + .../stylesheets/client/findSession.css.scss | 38 +++++ .../client/listenBroadcast.css.scss | 14 +- .../stylesheets/dialogs/shareDialog.css.scss | 6 + .../source_change_notification.rabl | 2 +- web/app/views/clients/_findSession.html.erb | 38 +++-- web/app/views/clients/_sessionList.html.erb | 3 +- web/config/scheduler.yml | 6 +- 19 files changed, 276 insertions(+), 80 deletions(-) create mode 100644 web/app/assets/images/content/join-icon.jpg create mode 100644 web/app/assets/images/content/listen-icon.jpg create mode 100644 web/app/assets/images/content/pause-icon.jpg create mode 100644 web/app/assets/images/content/rsvp-icon.jpg diff --git a/ruby/lib/jam_ruby/lib/subscription_message.rb b/ruby/lib/jam_ruby/lib/subscription_message.rb index 62409b6aa..8f4320249 100644 --- a/ruby/lib/jam_ruby/lib/subscription_message.rb +++ b/ruby/lib/jam_ruby/lib/subscription_message.rb @@ -14,11 +14,11 @@ module JamRuby end def self.mount_source_up_requested(mount) - Notification.send_subscription_message('mount', mount.id, {type: 'source_up_requested'}.to_json ) + Notification.send_subscription_message('mount', mount.id, {change_type: IcecastSourceChange::CHANGE_TYPE_MOUNT_UP_REQUEST}.to_json ) end def self.mount_source_down_requested(mount) - Notification.send_subscription_message('mount', mount.id, {type: 'source_down_requested'}.to_json ) + Notification.send_subscription_message('mount', mount.id, {change_type: IcecastSourceChange::CHANGE_TYPE_MOUNT_DOWN_REQUEST}.to_json ) end end end diff --git a/ruby/lib/jam_ruby/models/icecast_mount.rb b/ruby/lib/jam_ruby/models/icecast_mount.rb index 29f3a6888..be1cfb382 100644 --- a/ruby/lib/jam_ruby/models/icecast_mount.rb +++ b/ruby/lib/jam_ruby/models/icecast_mount.rb @@ -69,7 +69,7 @@ module JamRuby #IcecastSourceChange.delete_all(["icecast_mount_id = ?", self.id]) if source_direction # and tell anyone listening that the direction has changed - SubscriptionMessage.mount_source_direction(self) + # SubscriptionMessage.mount_source_direction(self) end # Note: @@ -139,7 +139,7 @@ module JamRuby first = source_changes.first # don't check source_changes if actual source state mirrors desired source state... just say we are good, and pass down relevant sourcing user ID if present - result = success_state('source_' + (source_direction ? 'up' : 'down'), first.nil? ? nil : first.user_id) + result = success_state('source_' + (sourced ? 'up' : 'down'), first.nil? ? nil : first.user_id) elsif source_changes.count > 0 # if the desired source direction is up, but we haven't sourced yet... let's try and find out why @@ -200,7 +200,7 @@ module JamRuby def source_up with_lock do self.sourced = true - self.sourced_needs_changing_at = nil + self.sourced_needs_changing_at = Time.now self.no_config_changed = true save(validate: false) end @@ -209,7 +209,7 @@ module JamRuby def source_down with_lock do self.sourced = false - self.sourced_needs_changing_at = nil + self.sourced_needs_changing_at = Time.now self.no_config_changed = true save(validate: false) end diff --git a/ruby/spec/jam_ruby/models/icecast_mount_spec.rb b/ruby/spec/jam_ruby/models/icecast_mount_spec.rb index 847e9697c..553b5a34d 100644 --- a/ruby/spec/jam_ruby/models/icecast_mount_spec.rb +++ b/ruby/spec/jam_ruby/models/icecast_mount_spec.rb @@ -296,7 +296,7 @@ describe IcecastMount do let(:mount_needing_source) {FactoryGirl.create(:iceast_mount_with_music_session, sourced: false, sourced_needs_changing_at: Time.now, listeners: 1)} it "happy sourced mount" do - sourced_mount.state.should == success_state('source_down') + sourced_mount.state.should == success_state('source_up') end it "just transitioned" do @@ -317,7 +317,7 @@ describe IcecastMount do it "happy sourced mount" do mount_needing_source.sourced = true mount_needing_source.save! - mount_needing_source.state.should == success_state('source_down', change1.user.id) + mount_needing_source.state.should == success_state('source_up', change1.user.id) end it "succeeded recently in correct transition" do diff --git a/web/app/assets/images/content/join-icon.jpg b/web/app/assets/images/content/join-icon.jpg new file mode 100644 index 0000000000000000000000000000000000000000..19342ce3ee526d1a15eae9e6ad470c39962c9bab GIT binary patch literal 1407 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 literal 0 HcmV?d00001 diff --git a/web/app/assets/images/content/rsvp-icon.jpg b/web/app/assets/images/content/rsvp-icon.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b9f0797c8c9a0415da538f5cfc7beb18012b0fae GIT binary patch literal 8651 zcmeI1e>7WZ8pq%KA_x%@KYDbT&@!EkNKiz=QA+7ys%o{`rIDKuKY|EC*-o|98BSY5 zC~LOM(it| zm=Iv0je_=$iVxM_fB=AD$Cw4shI7yc9`FPfWAK7kTbiLEpdp|kpdp|kpds*EB;dnM z6CwcM3NVX(1R3@Ve<{GO*bTD6MH}Pb2!KqsYOnSbc$u1;rlaNfL`r7p2&9k;Evz zJufkVF6AcC8TJlz!1k0Tad~lkiB%LoS}5Y!zHDl>wGtv6+c4)qhrlFnevEKirkEd+ z8MKR+8OL)&Y&|{nb=gvuG$AR0FX38A6XHcFEGdV&xH=2k>S;RFgDpk`terl-%O3EK zLtV}#Jw4q%-O)Z#98G7qxw+9Dm~ zE-X479UV6P$07fn!Qu?8Ir!X4g~BJT{s%)7WKEDYxHP!dL|{$Mn(ETvS`&daIcuux z{|wh^m&+Hy);1mXu&RFG4KQf5`hWuq4;&tc!(wr|+S*!pf-Zrer>m!@Z(wAoZ$L88 z(=#+NBpH(_6bgZ8YGy(P1i(_zV`OgTv{N_4V}0YaXgE00|H5fE@-!1!xiq zLqe(AfF*qAh=Xq_)h{ZS2MP^y)Y8W5=;}d-3x)uV!eG!?j5=%Roeh5nSQ5_YEryqt zaWGe#noMRMDy+m?Z#n-ZWoPHOjboHJM@QGh)XaR{hK;s%Z*OvP-t6M)#`5;r>g%`7 zKOkgR=pVv%?+NE2d_i=KFg8V!nwBoj$UJ=HXzsE1Kgg3670XLXPnDHd{jIv@%ts&B ze$w#S=NB3;Ub=kc+V!>@|7h>{>g%rVp1b$%_de(w8vbtN$Y3bCZp!%tLtcmcq*OU+P#p z?i{B?i92;oY@CKRDAdvxmHjedIscKe6=AEo`Tzlgf}4jS0Z%YquKQW@Ua5ju2n8^(-3%xl`sR@w3(4W~jdHJCVTpLwb)_*kr zMg_jVTkknsnm-v<`1|_GD>2;%-mlN6L`LXmj0Cg0Y?5m;ERKc-%lx0=vh@Z}>+h8k zuP1Kku1hDhqz<%K4Q3C_5=YD19dj}CGv$@0ZZYzU?yiEf*==TJTXv5X)Zj91mObx3 z`*I?%qCGb&(DDXe^qM2?B8jO?Z}#?_>ZEPjmFC~BxXY8?Kqp)&MpkM$8Ri#r{` zpdHv@=PHoSNY7KlpFWYx*)Er=i;^F1oIXFTbT1y1p2jNN%BQ-IJi&27ibKmq{V(sm z=rhXV{k=3)5%EE^)?=3R>gNMV%zY;UcPP@YnZM>x-EVtDx5N~=1j|Ps7GxestzB^Y zY-3YRgRGAB71qKqz5JQSI%U8g6L?*d{^&8Qggn7u5QjJy`Ast`HThIlORlwkUDRpj zi*xgtqO5z?dPM@Z_sK5=VaEex0TnN+(!%$~wQ_#f$5FHxNa^1c&1Ft_7V7NX%Dvmv zI&|m2Xjjp9rpG-x-@X$+GCzPgch}C{?y()}nVWy7Q8Ar2JRWgq;RMP4sh0chVnCjb z&m@lK%?$gm+hhJPzscyR~0xX^sJ!_D(G`#Dxj-;F#TxV!46sE z6|AIqbqeoA#C@E)e7T>OS4@ zqDj9euPOA5eH$?-_MFnLe)~dB+Ue<=DsYq>R&eR?dJ1xX;NX^d7%l(_Yd7S$Jk7fgSTdv7^D2w`?}VJk5n*aa+ literal 0 HcmV?d00001 diff --git a/web/app/assets/javascripts/globals.js b/web/app/assets/javascripts/globals.js index 4f68a3125..584eba17b 100644 --- a/web/app/assets/javascripts/globals.js +++ b/web/app/assets/javascripts/globals.js @@ -44,7 +44,8 @@ MUTE_SELECTED: 'mute_selected', SUBSCRIBE_NOTIFICATION: 'subscribe_notification', CONNECTION_UP: 'connection_up', - CONNECTION_DOWN: 'connection_down' + CONNECTION_DOWN: 'connection_down', + SCREEN_CHANGED: 'screen_changed' }; context.JK.ALERT_NAMES = { diff --git a/web/app/assets/javascripts/jquery.listenbroadcast.js b/web/app/assets/javascripts/jquery.listenbroadcast.js index d8dba3e4a..349305b57 100644 --- a/web/app/assets/javascripts/jquery.listenbroadcast.js +++ b/web/app/assets/javascripts/jquery.listenbroadcast.js @@ -35,7 +35,6 @@ var WAIT_FOR_BUFFER_TIMEOUT = 5000; 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; var rest = context.JK.Rest(); var $parent = $parentElement; @@ -44,10 +43,15 @@ var musicSessionId = null; var waitForBufferingTimeout = null; var fanAccess = null; + var audioSrc = null; + var audioType = null; var retryAttempts = 0; var self = this; var mountInfo = null; var $mountState = null; + var lazyAudioInit = options && options.lazyAudioInit; + var hoverOptions = (options && options.hoverOptions) ? options.hoverOptions : {} + var $detailHelper = options && options.detailHelper; var destroyed = false; @@ -73,6 +77,18 @@ 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" @@ -117,7 +133,7 @@ if(destroyed) return; - if(!audioDomElement) throw "no audio element supplied; the user should not be able to attempt a pause" + if(!lazyAudioInit && !audioDomElement) throw "no audio element supplied; the user should not be able to attempt a pause" transition(PlayStateNone); @@ -133,6 +149,12 @@ } } + function onScreenChanged(e, data) { + if(context.JK.ListenBroadcastCurrentlyPlaying) { + context.JK.ListenBroadcastCurrentlyPlaying.pause(); + } + } + // 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 @@ -408,6 +430,8 @@ logger.error("unknown state: " + playState) } + $parent.data('listenbroadcast-playstate', playState); + $parent.triggerHandler('statechange.listenBroadcast', { element: $parent, @@ -509,7 +533,9 @@ logger.debug("subscription notification received: type:" + data.type) - updateMountInfo(data.body.mount); + if(data.body.mount) { + updateMountInfo(data.body.mount); + } var id = data.id var type = data.type @@ -519,7 +545,7 @@ var $detailHolder = $mountState.find('.detail-items') var msgType = data.body.type; - var sourceChange = data.body.source_change; + var sourceChange = data.body; if(sourceChange) { var $detail = addSourceChange($detailHolder, sourceChange) if ($detail) { @@ -549,8 +575,8 @@ $detailText.text('Start Broadcast Requested') } else if(sourceChange.change_type == 'source_down_request') { - $who.text('Server') - $detailText.text('Start Broadcast Requested') + $who.html('Server') + $detailText.text('Stop Broadcast Requested') } else { @@ -597,43 +623,61 @@ return $detail; } + function cleanupDetails() { + var mountId = $parent.data('mount-id') + if(mountId) { + context.JK.SubscriptionUtils.unsubscribe('mount', mountId) + } + $mountState = null; + mountInfo = null; + } + + function openBubble() { + checkServer().done(function(response) { + var mountId = response.mount ? response.mount.id : null + + if(mountId) { + rest.getMount({id: mountId}) + .done(function (mount) { + mountInfo = mount + $parent.data('mount-id', mountId) + context.JK.SubscriptionUtils.subscribe('mount', mountId).on(context.JK.EVENTS.SUBSCRIBE_NOTIFICATION, onDetailEvent) + $parent.btOn() + }) + .fail(context.JK.app.ajaxError) + } + else { + mountInfo = null; + context.JK.app.layout.notify('This session can not currently broadcast') + } + }) + .fail(function() { + logger.debug("session is over") + }) + } + function bindHoverDetail() { var stateHolderHtml = context._.template($('#template-listen-broadcast-state').html(), {}, {variable: 'data'}); - context.JK.hoverBubble($parent, stateHolderHtml, {trigger: 'none', preShow: broadcastDetailPreShow, positions:['bottom'], width:'300px', height:'250px'}) + var btOptions = $.extend({}, {trigger: 'none', preShow: broadcastDetailPreShow, postHide: cleanupDetails, closeWhenOthersOpen: true, positions:['bottom', 'right', 'top', 'left'], width:'300px', height:'250px'}, hoverOptions) + context.JK.hoverBubble($parent, stateHolderHtml, btOptions) - $parent.hoverIntent({ - over: function() { - checkServer().done(function(response) { - var mountId = response.mount ? response.mount.id : null + // in case the bt is destroyed + $parent.on('remove', cleanupDetails); - if(mountId) { - rest.getMount({id: mountId}) - .done(function (mount) { - mountInfo = mount - $parent.data('mount-id', mountId) - context.JK.SubscriptionUtils.subscribe('mount', mountId).on(context.JK.EVENTS.SUBSCRIBE_NOTIFICATION, onDetailEvent) - $parent.btOn() - }) - .fail(context.JK.app.ajaxError) - } - else { - mountInfo = null; - context.JK.app.layout.notify('This session can not currently broadcast') - } - }) - .fail(function() { - logger.debug("session is over") - }) - }, - out: function() { - var mountId = $parent.data('mount-id') - context.JK.SubscriptionUtils.unsubscribe('mount', mountId) - $parent.btOff(); - $mountState = null; - mountInfo = null; - } - }) + if($detailHelper) { + $detailHelper.click(function() { openBubble(); return false; }) + } + else { + $parent.hoverIntent({ + over: function() { + openBubble(); + }, + out: function() { + + } + }) + } } function initialize() { @@ -645,23 +689,35 @@ if(fanAccess === null) throw 'fan-access must be specified in $parentElement'; fanAccess = $parent.attr('fan-access') === 'true' // coerce to boolean + if(lazyAudioInit) { + 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); - if($audio.length == 0) { + if($audio.length == 0 && !lazyAudioInit) { return; } + if($audio.length > 1) { throw "more than one