Merge branch 'feature/jbmvp' into develop

This commit is contained in:
Seth Call 2016-11-04 11:19:14 -05:00
commit 80145a09da
32 changed files with 262 additions and 74 deletions

View File

@ -368,4 +368,5 @@ retailers.sql
second_ed.sql
second_ed_v2.sql
retailers_v2.sql
retailer_interest.sql
retailer_interest.sql
connection_role.sql

View File

@ -0,0 +1,2 @@
ALTER TABLE connections ADD COLUMN client_role VARCHAR;
ALTER TABLE connections ADD COLUMN parent_client_id VARCHAR;

View File

@ -402,7 +402,7 @@ SQL
music_session.creator
end
def join_music_session(user, client_id, music_session, as_musician, tracks, audio_latency, video_sources=nil)
def join_music_session(user, client_id, music_session, as_musician, tracks, audio_latency, client_role = nil, parent_client_id = nil, video_sources=nil)
connection = nil
ConnectionManager.active_record_transaction do |connection_manager|
@ -418,7 +418,7 @@ SQL
raise JamPermissionError, "wrong user_id associated with connection #{client_id}"
end
connection.join_the_session(music_session, as_musician, tracks, user, audio_latency, video_sources)
connection.join_the_session(music_session, as_musician, tracks, user, audio_latency, client_role, parent_client_id, video_sources)
JamRuby::MusicSessionUserHistory.join_music_session(user.id, music_session.id, client_id)
# connection.music_session_id = music_session.id
# connection.as_musician = as_musician

View File

@ -501,7 +501,7 @@ module JamRuby
[music_sessions, user_scores]
end
def self.participant_create(user, music_session_id, client_id, as_musician, tracks, audio_latency, video_sources=nil)
def self.participant_create(user, music_session_id, client_id, as_musician, tracks, audio_latency, client_role = nil, parent_client_id = nil, video_sources=nil)
music_session = MusicSession.find(music_session_id)
# USERS ARE ALREADY IN SESSION
@ -514,7 +514,7 @@ module JamRuby
active_music_session.with_lock do # VRFS-1297
active_music_session.tick_track_changes
# VRFS-3986
connection = ConnectionManager.new.join_music_session(user, client_id, active_music_session, as_musician, tracks, audio_latency, video_sources)
connection = ConnectionManager.new.join_music_session(user, client_id, active_music_session, as_musician, tracks, audio_latency, client_role, parent_client_id, video_sources)
if connection.errors.any?
# rollback the transaction to make sure nothing is disturbed in the database
@ -573,7 +573,7 @@ module JamRuby
# auto-join this user into the newly created session
as_musician = true
connection = ConnectionManager.new.join_music_session(user, client_id, active_music_session, as_musician, tracks, audio_latency, video_sources)
connection = ConnectionManager.new.join_music_session(user, client_id, active_music_session, as_musician, tracks, audio_latency, client_role, parent_client_id, video_sources)
unless connection.errors.any?
user.update_progression_field(:first_music_session_at)

View File

@ -176,11 +176,13 @@ module JamRuby
true
end
def join_the_session(music_session, as_musician, tracks, user, audio_latency, videos=nil)
def join_the_session(music_session, as_musician, tracks, user, audio_latency, client_role = nil, parent_client_id = nil, videos=nil)
self.music_session_id = music_session.id
self.as_musician = as_musician == true # this is deliberate; otherwise we create a warning in one our tests that passes 'blarg' (rails warning about casting strings to false)
self.joining_session = true
self.joined_session_at = Time.now
self.client_role = client_role
self.parent_client_id = parent_client_id
associate_tracks(tracks) unless tracks.nil?
associate_videos(videos) unless videos.nil?
self.save

View File

@ -272,7 +272,9 @@ module JamRuby
music_session.connections.each do |connection|
connection.tracks.each do |track|
recording.recorded_tracks << RecordedTrack.create_from_track(track, recording)
if connection.client_role != 'child'
recording.recorded_tracks << RecordedTrack.create_from_track(track, recording)
end
end
connection.video_sources.each do |video|

View File

