context = window logger = context.JK.logger SessionActions = context.SessionActions JamTrackActions = context.JamTrackActions MIX_MODES = context.JK.MIX_MODES rest = context.JK.Rest() @MixerStore = Reflux.createStore( { METRO_SOUND_LOOKUP: { 0 : "BuiltIn", 1 : "SineWave", 2 : "Beep", 3 : "Click", 4 : "Kick", 5 : "Snare", 6 : "MetroFile" } metro: {tempo: 120, cricket: false, sound: "Beep" } noAudioUsers : {} checkingMissingPeers : {} missingMixerPeers : {} recheckTimeout : null clientsWithAudioOverride : {} init: -> # Register with the app store to get @app this.listenTo(context.AppStore, this.onAppInit); this.listenTo(context.SessionStore, this.onSessionChange) this.listenTo(context.MixerActions.mute, this.onMute) this.listenTo(context.MixerActions.faderChanged, this.onFaderChanged) this.listenTo(context.MixerActions.initGain, this.onInitGain) this.listenTo(context.MixerActions.initPan, this.onInitPan) this.listenTo(context.MixerActions.panChanged, this.onPanChanged) this.listenTo(context.MixerActions.mixersChanged, this.onMixersChanged) this.listenTo(context.MixerActions.syncTracks, this.onSyncTracks) this.listenTo(context.MixerActions.mixerModeChanged, this.onMixerModeChanged) this.listenTo(context.MixerActions.loopChanged, this.onLoopChanged) this.listenTo(context.MixerActions.openMetronome, this.onOpenMetronome) 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) this.listenTo(context.MixerActions.closeMedia, this.onCloseMedia) context.JK.HandleVolumeChangeCallback2 = @handleVolumeChangeCallback context.JK.HandleMetronomeCallback2 = @handleMetronomeCallback context.JK.HandleBridgeCallback2 = @handleBridgeCallback context.JK.HandleBackingTrackSelectedCallback2 = @handleBackingTrackSelectedCallback #setInterval(@dumpVUStats, 5000) dumpVUStats: () -> @mixers.dumpVUStats() if @mixers? issueChange: () -> @trigger({session: @session, mixers: @mixers}) handleVolumeChangeCallback: (mixerId, isLeft, value, isMuted) -> # TODO # Visually update mixer # There is no need to actually set the back-end mixer value as the # back-end will already have updated the audio mixer directly prior to sending # me this event. I simply need to visually show the new fader position. # TODO: Use mixer's range #faderValue = percentFromMixerValue(-80, 20, value); #context.JK.FaderHelpers.setFaderValue(mixerId, faderValue); #var $muteControl = $('[control="mute"][mixer-id="' + mixerId + '"]'); #_toggleVisualMuteControl($muteControl, isMuted); logger.debug("volume change") handleMetronomeCallback: (args) -> logger.debug("MetronomeCallback: ", args) @metro.tempo = args.bpm @metro.cricket = args.cricket; @metro.sound = @METRO_SOUND_LOOKUP[args.sound]; # This isn't actually there, so we rely on the metroSound as set from select on form: # metroSound = args.sound SessionActions.syncWithServer() @mixers = new context.MixerHelper(@session, @masterMixers, @personalMixers, @metro, @noAudioUsers, @clientsWithAudioOverride, @mixers?.mixMode || MIX_MODES.PERSONAL) @issueChange() handleBridgeCallback: (vuData) -> eventName = null mixerId = null value = null vuInfo = null for vuInfo in vuData eventName = vuInfo[0]; vuVal = 0.0; if eventName == "vu" mixerId = vuInfo[1]; mode = vuInfo[2]; leftValue = vuInfo[3]; leftClipping = vuInfo[4]; rightValue = vuInfo[5]; rightClipping = vuInfo[6]; # TODO - no guarantee range will be -80 to 20. Get from the # GetControlState for this mixer which returns min/max # value is a DB value from -80 to 20. Convert to float from 0.0-1.0 @mixers.updateVU(mixerId, mode, (leftValue + 80) / 80, leftClipping, (rightValue + 80) / 80, rightClipping) #@mixers.updateVU(mixerId + "_vur", (rightValue + 80) / 80, rightClipping) handleBackingTrackSelectedCallback: () -> logger.debug("backing track selected") onAppInit: (@app) -> @gearUtils = context.JK.GearUtilsInstance @sessionUtils = context.JK.SessionUtils context.jamClient.SetVURefreshRate(150) context.jamClient.RegisterVolChangeCallBack("JK.HandleVolumeChangeCallback2") context.jamClient.setMetronomeOpenCallback("JK.HandleMetronomeCallback2") sessionEnded: () -> @checkingMissingPeers = {} @noAudioUsers = {} @missingMixerPeers = {} clearTimeout(@recheckTimeout) if @recheckTimeout? onSessionChange: (session) -> @sessionEnded() unless session.inSession() @session = session @masterMixers = context.jamClient.SessionGetAllControlState(true); @personalMixers = context.jamClient.SessionGetAllControlState(false); @mixers = new context.MixerHelper(@session, @masterMixers, @personalMixers, @metro, @noAudioUsers, @clientsWithAudioOverride, @mixers?.mixMode || MIX_MODES.PERSONAL) @issueChange() onMute: (mixers, muting) -> mixers = [mixers] unless $.isArray(mixers) for mixer in mixers @mixers.mute(mixer.id, mixer.mode, muting); # simulate a state change to cause a UI redraw @issueChange() onFaderChanged: (data, mixers, gainType, controlGroup) -> @mixers.faderChanged(data, mixers, gainType, controlGroup) @issueChange() onPanChanged: (data, mixers, groupId) -> @mixers.panChanged(data, mixers, groupId) @issueChange() onLoopChanged: (mixer, shouldLoop) -> @mixers.loopChanged(mixer, shouldLoop) onOpenMetronome: () -> context.jamClient.SessionStopPlay() context.jamClient.SessionOpenMetronome(@mixers.metro.tempo, @mixers.metro.sound, 1, 0) onMetronomeChanged: (tempo, sound) -> logger.debug("onMetronomeChanged", tempo, sound) @metro.tempo = tempo @metro.sound = sound context.jamClient.SessionSetMetronome(@metro.tempo, @metro.sound, 1, 0); @mixers = new context.MixerHelper(@session, @masterMixers, @personalMixers, @metro, @noAudioUsers, @clientsWithAudioOverride, @mixers?.mixMode || MIX_MODES.PERSONAL) @issueChange() # codeInitiated means the user did not initiate this onCloseMedia: (codeInitiated) -> logger.debug("MixerStore: onCloseMedia", codeInitiated) if @session.recordedTracks() @closeRecording(codeInitiated) else if @session.jamTracks() || @session.downloadingJamTrack @closeJamTrack(codeInitiated) else if @session.backingTrack() && @session.backingTrack().path @closeBackingTrack(codeInitiated) else if @session.isMetronomeOpen() @closeMetronomeTrack(codeInitiated) else logger.error("don't know how to close open media", @session) unless codeInitiated closeRecording: (codeInitiated) -> logger.debug("closing recording"); if !@mixers.mediaSummary.isOpener logger.debug("not recordingas not opener") return SessionActions.closeMedia(codeInitiated) closeMetronomeTrack:(codeInitiated) -> logger.debug("closing metronome") SessionActions.closeMedia(codeInitiated) closeBackingTrack: (codeInitiated) -> logger.debug("closing backing track"); if !@mixers.mediaSummary.isOpener logger.debug("not closing backing as not opener") return SessionActions.closeMedia(codeInitiated) closeJamTrack: (codeInitiated) -> logger.debug("closing jam track"); if !@mixers.mediaSummary.isOpener logger.debug("not closing jamtrack as not opener") return SessionActions.closeMedia(codeInitiated) onDeadUserRemove: (clientId) -> return unless @session.inSession() participant = @session.participantsEverSeen[clientId]; if participant? logger.debug("todo :notify dead user") # XXX TODO trigger some notification store #app.notify({ # "title": ALERT_TYPES[type].title, # "text": participant.user.name + " is no longer sending audio.", # "icon_url": context.JK.resolveAvatarUrl(participant.user.photo_url) #}); @noAudioUsers[clientId] = true @issueChange() onClientsWithAudio: (clients) -> @clientsWithAudioOverride = clients onMissingPeerMixer: (clientId) -> missingPeerAttempts = @missingMixerPeers[clientId] # check for 5 tries (10 seconds if setTimeout is 2000ms) if !missingPeerAttempts? || missingPeerAttempts < 5 @checkingMissingPeers[clientId] = true @recheckTimeout = setTimeout(@recheckForMixers, 2000) unless @recheckTimeout? else logger.debug("ignoring missing peer recheck. missingPeerAttempts: #{missingPeerAttempts}") recheckForMixers: () -> # increment how many times we've checked for this particular peer for clientId, meh of @checkingMissingPeers missingPeerAttempts = @missingMixerPeers[clientId] missingPeerAttempts = 0 unless missingPeerAttempts? missingPeerAttempts++ @missingMixerPeers[clientId] = missingPeerAttempts # reset the peers we are looking for @checkingMissingPeers = {} @recheckTimeout = null @masterMixers = context.jamClient.SessionGetAllControlState(true); @personalMixers = context.jamClient.SessionGetAllControlState(false); logger.debug("MixerStore: recheckForMixers") @mixers = new context.MixerHelper(@session, @masterMixers, @personalMixers, @metro, @noAudioUsers, @clientsWithAudioOverride, @mixers?.mixMode || MIX_MODES.PERSONAL) @issueChange() onInitGain: (mixer) -> @mixers.initGain(mixer) onInitPan: (mixer) -> @mixers.initPan(mixer) onMixersChanged: (type, text) -> @masterMixers = context.jamClient.SessionGetAllControlState(true); @personalMixers = context.jamClient.SessionGetAllControlState(false); logger.debug("MixerStore: onMixersChanged") @mixers = new context.MixerHelper(@session, @masterMixers, @personalMixers, @metro, @noAudioUsers, @clientsWithAudioOverride, @mixers?.mixMode || MIX_MODES.PERSONAL) SessionActions.mixersChanged.trigger(type, text, @mixers.getTrackInfo()) @issueChange() onMixerModeChanged: (mode) -> if mode == MIX_MODES.MASTER @app.layout.showDialog('session-master-mix-dialog') unless @app.layout.isDialogShowing('session-master-mix-dialog') else @app.layout.closeDialog('session-master-mix-dialog') if @app.layout.isDialogShowing('session-master-mix-dialog') onSyncTracks: () -> logger.debug("MixerStore: onSyncTracks") unless @session.inSession() logger.debug("dropping sync tracks because no longer in session") return allTracks = @mixers.getTrackInfo() inputTracks = allTracks.userTracks; backingTracks = allTracks.backingTracks; metronomeTracks = allTracks.metronomeTracks; # create a trackSync request based on backend data syncTrackRequest = {} syncTrackRequest.client_id = @app.clientId syncTrackRequest.tracks = inputTracks syncTrackRequest.backing_tracks = backingTracks syncTrackRequest.metronome_open = metronomeTracks.length > 0 syncTrackRequest.id = @session.id() rest.putTrackSyncChange(syncTrackRequest) .fail((jqXHR)=> if jqXHR.status != 404 @app.notify({ "title": "Can't Sync Local Tracks", "text": "The client is unable to sync local track information with the server. You should rejoin the session to ensure a good experience.", "icon_url": "/assets/content/icon_alert_big.png" }) else logger.debug("Unable to sync local tracks because session is gone.") ) } )