working on livestream
This commit is contained in:
parent
b9f9856541
commit
4d7712093a
|
|
@ -4,15 +4,30 @@ module JamRuby
|
|||
|
||||
@@log = Logging.logger[Broadcast]
|
||||
|
||||
STATUS_COMPLETED = 'completed'
|
||||
STATUS_COMPLETED = 'complete'
|
||||
STATUS_ABANDONED = 'abandoned'
|
||||
STATUS_REVOKED = 'revoked'
|
||||
STATUS_DELETED = 'deleted'
|
||||
|
||||
DONE_STATUSES = [STATUS_COMPLETED, STATUS_ABANDONED, STATUS_REVOKED]
|
||||
DONE_STATUSES = [STATUS_ABANDONED, STATUS_REVOKED, STATUS_DELETED, STATUS_COMPLETED]
|
||||
belongs_to :music_session, :class_name => 'JamRuby::MusicSsession'
|
||||
|
||||
def self.current_broadcast(music_session)
|
||||
Broadcast.where(music_session_id: music_session.id).where('broadcast_status not in (?)', Broadcast::DONE_STATUSES).first
|
||||
end
|
||||
|
||||
def self.unlink_broadcast(music_session)
|
||||
broadcast = current_broadcast(music_session)
|
||||
if broadcast
|
||||
broadcast.broadcast_status = STATUS_DELETED
|
||||
broadcast.save
|
||||
end
|
||||
end
|
||||
|
||||
# data should be JSON hash from google API
|
||||
def update_broadcast_data(data)
|
||||
self.broadcast_status = data["status"]["lifeCycleStatus"]
|
||||
self.broadcast_data = data.to_json
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -83,31 +83,40 @@ module JamRuby
|
|||
Broadcast.current_broadcast(self)
|
||||
end
|
||||
|
||||
def create_broadcast(google_client, user, broadcast_options)
|
||||
def unlink_broadcast
|
||||
Broadcast.unlink_broadcast(self)
|
||||
end
|
||||
|
||||
def create_broadcast(user, broadcast_options, google_client = GoogleClient.new)
|
||||
|
||||
broadcast = current_broadcast
|
||||
|
||||
if broadcast.nil?
|
||||
broadcast = create_youtube_broadcast(google_client, user, broadcast_options)
|
||||
broadcast = create_youtube_broadcast(user, broadcast_options, google_client)
|
||||
else
|
||||
refresh_youtube_broadcast(google_client, user, broadcast)
|
||||
result = refresh_youtube_broadcast(user, broadcast, broadcast_options, google_client)
|
||||
# check against Youtube the real state of broadcast, to see if we need a new one?
|
||||
|
||||
if result.nil?
|
||||
unlink_broadcast # user probably deleted it, or marked it complete.
|
||||
broadcast = create_youtube_broadcast(user, broadcast_options, google_client)
|
||||
end
|
||||
end
|
||||
|
||||
broadcast
|
||||
end
|
||||
|
||||
def create_stream(google_client, user, broadcast_options)
|
||||
def create_stream(user, broadcast_options, google_client = GoogleClient.new)
|
||||
|
||||
broadcast = create_broadcast(google_client, user, broadcast_options)
|
||||
broadcast = create_broadcast(user, broadcast_options, google_client)
|
||||
|
||||
stream = current_stream(broadcast)
|
||||
|
||||
if stream.nil?
|
||||
create_youtube_stream(google_client, user, broadcast, broadcast_options)
|
||||
bind_broadcast(google_client, user, broadcast)
|
||||
create_youtube_stream(user, broadcast, broadcast_options, google_client)
|
||||
bind_broadcast(user, broadcast, google_client)
|
||||
else
|
||||
bind_broadcast(google_client, user, broadcast)
|
||||
bind_broadcast(user, broadcast, google_client)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -115,14 +124,66 @@ module JamRuby
|
|||
broadcast.stream_id
|
||||
end
|
||||
|
||||
def refresh_youtube_broadcast(google_client, user, broadcast)
|
||||
broadcast_data = google_client.get_broadcast(user, broadcast.broadcast_id)
|
||||
broadcast.broadcast_status = broadcast_data["status"]["lifeCycleStatus"]
|
||||
broadcast.broadcast_data = broadcast_data.to_json
|
||||
def refresh_youtube_broadcast(user, broadcast, broadcast_data = nil, google_client = GoogleClient.new)
|
||||
if broadcast_data.nil?
|
||||
broadcast_data = google_client.get_broadcast(user, broadcast.broadcast_id)
|
||||
end
|
||||
|
||||
if broadcast_data
|
||||
broadcast.update_broadcast_data(broadcast_data)
|
||||
broadcast.save
|
||||
true
|
||||
else
|
||||
# this path makes sense if the user deleted the video on the server, but we do not yet know it
|
||||
nil
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def get_livestream(user, google_client = GoogleClient.new)
|
||||
broadcast = current_broadcast
|
||||
|
||||
if broadcast.nil?
|
||||
nil
|
||||
else
|
||||
stream_id = current_stream(broadcast)
|
||||
|
||||
if stream_id.nil?
|
||||
nil
|
||||
else
|
||||
return google_client.get_livestream(user, stream_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def get_broadcast(user, google_client = UserManager.new.get_google_client)
|
||||
broadcast = current_broadcast
|
||||
|
||||
if broadcast.nil?
|
||||
nil
|
||||
else
|
||||
broadcast_data = google_client.get_broadcast(user, broadcast.broadcast_id)
|
||||
broadcast.update_broadcast_data(broadcast_data)
|
||||
broadcast.save
|
||||
broadcast
|
||||
end
|
||||
end
|
||||
|
||||
def set_livestream_live(user, google_client = GoogleClient.new)
|
||||
livestream = get_livestream(user, google_client)
|
||||
|
||||
if livestream
|
||||
if livestream["status"]["streamStatus"] == "active"
|
||||
transition_broadcast(user, broadcast, 'live', google_client)
|
||||
end
|
||||
else
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
# https://developers.google.com/youtube/v3/live/docs/liveStreams#resource
|
||||
def create_youtube_stream(google_client, user, broadcast, broadcast_options)
|
||||
def create_youtube_stream(user, broadcast, broadcast_options, google_client = GoogleClient.new)
|
||||
|
||||
# https://developers.google.com/youtube/v3/live/docs/liveStreams/insert
|
||||
# required
|
||||
|
|
@ -133,7 +194,7 @@ module JamRuby
|
|||
stream_options = {}
|
||||
stream_options[:snippet] ||= {}
|
||||
stream_options[:snippet][:title] ||= name
|
||||
stream_options[:snippet][:isDefaultStream] = false
|
||||
stream_options[:snippet][:isDefaultStream] ||= false
|
||||
#broadcast_options[:snippet][:scheduledEndTime] = end_time.utc.iso8601
|
||||
|
||||
stream_options[:cdn] ||= {}
|
||||
|
|
@ -142,7 +203,9 @@ module JamRuby
|
|||
stream_options[:cdn][:ingestionType] ||= 'rtmp'
|
||||
|
||||
stream_options[:contentDetails] ||= {}
|
||||
stream_options[:contentDetails][:isReusable] = false
|
||||
stream_options[:contentDetails][:isReusable] ||= false
|
||||
stream_options[:contentDetails][:monitorStream] ||= {}
|
||||
stream_options[:contentDetails][:monitorStream][:enableMonitorStream] ||= false
|
||||
|
||||
stream_options = google_client.create_stream(user, stream_options)
|
||||
|
||||
|
|
@ -155,7 +218,7 @@ module JamRuby
|
|||
broadcast
|
||||
end
|
||||
|
||||
def create_youtube_broadcast(google_client, user, broadcast_options)
|
||||
def create_youtube_broadcast(user, broadcast_options, google_client = GoogleClient.new)
|
||||
|
||||
start_time, end_time = youtube_times
|
||||
broadcast_options ||= {}
|
||||
|
|
@ -181,16 +244,24 @@ module JamRuby
|
|||
broadcast.music_session_id = self.id
|
||||
broadcast.user_id = user.id
|
||||
broadcast.broadcast_id = broadcast_data["id"]
|
||||
broadcast.broadcast_status = broadcast_data["status"]["lifeCycleStatus"]
|
||||
broadcast.broadcast_data = broadcast_data.to_json
|
||||
broadcast.update_broadcast_data(broadcast_data)
|
||||
broadcast.save!
|
||||
broadcast
|
||||
end
|
||||
|
||||
def bind_broadcast(google_client, user, broadcast)
|
||||
def bind_broadcast(user, broadcast, google_client = GoogleClient.new)
|
||||
|
||||
bind_data = google_client.bind_broadcast(user, broadcast.broadcast_id, broadcast.stream_id)
|
||||
broadcast.broadcast_data = bind_data.to_json
|
||||
broadcast.update_broadcast_data(bind_data)
|
||||
broadcast.save!
|
||||
broadcast
|
||||
end
|
||||
|
||||
# broadcastStatus one of complete, live, testing
|
||||
def transition_broadcast(user, broadcast, broadcastStatus, google_client = GoogleClient.new)
|
||||
|
||||
bind_data = google_client.transition_broadcast(user, broadcast.broadcast_id, broadcastStatus)
|
||||
broadcast.update_broadcast_data(bind_data)
|
||||
broadcast.save!
|
||||
broadcast
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1752,7 +1752,6 @@
|
|||
this.isSessVideoShared = isSessVideoShared;
|
||||
this.SessStopVideoSharing = SessStopVideoSharing;
|
||||
this.SessStartVideoSharing = SessStartVideoSharing;
|
||||
this.getOpenVideoSources = getOpenVideoSources;
|
||||
|
||||
// Clipboard
|
||||
this.SaveToClipboard = SaveToClipboard;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -22,6 +22,7 @@
|
|||
//= require ./react-components/stores/BrowserMediaStore
|
||||
//= require ./react-components/stores/RecordingStore
|
||||
//= require ./react-components/stores/VideoStore
|
||||
//= require ./react-components/stores/VideoLiveStreamStore
|
||||
//= require ./react-components/stores/SessionStore
|
||||
//= require ./react-components/stores/SessionStatsStore
|
||||
//= require ./react-components/stores/BroadcastStore
|
||||
|
|
|
|||
|
|
@ -0,0 +1,187 @@
|
|||
context = window
|
||||
logger = context.JK.logger
|
||||
rest = context.JK.Rest()
|
||||
|
||||
mixins = []
|
||||
|
||||
# make sure this is actually us opening the window, not someone else (by checking for MixerStore)
|
||||
|
||||
# this check ensures we attempt to listen if this component is created in a popup
|
||||
reactContext = if window.opener? then window.opener else window
|
||||
|
||||
accessOpener = false
|
||||
if window.opener?
|
||||
try
|
||||
m = window.opener.MixerStore
|
||||
accessOpener = true
|
||||
catch e
|
||||
reactContext = window
|
||||
|
||||
VideoLiveStreamStore = reactContext.VideoLiveStreamStore
|
||||
VideoLiveStreamActions = reactContext.VideoLiveStreamActions
|
||||
AppActions = reactContext.AppActions
|
||||
|
||||
if accessOpener
|
||||
mixins.push(Reflux.listenTo(VideoLiveStreamStore,"onVideoLiveStreamChanged"))
|
||||
|
||||
@PopupVideoLiveStream = React.createClass({
|
||||
mixins: mixins
|
||||
|
||||
onVideoLiveStreamChanged: (videoLiveStream) ->
|
||||
if @unloaded
|
||||
return
|
||||
|
||||
logger.debug("onVideoLiveStreamChanged", videoLiveStream)
|
||||
this.setState({videoLiveStream: videoLiveStream})
|
||||
|
||||
render: () ->
|
||||
|
||||
# there are a few initial states: if auth is null, we don't know yet (and are checking against the server)
|
||||
# if auth is set, then we can show the upload btn
|
||||
# and if auth == false, then we need the user to try and log in
|
||||
|
||||
if @state.auth == false
|
||||
action = `<input className="google_login_button" type='image' src="/assets/google_signin.png" height="30px" onClick={this.startGoogleLogin}/>`
|
||||
instructions = `<p>To upload this recording to YouTube, you must give JamKazam the necessary access to your YouTube account by clicking the button below.</p>`
|
||||
|
||||
else if @state.videoLiveStream
|
||||
|
||||
videoLiveStream = @state.videoLiveStream
|
||||
if videoLiveStream.broadcast?
|
||||
|
||||
controlsUrl = "https://www.youtube.com/live_event_analytics?v=" + videoLiveStream.broadcast.id
|
||||
videoUrl = "https://www.youtube.com/watch?v=" + videoLiveStream.broadcast.id
|
||||
controlLink = `<a onClick={this.watchVideo} className="video-url" href={controlsUrl}>Open Broadcast Controls</a>`
|
||||
videoLink = `<a onClick={this.watchVideo} className="video-url" href={videoUrl}>Open Video Page</a>`
|
||||
|
||||
if videoLiveStream.errorMessage
|
||||
action = null
|
||||
instructions = `<p>The stream setup failed. Reason: ({videoLiveStream.errorMessage})</p>`
|
||||
else if @state.auth == false
|
||||
action = `<input className="google_login_button" type='image' src="/assets/google_signin.png" height="30px" onClick={this.startGoogleLogin}/>`
|
||||
instructions = `<p>To upload this recording to YouTube, you must give JamKazam the necessary access to your YouTube account by clicking the button below.</p>`
|
||||
else if videoLiveStream.streaming
|
||||
action = `<div><a className="button-orange close-btn" onClick={this.onCloseRequested}>STOP LIVECASTING</a></div>`
|
||||
instructions = `<p>{videoLink}{controlLink}</p>`
|
||||
else if videoLiveStream.creatingBroadcast
|
||||
action = null
|
||||
instructions = `<p>Synchronizing with YouTube</p>`
|
||||
else if videoLiveStream.waitingOnReady
|
||||
action = null
|
||||
instructions = `<p>Synchronizing with YouTube ... waiting on stream setup</p>`
|
||||
else if videoLiveStream.waitingOnTesting || videoLiveStream.transitioningTesting
|
||||
action = null
|
||||
instructions = `<p>Synchronizing with YouTube ... stream is ready ... skipping preview</p>`
|
||||
else if videoLiveStream.waitingOnLive
|
||||
action = null
|
||||
instructions = `<p>Synchronizing with YouTube ... stream is ready ... waiting to go live</p>`
|
||||
else if !@state.initiated
|
||||
action = `<a onClick={this.startBroadcasting} className="start-btn button-orange" href='#'>START BROADCASTING</a>`
|
||||
if videoLiveStream.broadcast
|
||||
instructions = `<p>Click 'Start Broadcasting' to setup a live streaming session on YouTube.</p>`
|
||||
else
|
||||
instructions = `<p>Press 'Start Broadcasting' to start broadcasting on YouTube.</p>`
|
||||
else if @state.initiated
|
||||
instructions = `<p>Streaming initiated. Please wait...</p>`
|
||||
else
|
||||
name = null
|
||||
action = null
|
||||
instructions = `<p>UNKNOWN STATE: {JSON.stringify(videoLiveStream)}</p>`
|
||||
else
|
||||
name = 'Loading...'
|
||||
action = null
|
||||
|
||||
`<div className="video-live-stream">
|
||||
<h3>Live Stream Video</h3>
|
||||
{instructions}
|
||||
<div className="control-holder">
|
||||
{action}
|
||||
</div>
|
||||
</div>`
|
||||
|
||||
getInitialState: () ->
|
||||
{auth: null, initiated: false}
|
||||
|
||||
startBroadcasting: (e) ->
|
||||
e.preventDefault()
|
||||
VideoLiveStreamActions.startLiveStreaming()
|
||||
@setState({initiated: true})
|
||||
|
||||
watchVideo: (e) ->
|
||||
e.preventDefault()
|
||||
$link = $(e.target)
|
||||
AppActions.openExternalUrl($link.attr('href'))
|
||||
|
||||
onCloseRequested: (e) ->
|
||||
e.preventDefault()
|
||||
window.close()
|
||||
|
||||
startGoogleLogin: (e) ->
|
||||
e.preventDefault()
|
||||
|
||||
logger.debug("Starting google login")
|
||||
window._oauth_win = window.open("/auth/google_login", "Log In to Google", "height=700,width=500,menubar=no,resizable=no,status=no");
|
||||
window._oauth_callback = @oauthCallback
|
||||
|
||||
oauthCallback: () ->
|
||||
window._oauth_win.close()
|
||||
@checkAuth()
|
||||
|
||||
checkAuth:() ->
|
||||
rest.getGoogleAuth()
|
||||
.done((auth) =>
|
||||
if auth.auth?
|
||||
@setState({auth: auth.auth})
|
||||
else
|
||||
@setState({auth: false})
|
||||
)
|
||||
.fail(() =>
|
||||
@setState({errorReason: 'Unable to fetch user authorization'})
|
||||
)
|
||||
|
||||
componentDidMount: () ->
|
||||
|
||||
$(window).unload(@windowUnloaded)
|
||||
|
||||
@checkAuth()
|
||||
|
||||
VideoLiveStreamActions.loadBroadcast(gon.session_id)
|
||||
|
||||
@resizeWindow()
|
||||
|
||||
# this is necessary due to whatever the client's rendering behavior is.
|
||||
setTimeout(@resizeWindow, 300)
|
||||
|
||||
shouldComponentUpdate: () ->
|
||||
return !@unloaded
|
||||
|
||||
componentDidUpdate: () ->
|
||||
@resizeWindow()
|
||||
setTimeout(@resizeWindow, 1000)
|
||||
|
||||
resizeWindow: () =>
|
||||
$container = $('#minimal-container')
|
||||
width = $container.width()
|
||||
height = $container.height()
|
||||
|
||||
# there is 20px or so of unused space at the top of the page. can't figure out why it's there. (above #minimal-container)
|
||||
#mysteryTopMargin = 20
|
||||
mysteryTopMargin = 0
|
||||
# deal with chrome in real browsers
|
||||
offset = (window.outerHeight - window.innerHeight) + mysteryTopMargin
|
||||
|
||||
# handle native client chrome that the above outer-inner doesn't catch
|
||||
#if navigator.userAgent.indexOf('JamKazam') > -1
|
||||
|
||||
#offset += 25
|
||||
|
||||
width = 100 if width < 100
|
||||
height = 100 if height < 100
|
||||
|
||||
window.resizeTo(width, height + offset)
|
||||
|
||||
windowUnloaded: () ->
|
||||
@unloaded = true
|
||||
window.unloaded = true
|
||||
VideoLiveStreamActions.popupClosed()
|
||||
})
|
||||
|
|
@ -15,4 +15,5 @@ context = window
|
|||
checkPromptConfigureVideo: {}
|
||||
setVideoEnabled: {}
|
||||
refreshVideoState: {}
|
||||
startLiveStream: {}
|
||||
})
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
context = window
|
||||
|
||||
@VideoLiveStreamActions = Reflux.createActions({
|
||||
startLiveStream: {}
|
||||
streamStarted: {}
|
||||
popupClosed: {}
|
||||
loadBroadcast: {}
|
||||
startLiveStreaming: {}
|
||||
})
|
||||
|
|
@ -4,6 +4,7 @@ logger = context.JK.logger
|
|||
RecordingActions = @RecordingActions
|
||||
SessionActions = @SessionActions
|
||||
JamBlasterActions = @JamBlasterActions
|
||||
VideoLiveStreamActions = @VideoLiveStreamActions
|
||||
|
||||
#window.StupidCallback: () =>
|
||||
# alert("STUPID CALLBACK")
|
||||
|
|
@ -24,6 +25,8 @@ JamBlasterActions = @JamBlasterActions
|
|||
console.log("GENERIC CALLBACK CALLED: ", map)
|
||||
if map.cmd == 'join_session'
|
||||
SessionActions.joinSession(map['music_session_id'])
|
||||
else if map.cmd == 'start_livestream'
|
||||
VideoLiveStreamActions.startLiveStream()
|
||||
else if map.cmd == 'client_pair_state'
|
||||
JamBlasterActions.pairState(map)
|
||||
else if map.cmd == 'jamblaster_tracks_updated'
|
||||
|
|
@ -31,6 +34,5 @@ JamBlasterActions = @JamBlasterActions
|
|||
else if map.cmd == 'file_xfer_from_parent'
|
||||
if map.filename && map.filename.indexOf('RT-mix.wav') > -1
|
||||
RecordingActions.mixTransferred()
|
||||
|
||||
}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,265 @@
|
|||
context = window
|
||||
logger = context.JK.logger
|
||||
rest = context.JK.Rest()
|
||||
EVENTS = context.JK.EVENTS
|
||||
NAMED_MESSAGES = context.JK.NAMED_MESSAGES
|
||||
|
||||
VideoLiveStreamActions = @VideoLiveStreamActions
|
||||
|
||||
@VideoLiveStreamStore = Reflux.createStore(
|
||||
{
|
||||
listenables: VideoLiveStreamActions
|
||||
logger: context.JK.logger
|
||||
creatingBroadcast: false
|
||||
|
||||
init: ->
|
||||
this.listenTo(context.AppStore, this.onAppInit)
|
||||
|
||||
onAppInit: (@app) ->
|
||||
|
||||
onPopupClosed: () ->
|
||||
|
||||
if @childWindow?
|
||||
@childWindow = null
|
||||
|
||||
logger.debug("Popup closed")
|
||||
context.jamClient.StopLiveStreaming()
|
||||
@streaming = false
|
||||
@onRefresh()
|
||||
|
||||
|
||||
onRefresh: () ->
|
||||
@state = {
|
||||
creatingBroadcast: @creatingBroadcast,
|
||||
createdStream: @createdStream,
|
||||
createStreamError: @createStreamError,
|
||||
waitingForReady: @waitingForReady,
|
||||
waitingOnTesting: @waitingOnTesting,
|
||||
waitingOnLive: @waitingOnLive,
|
||||
transitioningTesting: @transitioningTesting,
|
||||
streaming: @streaming,
|
||||
errorMessage: @errorMessage,
|
||||
broadcast: @broadcast
|
||||
}
|
||||
this.trigger(@state)
|
||||
|
||||
onStartLiveStream: () ->
|
||||
@creatingBroadcast = false
|
||||
@createdStream = false
|
||||
@createStreamError = false
|
||||
@transitioningTesting = false
|
||||
@waitingForReady = false
|
||||
@waitingOnLive = false
|
||||
@waitingOnTesting = false
|
||||
@errorMessage = null
|
||||
@streaming = false
|
||||
|
||||
@logger.debug("onStartLiveStream")
|
||||
@onRefresh()
|
||||
|
||||
if @childWindow?
|
||||
logger.debug("show live stream popup being closed automatically")
|
||||
@childWindow.close()
|
||||
@childWindow = null
|
||||
|
||||
@childWindow = window.open("/popups/video/stream/" + context.SessionStore.id(), 'Video Live Stream', 'scrollbars=yes,toolbar=no,status=no,height=155,width=350')
|
||||
|
||||
startLiveStreaming: () ->
|
||||
@logger.debug("user requests live stream")
|
||||
@createLiveStream()
|
||||
|
||||
# do not use; here until can remove
|
||||
startGoogleLogin: (e) ->
|
||||
|
||||
@logger.debug("Starting google login")
|
||||
window._oauth_win = window.open("/auth/google_login", "Log In to Google", "height=700,width=500,menubar=no,resizable=no,status=no");
|
||||
window._oauth_callback = @oauthCallback
|
||||
|
||||
oauthCallback: () ->
|
||||
@creatingBroadcast = true
|
||||
@logger.debug("oauthCallback... checking auth")
|
||||
window._oauth_win.close()
|
||||
@checkAuth()
|
||||
|
||||
checkAuth:() ->
|
||||
rest.getGoogleAuth()
|
||||
.done((auth) =>
|
||||
@logger.debug("check Auth is done", auth)
|
||||
if auth.auth?
|
||||
@createLiveStream()
|
||||
else
|
||||
@creatingBroadcast = false
|
||||
@onRefresh()
|
||||
# alert to user
|
||||
)
|
||||
.fail(() =>
|
||||
@creatingBroadcast = false
|
||||
@onRefresh()
|
||||
# lert to user
|
||||
)
|
||||
|
||||
loadBroadcast: (sessionId) ->
|
||||
@broadcast = null
|
||||
@onRefresh()
|
||||
@fetchBroadcast(sessionId)
|
||||
|
||||
fetchBroadcast: (sessionId) ->
|
||||
rest.getLiveStream(sessionId)
|
||||
.done((broadcast) =>
|
||||
@broadcast = broadcast
|
||||
@onRefresh()
|
||||
)
|
||||
.fail((jqXHR) =>
|
||||
logger.error("unabe to fetch broadcast", jqXHR.responseText)
|
||||
@onRefresh()
|
||||
)
|
||||
|
||||
createLiveStream: () ->
|
||||
|
||||
@creatingBroadcast = true
|
||||
|
||||
rest.createLiveStream(context.SessionStore.id())
|
||||
.done((broadcast) =>
|
||||
@creatingBroadcast = false
|
||||
@onRefresh()
|
||||
success = context.jamClient.StartLiveStreaming(broadcast.stream_name)
|
||||
|
||||
if success
|
||||
@createdStream = true
|
||||
@waitingForReady = true
|
||||
@transitionTimeout = new Date().getTime() + 10000 # die in 10 seconds
|
||||
@onRefresh()
|
||||
setTimeout(() =>
|
||||
@waitForReady()
|
||||
, 1000)
|
||||
|
||||
else
|
||||
@createStreamError = true
|
||||
@onRefresh()
|
||||
)
|
||||
.fail(() =>
|
||||
@creatingBroadcast = false
|
||||
@onRefresh()
|
||||
)
|
||||
|
||||
waitForReady: () ->
|
||||
rest.getLiveStream(context.SessionStore.id())
|
||||
.done((broadcast) =>
|
||||
if broadcast.broadcast_status == 'ready'
|
||||
@waitingForReady = false
|
||||
@transitionTesting()
|
||||
else
|
||||
if new Date().getTime() > @transitionTimeout
|
||||
# uh oh. waited fo ra while; stream never became ready
|
||||
@errorMessage = 'YouTube never indicated stream is ready for testing'
|
||||
@waitingForReady = false
|
||||
@onRefresh()
|
||||
else
|
||||
setTimeout(() =>
|
||||
@waitForReady()
|
||||
, 1000)
|
||||
)
|
||||
.fail(() =>
|
||||
@waitingForReady = false
|
||||
@errorMessage = 'Could not check status of YouTube broadcast'
|
||||
context.jamClient.StopLiveStreaming()
|
||||
@streaming = false
|
||||
@onRefresh()
|
||||
)
|
||||
|
||||
transitionTesting: () ->
|
||||
@transitioningTesting = true
|
||||
@onRefresh()
|
||||
|
||||
rest.liveStreamTransition(context.SessionStore.id(), 'testing')
|
||||
.done((broadcast) =>
|
||||
@transitioningTesting = false
|
||||
@waitingOnTesting = true
|
||||
@transitionTimeout = new Date().getTime() + 20000 # die in 20 seconds
|
||||
setTimeout(() =>
|
||||
@waitForTesting()
|
||||
, 1000)
|
||||
)
|
||||
.fail(() =>
|
||||
@transitioningTesting = false
|
||||
@errorMessage = 'Could not transition live stream to "testing"'
|
||||
context.jamClient.StopLiveStreaming()
|
||||
@streaming = false
|
||||
@onRefresh()
|
||||
)
|
||||
|
||||
transitionLive: () ->
|
||||
@transitioningLive = true
|
||||
@onRefresh()
|
||||
|
||||
rest.liveStreamTransition(context.SessionStore.id(), 'live')
|
||||
.done((broadcast) =>
|
||||
@transitioningLive = false
|
||||
@waitingOnLive = true
|
||||
@transitionTimeout = new Date().getTime() + 20000 # die in 20 seconds
|
||||
setTimeout(() =>
|
||||
@waitForLive()
|
||||
, 1000)
|
||||
)
|
||||
.fail(() =>
|
||||
@transitioningLive = false
|
||||
@errorMessage = 'Could not transition live stream to "live"'
|
||||
context.jamClient.StopLiveStreaming()
|
||||
@streaming = false
|
||||
@onRefresh()
|
||||
)
|
||||
|
||||
|
||||
waitForTesting: () ->
|
||||
rest.getBroadcast(context.SessionStore.id())
|
||||
.done((broadcast) =>
|
||||
if broadcast.broadcast_status == 'testing'
|
||||
@waitingOnTesting = false
|
||||
@transitionLive()
|
||||
else
|
||||
if new Date().getTime() > @transitionTimeout
|
||||
# uh oh. waited fo ra while; stream never became ready
|
||||
@errorMessage = 'YouTube never indicated stream converted to testing'
|
||||
@waitingOnTesting = false
|
||||
@onRefresh()
|
||||
else
|
||||
setTimeout(() =>
|
||||
@waitForTesting()
|
||||
, 1000)
|
||||
)
|
||||
.fail(() =>
|
||||
@waitingForTesting = false
|
||||
@errorMessage = 'Could not check status of YouTube broadcast'
|
||||
context.jamClient.StopLiveStreaming()
|
||||
@streaming = false
|
||||
@onRefresh()
|
||||
)
|
||||
|
||||
waitForLive: () ->
|
||||
rest.getBroadcast(context.SessionStore.id())
|
||||
.done((broadcast) =>
|
||||
if broadcast.broadcast_status == 'live'
|
||||
@waitingOnLive = false
|
||||
@streaming = true
|
||||
console.log("BROADCAST TIME", broadcast)
|
||||
@onRefresh()
|
||||
else
|
||||
if new Date().getTime() > @transitionTimeout
|
||||
# uh oh. waited fo ra while; stream never became ready
|
||||
@errorMessage = 'YouTube never indicated stream converted to live'
|
||||
@waitingOnLive = false
|
||||
@onRefresh()
|
||||
else
|
||||
setTimeout(() =>
|
||||
@waitForLive()
|
||||
, 1000)
|
||||
)
|
||||
.fail(() =>
|
||||
@waitingForLive = false
|
||||
@errorMessage = 'Could not check status of YouTube broadcast'
|
||||
context.jamClient.StopLiveStreaming()
|
||||
@streaming = false
|
||||
@onRefresh()
|
||||
)
|
||||
}
|
||||
)
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
$ = jQuery
|
||||
context = window
|
||||
logger = context.JK.logger
|
||||
rest = context.JK.Rest()
|
||||
EVENTS = context.JK.EVENTS
|
||||
NAMED_MESSAGES = context.JK.NAMED_MESSAGES
|
||||
|
||||
|
|
@ -236,5 +237,6 @@ BackendToFrontendFPS = {
|
|||
isVideoEnabled:() ->
|
||||
return @videoEnabled
|
||||
|
||||
|
||||
}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,57 @@
|
|||
@import "client/common";
|
||||
|
||||
#live-streaming-dialog {
|
||||
width: 600px;
|
||||
|
||||
h2 {
|
||||
color:white;
|
||||
margin-bottom:10px;
|
||||
font-size:16px;
|
||||
}
|
||||
.dialog-inner {
|
||||
width: auto;
|
||||
height:calc(100% - 29px);
|
||||
padding-bottom:75px;
|
||||
}
|
||||
|
||||
.field {
|
||||
margin-bottom:10px;
|
||||
}
|
||||
|
||||
input {
|
||||
display:inline-block;
|
||||
}
|
||||
label {
|
||||
display:inline-block;
|
||||
}
|
||||
.iradio_minimal {
|
||||
display:inline-block;
|
||||
margin-right: 5px;
|
||||
top: 4px;
|
||||
}
|
||||
|
||||
div[data-react-class="LiveStreamingDialog"] {
|
||||
|
||||
}
|
||||
.actions {
|
||||
position:absolute;
|
||||
right:0;
|
||||
bottom:0;
|
||||
margin:0 20px 30px 0;
|
||||
}
|
||||
.countdown-msg {
|
||||
margin-top:30px;
|
||||
}
|
||||
.countdown {
|
||||
color:white;
|
||||
font-size:18px;
|
||||
font-weight:bold;
|
||||
padding:0 10px;
|
||||
width:30px;
|
||||
display:inline-block;
|
||||
text-align:center;
|
||||
}
|
||||
.message {
|
||||
margin-top:20px;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
@import "client/common";
|
||||
|
||||
body.video-live-stream{
|
||||
|
||||
position: relative;
|
||||
color: $ColorTextTypical;
|
||||
|
||||
#minimal-container {
|
||||
padding-bottom: 20px;
|
||||
height:240px;
|
||||
}
|
||||
|
||||
.video-uploader {
|
||||
padding-left: 30px;
|
||||
padding-right:30px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin-top:20px;
|
||||
font-size:16px;
|
||||
font-weight:bold;
|
||||
margin-bottom:20px;
|
||||
text-align:center;
|
||||
line-height:125%;
|
||||
}
|
||||
|
||||
.control-holder {
|
||||
margin: 20px 0 20px;
|
||||
text-align:center;
|
||||
padding-bottom:20px;
|
||||
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
background-color:#ED3618;
|
||||
border:solid 1px #000;
|
||||
height:20px;
|
||||
display:block;
|
||||
@include border_box_sizing;
|
||||
margin:20px 0;
|
||||
position:relative;
|
||||
}
|
||||
|
||||
.percentage-progress {
|
||||
position:absolute;
|
||||
right:-32px;
|
||||
}
|
||||
|
||||
.video-url {
|
||||
text-align:center;
|
||||
display:block;
|
||||
margin:20px 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -7,7 +7,7 @@ body.video-stream {
|
|||
|
||||
#minimal-container {
|
||||
padding-bottom: 20px;
|
||||
height:240px;
|
||||
height:170px;
|
||||
}
|
||||
|
||||
.video-stream {
|
||||
|
|
@ -55,4 +55,8 @@ body.video-stream {
|
|||
display:block;
|
||||
margin:20px 0;
|
||||
}
|
||||
|
||||
.video-live-stream {
|
||||
padding:0 20px;
|
||||
}
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ class ApiMusicSessionsController < ApiController
|
|||
# have to be signed in currently to see this screen
|
||||
before_filter :api_signed_in_user, :except => [ :add_like, :show, :show_history, :add_session_info_comment ]
|
||||
before_filter :lookup_session, only: [:show, :update, :delete, :claimed_recording_start, :claimed_recording_stop, :track_sync, :jam_track_open, :jam_track_close, :backing_track_open, :backing_track_close, :metronome_open, :metronome_close]
|
||||
before_filter :lookup_perm_session, only: [:get_livestream, :create_livestream, :livestream_transition]
|
||||
skip_before_filter :api_signed_in_user, only: [:perf_upload]
|
||||
around_filter :transactions_filter, only:[:sms_index, :ams_index]
|
||||
|
||||
|
|
@ -648,10 +649,51 @@ class ApiMusicSessionsController < ApiController
|
|||
respond_with_model(@music_session)
|
||||
end
|
||||
|
||||
private
|
||||
def get_livestream
|
||||
unless @music_session.active_music_session.users.exists?(current_user.id)
|
||||
raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
|
||||
end
|
||||
|
||||
@livestream = @music_session.get_broadcast(current_user)
|
||||
|
||||
if @livestream
|
||||
respond_with (@livestream), responder: ApiResponder
|
||||
else
|
||||
render :json => { :message => "No broadcast associated with this session" }, :status => 404
|
||||
end
|
||||
end
|
||||
|
||||
def create_livestream
|
||||
unless @music_session.active_music_session.users.exists?(current_user.id)
|
||||
raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
|
||||
end
|
||||
|
||||
@livestream = @music_session.create_stream(current_user, params[:options])
|
||||
respond_with (@livestream), responder: ApiResponder
|
||||
end
|
||||
|
||||
def livestream_transition
|
||||
unless @music_session.active_music_session.users.exists?(current_user.id)
|
||||
raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
|
||||
end
|
||||
|
||||
broadcast = @music_session.music_session.current_broadcast
|
||||
|
||||
if broadcast
|
||||
@livestream = @music_session.transition_broadcast(current_user, broadcast, params[:broadcastStatus])
|
||||
respond_with (@livestream), responder: ApiResponder
|
||||
else
|
||||
render :json => { :message => "No broadcast associated with this session" }, :status => 404
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def lookup_session
|
||||
@music_session = ActiveMusicSession.find(params[:id])
|
||||
end
|
||||
|
||||
def lookup_perm_session
|
||||
@music_session = MusicSession.find(params[:id])
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -30,6 +30,12 @@ class PopupsController < ApplicationController
|
|||
end
|
||||
|
||||
|
||||
def video_stream
|
||||
@session_id = params[:session_id]
|
||||
gon.session_id= @session_id
|
||||
render :layout => "minimal"
|
||||
end
|
||||
|
||||
def video_stream
|
||||
@session_id = params[:session_id]
|
||||
gon.session_id= @session_id
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
object @livestream
|
||||
|
||||
extends "api_music_sessions/livestream_show"
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
object @livestream
|
||||
|
||||
extends "api_music_sessions/livestream_show"
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
object @livestream
|
||||
|
||||
attributes :id, :broadcast_status, :stream_status, :stream_name, :stream_address, :broadcast_data, :broadcast_id, :stream_id
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
object @livestream
|
||||
|
||||
extends "api_music_sessions/livestream_show"
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
.dialog.dialog-overlay-sm.top-parent layout='dialog' layout-id='jamblaster-pairing-dialog' id='jamblaster-pairing-dialog'
|
||||
= react_component 'JamBlasterPairingDialog', {}
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
- provide(:page_name, 'video-stream popup')
|
||||
- provide(:title, 'Video Stream')
|
||||
= react_component 'PopupVideoStreamer', {}
|
||||
= react_component 'PopupVideoLiveStream', {}
|
||||
|
|
@ -251,6 +251,10 @@ Rails.application.routes.draw do
|
|||
match '/sessions/:id/metronome/close' => 'api_music_sessions#metronome_close', :via => :post
|
||||
match '/sessions/:id/session_controller' => 'api_music_sessions#session_controller', :via => :post
|
||||
|
||||
match '/sessions/:id/livestream' => 'api_music_sessions#get_livestream', :via => :get
|
||||
match '/sessions/:id/livestream' => 'api_music_sessions#create_livestream', :via => :post
|
||||
match '/sessions/:id/livestream/transition' => 'api_music_sessions#livestream_transition', :via => :post
|
||||
|
||||
# music session tracks
|
||||
match '/sessions/:id/tracks' => 'api_music_sessions#track_create', :via => :post
|
||||
match '/sessions/:id/tracks' => 'api_music_sessions#track_sync', :via => :put
|
||||
|
|
|
|||
|
|
@ -178,6 +178,29 @@ module JamRuby
|
|||
end
|
||||
end
|
||||
|
||||
def transition_broadcast(user, broadcast_id, broadcastStatus)
|
||||
auth = UserAuthorization.google_auth(user).first
|
||||
if auth.nil? || auth.token.nil?
|
||||
raise JamPermissionError, "No current google token found for user #{user}"
|
||||
end
|
||||
|
||||
begin
|
||||
my_client = create_client
|
||||
|
||||
my_client.authorization = create_authorization(auth, 'https://www.googleapis.com/auth/youtube https://www.googleapis.com/auth/youtube.force-ssl', true)
|
||||
#y = my_client.discovered_api('youtube', 'v3')
|
||||
response = my_client.execute!(:api_method => youtube.live_broadcasts.transition,
|
||||
:parameters => {:part => 'id,contentDetails,status,snippet', :id => broadcast_id, :broadcastStatus => broadcastStatus })
|
||||
|
||||
body = JSON.parse(response.body)
|
||||
puts "TRANSITION RESPONSE: #{body}"
|
||||
return body
|
||||
rescue Google::APIClient::ClientError => e
|
||||
puts e.result.body
|
||||
raise e
|
||||
end
|
||||
end
|
||||
|
||||
def get_broadcast(user, broadcast_id)
|
||||
auth = UserAuthorization.google_auth(user).first
|
||||
if auth.nil? || auth.token.nil?
|
||||
|
|
@ -193,8 +216,39 @@ module JamRuby
|
|||
:parameters => {:part => 'id,contentDetails,status,snippet', :id => broadcast_id })
|
||||
|
||||
body = JSON.parse(response.body)
|
||||
puts "BIND RESPONSE: #{body}"
|
||||
return body["items"][0] # returns array of items. meh
|
||||
puts "GET BROADCAST RESPONSE: #{body}"
|
||||
if body["items"].length == 0
|
||||
nil
|
||||
else
|
||||
body["items"][0] # returns array of items. meh
|
||||
end
|
||||
rescue Google::APIClient::ClientError => e
|
||||
puts e.result.body
|
||||
raise e
|
||||
end
|
||||
end
|
||||
|
||||
def get_livestream(user, stream_id)
|
||||
auth = UserAuthorization.google_auth(user).first
|
||||
if auth.nil? || auth.token.nil?
|
||||
raise JamPermissionError, "No current google token found for user #{user}"
|
||||
end
|
||||
|
||||
begin
|
||||
my_client = create_client
|
||||
|
||||
my_client.authorization = create_authorization(auth, 'https://www.googleapis.com/auth/youtube https://www.googleapis.com/auth/youtube.force-ssl', true)
|
||||
#y = my_client.discovered_api('youtube', 'v3')
|
||||
response = my_client.execute!(:api_method => youtube.live_streams.list,
|
||||
:parameters => {:part => 'id,snippet,cdn,status', :id => stream_id })
|
||||
|
||||
body = JSON.parse(response.body)
|
||||
puts "GET LIVE STREAM RESPONSE: #{body}"
|
||||
if body["items"].length == 0
|
||||
nil
|
||||
else
|
||||
body["items"][0] # returns array of items. meh
|
||||
end
|
||||
rescue Google::APIClient::ClientError => e
|
||||
puts e.result.body
|
||||
raise e
|
||||
|
|
|
|||
|
|
@ -11,4 +11,76 @@ namespace :google do
|
|||
|
||||
puts broadcast.inspect
|
||||
end
|
||||
|
||||
task get_livestream: :environment do |task, args|
|
||||
google_client = JamRuby::GoogleClient.new
|
||||
music_session = MusicSession.first
|
||||
user = User.find_by_email('seth@jamkazam.com')
|
||||
|
||||
livestream = music_session.get_livestream(google_client, user)
|
||||
|
||||
puts livestream.inspect
|
||||
|
||||
# example:
|
||||
#{"kind"=>"youtube#liveStream",
|
||||
# "etag"=>"\"m2yskBQFythfE4irbTIeOgYYfBU/fq4yPJsfCN91Qi2Dd9VuLZ3sm9U\"",
|
||||
# "id"=>"lgXe2spB8uVk-U6H_b8aSQ1495983496676422",
|
||||
# "snippet"=>{"publishedAt"=>"2017-05-28T14:58:16.000Z",
|
||||
# "channelId"=>"UClgXe2spB8uVk-U6H_b8aSQ",
|
||||
# "title"=>"Private Test Session", "description"=>"", "isDefaultStream"=>false},
|
||||
# "cdn"=>{"format"=>"360p", "ingestionType"=>"rtmp", "ingestionInfo"=>{"streamName"=>"6axs-3zpj-0esg-d7uv", "ingestionAddress"=>"rtmp://a.rtmp.youtube.com/live2", "backupIngestionAddress"=>"rtmp://b.rtmp.youtube.com/live2?backup=1"}, "resolution"=>"360p", "frameRate"=>"30fps"},
|
||||
# "status"=>{"streamStatus"=>"active", "healthStatus"=>{"status"=>"good", "configurationIssues"=>[{"type"=>"audioBitrateHigh", "severity"=>"info", "reason"=>"Check audio settings", "description"=>"The audio stream's current bitrate of 255.00 Kbps is higher than the recommended bitrate. We recommend that you use an audio stream bitrate of 128 Kbps."}, {"type"=>"bitrateHigh", "severity"=>"info", "reason"=>"Check video settings", "description"=>"The stream's current bitrate (1286.00 Kbps) is higher than the recommended bitrate. We recommend that you use a stream bitrate of 750 Kbps."}]}}}
|
||||
|
||||
end
|
||||
|
||||
task get_broadcast: :environment do |task, args|
|
||||
google_client = JamRuby::GoogleClient.new
|
||||
music_session = MusicSession.first
|
||||
user = User.find_by_email('seth@jamkazam.com')
|
||||
|
||||
broadcast = music_session.get_broadcast(google_client, user)
|
||||
|
||||
# example:
|
||||
#{"kind"=>"youtube#liveBroadcast",
|
||||
# "etag"=>"\"m2yskBQFythfE4irbTIeOgYYfBU/7ARgOe0WJLQdOvjeISlnBnnK3L0\"",
|
||||
# "id"=>"4CLE1CXfKB8",
|
||||
# "snippet"=>{"publishedAt"=>"2017-05-28T14:58:16.000Z", "channelId"=>"UClgXe2spB8uVk-U6H_b8aSQ", "title"=>"Private Test Session", "description"=>"Private session set up just to test things out in the session interface by myself.", "thumbnails"=>{"default"=>{"url"=>"https://i9.ytimg.com/vi/4CLE1CXfKB8/default_live.jpg?sqp=CMzXq8kF&rs=AOn4CLCo_lxnPzD52m7nQgJ7xHsyRSBLkw", "width"=>120, "height"=>90}, "medium"=>{"url"=>"https://i9.ytimg.com/vi/4CLE1CXfKB8/mqdefault_live.jpg?sqp=CMzXq8kF&rs=AOn4CLDF5tDY7i0H__d27ZTdSfbvrpgc6w", "width"=>320, "height"=>180}, "high"=>{"url"=>"https://i9.ytimg.com/vi/4CLE1CXfKB8/hqdefault_live.jpg?sqp=CMzXq8kF&rs=AOn4CLAl1XUfz8faQDBXEydsDG9D5iRe6g", "width"=>480, "height"=>360}}, "scheduledStartTime"=>"2017-05-28T14:58:17.000Z", "isDefaultBroadcast"=>false, "liveChatId"=>"Cg0KCzRDTEUxQ1hmS0I4"},
|
||||
# "status"=>{"lifeCycleStatus"=>"testing", "privacyStatus"=>"private", "recordingStatus"=>"notRecording"},
|
||||
# "contentDetails"=>{"boundStreamId"=>"lgXe2spB8uVk-U6H_b8aSQ1495983496676422", "boundStreamLastUpdateTimeMs"=>"2017-05-28T14:58:16.695Z", "monitorStream"=>{"enableMonitorStream"=>true, "broadcastStreamDelayMs"=>0, "embedHtml"=>"<iframe width=\"425\" height=\"344\" src=\"https://www.youtube.com/embed/4CLE1CXfKB8?autoplay=1&livemonitor=1\" frameborder=\"0\" allowfullscreen></iframe>"}, "enableEmbed"=>true, "enableDvr"=>true, "enableContentEncryption"=>false, "startWithSlate"=>false, "recordFromStart"=>true, "enableClosedCaptions"=>false, "closedCaptionsType"=>"closedCaptionsDisabled", "enableLowLatency"=>false, "projection"=>"rectangular"}}
|
||||
|
||||
puts broadcast.inspect
|
||||
end
|
||||
|
||||
task transition_broadcast_live: :environment do |task, args|
|
||||
google_client = JamRuby::GoogleClient.new
|
||||
music_session = MusicSession.first
|
||||
user = User.find_by_email('seth@jamkazam.com')
|
||||
|
||||
|
||||
livestream = music_session.transition_broadcast(google_client, user, music_session.current_broadcast, 'live')
|
||||
|
||||
puts livestream.inspect
|
||||
end
|
||||
|
||||
|
||||
task transition_broadcast_testing: :environment do |task, args|
|
||||
google_client = JamRuby::GoogleClient.new
|
||||
music_session = MusicSession.first
|
||||
user = User.find_by_email('seth@jamkazam.com')
|
||||
|
||||
|
||||
livestream = music_session.transition_broadcast(google_client, user, music_session.current_broadcast, 'testing')
|
||||
|
||||
puts livestream.inspect
|
||||
end
|
||||
|
||||
task transition_broadcast_complete: :environment do |task, args|
|
||||
google_client = JamRuby::GoogleClient.new
|
||||
music_session = MusicSession.first
|
||||
user = User.find_by_email('seth@jamkazam.com')
|
||||
|
||||
livestream = music_session.transition_broadcast(google_client, user, music_session.current_broadcast, 'complete')
|
||||
|
||||
puts livestream.inspect
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -7,6 +7,10 @@ class UserManager < BaseManager
|
|||
@google_client = GoogleClient.new()
|
||||
end
|
||||
|
||||
def get_google_client
|
||||
@google_client
|
||||
end
|
||||
|
||||
# Note that almost everything can be nil here. This is because when users sign up via social media,
|
||||
# we don't know much about them.
|
||||
def signup(options)
|
||||
|
|
|
|||
Loading…
Reference in New Issue