@ -65,6 +65,8 @@
return;
}
console.log("GetLocalRecordingState", localResults)
$.each(claimedRecordings, function(index, claimedRecording) {
var options = {

View File

@ -10,6 +10,8 @@
var $dialog = null;
var $saveVideoCheckbox = null
var $uploadToYoutube = null
var timeout = null
var CLIENT_ROLE = context.JK.CLIENT_ROLE
function resetForm() {
// remove all display errors
@ -44,6 +46,47 @@
resetForm();
if(context.jamClient.getClientParentChildRole() == CLIENT_ROLE.CHILD) {
logger.debug("child client; launching preview after xfer");
$('#recording-finished-dialog span.nowait').addClass('hidden')
$('#recording-finished-dialog span.pleasewait').removeClass('hidden')
$('#recording-finished-dialog .preview-area').css('visibility', 'hidden')
$('#recording-finished-dialog form').css('visibility', 'hidden')
waitForMixTransfer()
}
else {
console.log("normal client; launching preview immediately")
$('#recording-finished-dialog span.pleasewait').addClass('hidden')
$('#recording-finished-dialog span.nowait').removeClass('hidden')
$('#recording-finished-dialog .preview-area').css('visibility', 'visible')
$('#recording-finished-dialog form').css('visibility', 'visible')
launchPreview();
}
}
function waitForMixTransfer() {
timeout = setTimeout(function() {
console.log("checking for file transfer", window.RecordingStore.mixTransferred)
if(window.RecordingStore.mixTransferred) {
$('#recording-finished-dialog span.pleasewait').addClass('hidden')
$('#recording-finished-dialog span.nowait').removeClass('hidden')
$('#recording-finished-dialog .preview-area').css('visibility', 'visible')
$('#recording-finished-dialog form').css('visibility', 'visible')
timeout = null
launchPreview()
}
else {
waitForMixTransfer();
}
}, 1000)
}
function launchPreview() {
var parentSelector = '#recording-finished-dialog div.genre-selector';
context.JK.GenreSelectorHelper.render(parentSelector);
@ -117,10 +160,12 @@
playbackControls.startMonitor();
}
}
}
function afterHide() {
if(timeout) {
clearTimeout(timeout)
timeout = null
}
if(recording && recording.video) {
var name = $('#recording-finished-dialog form input[name=name]').val();
name = name.replace(/[^A-Za-z0-9\-\ ]/g, '');

View File

@ -496,7 +496,10 @@
monitoring = false;
logger.debug("playbackControl.stopMonitor")
if (monitorPlaybackTimeout != null) {
clearTimeout(monitorPlaybackTimeout);
if(clearTimeout) {
clearTimeout(monitorPlaybackTimeout);
}
monitorPlaybackTimeout = null;
}
}

View File

@ -249,7 +249,7 @@ JamBlasterActions = @JamBlasterActions
audio: () ->
`<div className="audio-content">
<JamBlasterTrackConfig />
To edit the JamBlaster audio settings, get into a session, and click the Settings link under My Tracks.
</div>`
ipSettingsChanged: (key, e) ->

View File

@ -716,7 +716,6 @@ mixins.push(Reflux.listenTo(UserStore, 'onUserChanged'))
setTimeout(@resizeWindow, 1000)
shouldComponentUpdate: () ->
console.log("THIS UNLOADED", @unloaded)
return !@unloaded
resizeWindow: () =>

View File

@ -36,6 +36,10 @@ if accessOpener
# this.setState(chatMixer: mixers.chatMixer)
onRecordingStateChanged: (recordingState) ->
if @unloaded
#console.log("PopupMediaControls unloaded. ignore onMixersChnaged")
return
this.setState(isRecording: recordingState.isRecording, recordedOnce: this.state.recordedOnce || recordingState.isRecording)
startStopRecording: () ->
@ -165,6 +169,9 @@ if accessOpener
</div>`
windowUnloaded: () ->
@unloaded = true
window.unloaded = true
window.opener.RecordingActions.recordingControlsClosed()
onChatHelp: (e) ->
@ -215,6 +222,9 @@ if accessOpener
$root = jQuery(this.getDOMNode())
$includeChat = $root.find('#include-chat')
shouldComponentUpdate: () ->
return !@unloaded
resizeWindow: () =>
$container = $('#minimal-container')
width = $container.width()

View File

@ -119,7 +119,7 @@ ConfigureTracksActions = @ConfigureTracksActions
$connectionState,
'SessionStatsHover',
() =>
{participant: {client_id: this.props.clientId, user: name: 'You', possessive: 'Your'}, }
{myTrack: true, participant: {client_id: this.props.connStatsClientId, user: name: 'You', possessive: 'Your'}, }
,
{width:385, positions:['right', 'left'], offsetParent:$root.closest('.screen'), extraClasses: 'self'})

View File

@ -9,15 +9,29 @@ MixerActions = context.MixerActions
session = sessionMixers.session
mixers = sessionMixers.mixers
noAudioUsers = mixers.noAudioUsers
clientsWithAudioOverride = mixers.clientsWithAudioOverride
participants = []
if session.inSession()
self = session.getParticipant(@app.clientId)
myJamBlasterClientId = null
if self? && self.client_role == 'child' && self.parent_client_id?
myJamBlasterClientId = self.parent_client_id
for participant in session.otherParticipants()
#if participant.is_jamblaster
#continue
if myJamBlasterClientId? && participant.client_id == myJamBlasterClientId
# don't show my parent jamblaster in 'others'
continue
if participant.client_role == 'child' && participant.parent_client_id?
#participant.parent = session.getParticipant(participant.parent_client_id)
# don't show children nodes
continue
if participant.client_id == @app.clientId
participant.user.possessive = "Your"
@ -55,6 +69,10 @@ MixerActions = context.MixerActions
name = "#{name}: #{instrumentDescription}"
noAudio = false
if !clientsWithAudioOverride[participant.client_id]
noAudio = noAudioUsers[participant.client_id]
participantState = {
participant: participant,
tracks: tracks,
@ -63,7 +81,7 @@ MixerActions = context.MixerActions
instrumentIcon: instrumentIcon,
photoUrl: photoUrl,
hasMixer: hasMixer,
noAudio: noAudioUsers[participant.client_id]
noAudio: noAudio
}
MixerActions.missingPeerMixer(participant.client_id) unless hasMixer

View File

@ -81,7 +81,7 @@ MixerActions = @MixerActions
<div>Volume</div>
<div>{monitorVolumeLeft}dB</div>
</div>
<SessionTrackGain mixers={this.state.inputGroupMixers} gainType='music' />
<SessionTrackGain mixers={this.state.inputGroupMixers} gainType='music' controlGroup="music" />
<div className={monitorMuteClasses} data-control="mute" onClick={this.handleAudioInputMute}/>
<input type="checkbox" name="mute"/>
@ -108,7 +108,7 @@ MixerActions = @MixerActions
<div>Volume</div>
<div>{chatVolumeLeft}dB</div>
</div>
<SessionTrackGain mixers={this.state.chatGroupMixers} />
<SessionTrackGain mixers={this.state.chatGroupMixers} controlGroup="chat" />
<div className={chatMuteClasses} data-control="mute" onClick={this.handleChatMute}/>
<input type="checkbox" name="mute"/>

View File

@ -143,7 +143,7 @@ StatsInfo = {
audio = @state.stats?.audio
aggregateTag = null
if aggregate?
if aggregate? && !this.props.myTrack
if aggregate.latency
aggregateStats.push(@stat(aggregate, 'aggregate', 'Tot Latency', 'latency', Math.round(aggregate.latency)))
@ -173,10 +173,16 @@ StatsInfo = {
audio_type = 'WDM'
else if audio_long.indexOf('core') > -1
audio_type = 'CoreAudio'
else if audio_long.indexOf('alsa') > -1
audio_type = 'JamBlaster'
audioStats.push(@stat(audio, 'audio', 'Gear Driver', 'audio_in_type', audio_type))
if audio.framesize?
framesize = '?'
if audio.framesize == 2.5
if audio.framesize == 1.0
framesize = '1 ms'
else if audio.framesize == 2.0
framesize = '1 ms'
else if audio.framesize == 2.5
framesize = '2.5 ms'
else if audio.framesize == 5
framesize = '5 ms'
@ -185,7 +191,7 @@ StatsInfo = {
audioStats.push(@stat(audio, 'audio', 'Frame Size', 'framesize', framesize))
networkTag = null
if network?
if network? && !this.props.myTrack
if network.ping?
networkStats.push(@stat(network, 'network', 'Latency', 'ping', (network.ping / 2).toFixed(1) + ' ms'))
if network.audiojq_median?
@ -238,7 +244,11 @@ StatsInfo = {
onStatsChanged: (stats) ->
stats = window.SessionStatsStore.stats
if stats?
clientStats = stats[@props.participant.client_id]
if stats.parent?
# if we have a parent, then use stats from the JamBlaster (parent), not ourselves. Otherwise we'll get bad stats (no Audio etc)
clientStats = stats.parent[@props.participant.client_id]
else
clientStats = stats[@props.participant.client_id]
else
clientStats = null
@setState({stats: clientStats})

View File

@ -8,6 +8,7 @@ MIX_MODES = context.JK.MIX_MODES
propTypes: {
gainType: React.PropTypes.string
controlGroup: React.PropTypes.string
}
getInitialState: () ->
@ -22,12 +23,11 @@ MIX_MODES = context.JK.MIX_MODES
mixers = @state.mixers.mixer
# if this is a media track, jam track , or media category, affect volume of both mixer and opposing mixer
if @state.mixers.mixer.group_id == ChannelGroupIds.MediaTrackGroup || @state.mixers.mixer.group_id == ChannelGroupIds.JamTrackGroup || ((@state.mixers.mixer.group_id == ChannelGroupIds.MonitorCatGroup || @state.mixers.mixer.group_id == ChannelGroupIds.MasterCatGroup) && @state.mixers.mixer.name == CategoryGroupIds.MediaTrack)
MixerActions.faderChanged(data, [@state.mixers.mixer, @state.mixers.oppositeMixer], @props.gainType)
MixerActions.faderChanged(data, [@state.mixers.mixer, @state.mixers.oppositeMixer], @props.gainType, @props.controlGroup)
else
MixerActions.faderChanged(data, mixers, @props.gainType)
MixerActions.faderChanged(data, mixers, @props.gainType, @props.controlGroup)
render: () ->
# mixer can be a single item or array

View File

@ -14,4 +14,5 @@ context = window
metronomeChanged: {}
deadUserRemove: {}
missingPeerMixer: {}
clientsWithAudio: {}
})

View File

@ -11,4 +11,5 @@ context = window
abortedRecording: {}
openRecordingControls: {}
recordingControlsClosed: {}
mixTransferred: {}
})

View File

@ -8,7 +8,7 @@ MIX_MODES = context.JK.MIX_MODES;
@MixerHelper = class MixerHelper
constructor: (@session, @masterMixers, @personalMixers, @metro, @noAudioUsers, @mixMode) ->
constructor: (@session, @masterMixers, @personalMixers, @metro, @noAudioUsers, @clientsWithAudioOverride, @mixMode) ->
@mixMode = MIX_MODES.PERSONAL # TODO - remove mixMode from MixerHelper? Or at least stop using it in most functions
@app = @session.app
@mixersByResourceId = {}
@ -622,13 +622,12 @@ MIX_MODES = context.JK.MIX_MODES;
return mixerPair.personal
findMixerForTrack: (client_id, track, myTrack, mode = MIX_MODES.PERSONAL) ->
findMixerForTrack: (client_id, track, myTrack, mode) ->
mixer = null # what is the best mixer for this track/client ID?
oppositeMixer = null # what is the corresponding mixer in the opposite mode?
vuMixer = null
muteMixer = null
if myTrack
# when it's your track, look it up by the backend resource ID
mixer = @getMixerByTrackId(track.client_track_id, mode)
@ -674,7 +673,7 @@ MIX_MODES = context.JK.MIX_MODES;
oppositeMixer = oppositeMixers[ChannelGroupIds.UserMusicInputGroup][0]
if !oppositeMixer
logger.warn("unable to find UserMusicInputGroup corresponding to PeerAudioInputMusicGroup mixer", mixer, @personalMixers )
logger.warn("unable to find UserMusicInputGroup corresponding to PeerAudioInputMusicGroup mixer", mixer, @personalMixers)
when MIX_MODES.PERSONAL
mixers = @groupedMixersForClientId(client_id, [ ChannelGroupIds.UserMusicInputGroup], {}, MIX_MODES.PERSONAL)
@ -693,6 +692,8 @@ MIX_MODES = context.JK.MIX_MODES;
logger.error("personaol: found remote mixer that was not of groupID: PeerAudioInputMusicGroup", client_id, track.client_track_id, mixer)
#vuMixer = oppositeMixer; # for personal mode, use the PeerAudioInputMusicGroup's VUs
else
logger.error("no UserMusicInputGroup for client_id #{client_id} in PERSONAL mode", mixers)
{
mixer: mixer,
@ -729,26 +730,43 @@ MIX_MODES = context.JK.MIX_MODES;
originalVolume
faderChanged: (data, mixers, gainType) ->
faderChanged: (data, mixers, gainType, controlGroup) ->
mixers = [mixers] unless $.isArray(mixers)
originalVolume = @getOriginalVolume(mixers, gainType)
for mixer in mixers
broadcast = !(data.dragging) # If fader is still dragging, don't broadcast
mixer = @fillTrackVolumeObject(mixer.id, mixer.mode, broadcast)
if controlGroup?
mixers = [mixers[0]]
relative = gainType == 'music' && (mixer.name == CategoryGroupIds.UserMedia || mixer.name == CategoryGroupIds.MediaTrack)
for mixer in mixers
broadcast = !(data.dragging) # If fader is still dragging, don't broadcast
mixer = @fillTrackVolumeObject(mixer.id, mixer.mode, broadcast)
@setMixerVolume(mixer, data.percentage, relative, originalVolume)
relative = gainType == 'music' && (mixer.name == CategoryGroupIds.UserMedia || mixer.name == CategoryGroupIds.MediaTrack)
# keep state of mixer in sync with backend
mixer = @getMixer(mixer.id, mixer.mode)
mixer.volume_left = context.trackVolumeObject.volL
@setMixerVolume(mixer, data.percentage, relative, originalVolume, controlGroup)
#if groupId == ChannelGroupIds.UserMusicInputGroup
# # there may be other mixers with this same ID in the case of a Peer Music Stream, so update them as well
# context.JK.FaderHelpers.setFaderValue(mixerId, data.percentage)
# keep state of mixer in sync with backend
mixer = @getMixer(mixer.id, mixer.mode)
mixer.volume_left = context.trackVolumeObject.volL
else
for mixer in mixers
broadcast = !(data.dragging) # If fader is still dragging, don't broadcast
mixer = @fillTrackVolumeObject(mixer.id, mixer.mode, broadcast)
relative = gainType == 'music' && (mixer.name == CategoryGroupIds.UserMedia || mixer.name == CategoryGroupIds.MediaTrack)
@setMixerVolume(mixer, data.percentage, relative, originalVolume)
# keep state of mixer in sync with backend
mixer = @getMixer(mixer.id, mixer.mode)
mixer.volume_left = context.trackVolumeObject.volL
#if groupId == ChannelGroupIds.UserMusicInputGroup
# # there may be other mixers with this same ID in the case of a Peer Music Stream, so update them as well
# context.JK.FaderHelpers.setFaderValue(mixerId, data.percentage)
initGain: (mixer) ->
if $.isArray(mixer)
@ -791,7 +809,7 @@ MIX_MODES = context.JK.MIX_MODES;
mixer = @getMixer(mixer.id, mixer.mode)
mixer.loop = context.trackVolumeObject.loop
setMixerVolume: (mixer, volumePercent, relative, originalVolume) ->
setMixerVolume: (mixer, volumePercent, relative, originalVolume, controlGroup) ->
###
// The context.trackVolumeObject has been filled with the mixer values
// that go with mixerId, and the range of that mixer
@ -821,7 +839,15 @@ MIX_MODES = context.JK.MIX_MODES;
else
context.trackVolumeObject.volL = newVolume
context.trackVolumeObject.volR = newVolume
context.jamClient.SessionSetControlState(mixer.id, mixer.mode);
if controlGroup?
if mixer.mode == MIX_MODES.PERSONAL
controlGroupsArg = 0
else
controlGroupsArg = 1
context.jamClient.setSessionMixerCategoryPlayoutState(controlGroup == 'music', controlGroupsArg);
else
context.jamClient.SessionSetControlState(mixer.id, mixer.mode);
percentFromMixerValue: (min, max, value) ->
try

View File

@ -22,7 +22,7 @@ badCode = 'This is not a valid code. Please carefully re-enter the code and try
if errorText? && errorText.indexOf('already claimed') > -1
errorText = 'This card has already been claimed. If you believe this is in error, please email us at support@jamkazam.com to report this problem.'
buttonClassnames = classNames({'redeem-giftcard': true, 'button-orange': true, disabled: @state.processing || @state.done })

View File

@ -28,6 +28,12 @@ MIDI_TRACK = context.JK.MIDI_TRACK
if session.inSession()
participant = session.getParticipant(@app.clientId)
connStatsClientId = @app.clientId
if participant.client_role == 'child' && participant.parent_client_id?
participant.parent = session.getParticipant(participant.parent_client_id)
connStatsClientId = participant.parent_client_id
if participant
photoUrl = context.JK.resolveAvatarUrl(participant.user.photo_url);
@ -79,7 +85,7 @@ MIDI_TRACK = context.JK.MIDI_TRACK
associatedVst = vst
break
tracks.push({track: track, mixerFinder: mixerFinder, mixers: mixerData, hasMixer:hasMixer, name: name, trackName: trackName, instrumentIcon: instrumentIcon, photoUrl: photoUrl, clientId: participant.client_id, associatedVst: associatedVst})
tracks.push({track: track, mixerFinder: mixerFinder, mixers: mixerData, hasMixer:hasMixer, name: name, trackName: trackName, instrumentIcon: instrumentIcon, photoUrl: photoUrl, clientId: participant.client_id, associatedVst: associatedVst, connStatsClientId: connStatsClientId})
else
logger.warn("SessionMyTracks: unable to find participant")

View File

@ -1,6 +1,7 @@
$ = jQuery
context = window
logger = context.JK.logger
RecordingActions = @RecordingActions
SessionActions = @SessionActions
JamBlasterActions = @JamBlasterActions
@ -27,6 +28,9 @@ JamBlasterActions = @JamBlasterActions
JamBlasterActions.pairState(map)
else if map.cmd == 'jamblaster_tracks_updated'
JamBlasterActions.jamblasterTracksUpdated()
else if map.cmd == 'file_xfer_from_parent'
if map.filename && map.filename.indexOf('RT-mix.wav') > -1
RecordingActions.mixTransferred()
}
)

View File

@ -20,6 +20,7 @@ rest = context.JK.Rest()
checkingMissingPeers : {}
missingMixerPeers : {}
recheckTimeout : null
clientsWithAudioOverride : {}
init: ->
# Register with the app store to get @app
@ -38,6 +39,7 @@ rest = context.JK.Rest()
this.listenTo(context.MixerActions.metronomeChanged, this.onMetronomeChanged)
this.listenTo(context.MixerActions.deadUserRemove, this.onDeadUserRemove)
this.listenTo(context.MixerActions.missingPeerMixer, this.onMissingPeerMixer)
this.listenTo(context.MixerActions.clientsWithAudio, this.onClientsWithAudio)
context.JK.HandleVolumeChangeCallback2 = @handleVolumeChangeCallback
context.JK.HandleMetronomeCallback2 = @handleMetronomeCallback
@ -76,7 +78,7 @@ rest = context.JK.Rest()
# metroSound = args.sound
SessionActions.syncWithServer()
@mixers = new context.MixerHelper(@session, @masterMixers, @personalMixers, @metro, @noAudioUsers, @mixers?.mixMode || MIX_MODES.PERSONAL)
@mixers = new context.MixerHelper(@session, @masterMixers, @personalMixers, @metro, @noAudioUsers, @clientsWithAudioOverride, @mixers?.mixMode || MIX_MODES.PERSONAL)
@issueChange()
@ -132,7 +134,7 @@ rest = context.JK.Rest()
@masterMixers = context.jamClient.SessionGetAllControlState(true);
@personalMixers = context.jamClient.SessionGetAllControlState(false);
@mixers = new context.MixerHelper(@session, @masterMixers, @personalMixers, @metro, @noAudioUsers, @mixers?.mixMode || MIX_MODES.PERSONAL)
@mixers = new context.MixerHelper(@session, @masterMixers, @personalMixers, @metro, @noAudioUsers, @clientsWithAudioOverride, @mixers?.mixMode || MIX_MODES.PERSONAL)
@issueChange()
@ -146,9 +148,9 @@ rest = context.JK.Rest()
# simulate a state change to cause a UI redraw
@issueChange()
onFaderChanged: (data, mixers, gainType) ->
onFaderChanged: (data, mixers, gainType, controlGroup) ->
@mixers.faderChanged(data, mixers, gainType)
@mixers.faderChanged(data, mixers, gainType, controlGroup)
@issueChange()
@ -171,7 +173,7 @@ rest = context.JK.Rest()
@metro.sound = sound
context.jamClient.SessionSetMetronome(@metro.tempo, @metro.sound, 1, 0);
@mixers = new context.MixerHelper(@session, @masterMixers, @personalMixers, @metro, @noAudioUsers, @mixers?.mixMode || MIX_MODES.PERSONAL)
@mixers = new context.MixerHelper(@session, @masterMixers, @personalMixers, @metro, @noAudioUsers, @clientsWithAudioOverride, @mixers?.mixMode || MIX_MODES.PERSONAL)
@issueChange()
onDeadUserRemove: (clientId) ->
@ -193,6 +195,9 @@ rest = context.JK.Rest()
@issueChange()
onClientsWithAudio: (clients) ->
@clientsWithAudioOverride = clients
onMissingPeerMixer: (clientId) ->
missingPeerAttempts = @missingMixerPeers[clientId]
@ -219,7 +224,7 @@ rest = context.JK.Rest()
@masterMixers = context.jamClient.SessionGetAllControlState(true);
@personalMixers = context.jamClient.SessionGetAllControlState(false);
logger.debug("MixerStore: recheckForMixers")
@mixers = new context.MixerHelper(@session, @masterMixers, @personalMixers, @metro, @noAudioUsers, @mixers?.mixMode || MIX_MODES.PERSONAL)
@mixers = new context.MixerHelper(@session, @masterMixers, @personalMixers, @metro, @noAudioUsers, @clientsWithAudioOverride, @mixers?.mixMode || MIX_MODES.PERSONAL)
@issueChange()
onInitGain: (mixer) ->
@ -234,7 +239,7 @@ rest = context.JK.Rest()
logger.debug("MixerStore: onMixersChanged")
@mixers = new context.MixerHelper(@session, @masterMixers, @personalMixers, @metro, @noAudioUsers, @mixers?.mixMode || MIX_MODES.PERSONAL)
@mixers = new context.MixerHelper(@session, @masterMixers, @personalMixers, @metro, @noAudioUsers, @clientsWithAudioOverride, @mixers?.mixMode || MIX_MODES.PERSONAL)
SessionActions.mixersChanged.trigger(type, text, @mixers.getTrackInfo())

View File

@ -33,10 +33,11 @@ BackendToFrontendFPS = {
this.trigger({isRecording: @recordingModel.isRecording()})
onStartRecording: (recordVideo, recordChat) ->
frameRate = context.jamClient.GetCurrentVideoFrameRate() || 0;
frameRate = BackendToFrontendFPS[frameRate]
frameRate = 0
if recordVideo
if context.jamClient.GetCurrentVideoFrameRate?
frameRate = context.jamClient.GetCurrentVideoFrameRate() || 0;
frameRate = BackendToFrontendFPS[frameRate]
NoVideoRecordActive = 0
WebCamRecordActive = 1
@ -49,12 +50,14 @@ BackendToFrontendFPS = {
onStartingRecording: (details) ->
details.cause = 'starting'
@mixTransferred = false
this.trigger(details)
@popupRecordingControls() unless @recordingWindow?
onStartedRecording: (details) ->
details.cause = 'started'
@mixTransferred = false
this.trigger(details)
@popupRecordingControls() unless @recordingWindow?
@ -92,6 +95,9 @@ BackendToFrontendFPS = {
logger.debug("recording controls closed")
@recordingWindow = null
onMixTransferred: () ->
@mixTransferred = true
popupRecordingControls: () ->
logger.debug("poupRecordingControls")
@recordingWindow = window.open("/popups/recording-controls", 'Recording', 'scrollbars=yes,toolbar=no,status=no,height=315,width=340')

View File

@ -6,6 +6,7 @@ EVENTS = context.JK.EVENTS
MIX_MODES = context.JK.MIX_MODES
SessionActions = @SessionActions
MixerActions = @MixerActions
SessionStatThresholds = gon.session_stat_thresholds
NetworkThresholds = SessionStatThresholds.network
@ -16,7 +17,9 @@ AggregateThresholds = SessionStatThresholds.aggregate
@SessionStatsStore = Reflux.createStore(
{
listenables: @SessionStatsActions
rawStats: null
rawStats: null,
parentStats: null
clientsWithAudio: null
init: ->
# Register with the app store to get @app
@ -24,8 +27,9 @@ AggregateThresholds = SessionStatThresholds.aggregate
onAppInit: (@app) ->
onPushStats: (stats) ->
onPushStats: (stats, parentStats) ->
@rawStats = stats
@parentStats = parentStats
@changed()
classify: (holder, field, threshold) ->
@ -65,17 +69,15 @@ AggregateThresholds = SessionStatThresholds.aggregate
else
holder[fieldLevel] = 'good'
changed: () ->
@stats = {}
classifyStats: (statBag) ->
container = {}
self = null
for participant in @rawStats
for participant in statBag
if participant.id == @app.clientId
self = participant
break
for participant in @rawStats
for participant in statBag
aggregate = {}
@ -93,6 +95,9 @@ AggregateThresholds = SessionStatThresholds.aggregate
network = participant.network
if network?
if network.audio_bitrate_rx > 0 && network.audio_bitrate_tx > 0
@clientsWithAudio[participant.id] = true
@classify(network, 'audiojq_median', NetworkThresholds)
@classify(network, 'jitter_var', NetworkThresholds)
@classify(network, 'audio_bitrate_rx', NetworkThresholds)
@ -151,8 +156,23 @@ AggregateThresholds = SessionStatThresholds.aggregate
else
participant.classification = 'unknown'
@stats[participant.id] = participant
container[participant.id] = participant
return container
changed: () ->
@clientsWithAudio = {}
@stats = {}
@stats = @classifyStats(@rawStats)
if @parentStats
@stats.parent = @classifyStats(@parentStats)
else
@stats.parent = null
MixerActions.clientsWithAudio(@clientsWithAudio)
# see if we can reset noAudio
@trigger(@stats)
}
)

View File

@ -728,8 +728,19 @@ ConfigureTracksActions = @ConfigureTracksActions
context.jamClient.SessionRegisterCallback("JK.HandleBridgeCallback2");
context.jamClient.RegisterRecordingCallbacks("JK.HandleRecordingStartResult", "JK.HandleRecordingStopResult", "JK.HandleRecordingStarted", "JK.HandleRecordingStopped", "JK.HandleRecordingAborted");
context.jamClient.SessionSetConnectionStatusRefreshRate(1000);
clientRole = context.jamClient.getClientParentChildRole();
parentClientId = context.jamClient.getParentClientId();
logger.debug("role when joining session: #{clientRole}, parent client id #{parentClientId}")
#context.JK.HelpBubbleHelper.jamtrackGuideSession($screen.find('li.open-a-jamtrack'), $screen)
if clientRole == 0
clientRole = 'child'
else if clientRole == 1
clientRole = 'parent'
if clientRole == '' || !clientRole
clientRole = null
# subscribe to events from the recording model
@recordingRegistration()
@ -741,6 +752,8 @@ ConfigureTracksActions = @ConfigureTracksActions
as_musician: true,
tracks: @userTracks,
session_id: @currentSessionId,
client_role: clientRole,
parent_client_id: parentClientId
audio_latency: context.jamClient.FTUEGetExpectedLatency().latency
})
.done((response) =>
@ -840,8 +853,11 @@ ConfigureTracksActions = @ConfigureTracksActions
@backendStatsInterval = window.setInterval((() => (@updateBackendStats())), 1000)
updateBackendStats: () ->
connectionStats = window.jamClient.getConnectionDetail('')
SessionStatsActions.pushStats(connectionStats)
connectionStats = window.jamClient.getConnectionDetail('', false)
parentConnectionStats = window.jamClient.getConnectionDetail('', true)
#console.log("CONNECTION STATES", connectionStats)
#console.log("PARENT STATES", parentConnectionStats)
SessionStatsActions.pushStats(connectionStats, parentConnectionStats)
trackChanges: (header, payload) ->
if @currentTrackChanges < payload.track_changes_counter

View File

@ -297,7 +297,9 @@ class ApiMusicSessionsController < ApiController
params[:client_id],
params[:as_musician],
params[:tracks],
params[:audio_latency]
params[:audio_latency],
params[:client_role],
params[:parent_client_id]
)
if @connection.errors.any?

View File

@ -50,7 +50,7 @@ else
child(:connections => :participants) {
collection @music_sessions, :object_root => false
attributes :ip_address, :client_id, :joined_session_at, :audio_latency, :id, :metronome_open, :is_jamblaster
attributes :ip_address, :client_id, :joined_session_at, :audio_latency, :id, :metronome_open, :is_jamblaster, :client_role, :parent_client_id
node :user do |connection|
{ :id => connection.user.id, :photo_url => connection.user.photo_url, :name => connection.user.name, :is_friend => connection.user.friends?(current_user), :connection_state => connection.aasm_state }

View File

@ -4,8 +4,11 @@
= image_tag "content/recordbutton-off.png", {:height => 20, :width => 20, :class => 'content-icon'}
%h1 recording finished
.dialog-inner
Fill out the fields below and click the "SAVE" button to save this recording to your library. If you do not want to
keep the recording, click the "DISCARD" button.
%span.nowait
Fill out the fields below and click the "SAVE" button to save this recording to your library. If you do not want to
keep the recording, click the "DISCARD" button.
%span.pleasewait
Please wait while we transfer the necessary audio files from your JamBlaster to your client...
%br/
%br/
%form.left.w40.mr20
@ -36,7 +39,7 @@
%input{:checked => "checked", :name => "is_public", :type => "checkbox"}/
%label{:for => "is_public"} Public Recording
/ <a href="#"><<img src="images/shared/icon_help.png" width="12" height="12" /></a>
.left.w50.ml30
.left.w50.ml30.preview-area
Preview Recording:
\#{render "clients/play_controls"}

View File

@ -48,7 +48,7 @@
<li class="affiliate account-menu-group"><%= link_to "Affiliate Report", '/client#/account/affiliate' %></li>
<% end %>
<% if @nativeClient && Rails.application.config.jamblaster_menu %>
<li class="jamblaster-config"><%= link_to "JamBlaster", '/client#/jamblaster' %></li>
<li class="jamblaster-config"><%= link_to "JamBlaster Settings", '/client#/jamblaster' %></li>
<% end %>
<% if current_user && current_user.musician? %>
<li class="band-setup"><%= link_to "Band Setup", '/client#/band/setup/new' %></li>

View File

@ -740,6 +740,10 @@ module JamWebsockets
ipv4_link_local = options["ipv4_link_local"]
ipv6_link_local = options["ipv6_link_local"]
# it's nice to have client_ids not flap in the wind, and we can do that with jamblasters
if jamblaster_serial_no && client_id.nil?
client_id = jamblaster_serial_no
end
# TESTING
#if jamblaster_serial_no.nil?
# jamblaster_serial_no = 'hi'