This commit is contained in:
Seth Call 2016-10-27 18:24:54 -05:00
parent abf3c6f0f5
commit a8b181394c
20 changed files with 121 additions and 40 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

@ -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

@ -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

@ -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,14 @@ 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.5
framesize = '2.5 ms'
else if audio.framesize == 5
framesize = '5 ms'
@ -185,7 +189,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?

View File

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

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,

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

@ -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()
@ -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

@ -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,22 @@ AggregateThresholds = SessionStatThresholds.aggregate
else
participant.classification = 'unknown'
@stats[participant.id] = participant
container[participant.id] = participant
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

@ -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'