From cd932114069b07767044de550c145d03313b34ce Mon Sep 17 00:00:00 2001 From: Nuwan Date: Wed, 13 Apr 2022 03:02:44 +0530 Subject: [PATCH] wip promised based jamClient --- .../javascripts/accounts_jamtracks.js.coffee | 140 +- web/app/assets/javascripts/asyncJamClient.js | 1 + .../assets/javascripts/client_init.js.coffee | 28 +- .../dialog/sessionMasterMixDialog.js.coffee | 19 +- .../javascripts/download_jamtrack.js.coffee | 155 +- .../JamBlasterNameDialog.js.jsx.coffee | 83 +- .../JamBlasterPairingDialog.js.jsx.coffee | 66 +- .../JamBlasterPortDialog.js.jsx.coffee | 71 +- .../JamBlasterScreen.js.jsx.coffee | 182 ++- .../JamTrackLandingScreen.js.jsx.coffee | 177 ++- .../PopupRecordingStartStop.js.jsx.coffee | 88 +- .../SessionMediaTracks.js.jsx.coffee | 225 ++- .../SessionMyTrack.js.jsx.coffee | 134 +- .../helpers/MixerHelper.js.coffee | 113 +- .../stores/CallbackStore.js.coffee | 18 +- .../stores/ConfigureTracksStore.js.coffee | 803 +++++++--- .../stores/JamBlasterStore.js.coffee | 501 ++++-- .../stores/JamTrackStore.js.coffee | 190 ++- .../stores/MediaPlaybackStore.js.coffee | 153 +- .../stores/MixerStore.js.coffee | 164 +- .../stores/PlatformStore.js.coffee | 43 +- .../stores/RecordingStore.js.jsx.coffee | 37 +- .../stores/SessionStore.js.coffee | 1398 ++++++++++++----- .../stores/VideoLiveStreamStore.js.coffee | 567 ++++--- .../stores/VideoStore.js.coffee | 391 +++-- .../stores/VideoUploaderStore.js.coffee | 317 ++-- .../assets/javascripts/sync_viewer.js.coffee | 639 +++++--- .../javascripts/webcam_viewer.js.coffee | 239 ++- 28 files changed, 4942 insertions(+), 2000 deletions(-) diff --git a/web/app/assets/javascripts/accounts_jamtracks.js.coffee b/web/app/assets/javascripts/accounts_jamtracks.js.coffee index 5793d7941..6c00a8efa 100644 --- a/web/app/assets/javascripts/accounts_jamtracks.js.coffee +++ b/web/app/assets/javascripts/accounts_jamtracks.js.coffee @@ -57,49 +57,101 @@ context.JK.AccountJamTracks = class AccountJamTracks @createSession(jamRow.data(), false, jamRow.data('jamTrack')) return false; - createSession:(sessionData, solo, jamTrack) => - tracks = context.JK.TrackHelpers.getUserTracks(context.jamClient) + # createSession:(sessionData, solo, jamTrack) => + # tracks = context.JK.TrackHelpers.getUserTracks(context.jamClient) - if (context.JK.guardAgainstBrowser(@app)) - data = {} - data.client_id = @app.clientId - #data.description = $('#description').val() - data.description = "Jam Track Session" - data.as_musician = true - data.legal_terms = true - data.intellectual_property = true - data.approval_required = false - data.musician_access = !solo - data.fan_access = false - data.fan_chat = false - data.genre = $.map(sessionData.jamTrack.genres, (genre) -> genre.id) - data.genres = $.map(sessionData.jamTrack.genres, (genre)-> genre.id) - # data.genres = context.JK.GenreSelectorHelper.getSelectedGenres('#create-session-genre') - # data.musician_access = if $('#musician-access option:selected').val() == 'true' then true else false - # data.approval_required = if $('input[name=\'musician-access-option\']:checked').val() == 'true' then true else false - # data.fan_access = if $('#fan-access option:selected').val() == 'true' then true else false - # data.fan_chat = if $('input[name=\'fan-chat-option\']:checked').val() == 'true' then true else false - # if $('#band-list option:selected').val() != '' - # data.band = $('#band-list option:selected').val() - data.audio_latency = context.jamClient.FTUEGetExpectedLatency().latency - data.tracks = tracks + # if (context.JK.guardAgainstBrowser(@app)) + # data = {} + # data.client_id = @app.clientId + # #data.description = $('#description').val() + # data.description = "Jam Track Session" + # data.as_musician = true + # data.legal_terms = true + # data.intellectual_property = true + # data.approval_required = false + # data.musician_access = !solo + # data.fan_access = false + # data.fan_chat = false + # data.genre = $.map(sessionData.jamTrack.genres, (genre) -> genre.id) + # data.genres = $.map(sessionData.jamTrack.genres, (genre)-> genre.id) + # # data.genres = context.JK.GenreSelectorHelper.getSelectedGenres('#create-session-genre') + # # data.musician_access = if $('#musician-access option:selected').val() == 'true' then true else false + # # data.approval_required = if $('input[name=\'musician-access-option\']:checked').val() == 'true' then true else false + # # data.fan_access = if $('#fan-access option:selected').val() == 'true' then true else false + # # data.fan_chat = if $('input[name=\'fan-chat-option\']:checked').val() == 'true' then true else false + # # if $('#band-list option:selected').val() != '' + # # data.band = $('#band-list option:selected').val() + # data.audio_latency = context.jamClient.FTUEGetExpectedLatency().latency + # data.tracks = tracks - rest.legacyCreateSession(data).done((response) => - newSessionId = response.id - @sessionUtils.setAutoOpenJamTrack(jamTrack) # so that the session screen will pick this up - context.location = '/client#/session/' + newSessionId - # Re-loading the session settings will cause the form to reset with the right stuff in it. - # This is an extra xhr call, but it keeps things to a single codepath - #loadSessionSettings() - context.JK.GA.trackSessionCount data.musician_access, data.fan_access, 0 - context.JK.GA.trackSessionMusicians context.JK.GA.SessionCreationTypes.create - ).fail (jqXHR) => - handled = false - if jqXHR.status = 422 - response = JSON.parse(jqXHR.responseText) - if response['errors'] and response['errors']['tracks'] and response['errors']['tracks'][0] == 'Please select at least one track' - @app.notifyAlert 'No Inputs Configured', $('You will need to reconfigure your audio device.') - handled = true - if !handled - @app.notifyServerError jqXHR, 'Unable to Create Session' - \ No newline at end of file + # rest.legacyCreateSession(data).done((response) => + # newSessionId = response.id + # @sessionUtils.setAutoOpenJamTrack(jamTrack) # so that the session screen will pick this up + # context.location = '/client#/session/' + newSessionId + # # Re-loading the session settings will cause the form to reset with the right stuff in it. + # # This is an extra xhr call, but it keeps things to a single codepath + # #loadSessionSettings() + # context.JK.GA.trackSessionCount data.musician_access, data.fan_access, 0 + # context.JK.GA.trackSessionMusicians context.JK.GA.SessionCreationTypes.create + # ).fail (jqXHR) => + # handled = false + # if jqXHR.status = 422 + # response = JSON.parse(jqXHR.responseText) + # if response['errors'] and response['errors']['tracks'] and response['errors']['tracks'][0] == 'Please select at least one track' + # @app.notifyAlert 'No Inputs Configured', $('You will need to reconfigure your audio device.') + # handled = true + # if !handled + # @app.notifyServerError jqXHR, 'Unable to Create Session' + + createSession: `async function(sessionData, solo, jamTrack){ + const tracks = context.JK.TrackHelpers.getUserTracks(context.jamClient); + + if (context.JK.guardAgainstBrowser(this.app)) { + const data = {}; + data.client_id = this.app.clientId; + //data.description = $('#description').val() + data.description = "Jam Track Session"; + data.as_musician = true; + data.legal_terms = true; + data.intellectual_property = true; + data.approval_required = false; + data.musician_access = !solo; + data.fan_access = false; + data.fan_chat = false; + data.genre = $.map(sessionData.jamTrack.genres, genre => genre.id); + data.genres = $.map(sessionData.jamTrack.genres, genre => genre.id); + // data.genres = context.JK.GenreSelectorHelper.getSelectedGenres('#create-session-genre') + // data.musician_access = if $('#musician-access option:selected').val() == 'true' then true else false + // data.approval_required = if $('input[name=\'musician-access-option\']:checked').val() == 'true' then true else false + // data.fan_access = if $('#fan-access option:selected').val() == 'true' then true else false + // data.fan_chat = if $('input[name=\'fan-chat-option\']:checked').val() == 'true' then true else false + // if $('#band-list option:selected').val() != '' + // data.band = $('#band-list option:selected').val() + let expectedLatency = await context.jamClient.FTUEGetExpectedLatency() + data.audio_latency = expectedLatency.latency; + data.tracks = tracks; + + return rest.legacyCreateSession(data).done(response => { + const newSessionId = response.id; + this.sessionUtils.setAutoOpenJamTrack(jamTrack); // so that the session screen will pick this up + context.location = '/client#/session/' + newSessionId; + // Re-loading the session settings will cause the form to reset with the right stuff in it. + // This is an extra xhr call, but it keeps things to a single codepath + //loadSessionSettings() + context.JK.GA.trackSessionCount(data.musician_access, data.fan_access, 0); + return context.JK.GA.trackSessionMusicians(context.JK.GA.SessionCreationTypes.create); + }).fail(jqXHR => { + let handled = false; + if (jqXHR.status = 422) { + const response = JSON.parse(jqXHR.responseText); + if (response['errors'] && response['errors']['tracks'] && (response['errors']['tracks'][0] === 'Please select at least one track')) { + this.app.notifyAlert('No Inputs Configured', $('You will need to reconfigure your audio device.')); + handled = true; + } + } + if (!handled) { + return this.app.notifyServerError(jqXHR, 'Unable to Create Session'); + } + }); + } + }` \ No newline at end of file diff --git a/web/app/assets/javascripts/asyncJamClient.js b/web/app/assets/javascripts/asyncJamClient.js index 633f037d4..e94bdd7c3 100644 --- a/web/app/assets/javascripts/asyncJamClient.js +++ b/web/app/assets/javascripts/asyncJamClient.js @@ -344,6 +344,7 @@ resolve(resp); } ); + //TODO: handle 404 error - return null if method does not exist } catch (e) { console.log("[asyncJamClient] error: Native app not connected"); reject(Error(e.message)); //TODO: reject with custom error object QWebChannelError(e.message, e.data) diff --git a/web/app/assets/javascripts/client_init.js.coffee b/web/app/assets/javascripts/client_init.js.coffee index a991dee6f..d1bc5bd97 100644 --- a/web/app/assets/javascripts/client_init.js.coffee +++ b/web/app/assets/javascripts/client_init.js.coffee @@ -11,16 +11,30 @@ context.JK.ClientInit = class ClientInit @ALERT_NAMES = context.JK.ALERT_NAMES; @lastCheckedBroadcast = null - init: () => - if context.gon.isNativeClient - this.nativeClientInit() + # init: () => + # if context.gon.isNativeClient + # this.nativeClientInit() - context.JK.onBackendEvent(@ALERT_NAMES.WINDOW_OPEN_FOREGROUND_MODE, 'client_init', @watchBroadcast); + # context.JK.onBackendEvent(@ALERT_NAMES.WINDOW_OPEN_FOREGROUND_MODE, 'client_init', @watchBroadcast); - this.watchBroadcast() + # this.watchBroadcast() - if context.jamClient.RegisterSessionJoinLeaveRequestCallBack? - context.jamClient.RegisterSessionJoinLeaveRequestCallBack("SessionStore.handleJoinLeaveRequestCallback") + # if context.jamClient.RegisterSessionJoinLeaveRequestCallBack? + # context.jamClient.RegisterSessionJoinLeaveRequestCallBack("SessionStore.handleJoinLeaveRequestCallback") + + init: `async function(){ + if (context.gon.isNativeClient) { + this.nativeClientInit(); + } + + context.JK.onBackendEvent(this.ALERT_NAMES.WINDOW_OPEN_FOREGROUND_MODE, 'client_init', this.watchBroadcast); + + this.watchBroadcast(); + + //if (await context.jamClient.RegisterSessionJoinLeaveRequestCallBack != null) { + await context.jamClient.RegisterSessionJoinLeaveRequestCallBack("SessionStore.handleJoinLeaveRequestCallback"); + //} + }` checkBroadcast: () => promise = window.BroadcastActions.load.trigger() diff --git a/web/app/assets/javascripts/dialog/sessionMasterMixDialog.js.coffee b/web/app/assets/javascripts/dialog/sessionMasterMixDialog.js.coffee index 781031b95..d58657575 100644 --- a/web/app/assets/javascripts/dialog/sessionMasterMixDialog.js.coffee +++ b/web/app/assets/javascripts/dialog/sessionMasterMixDialog.js.coffee @@ -23,14 +23,23 @@ context.JK.SessionMasterMixDialog = class SessionMasterMixDialog @app.bindDialog(@dialogId, dialogBindings) @content = @dialog.find(".dialog-inner") - beforeShow:() => - @logger.debug("session-master-mix-dlg: beforeShow") - context.jamClient.SetMixerMode(MIX_MODES.MASTER) + # beforeShow:() => + # @logger.debug("session-master-mix-dlg: beforeShow") + # context.jamClient.SetMixerMode(MIX_MODES.MASTER) + + beforeShow: `async function(){ + this.logger.debug("session-master-mix-dlg: beforeShow"); + await context.jamClient.SetMixerMode(MIX_MODES.MASTER); + }` afterShow:() => @logger.debug("session-master-mix-dlg: afterShow") - afterHide:() => - context.jamClient.SetMixerMode(MIX_MODES.PERSONAL) + # afterHide:() => + # context.jamClient.SetMixerMode(MIX_MODES.PERSONAL) + + afterHide: `async function(){ + await context.jamClient.SetMixerMode(MIX_MODES.PERSONAL); + }` diff --git a/web/app/assets/javascripts/download_jamtrack.js.coffee b/web/app/assets/javascripts/download_jamtrack.js.coffee index eb9846546..bea123ac4 100644 --- a/web/app/assets/javascripts/download_jamtrack.js.coffee +++ b/web/app/assets/javascripts/download_jamtrack.js.coffee @@ -187,32 +187,59 @@ context.JK.DownloadJamTrack = class DownloadJamTrack @logger.debug("showing #{@state.name}") this.expectTransition() - showDownloading: () => - @logger.debug("showing #{@state.name}") - # while downloading, we don't run the transition timer, because the download API is guaranteed to call success, or failure, eventually - context.jamClient.JamTrackDownload(@jamTrack.id, null, context.JK.currentUserId, + # showDownloading: () => + # @logger.debug("showing #{@state.name}") + # # while downloading, we don't run the transition timer, because the download API is guaranteed to call success, or failure, eventually + # context.jamClient.JamTrackDownload(@jamTrack.id, null, context.JK.currentUserId, + # this.makeDownloadProgressCallback(), + # this.makeDownloadSuccessCallback(), + # this.makeDownloadFailureCallback()) + + showDownloading: `async function(){ + this.logger.debug('showing '+this.state.name); + // while downloading, we do not run the transition timer, because the download API is guaranteed to call success, or failure, eventually + await context.jamClient.JamTrackDownload(this.jamTrack.id, null, context.JK.currentUserId, this.makeDownloadProgressCallback(), this.makeDownloadSuccessCallback(), - this.makeDownloadFailureCallback()) + this.makeDownloadFailureCallback()); + }` - showKeying: () => - @logger.debug("showing #{@state.name}") - context.jamClient.JamTrackKeysRequest() - this.waitForState() + # showKeying: () => + # @logger.debug("showing #{@state.name}") + # context.jamClient.JamTrackKeysRequest() + # this.waitForState() + + showKeying: `async function(){ + this.logger.debug('showing '+this.state.name); + await context.jamClient.JamTrackKeysRequest(); + this.waitForState(); + }` showQuiet: () => @logger.debug("showing #{@state.name}") - showInitial: () => - @logger.debug("showing #{@state.name}") - @sampleRate = context.jamClient.GetSampleRate() - @fingerprint = context.jamClient.SessionGetMacHash() - logger.debug("fingerprint: ", @fingerprint) - @sampleRateForFilename = if @sampleRate == 48 then '48' else '44' - @attempts = @attempts + 1 - this.expectTransition() - context.JK.SubscriptionUtils.subscribe('jam_track_right', @jamTrack.jam_track_right_id).on(context.JK.EVENTS.SUBSCRIBE_NOTIFICATION, this.onJamTrackRightEvent) - this.checkState() + # showInitial: () => + # @logger.debug("showing #{@state.name}") + # @sampleRate = context.jamClient.GetSampleRate() + # @fingerprint = context.jamClient.SessionGetMacHash() + # logger.debug("fingerprint: ", @fingerprint) + # @sampleRateForFilename = if @sampleRate == 48 then '48' else '44' + # @attempts = @attempts + 1 + # this.expectTransition() + # context.JK.SubscriptionUtils.subscribe('jam_track_right', @jamTrack.jam_track_right_id).on(context.JK.EVENTS.SUBSCRIBE_NOTIFICATION, this.onJamTrackRightEvent) + # this.checkState() + + showInitial: `async function() { + this.logger.debug('showing '+this.state.name); + this.sampleRate = await context.jamClient.GetSampleRate(); + this.fingerprint = await context.jamClient.SessionGetMacHash(); + logger.debug("fingerprint: ", this.fingerprint); + this.sampleRateForFilename = this.sampleRate === 48 ? '48' : '44'; + this.attempts = this.attempts + 1; + this.expectTransition(); + context.JK.SubscriptionUtils.subscribe('jam_track_right', this.jamTrack.jam_track_right_id).on(context.JK.EVENTS.SUBSCRIBE_NOTIFICATION, this.onJamTrackRightEvent); + this.checkState(); + }` showError: () => @logger.debug("showing #{@state.name}") @@ -353,38 +380,76 @@ context.JK.DownloadJamTrack = class DownloadJamTrack $(this).triggerHandler(@EVENTS.JAMTRACK_DOWNLOADER_STATE_CHANGED, {state: @state}) - checkState: () => - # check for the success state against the local state of the client... if it's playable, then we should be OK - fqId = "#{@jamTrack.id}-#{@sampleRateForFilename}" - @trackDetail = context.jamClient.JamTrackGetTrackDetail (fqId) + # checkState: () => + # # check for the success state against the local state of the client... if it's playable, then we should be OK + # fqId = "#{@jamTrack.id}-#{@sampleRateForFilename}" + # @trackDetail = context.jamClient.JamTrackGetTrackDetail (fqId) - @logger.debug("DownloadJamTrack: JamTrackGetTrackDetail(#{fqId}).key_state: " + @trackDetail.key_state, @trackDetail) + # @logger.debug("DownloadJamTrack: JamTrackGetTrackDetail(#{fqId}).key_state: " + @trackDetail.key_state, @trackDetail) - # first check if the version is not the same; if so, invalidate. + # # first check if the version is not the same; if so, invalidate. - if @trackDetail.version? - if @jamTrack.version != @trackDetail.version - @logger.info("DownloadJamTrack: JamTrack on disk is different version (stored: #{@trackDetail.version}, server: #{@jamTrack.version}. Invalidating") - context.jamClient.InvalidateJamTrack("#{@jamTrack.id}-#{@sampleRateForFilename}") - @trackDetail = context.jamClient.JamTrackGetTrackDetail ("#{@jamTrack.id}-#{@sampleRateForFilename}") + # if @trackDetail.version? + # if @jamTrack.version != @trackDetail.version + # @logger.info("DownloadJamTrack: JamTrack on disk is different version (stored: #{@trackDetail.version}, server: #{@jamTrack.version}. Invalidating") + # context.jamClient.InvalidateJamTrack("#{@jamTrack.id}-#{@sampleRateForFilename}") + # @trackDetail = context.jamClient.JamTrackGetTrackDetail ("#{@jamTrack.id}-#{@sampleRateForFilename}") - if @trackDetail.version? - @logger.error("after invalidating package, the version is still wrong!", @trackDetail) - throw "after invalidating package, the version is still wrong! #{@trackDetail.version}" + # if @trackDetail.version? + # @logger.error("after invalidating package, the version is still wrong!", @trackDetail) + # throw "after invalidating package, the version is still wrong! #{@trackDetail.version}" - switch @trackDetail.key_state - when 'pending' - this.transition(@states.keying) - when 'not authorized' - # TODO: if not authorized, do we need to re-initiate a keying attempt? - this.transition(@states.keying) - when 'ready' - this.transition(@states.synchronized) - when 'unknown' - @ajaxGetJamTrackRightAborted = false - @rest.getJamTrackRight({id: @jamTrack.id}) + # switch @trackDetail.key_state + # when 'pending' + # this.transition(@states.keying) + # when 'not authorized' + # # TODO: if not authorized, do we need to re-initiate a keying attempt? + # this.transition(@states.keying) + # when 'ready' + # this.transition(@states.synchronized) + # when 'unknown' + # @ajaxGetJamTrackRightAborted = false + # @rest.getJamTrackRight({id: @jamTrack.id}) + # .done(this.processJamTrackRight) + # .fail(this.processJamTrackRightFail) + + checkState: `async function() { + // check for the success state against the local state of the client... if its playable, then we should be OK + const fqId = this.jamTrack.id+'-'+this.sampleRateForFilename; + this.trackDetail = await context.jamClient.JamTrackGetTrackDetail((fqId)); + + this.logger.debug('DownloadJamTrack: JamTrackGetTrackDetail('+fqId+').key_state: ' + this.trackDetail.key_state, this.trackDetail); + + //first check if the version is not the same; if so, invalidate. + + if (this.trackDetail.version != null) { + if (this.jamTrack.version !== this.trackDetail.version) { + this.logger.info('DownloadJamTrack: JamTrack on disk is different version (stored: '+this.trackDetail.version+', server: '+this.jamTrack.version+'. Invalidating'); + await context.jamClient.InvalidateJamTrack(this.jamTrack.id+'-'+this.sampleRateForFilename); + this.trackDetail = await context.jamClient.JamTrackGetTrackDetail((this.jamTrack.id+'-'+this.sampleRateForFilename)); + + if (this.trackDetail.version != null) { + this.logger.error("after invalidating package, the version is still wrong!", this.trackDetail); + throw 'after invalidating package, the version is still wrong! ' + this.trackDetail.version; + } + } + } + + switch (this.trackDetail.key_state) { + case 'pending': + return this.transition(this.states.keying); + case 'not authorized': + // TODO: if not authorized, do we need to re-initiate a keying attempt? + return this.transition(this.states.keying); + case 'ready': + return this.transition(this.states.synchronized); + case 'unknown': + this.ajaxGetJamTrackRightAborted = false; + return this.rest.getJamTrackRight({id: this.jamTrack.id}) .done(this.processJamTrackRight) - .fail(this.processJamTrackRightFail) + .fail(this.processJamTrackRightFail); + } + }` # update progress indicator for packaging step updateSteps: () => diff --git a/web/app/assets/javascripts/react-components/JamBlasterNameDialog.js.jsx.coffee b/web/app/assets/javascripts/react-components/JamBlasterNameDialog.js.jsx.coffee index 1b3e77ad7..eee8ae41e 100644 --- a/web/app/assets/javascripts/react-components/JamBlasterNameDialog.js.jsx.coffee +++ b/web/app/assets/javascripts/react-components/JamBlasterNameDialog.js.jsx.coffee @@ -37,36 +37,71 @@ context = window @setState({name: $(e.target).val()}) - updateName: (e) -> - e.preventDefault() + # updateName: (e) -> + # e.preventDefault() - # validate + # # validate - name = @root.find('.name').val() + # name = @root.find('.name').val() - characterMatch = /^[^a-z0-9,' -]+$/i + # characterMatch = /^[^a-z0-9,' -]+$/i - if name.length == 0 || name == '' - context.JK.Banner.showAlert('invalid name', 'Please specify a name.') - return - else if name.length < 2 - context.JK.Banner.showAlert('invalid name', 'Please specify a name at least 3 characters long.') - return - else if name.length > 63 - context.JK.Banner.showAlert('invalid name', 'The name must be less than 64 characters long.') - return - else if characterMatch.test(name) - context.JK.Banner.showAlert('invalid name', - 'The can only contain A-Z, 0-9, commas, apostrophes, spaces, or hyphens.') - return + # if name.length == 0 || name == '' + # context.JK.Banner.showAlert('invalid name', 'Please specify a name.') + # return + # else if name.length < 2 + # context.JK.Banner.showAlert('invalid name', 'Please specify a name at least 3 characters long.') + # return + # else if name.length > 63 + # context.JK.Banner.showAlert('invalid name', 'The name must be less than 64 characters long.') + # return + # else if characterMatch.test(name) + # context.JK.Banner.showAlert('invalid name', + # 'The can only contain A-Z, 0-9, commas, apostrophes, spaces, or hyphens.') + # return - result = context.jamClient.setJBName(name.trim()) + # result = context.jamClient.setJBName(name.trim()) + + # if !result + # context.JK.Banner.showAlert('unable to set the name', + # 'Please email support@jamkazam.com and let us know the name you are specifying unsuccessfully, or refresh the page and try again.') + # else + # @app.layout.closeDialog('jamblaster-name-dialog') + + updateName: `async function(e) { + e.preventDefault(); + + // validate + + const name = this.root.find('.name').val(); + + const characterMatch = /^[^a-z0-9,' -]+$/i; + + if ((name.length === 0) || (name === '')) { + context.JK.Banner.showAlert('invalid name', 'Please specify a name.'); + return; + } else if (name.length < 2) { + context.JK.Banner.showAlert('invalid name', 'Please specify a name at least 3 characters long.'); + return; + } else if (name.length > 63) { + context.JK.Banner.showAlert('invalid name', 'The name must be less than 64 characters long.'); + return; + } else if (characterMatch.test(name)) { + context.JK.Banner.showAlert('invalid name', + 'The can only contain A-Z, 0-9, commas, apostrophes, spaces, or hyphens.'); + return; + } + + const result = await context.jamClient.setJBName(name.trim()); + + if (!result) { + return context.JK.Banner.showAlert('unable to set the name', + 'Please email support@jamkazam.com and let us know the name you are specifying unsuccessfully, or refresh the page and try again.'); + } else { + return this.app.layout.closeDialog('jamblaster-name-dialog'); + } + }` - if !result - context.JK.Banner.showAlert('unable to set the name', - 'Please email support@jamkazam.com and let us know the name you are specifying unsuccessfully, or refresh the page and try again.') - else - @app.layout.closeDialog('jamblaster-name-dialog') render: () -> `
diff --git a/web/app/assets/javascripts/react-components/JamBlasterPairingDialog.js.jsx.coffee b/web/app/assets/javascripts/react-components/JamBlasterPairingDialog.js.jsx.coffee index 3698fd26e..ccd632982 100644 --- a/web/app/assets/javascripts/react-components/JamBlasterPairingDialog.js.jsx.coffee +++ b/web/app/assets/javascripts/react-components/JamBlasterPairingDialog.js.jsx.coffee @@ -100,29 +100,57 @@ JamBlasterActions = @JamBlasterActions e.preventDefault() @app.layout.closeDialog('jamblaster-pairing-dialog') - pair: (e) -> - e.preventDefault() + # pair: (e) -> + # e.preventDefault() - if @state.pairing - return + # if @state.pairing + # return - @setState({pairing: true, pairStart: new Date().getTime(), timer: 60, pairingTimeout: false, paired: false}) - @setTimer(true) + # @setState({pairing: true, pairStart: new Date().getTime(), timer: 60, pairingTimeout: false, paired: false}) + # @setTimer(true) - client = @findJamBlaster(this.state.bonjourClientId) + # client = @findJamBlaster(this.state.bonjourClientId) - if client.isPaired - context.JK.Banner.showNotice("JamBlaster already paired", "This JamBlaster is already paired.") - @app.layout.closeDialog("jamblaster-pairing-dialog", true) - else if client? - logger.debug("trying to connect to #{client.connect_url}") - if client.connect_url? - @pairingTimer() - context.jamClient.startPairing(client.connect_url) - else - context.JK.Banner.showAlert("JamBlaster offline", "JamBlaster appears to be offline. Please reboot it.") - else - context.JK.Banner.showAlert("JamBlaster offline", "JamBlaster appears to be offline. Please reboot it.") + # if client.isPaired + # context.JK.Banner.showNotice("JamBlaster already paired", "This JamBlaster is already paired.") + # @app.layout.closeDialog("jamblaster-pairing-dialog", true) + # else if client? + # logger.debug("trying to connect to #{client.connect_url}") + # if client.connect_url? + # @pairingTimer() + # context.jamClient.startPairing(client.connect_url) + # else + # context.JK.Banner.showAlert("JamBlaster offline", "JamBlaster appears to be offline. Please reboot it.") + # else + # context.JK.Banner.showAlert("JamBlaster offline", "JamBlaster appears to be offline. Please reboot it.") + + pair: `async function(e) { + e.preventDefault(); + + if (this.state.pairing) { + return; + } + + this.setState({pairing: true, pairStart: new Date().getTime(), timer: 60, pairingTimeout: false, paired: false}); + this.setTimer(true); + + const client = this.findJamBlaster(this.state.bonjourClientId); + + if (client.isPaired) { + context.JK.Banner.showNotice("JamBlaster already paired", "This JamBlaster is already paired."); + return this.app.layout.closeDialog("jamblaster-pairing-dialog", true); + } else if (client != null) { + logger.debug('trying to connect to '+client.connect_url); + if (client.connect_url != null) { + this.pairingTimer(); + await context.jamClient.startPairing(client.connect_url); + } else { + context.JK.Banner.showAlert("JamBlaster offline", "JamBlaster appears to be offline. Please reboot it."); + } + } else { + context.JK.Banner.showAlert("JamBlaster offline", "JamBlaster appears to be offline. Please reboot it."); + } + }` render: () -> diff --git a/web/app/assets/javascripts/react-components/JamBlasterPortDialog.js.jsx.coffee b/web/app/assets/javascripts/react-components/JamBlasterPortDialog.js.jsx.coffee index 21a345a1d..16827dc67 100644 --- a/web/app/assets/javascripts/react-components/JamBlasterPortDialog.js.jsx.coffee +++ b/web/app/assets/javascripts/react-components/JamBlasterPortDialog.js.jsx.coffee @@ -32,31 +32,66 @@ context = window e.preventDefault() @app.layout.closeDialog('jamblaster-port-dialog', true); - updatePort: (e) -> - e.preventDefault() + # updatePort: (e) -> + # e.preventDefault() - # validate + # # validate - staticPort = @root.find('.port').val() + # staticPort = @root.find('.port').val() - staticPort = new Number(staticPort); + # staticPort = new Number(staticPort); - console.log("staticPort", staticPort) - if context._.isNaN(staticPort) - @app.layout.notify({title: 'No Settings Have Been Saved!', text: 'Please enter a number from 1026-49150.'}) - return + # console.log("staticPort", staticPort) + # if context._.isNaN(staticPort) + # @app.layout.notify({title: 'No Settings Have Been Saved!', text: 'Please enter a number from 1026-49150.'}) + # return - if staticPort < 1026 || staticPort >= 65525 - @app.layout.notify({title: 'No Settings Have Been Saved!', text: 'Please pick a port from 1026 to 65524.'}) - return + # if staticPort < 1026 || staticPort >= 65525 + # @app.layout.notify({title: 'No Settings Have Been Saved!', text: 'Please pick a port from 1026 to 65524.'}) + # return - result = context.jamClient.setJbPortBindState({use_static_port: true, static_port: staticPort}) + # result = context.jamClient.setJbPortBindState({use_static_port: true, static_port: staticPort}) + + # if !result + # context.JK.Banner.showAlert('unable to set a static port', + # 'Please email support@jamkazam.com and let us know the port number you are specifying unsuccessfully, or refresh the page and try again.') + # else + # @app.layout.closeDialog('jamblaster-port-dialog') + + updatePort: `async function(e) { + e.preventDefault(); + + // validate + + const name = this.root.find('.name').val(); + + const characterMatch = /^[^a-z0-9,' -]+$/i; + + if ((name.length === 0) || (name === '')) { + context.JK.Banner.showAlert('invalid name', 'Please specify a name.'); + return; + } else if (name.length < 2) { + context.JK.Banner.showAlert('invalid name', 'Please specify a name at least 3 characters long.'); + return; + } else if (name.length > 63) { + context.JK.Banner.showAlert('invalid name', 'The name must be less than 64 characters long.'); + return; + } else if (characterMatch.test(name)) { + context.JK.Banner.showAlert('invalid name', + 'The can only contain A-Z, 0-9, commas, apostrophes, spaces, or hyphens.'); + return; + } + + const result = await context.jamClient.setJBName(name.trim()); + + if (!result) { + return context.JK.Banner.showAlert('unable to set the name', + 'Please email support@jamkazam.com and let us know the name you are specifying unsuccessfully, or refresh the page and try again.'); + } else { + return this.app.layout.closeDialog('jamblaster-name-dialog'); + } + }` - if !result - context.JK.Banner.showAlert('unable to set a static port', - 'Please email support@jamkazam.com and let us know the port number you are specifying unsuccessfully, or refresh the page and try again.') - else - @app.layout.closeDialog('jamblaster-port-dialog') render: () -> `
diff --git a/web/app/assets/javascripts/react-components/JamBlasterScreen.js.jsx.coffee b/web/app/assets/javascripts/react-components/JamBlasterScreen.js.jsx.coffee index 78402982f..3e857b8e5 100644 --- a/web/app/assets/javascripts/react-components/JamBlasterScreen.js.jsx.coffee +++ b/web/app/assets/javascripts/react-components/JamBlasterScreen.js.jsx.coffee @@ -3,9 +3,6 @@ rest = context.JK.Rest() logger = context.JK.logger JamBlasterActions = @JamBlasterActions -_disconnect = `async function(client,e){logger.debug('disconnecting from currently paired client' +client.connect_url);await context.jamClient.endPairing();setTimeout((()=>JamBlasterActions.resyncBonjour()),1000);}` - - @JamBlasterScreen = React.createClass({ mixins: [ @@ -42,8 +39,6 @@ _disconnect = `async function(client,e){logger.debug('disconnecting from current @root = $(@getDOMNode()) @iCheckify() - - componentDidUpdate: () -> @iCheckify() @@ -94,65 +89,132 @@ _disconnect = `async function(client,e){logger.debug('disconnecting from current #context.JK.popExternalLinks(@root) - jamblasterOptionSelected: (e, data) -> - jamblaster = data.options - jamblaster = @findJamBlaster(jamblaster) + # jamblasterOptionSelected: (e, data) -> + # jamblaster = data.options + # jamblaster = @findJamBlaster(jamblaster) - if data.option == 'auto-connect' - JamBlasterActions.setAutoPair(!jamblaster.autoconnect) - else if data.option == 'restart' - context.JK.Banner.showYesNo({ - title: "reboot JamBlaster", - html: "Are you sure?" - yes: => - result = context.jamClient.rebootJamBlaster() - if result - setTimeout((() => context.JK.Banner.showNotice("JamBlaster is rebooting", - "It should be back online within a minute.")), 1) - setTimeout((() => JamBlasterActions.resyncBonjour()), 1000) + # if data.option == 'auto-connect' + # JamBlasterActions.setAutoPair(!jamblaster.autoconnect) + # else if data.option == 'restart' + # context.JK.Banner.showYesNo({ + # title: "reboot JamBlaster", + # html: "Are you sure?" + # yes: => + # result = context.jamClient.rebootJamBlaster() + # if result + # setTimeout((() => context.JK.Banner.showNotice("JamBlaster is rebooting", + # "It should be back online within a minute.")), 1) + # setTimeout((() => JamBlasterActions.resyncBonjour()), 1000) - else - setTimeout((() => context.JK.Banner.showAlert("could not reboot", - "The JamBlaster could not be rebooted remotely. Please cycle the power manually.")), 1) + # else + # setTimeout((() => context.JK.Banner.showAlert("could not reboot", + # "The JamBlaster could not be rebooted remotely. Please cycle the power manually.")), 1) - }) + # }) - else if data.option == 'name' - @app.layout.showDialog('jamblaster-name-dialog', {d1: jamblaster.name}).one(context.JK.EVENTS.DIALOG_CLOSED, - (e, data) => - setTimeout((() => JamBlasterActions.resyncBonjour()), 1000) - ) + # else if data.option == 'name' + # @app.layout.showDialog('jamblaster-name-dialog', {d1: jamblaster.name}).one(context.JK.EVENTS.DIALOG_CLOSED, + # (e, data) => + # setTimeout((() => JamBlasterActions.resyncBonjour()), 1000) + # ) - else if data.option == 'check-for-updates' - context.JK.Banner.showNotice('Check for Update', - 'The JamBlaster only checks for updates when booting up. Please reboot the JamBlaster to initiate an update check.') - else if data.option == 'set-static-ports' - if jamblaster.isDynamicPorts - context.JK.Banner.showYesNo({ - title: "revert to dynamic ports", - html: "Your JamBlaster is currently configured to use ports #{jamblaster.portState.static_port} - #{jamblaster.portState.static_port + 10}). Would you like to revert to the use of dynamic ports for UDP communication?" - yes: => - context.jamClient.setJbPortBindState({use_static_port: false, static_port: 12000}) - JamBlasterActions.clearPortBindState() - #setTimeout((() => JamBlasterActions.resyncBonjour()), 1000) - JamBlasterActions.resyncBonjour() - setTimeout((() => context.JK.Banner.showNotice("reboot JamBlaster", - "For these settings to take effect, you must restart the JamBlaster.")), 1) + # else if data.option == 'check-for-updates' + # context.JK.Banner.showNotice('Check for Update', + # 'The JamBlaster only checks for updates when booting up. Please reboot the JamBlaster to initiate an update check.') + # else if data.option == 'set-static-ports' + # if jamblaster.isDynamicPorts + # context.JK.Banner.showYesNo({ + # title: "revert to dynamic ports", + # html: "Your JamBlaster is currently configured to use ports #{jamblaster.portState.static_port} - #{jamblaster.portState.static_port + 10}). Would you like to revert to the use of dynamic ports for UDP communication?" + # yes: => + # context.jamClient.setJbPortBindState({use_static_port: false, static_port: 12000}) + # JamBlasterActions.clearPortBindState() + # #setTimeout((() => JamBlasterActions.resyncBonjour()), 1000) + # JamBlasterActions.resyncBonjour() + # setTimeout((() => context.JK.Banner.showNotice("reboot JamBlaster", + # "For these settings to take effect, you must restart the JamBlaster.")), 1) - }) + # }) + + # else + # @app.layout.showDialog('jamblaster-port-dialog').one(context.JK.EVENTS.DIALOG_CLOSED, (e, data) => + # JamBlasterActions.clearPortBindState() + # JamBlasterActions.resyncBonjour() + # context.JK.Banner.showNotice("reboot JamBlaster", + # "For these settings to take effect, you must restart the JamBlaster.") + # ) + # else if data.option == 'factory-reset' + # context.JK.Banner.showNotice('Factory Reset', + # 'The JamBlaster only checks for updates when it boots up, and if there is an update available, it will automatically begin updating.

Please reboot the JamBlaster to initiate an update check.') + # else + # logger.debug("unknown action") + + jamblasterOptionSelected: `function(e, data) { + let jamblaster = data.options; + jamblaster = this.findJamBlaster(jamblaster); + + if (data.option === 'auto-connect') { + return JamBlasterActions.setAutoPair(!jamblaster.autoconnect); + } else if (data.option === 'restart') { + return context.JK.Banner.showYesNo({ + title: "reboot JamBlaster", + html: "Are you sure?", + yes: async () => { + const result = await context.jamClient.rebootJamBlaster(); + if (result) { + setTimeout((() => context.JK.Banner.showNotice("JamBlaster is rebooting", + "It should be back online within a minute.")), 1); + return setTimeout((() => JamBlasterActions.resyncBonjour()), 1000); + + } else { + return setTimeout((() => context.JK.Banner.showAlert("could not reboot", + "The JamBlaster could not be rebooted remotely. Please cycle the power manually.")), 1); + } + } + + }); + + } else if (data.option === 'name') { + return this.app.layout.showDialog('jamblaster-name-dialog', {d1: jamblaster.name}).one(context.JK.EVENTS.DIALOG_CLOSED, + (e, data) => { + return setTimeout((() => JamBlasterActions.resyncBonjour()), 1000); + }); + + } else if (data.option === 'check-for-updates') { + return context.JK.Banner.showNotice('Check for Update', + 'The JamBlaster only checks for updates when booting up. Please reboot the JamBlaster to initiate an update check.'); + } else if (data.option === 'set-static-ports') { + if (jamblaster.isDynamicPorts) { + return context.JK.Banner.showYesNo({ + title: "revert to dynamic ports", + html: 'Your JamBlaster is currently configured to use ports '+jamblaster.portState.static_port+' - '+(jamblaster.portState.static_port + 10)+'. Would you like to revert to the use of dynamic ports for UDP communication?', + yes: async () => { + await context.jamClient.setJbPortBindState({use_static_port: false, static_port: 12000}); + JamBlasterActions.clearPortBindState(); + //setTimeout((() => JamBlasterActions.resyncBonjour()), 1000) + JamBlasterActions.resyncBonjour(); + return setTimeout((() => context.JK.Banner.showNotice("reboot JamBlaster", + "For these settings to take effect, you must restart the JamBlaster.")), 1); + } + + }); + + } else { + return this.app.layout.showDialog('jamblaster-port-dialog').one(context.JK.EVENTS.DIALOG_CLOSED, (e, data) => { + JamBlasterActions.clearPortBindState(); + JamBlasterActions.resyncBonjour(); + return context.JK.Banner.showNotice("reboot JamBlaster", + "For these settings to take effect, you must restart the JamBlaster."); + }); + } + } else if (data.option === 'factory-reset') { + return context.JK.Banner.showNotice('Factory Reset', + 'The JamBlaster only checks for updates when it boots up, and if there is an update available, it will automatically begin updating.

Please reboot the JamBlaster to initiate an update check.'); + } else { + return logger.debug("unknown action"); + } + }` - else - @app.layout.showDialog('jamblaster-port-dialog').one(context.JK.EVENTS.DIALOG_CLOSED, (e, data) => - JamBlasterActions.clearPortBindState() - JamBlasterActions.resyncBonjour() - context.JK.Banner.showNotice("reboot JamBlaster", - "For these settings to take effect, you must restart the JamBlaster.") - ) - else if data.option == 'factory-reset' - context.JK.Banner.showNotice('Factory Reset', - 'The JamBlaster only checks for updates when it boots up, and if there is an update available, it will automatically begin updating.

Please reboot the JamBlaster to initiate an update check.') - else - logger.debug("unknown action") getInitialState: () -> { selected: 'management', @@ -204,7 +266,11 @@ _disconnect = `async function(client,e){logger.debug('disconnecting from current # context.jamClient.endPairing() # setTimeout((() => JamBlasterActions.resyncBonjour()), 1000) - disconnect: _disconnect + disconnect: `async function(client,e){ + logger.debug('disconnecting from currently paired client' +client.connect_url); + await context.jamClient.endPairing(); + setTimeout((()=>JamBlasterActions.resyncBonjour()),1000); + }` mergeClients: () -> clientsJsx = [] diff --git a/web/app/assets/javascripts/react-components/JamTrackLandingScreen.js.jsx.coffee b/web/app/assets/javascripts/react-components/JamTrackLandingScreen.js.jsx.coffee index 5250832f0..d25bd4909 100644 --- a/web/app/assets/javascripts/react-components/JamTrackLandingScreen.js.jsx.coffee +++ b/web/app/assets/javascripts/react-components/JamTrackLandingScreen.js.jsx.coffee @@ -231,69 +231,136 @@ rest = context.JK.Rest() e.preventDefault() context.JK.popExternalLink($(e.target).attr('href')) - onPlayJamTrack: (jamTrack, e) -> + # onPlayJamTrack: (jamTrack, e) -> - if context.jamClient.IsNativeClient() - e.preventDefault() - tracks = context.JK.TrackHelpers.getUserTracks(context.jamClient) - data = {} - data.client_id = @app.clientId - #data.description = $('#description').val() - data.description = "Jam Track Session" - data.as_musician = true - data.legal_terms = true - data.intellectual_property = true - data.approval_required = false - data.musician_access = false - data.fan_access = false - data.fan_chat = false - console.log("jamTrack", jamTrack) - data.genre = $.map(jamTrack.genres, (genre) -> genre.id) - data.genres = $.map(jamTrack.genres, (genre)-> genre.id) + # if context.jamClient.IsNativeClient() + # e.preventDefault() + # tracks = context.JK.TrackHelpers.getUserTracks(context.jamClient) + # data = {} + # data.client_id = @app.clientId + # #data.description = $('#description').val() + # data.description = "Jam Track Session" + # data.as_musician = true + # data.legal_terms = true + # data.intellectual_property = true + # data.approval_required = false + # data.musician_access = false + # data.fan_access = false + # data.fan_chat = false + # console.log("jamTrack", jamTrack) + # data.genre = $.map(jamTrack.genres, (genre) -> genre.id) + # data.genres = $.map(jamTrack.genres, (genre)-> genre.id) - data.genre = ['rock'] if data.genre.length == 0 - data.genres = ['rock'] if data.genres.length == 0 - # data.genres = context.JK.GenreSelectorHelper.getSelectedGenres('#create-session-genre') - # data.musician_access = if $('#musician-access option:selected').val() == 'true' then true else false - # data.approval_required = if $('input[name=\'musician-access-option\']:checked').val() == 'true' then true else false - # data.fan_access = if $('#fan-access option:selected').val() == 'true' then true else false - # data.fan_chat = if $('input[name=\'fan-chat-option\']:checked').val() == 'true' then true else false - # if $('#band-list option:selected').val() != '' - # data.band = $('#band-list option:selected').val() - data.audio_latency = context.jamClient.FTUEGetExpectedLatency().latency - data.tracks = tracks + # data.genre = ['rock'] if data.genre.length == 0 + # data.genres = ['rock'] if data.genres.length == 0 + # # data.genres = context.JK.GenreSelectorHelper.getSelectedGenres('#create-session-genre') + # # data.musician_access = if $('#musician-access option:selected').val() == 'true' then true else false + # # data.approval_required = if $('input[name=\'musician-access-option\']:checked').val() == 'true' then true else false + # # data.fan_access = if $('#fan-access option:selected').val() == 'true' then true else false + # # data.fan_chat = if $('input[name=\'fan-chat-option\']:checked').val() == 'true' then true else false + # # if $('#band-list option:selected').val() != '' + # # data.band = $('#band-list option:selected').val() + # data.audio_latency = context.jamClient.FTUEGetExpectedLatency().latency + # data.tracks = tracks - rest.legacyCreateSession(data).done((response) => - newSessionId = response.id - context.JK.SessionUtils.setAutoOpenJamTrack(jamTrack) # so that the session screen will pick this up - context.SessionActions.enterSession(newSessionId) - # Re-loading the session settings will cause the form to reset with the right stuff in it. - # This is an extra xhr call, but it keeps things to a single codepath - #loadSessionSettings() - context.JK.GA.trackSessionCount data.musician_access, data.fan_access, 0 - context.JK.GA.trackSessionMusicians context.JK.GA.SessionCreationTypes.create - ).fail (jqXHR) => - handled = false - if jqXHR.status = 422 - response = JSON.parse(jqXHR.responseText) - if response['errors'] and response['errors']['tracks'] and response['errors']['tracks'][0] == 'Please select at least one track' - @app.notifyAlert 'No Inputs Configured', $('You will need to reconfigure your audio device.') - handled = true - if !handled - @app.notifyServerError jqXHR, 'Unable to Create Session' + # rest.legacyCreateSession(data).done((response) => + # newSessionId = response.id + # context.JK.SessionUtils.setAutoOpenJamTrack(jamTrack) # so that the session screen will pick this up + # context.SessionActions.enterSession(newSessionId) + # # Re-loading the session settings will cause the form to reset with the right stuff in it. + # # This is an extra xhr call, but it keeps things to a single codepath + # #loadSessionSettings() + # context.JK.GA.trackSessionCount data.musician_access, data.fan_access, 0 + # context.JK.GA.trackSessionMusicians context.JK.GA.SessionCreationTypes.create + # ).fail (jqXHR) => + # handled = false + # if jqXHR.status = 422 + # response = JSON.parse(jqXHR.responseText) + # if response['errors'] and response['errors']['tracks'] and response['errors']['tracks'][0] == 'Please select at least one track' + # @app.notifyAlert 'No Inputs Configured', $('You will need to reconfigure your audio device.') + # handled = true + # if !handled + # @app.notifyServerError jqXHR, 'Unable to Create Session' - else - if true # /iPhone|iPad|iPod|android/i.test(navigator.userAgent) - # popup window - JamTrackPlayerActions.opened(jamTrack) + # else + # if true # /iPhone|iPad|iPod|android/i.test(navigator.userAgent) + # # popup window + # JamTrackPlayerActions.opened(jamTrack) - else - # popup window - JamTrackPlayerActions.open(jamTrack) - e.preventDefault() + # else + # # popup window + # JamTrackPlayerActions.open(jamTrack) + # e.preventDefault() + onPlayJamTrack: `async function(jamTrack, e) { + if (await context.jamClient.IsNativeClient()) { + e.preventDefault(); + const tracks = context.JK.TrackHelpers.getUserTracks(context.jamClient); + const data = {}; + data.client_id = this.app.clientId; + //data.description = $('#description').val() + data.description = "Jam Track Session"; + data.as_musician = true; + data.legal_terms = true; + data.intellectual_property = true; + data.approval_required = false; + data.musician_access = false; + data.fan_access = false; + data.fan_chat = false; + console.log("jamTrack", jamTrack); + data.genre = $.map(jamTrack.genres, genre => genre.id); + data.genres = $.map(jamTrack.genres, genre => genre.id); + + if (data.genre.length === 0) { data.genre = ['rock']; } + if (data.genres.length === 0) { data.genres = ['rock']; } + // data.genres = context.JK.GenreSelectorHelper.getSelectedGenres('#create-session-genre') + // data.musician_access = if $('#musician-access option:selected').val() == 'true' then true else false + // data.approval_required = if $('input[name=\'musician-access-option\']:checked').val() == 'true' then true else false + // data.fan_access = if $('#fan-access option:selected').val() == 'true' then true else false + // data.fan_chat = if $('input[name=\'fan-chat-option\']:checked').val() == 'true' then true else false + // if $('#band-list option:selected').val() != '' + // data.band = $('#band-list option:selected').val() + let expectedLatency = await context.jamClient.FTUEGetExpectedLatency() + data.audio_latency = expectedLatency.latency; + data.tracks = tracks; + + rest.legacyCreateSession(data).done(response => { + const newSessionId = response.id; + context.JK.SessionUtils.setAutoOpenJamTrack(jamTrack); // so that the session screen will pick this up + context.SessionActions.enterSession(newSessionId); + // Re-loading the session settings will cause the form to reset with the right stuff in it. + // This is an extra xhr call, but it keeps things to a single codepath + //loadSessionSettings() + context.JK.GA.trackSessionCount(data.musician_access, data.fan_access, 0); + context.JK.GA.trackSessionMusicians(context.JK.GA.SessionCreationTypes.create); + }).fail(jqXHR => { + let handled = false; + if (jqXHR.status = 422) { + const response = JSON.parse(jqXHR.responseText); + if (response['errors'] && response['errors']['tracks'] && (response['errors']['tracks'][0] === 'Please select at least one track')) { + this.app.notifyAlert('No Inputs Configured', $('You will need to reconfigure your audio device.')); + handled = true; + } + } + if (!handled) { + this.app.notifyServerError(jqXHR, 'Unable to Create Session'); + } + }); + + } else { + if (true) { // /iPhone|iPad|iPod|android/i.test(navigator.userAgent) + // popup window + JamTrackPlayerActions.opened(jamTrack); + + } else { + // popup window + JamTrackPlayerActions.open(jamTrack); + e.preventDefault(); + } + } + }` onAppInit: (@app) -> @rest = context.JK.Rest() diff --git a/web/app/assets/javascripts/react-components/PopupRecordingStartStop.js.jsx.coffee b/web/app/assets/javascripts/react-components/PopupRecordingStartStop.js.jsx.coffee index b27d5f14d..74d73a3db 100644 --- a/web/app/assets/javascripts/react-components/PopupRecordingStartStop.js.jsx.coffee +++ b/web/app/assets/javascripts/react-components/PopupRecordingStartStop.js.jsx.coffee @@ -230,41 +230,81 @@ if accessOpener @audioType = $checkedType.val() logger.debug("updated @audioType", @inputType) - componentDidMount: () -> - $(window).unload(@windowUnloaded) + # componentDidMount: () -> + # $(window).unload(@windowUnloaded) - $root = jQuery(this.getDOMNode()) + # $root = jQuery(this.getDOMNode()) - $recordingType = $root.find('input[type="radio"]') - context.JK.checkbox($recordingType) + # $recordingType = $root.find('input[type="radio"]') + # context.JK.checkbox($recordingType) - @inputType = 'audio-only' - @audioType = 'audio-only' + # @inputType = 'audio-only' + # @audioType = 'audio-only' - $root.find('input[name="recording-input-type"]').on('ifChanged', @trackInputType) - $root.find('input[name="recording-input-chat-option"]').on('ifChanged', @trackAudioType) + # $root.find('input[name="recording-input-type"]').on('ifChanged', @trackInputType) + # $root.find('input[name="recording-input-chat-option"]').on('ifChanged', @trackAudioType) - $recordingRegion = $root.find('#recording-selection') - #console.log("$recordingou", $recordingRegion) - #context.JK.dropdown($recordingRegion) + # $recordingRegion = $root.find('#recording-selection') + # #console.log("$recordingou", $recordingRegion) + # #context.JK.dropdown($recordingRegion) - $includeChat = $root.find('#include-chat') - context.JK.checkbox($includeChat) + # $includeChat = $root.find('#include-chat') + # context.JK.checkbox($includeChat) - openWindows = window.opener.jamClient.getOpenVideoSources() + # openWindows = window.opener.jamClient.getOpenVideoSources() - console.log("open video sources", openWindows) + # console.log("open video sources", openWindows) - fixedwindows = [] - if openWindows? - for key, value of openWindows - fixedwindows.push(value) + # fixedwindows = [] + # if openWindows? + # for key, value of openWindows + # fixedwindows.push(value) - this.setState({openWindows: fixedwindows}) - @resizeWindow() + # this.setState({openWindows: fixedwindows}) + # @resizeWindow() - # this is necessary due to whatever the client's rendering behavior is. - setTimeout(@resizeWindow, 300) + # # this is necessary due to whatever the client's rendering behavior is. + # setTimeout(@resizeWindow, 300) + + componentDidMount: `async function() { + $(window).unload(this.windowUnloaded); + + const $root = jQuery(this.getDOMNode()); + + const $recordingType = $root.find('input[type="radio"]'); + context.JK.checkbox($recordingType); + + this.inputType = 'audio-only'; + this.audioType = 'audio-only'; + + $root.find('input[name="recording-input-type"]').on('ifChanged', this.trackInputType); + $root.find('input[name="recording-input-chat-option"]').on('ifChanged', this.trackAudioType); + + const $recordingRegion = $root.find('#recording-selection'); + //console.log("$recordingou", $recordingRegion) + //context.JK.dropdown($recordingRegion) + + const $includeChat = $root.find('#include-chat'); + context.JK.checkbox($includeChat); + + const openWindows = await window.opener.jamClient.getOpenVideoSources(); + + console.log("open video sources", openWindows); + + const fixedwindows = []; + if (openWindows != null) { + for (let key in openWindows) { + const value = openWindows[key]; + fixedwindows.push(value); + } + } + + this.setState({openWindows: fixedwindows}); + this.resizeWindow(); + + //this is necessary due to whatever the client rendering behavior is. + return setTimeout(this.resizeWindow, 300); + }` componentDidUpdate: () -> @resizeWindow() diff --git a/web/app/assets/javascripts/react-components/SessionMediaTracks.js.jsx.coffee b/web/app/assets/javascripts/react-components/SessionMediaTracks.js.jsx.coffee index a1a35e9ce..cfda3029e 100644 --- a/web/app/assets/javascripts/react-components/SessionMediaTracks.js.jsx.coffee +++ b/web/app/assets/javascripts/react-components/SessionMediaTracks.js.jsx.coffee @@ -71,24 +71,46 @@ ChannelGroupIds = context.JK.ChannelGroupIds @app.layout.showDialog('localRecordings') unless @app.layout.isDialogShowing('localRecordings') - openBackingTrack: (e) -> - e.preventDefault() - if @state.backingTrackDialogOpen - logger.debug("backing track dialog already open") - return + # openBackingTrack: (e) -> + # e.preventDefault() + # if @state.backingTrackDialogOpen + # logger.debug("backing track dialog already open") + # return - # just ignore the click if they are currently recording for now - if @state.isRecording - @app.notify({ - "title": "Currently Recording", - "text": "You can't open a backing track while creating a recording.", - "icon_url": "/assets/content/icon_alert_big.png" - }); - return + # # just ignore the click if they are currently recording for now + # if @state.isRecording + # @app.notify({ + # "title": "Currently Recording", + # "text": "You can't open a backing track while creating a recording.", + # "icon_url": "/assets/content/icon_alert_big.png" + # }); + # return - @setState({backingTrackDialogOpen: true}) - context.jamClient.ShowSelectBackingTrackDialog("window.JK.HandleBackingTrackSelectedCallback2"); + # @setState({backingTrackDialogOpen: true}) + # context.jamClient.ShowSelectBackingTrackDialog("window.JK.HandleBackingTrackSelectedCallback2"); + + openBackingTrack: `async function(e) { + e.preventDefault(); + if (this.state.backingTrackDialogOpen) { + logger.debug("backing track dialog already open"); + return; + } + + + // just ignore the click if they are currently recording for now + if (this.state.isRecording) { + this.app.notify({ + "title": "Currently Recording", + "text": "You can't open a backing track while creating a recording.", + "icon_url": "/assets/content/icon_alert_big.png" + }); + return; + } + + this.setState({backingTrackDialogOpen: true}); + await context.jamClient.ShowSelectBackingTrackDialog("window.JK.HandleBackingTrackSelectedCallback2"); + }` openMetronome: (e) -> @@ -121,71 +143,142 @@ ChannelGroupIds = context.JK.ChannelGroupIds logger.debug("OpenJamTrack dialog closed with no selection; ignoring", data) ) - loadJamTrack: (jamTrack) -> - if @state.downloadJamTrack - # if there was one showing before somehow, destroy it. - logger.warn("destroying existing JamTrack") - @state.downloadJamTrack.root.remove() - @state.downloadJamTrack.destroy() - #set to null + # loadJamTrack: (jamTrack) -> + # if @state.downloadJamTrack + # # if there was one showing before somehow, destroy it. + # logger.warn("destroying existing JamTrack") + # @state.downloadJamTrack.root.remove() + # @state.downloadJamTrack.destroy() + # #set to null - downloadJamTrack = new context.JK.DownloadJamTrack(@app, jamTrack, 'large'); + # downloadJamTrack = new context.JK.DownloadJamTrack(@app, jamTrack, 'large'); - # the widget indicates when it gets to any transition; we can hide it once it reaches completion - $(downloadJamTrack).on(EVENTS.JAMTRACK_DOWNLOADER_STATE_CHANGED, (e, data) => - if data.state == downloadJamTrack.states.synchronized - logger.debug("jamtrack synchronized; hide widget and show tracks") - downloadJamTrack.root.remove() - downloadJamTrack.destroy() - downloadJamTrack = null + # # the widget indicates when it gets to any transition; we can hide it once it reaches completion + # $(downloadJamTrack).on(EVENTS.JAMTRACK_DOWNLOADER_STATE_CHANGED, (e, data) => + # if data.state == downloadJamTrack.states.synchronized + # logger.debug("jamtrack synchronized; hide widget and show tracks") + # downloadJamTrack.root.remove() + # downloadJamTrack.destroy() + # downloadJamTrack = null - this.setState({downloadJamTrack: null}) + # this.setState({downloadJamTrack: null}) - # XXX: test with this removed; it should be unnecessary - context.jamClient.JamTrackStopPlay(); + # # XXX: test with this removed; it should be unnecessary + # context.jamClient.JamTrackStopPlay(); - sampleRate = context.jamClient.GetSampleRate() - sampleRateForFilename = if sampleRate == 48 then '48' else '44' - fqId = jamTrack.id + '-' + sampleRateForFilename + # sampleRate = context.jamClient.GetSampleRate() + # sampleRateForFilename = if sampleRate == 48 then '48' else '44' + # fqId = jamTrack.id + '-' + sampleRateForFilename - if jamTrack.jmep - logger.debug("setting jmep data") + # if jamTrack.jmep + # logger.debug("setting jmep data") - context.jamClient.JamTrackLoadJmep(fqId, jamTrack.jmep) - else - logger.debug("no jmep data for jamtrack") + # context.jamClient.JamTrackLoadJmep(fqId, jamTrack.jmep) + # else + # logger.debug("no jmep data for jamtrack") - # JamTrackPlay means 'load' - result = context.jamClient.JamTrackPlay(fqId); + # # JamTrackPlay means 'load' + # result = context.jamClient.JamTrackPlay(fqId); - SessionActions.downloadingJamTrack(false) + # SessionActions.downloadingJamTrack(false) - console.log("JamTrackPlay: result", result) - if !result - @app.notify( - { - title: "JamTrack Can Not Open", - text: "Unable to open your JamTrack. Please contact support@jamkazam.com" - } - , null, true) - else - participantCnt = context.SessionStore.participants().length - rest.playJamTrack(jamTrack.id) - .done(() => - @app.refreshUser(); - ) + # console.log("JamTrackPlay: result", result) + # if !result + # @app.notify( + # { + # title: "JamTrack Can Not Open", + # text: "Unable to open your JamTrack. Please contact support@jamkazam.com" + # } + # , null, true) + # else + # participantCnt = context.SessionStore.participants().length + # rest.playJamTrack(jamTrack.id) + # .done(() => + # @app.refreshUser(); + # ) - context.stats.write('web.jamtrack.open', { - value: 1, - session_size: participantCnt, - user_id: context.JK.currentUserId, - user_name: context.JK.currentUserName - }) - ) + # context.stats.write('web.jamtrack.open', { + # value: 1, + # session_size: participantCnt, + # user_id: context.JK.currentUserId, + # user_name: context.JK.currentUserName + # }) + # ) - @setState({downloadJamTrack: downloadJamTrack}) + # @setState({downloadJamTrack: downloadJamTrack}) + + loadJamTrack: `async function(jamTrack) { + if (this.state.downloadJamTrack) { + // if there was one showing before somehow, destroy it. + logger.warn("destroying existing JamTrack"); + this.state.downloadJamTrack.root.remove(); + this.state.downloadJamTrack.destroy(); + } + //set to null + + + let downloadJamTrack = new context.JK.DownloadJamTrack(this.app, jamTrack, 'large'); + + // the widget indicates when it gets to any transition; we can hide it once it reaches completion + $(downloadJamTrack).on(EVENTS.JAMTRACK_DOWNLOADER_STATE_CHANGED, async (e, data) => { + if (data.state === downloadJamTrack.states.synchronized) { + logger.debug("jamtrack synchronized; hide widget and show tracks"); + downloadJamTrack.root.remove(); + downloadJamTrack.destroy(); + downloadJamTrack = null; + + this.setState({downloadJamTrack: null}); + + //XXX: test with this removed; it should be unnecessary + await context.jamClient.JamTrackStopPlay(); + + const sampleRate = await context.jamClient.GetSampleRate(); + const sampleRateForFilename = sampleRate === 48 ? '48' : '44'; + const fqId = jamTrack.id + '-' + sampleRateForFilename; + + if (jamTrack.jmep) { + logger.debug("setting jmep data"); + + await context.jamClient.JamTrackLoadJmep(fqId, jamTrack.jmep); + } else { + logger.debug("no jmep data for jamtrack"); + } + + // JamTrackPlay means 'load' + const result = await context.jamClient.JamTrackPlay(fqId); + + SessionActions.downloadingJamTrack(false); + + console.log("JamTrackPlay: result", result); + if (!result) { + return this.app.notify( + { + title: "JamTrack Can Not Open", + text: "Unable to open your JamTrack. Please contact support@jamkazam.com" + } + , null, true); + } else { + const participantCnt = context.SessionStore.participants().length; + rest.playJamTrack(jamTrack.id) + .done(() => { + return this.app.refreshUser(); + }); + + return context.stats.write('web.jamtrack.open', { + value: 1, + session_size: participantCnt, + user_id: context.JK.currentUserId, + user_name: context.JK.currentUserName + }); + } + } + }); + + + return this.setState({downloadJamTrack}); + }` render: () -> diff --git a/web/app/assets/javascripts/react-components/SessionMyTrack.js.jsx.coffee b/web/app/assets/javascripts/react-components/SessionMyTrack.js.jsx.coffee index 4e9e480fb..19e888e3e 100644 --- a/web/app/assets/javascripts/react-components/SessionMyTrack.js.jsx.coffee +++ b/web/app/assets/javascripts/react-components/SessionMyTrack.js.jsx.coffee @@ -91,53 +91,107 @@ ConfigureTracksActions = @ConfigureTracksActions
` - componentDidMount: () -> + # componentDidMount: () -> - context.jamClient.SessionSetUserName(this.props.clientId, this.props.name) + # context.jamClient.SessionSetUserName(this.props.clientId, this.props.name) - $root = $(this.getDOMNode()) - $mute = $root.find('.track-icon-mute') - $pan = $root.find('.track-icon-pan') - $connectionState = $root.find('.track-connection-state') + # $root = $(this.getDOMNode()) + # $mute = $root.find('.track-icon-mute') + # $pan = $root.find('.track-icon-pan') + # $connectionState = $root.find('.track-connection-state') - context.JK.interactReactBubble( - $mute, - 'SessionTrackVolumeHover', - () => - {mixers:this.props.mixers, trackType: 'SessionMyTrack', mode: @props.mode} + # context.JK.interactReactBubble( + # $mute, + # 'SessionTrackVolumeHover', + # () => + # {mixers:this.props.mixers, trackType: 'SessionMyTrack', mode: @props.mode} + # , + # {width:235, positions:['right', 'left'], offsetParent:$root.closest('.top-parent')}) + + # context.JK.interactReactBubble( + # $pan, + # 'SessionTrackPanHover', + # () => + # {mixers:this.props.mixers} + # , + # {width:331, positions:['right', 'left'], offsetParent:$root.closest('.top-parent')}) + + # context.JK.interactReactBubble( + # $connectionState, + # 'SessionStatsHover', + # () => + # {myTrack: true, participant: {client_id: this.props.connStatsClientId, user: name: 'You', possessive: 'Your'}, } + # , + # {width:385, positions:['right', 'left'], offsetParent:$root.closest('.screen'), extraClasses: 'self'}) + + # unless this.props.hasMixer + # $mute.on("mouseenter", false) + # $mute.on("mouseleave", false) + # $pan.on("mouseentere", false) + # $pan.on("mouseleave", false) + # unless this.props.hasMixer + # $mute.on("mouseenter", false) + # $mute.on("mouseleave", false) + # $pan.on("mouseentere", false) + # $pan.on("mouseleave", false) + + # context.JK.helpBubble($root.find('.disabled-track-overlay'), 'missing-my-tracks', {}, {positions:['top'], offsetParent: $root.closest('.top-parent')}) + + # @initializeVstEffects() + + componentDidMount: `async function() { + + await context.jamClient.SessionSetUserName(this.props.clientId, this.props.name); + + const $root = $(this.getDOMNode()); + const $mute = $root.find('.track-icon-mute'); + const $pan = $root.find('.track-icon-pan'); + const $connectionState = $root.find('.track-connection-state'); + + context.JK.interactReactBubble( + $mute, + 'SessionTrackVolumeHover', + () => { + return {mixers:this.props.mixers, trackType: 'SessionMyTrack', mode: this.props.mode}; + } + , + {width:235, positions:['right', 'left'], offsetParent:$root.closest('.top-parent')}); + + context.JK.interactReactBubble( + $pan, + 'SessionTrackPanHover', + () => { + return {mixers:this.props.mixers}; + } + , + {width:331, positions:['right', 'left'], offsetParent:$root.closest('.top-parent')}); + + context.JK.interactReactBubble( + $connectionState, + 'SessionStatsHover', + () => { + return {myTrack: true, participant: {client_id: this.props.connStatsClientId, user: {name: 'You', possessive: 'Your'}}, }; + } , - {width:235, positions:['right', 'left'], offsetParent:$root.closest('.top-parent')}) + {width:385, positions:['right', 'left'], offsetParent:$root.closest('.screen'), extraClasses: 'self'}); - context.JK.interactReactBubble( - $pan, - 'SessionTrackPanHover', - () => - {mixers:this.props.mixers} - , - {width:331, positions:['right', 'left'], offsetParent:$root.closest('.top-parent')}) + if (!this.props.hasMixer) { + $mute.on("mouseenter", false); + $mute.on("mouseleave", false); + $pan.on("mouseentere", false); + $pan.on("mouseleave", false); + } + if (!this.props.hasMixer) { + $mute.on("mouseenter", false); + $mute.on("mouseleave", false); + $pan.on("mouseentere", false); + $pan.on("mouseleave", false); + } - context.JK.interactReactBubble( - $connectionState, - 'SessionStatsHover', - () => - {myTrack: true, participant: {client_id: this.props.connStatsClientId, user: name: 'You', possessive: 'Your'}, } - , - {width:385, positions:['right', 'left'], offsetParent:$root.closest('.screen'), extraClasses: 'self'}) + context.JK.helpBubble($root.find('.disabled-track-overlay'), 'missing-my-tracks', {}, {positions:['top'], offsetParent: $root.closest('.top-parent')}); - unless this.props.hasMixer - $mute.on("mouseenter", false) - $mute.on("mouseleave", false) - $pan.on("mouseentere", false) - $pan.on("mouseleave", false) - unless this.props.hasMixer - $mute.on("mouseenter", false) - $mute.on("mouseleave", false) - $pan.on("mouseentere", false) - $pan.on("mouseleave", false) - - context.JK.helpBubble($root.find('.disabled-track-overlay'), 'missing-my-tracks', {}, {positions:['top'], offsetParent: $root.closest('.top-parent')}) - - @initializeVstEffects() + return this.initializeVstEffects(); + }` componentWillUpdate: (nextProps, nextState) -> $root = $(this.getDOMNode()) diff --git a/web/app/assets/javascripts/react-components/helpers/MixerHelper.js.coffee b/web/app/assets/javascripts/react-components/helpers/MixerHelper.js.coffee index ae4a65a7f..24ebea26c 100644 --- a/web/app/assets/javascripts/react-components/helpers/MixerHelper.js.coffee +++ b/web/app/assets/javascripts/react-components/helpers/MixerHelper.js.coffee @@ -810,45 +810,92 @@ MIX_MODES = context.JK.MIX_MODES; mixer = @getMixer(mixer.id, mixer.mode) mixer.loop = context.trackVolumeObject.loop - 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 - // has been set in currentMixerRangeMin-Max. - // All that needs doing is to translate the incoming percent - // into the real value ont the sliders range. Set Left/Right - // volumes on trackVolumeObject, and call SetControlState to stick. - ### + # 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 + # // has been set in currentMixerRangeMin-Max. + # // All that needs doing is to translate the incoming percent + # // into the real value ont the sliders range. Set Left/Right + # // volumes on trackVolumeObject, and call SetControlState to stick. + # ### - newVolume = context.JK.FaderHelpers.convertPercentToAudioTaper(volumePercent); - if relative - context.trackVolumeObject.volL = context.trackVolumeObject.volL + (newVolume - originalVolume) - context.trackVolumeObject.volR = context.trackVolumeObject.volR + (newVolume - originalVolume) + # newVolume = context.JK.FaderHelpers.convertPercentToAudioTaper(volumePercent); + # if relative + # context.trackVolumeObject.volL = context.trackVolumeObject.volL + (newVolume - originalVolume) + # context.trackVolumeObject.volR = context.trackVolumeObject.volR + (newVolume - originalVolume) - # keep within range - if context.trackVolumeObject.volL < -80 - context.trackVolumeObject.volL = -80 - else if context.trackVolumeObject.volL > 20 - context.trackVolumeObject.volL = 20 + # # keep within range + # if context.trackVolumeObject.volL < -80 + # context.trackVolumeObject.volL = -80 + # else if context.trackVolumeObject.volL > 20 + # context.trackVolumeObject.volL = 20 - if context.trackVolumeObject.volR < -80 - context.trackVolumeObject.volR = -80 - else if context.trackVolumeObject.volR > 20 - context.trackVolumeObject.volR = 20 + # if context.trackVolumeObject.volR < -80 + # context.trackVolumeObject.volR = -80 + # else if context.trackVolumeObject.volR > 20 + # context.trackVolumeObject.volR = 20 - else - context.trackVolumeObject.volL = newVolume - context.trackVolumeObject.volR = newVolume - if controlGroup? + # else + # context.trackVolumeObject.volL = newVolume + # context.trackVolumeObject.volR = newVolume + # 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); + # 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); + + setMixerVolume: `async function(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 + // has been set in currentMixerRangeMin-Max. + // All that needs doing is to translate the incoming percent + // into the real value ont the sliders range. Set Left/Right + // volumes on trackVolumeObject, and call SetControlState to stick. + */ + + const newVolume = context.JK.FaderHelpers.convertPercentToAudioTaper(volumePercent); + if (relative) { + context.trackVolumeObject.volL = context.trackVolumeObject.volL + (newVolume - originalVolume); + context.trackVolumeObject.volR = context.trackVolumeObject.volR + (newVolume - originalVolume); + + // keep within range + if (context.trackVolumeObject.volL < -80) { + context.trackVolumeObject.volL = -80; + } else if (context.trackVolumeObject.volL > 20) { + context.trackVolumeObject.volL = 20; + } + + if (context.trackVolumeObject.volR < -80) { + context.trackVolumeObject.volR = -80; + } else if (context.trackVolumeObject.volR > 20) { + context.trackVolumeObject.volR = 20; + } + + + } else { + context.trackVolumeObject.volL = newVolume; + context.trackVolumeObject.volR = newVolume; + } + if (controlGroup != null) { + + let controlGroupsArg; + if (mixer.mode === MIX_MODES.PERSONAL) { + controlGroupsArg = 0; + } else { + controlGroupsArg = 1; + } + await context.jamClient.setSessionMixerCategoryPlayoutState(controlGroup === 'music', controlGroupsArg); + } else { + await context.jamClient.SessionSetControlState(mixer.id, mixer.mode); + } + }` percentFromMixerValue: (min, max, value) -> try diff --git a/web/app/assets/javascripts/react-components/stores/CallbackStore.js.coffee b/web/app/assets/javascripts/react-components/stores/CallbackStore.js.coffee index d407b27d3..3dfc628f1 100644 --- a/web/app/assets/javascripts/react-components/stores/CallbackStore.js.coffee +++ b/web/app/assets/javascripts/react-components/stores/CallbackStore.js.coffee @@ -15,11 +15,19 @@ VideoLiveStreamActions = @VideoLiveStreamActions # Register with the app store to get @app this.listenTo(context.AppStore, this.onAppInit) - onAppInit: (@app) -> - if context.jamClient.RegisterGenericCallBack? - console.log("REGISTERING GENERIC CALLBACK") - context.jamClient.RegisterGenericCallBack('CallbackStore.onGenericCallback') - #context.jamClient.RegisterGenericCallBack('StupidCallback') + # onAppInit: (@app) -> + # if context.jamClient.RegisterGenericCallBack? + # console.log("REGISTERING GENERIC CALLBACK") + # context.jamClient.RegisterGenericCallBack('CallbackStore.onGenericCallback') + # #context.jamClient.RegisterGenericCallBack('StupidCallback') + + onAppInit: `async function(app) { + this.app = app; + //if (context.jamClient.RegisterGenericCallBack != null) { + console.log("REGISTERING GENERIC CALLBACK"); + return await context.jamClient.RegisterGenericCallBack('CallbackStore.onGenericCallback'); + //} + }` onGenericCallback: (map) -> console.log("GENERIC CALLBACK CALLED: ", map) diff --git a/web/app/assets/javascripts/react-components/stores/ConfigureTracksStore.js.coffee b/web/app/assets/javascripts/react-components/stores/ConfigureTracksStore.js.coffee index ecf944d35..719f70436 100644 --- a/web/app/assets/javascripts/react-components/stores/ConfigureTracksStore.js.coffee +++ b/web/app/assets/javascripts/react-components/stores/ConfigureTracksStore.js.coffee @@ -25,8 +25,6 @@ void addSearchPath(int typeId, QString pathToAdd); void removeSearchPath(int typeId, QString pathToRemove); ### -_loadChannels = `async function(forceInputsToUnassign,inputChannelFilter){let assigned;this.musicPorts=await context.jamClient.FTUEGetChannels();this.trackAssignments={inputs:{unassigned:[],assigned:[],chat:[]},outputs:{unassigned:[],assigned:[]}};let nextTrackNumber=0;for(let input of Array.from(this.musicPorts.inputs)){if(input.assignment===ASSIGNMENT.UNASSIGNED){this.trackAssignments.inputs.unassigned.push(input);}else if(input.assignment===ASSIGNMENT.CHAT){this.trackAssignments.inputs.chat.push(input);}else{if(input.assignment>nextTrackNumber){nextTrackNumber=input.assignment;}let found=false;for(assigned of Array.from(this.trackAssignments.inputs.assigned)){if(assigned.assignment===input.assignment){assigned.push(input);found=true;}}if(!found){const initial=[input];initial.assignment=input.assignment;this.trackAssignments.inputs.assigned.push(initial);}}}for(let output of Array.from(this.musicPorts.outputs)){if(output.assignment===ASSIGNMENT.OUTPUT){this.trackAssignments.outputs.assigned.push(output);}else{this.trackAssignments.outputs.unassigned.push(output);}}this.nextTrackNumber=nextTrackNumber+1;}` - @ConfigureTracksStore = Reflux.createStore( { listenables: ConfigureTracksActions @@ -83,15 +81,27 @@ _loadChannels = `async function(forceInputsToUnassign,inputChannelFilter){let as @changed() - onEnableVst: () -> - logger.debug("enabling VSTs") - context.jamClient.VSTLoad() + # onEnableVst: () -> + # logger.debug("enabling VSTs") + # context.jamClient.VSTLoad() - setTimeout((() => - @listVsts() + # setTimeout((() => + # @listVsts() - @changed() - ), 250) + # @changed() + # ), 250) + + onEnableVst: `async function() { + logger.debug("enabling VSTs"); + await context.jamClient.VSTLoad(); + + return setTimeout((() => { + this.listVsts(); + + return this.changed(); + } + ), 250); + }` onTrySave: () -> logger.debug("ConfigureTracksStore:trySave") @@ -104,23 +114,46 @@ _loadChannels = `async function(forceInputsToUnassign,inputChannelFilter){let as @changed() - performVstScan: (sendChanged) -> - #@hasVst = gon.global.vst_enabled & context.jamClient.hasVstHost() - logger.debug("hasVst", @hasVst) - if @hasVst - logger.debug("vstScan starting") - @scanningVsts = true - @scannedBefore = true - result = context.jamClient.VSTScan("window.ConfigureTracksStore.onVstScanComplete") + # performVstScan: (sendChanged) -> + # #@hasVst = gon.global.vst_enabled & context.jamClient.hasVstHost() + # logger.debug("hasVst", @hasVst) + # if @hasVst + # logger.debug("vstScan starting") + # @scanningVsts = true + # @scannedBefore = true + # result = context.jamClient.VSTScan("window.ConfigureTracksStore.onVstScanComplete") - onClearVsts: () -> - context.jamClient.VSTClearAll() + performVstScan: `async function(sendChanged) { + //@hasVst = gon.global.vst_enabled & context.jamClient.hasVstHost() + logger.debug("hasVst", this.hasVst); + if (this.hasVst) { + let result; + logger.debug("vstScan starting"); + this.scanningVsts = true; + this.scannedBefore = true; + return result = await context.jamClient.VSTScan("window.ConfigureTracksStore.onVstScanComplete"); + } + }` - setTimeout((() => - @listVsts() + # onClearVsts: () -> + # context.jamClient.VSTClearAll() - @changed() - ), 250) + # setTimeout((() => + # @listVsts() + + # @changed() + # ), 250) + + onClearVsts: `async function() { + await context.jamClient.VSTClearAll(); + + return setTimeout((() => { + this.listVsts(); + + return this.changed(); + } + ), 250); + }` onManageVsts:() -> logger.debug("manage vst selected") @@ -144,8 +177,12 @@ _loadChannels = `async function(forceInputsToUnassign,inputChannelFilter){let as @changed() ), 0) - listPaths: () -> - @scanPaths = context.jamClient.VSTListSearchPaths() + # listPaths: () -> + # @scanPaths = context.jamClient.VSTListSearchPaths() + + listPaths: `async function() { + this.scanPaths = await context.jamClient.VSTListSearchPaths(); + }` # this comes from the JUCE library behavior vstTypeId: () -> @@ -156,20 +193,38 @@ _loadChannels = `async function(forceInputsToUnassign,inputChannelFilter){let as logger.debug("vstTypeId is not-windows") 1 - onAddSearchPath: (path) -> - logger.debug("VSTAddSearchPath: " + path) - context.jamClient.VSTAddSearchPath(@vstTypeId(), path) - @listPaths() - @changed() + # onAddSearchPath: (path) -> + # logger.debug("VSTAddSearchPath: " + path) + # context.jamClient.VSTAddSearchPath(@vstTypeId(), path) + # @listPaths() + # @changed() - onRemoveSearchPath: (path) -> - logger.debug("VSTRemoveSearchPath: " + path) - context.jamClient.VSTRemoveSearchPath(@vstTypeId(), path) - @listPaths() - @changed() + onAddSearchPath: `async function(path) { + logger.debug("VSTAddSearchPath: " + path); + await context.jamClient.VSTAddSearchPath(this.vstTypeId(), path); + this.listPaths(); + return this.changed(); + }` - onSelectVSTDirectory:() -> - context.jamClient.ShowSelectVSTScanDialog("window.ConfigureTracksStore.onVSTPathSelected") + # onRemoveSearchPath: (path) -> + # logger.debug("VSTRemoveSearchPath: " + path) + # context.jamClient.VSTRemoveSearchPath(@vstTypeId(), path) + # @listPaths() + # @changed() + + onRemoveSearchPath: `async function(path) { + logger.debug("VSTRemoveSearchPath: " + path); + await context.jamClient.VSTRemoveSearchPath(this.vstTypeId(), path); + this.listPaths(); + this.changed(); + }` + + # onSelectVSTDirectory:() -> + # context.jamClient.ShowSelectVSTScanDialog("window.ConfigureTracksStore.onVSTPathSelected") + + onSelectVSTDirectory: `async function() { + await context.jamClient.ShowSelectVSTScanDialog("window.ConfigureTracksStore.onVSTPathSelected"); + }` onVSTPathSelected: (result) -> success = result.success @@ -181,36 +236,63 @@ _loadChannels = `async function(forceInputsToUnassign,inputChannelFilter){let as else logger.debug("nothing selected") - listVsts: () -> + # listVsts: () -> - @vstPluginList = context.jamClient.VSTListVsts() - @vstTrackAssignments = context.jamClient.VSTListTrackAssignments() + # @vstPluginList = context.jamClient.VSTListVsts() + # @vstTrackAssignments = context.jamClient.VSTListTrackAssignments() + listVsts: `async function() { + this.vstPluginList = await context.jamClient.VSTListVsts(); + this.vstTrackAssignments = await context.jamClient.VSTListTrackAssignments(); + }` onMidiScan: () -> @performMidiScan() @changed() - performMidiScan: () -> + # performMidiScan: () -> - if !@hasVst - logger.debug("performMidiScan skipped due to no VST") - return - context.jamClient.VST_ScanForMidiDevices(); - @attachedMidiDevices = context.jamClient.VST_GetMidiDeviceList(); + # if !@hasVst + # logger.debug("performMidiScan skipped due to no VST") + # return + # context.jamClient.VST_ScanForMidiDevices(); + # @attachedMidiDevices = context.jamClient.VST_GetMidiDeviceList(); + + performMidiScan: `async function() { + if (!this.hasVst) { + logger.debug("performMidiScan skipped due to no VST"); + return; + } + await context.jamClient.VST_ScanForMidiDevices(); + this.attachedMidiDevices = await context.jamClient.VST_GetMidiDeviceList(); + }` # trackNumber is 0-based, and optional - onShowVstSettings: (trackNumber) -> - if !@hasVst - logger.debug("onShowVstSettings skipped due to no VST") - return + # onShowVstSettings: (trackNumber) -> + # if !@hasVst + # logger.debug("onShowVstSettings skipped due to no VST") + # return - if !trackNumber? - trackNumber = @trackNumber - 1 if @trackNumber? + # if !trackNumber? + # trackNumber = @trackNumber - 1 if @trackNumber? - logger.debug("show VST GUI", trackNumber) + # logger.debug("show VST GUI", trackNumber) - context.jamClient.VSTShowHideGui(true, trackNumber) if trackNumber? + # context.jamClient.VSTShowHideGui(true, trackNumber) if trackNumber? + + onShowVstSettings: `async function(trackNumber) { + if (!this.hasVst) { + logger.debug("onShowVstSettings skipped due to no VST"); + } + + if ((trackNumber == null)) { + if (this.trackNumber != null) { trackNumber = this.trackNumber - 1; } + } + + logger.debug("show VST GUI", trackNumber); + + if (trackNumber != null) { await context.jamClient.VSTShowHideGui(true, trackNumber); } + }` findMidiTrack: () -> @@ -232,15 +314,27 @@ _loadChannels = `async function(forceInputsToUnassign,inputChannelFilter){let as if removeIndex > -1 @trackAssignments.inputs.assigned.splice(removeIndex, 1) - defaultTrackInstrument: (trackNumber) -> - clientInstrument = context.jamClient.TrackGetInstrument(trackNumber) - if clientInstrument == 0 - logger.debug("defaulting midi instrument for assignment #{trackNumber}") - # ensure that we always have an instrument set (50 = electric guitar - context.jamClient.TrackSetInstrument(trackNumber, 50) - clientInstrument = 50 + # defaultTrackInstrument: (trackNumber) -> + # clientInstrument = context.jamClient.TrackGetInstrument(trackNumber) + # if clientInstrument == 0 + # logger.debug("defaulting midi instrument for assignment #{trackNumber}") + # # ensure that we always have an instrument set (50 = electric guitar + # context.jamClient.TrackSetInstrument(trackNumber, 50) + # clientInstrument = 50 + + # context.JK.client_to_server_instrument_map[clientInstrument]; + + defaultTrackInstrument: `async function(trackNumber) { + let clientInstrument = await context.jamClient.TrackGetInstrument(trackNumber); + if (clientInstrument === 0) { + logger.debug('defaulting midi instrument for assignment ' + trackNumber); + await context.jamClient.TrackSetInstrument(trackNumber, 50); + clientInstrument = 50; + } + + context.JK.client_to_server_instrument_map[clientInstrument]; + }` - context.JK.client_to_server_instrument_map[clientInstrument]; # the backend does not have a consistent way of tracking assigned inputs for midi. # let's make it seem consistent injectMidiToTrackAssignments: () -> @@ -350,146 +444,359 @@ _loadChannels = `async function(forceInputsToUnassign,inputChannelFilter){let as # @nextTrackNumber = nextTrackNumber + 1 - loadChannels: _loadChannels + loadChannels: `async function(forceInputsToUnassign, inputChannelFilter) { + let assigned; + this.musicPorts = await context.jamClient.FTUEGetChannels(); + + this.trackAssignments = {inputs: {unassigned: [], assigned: [], chat: []}, outputs: {unassigned: [], assigned: []}}; + + let nextTrackNumber = 0; + + for (let input of Array.from(this.musicPorts.inputs)) { + if (input.assignment === ASSIGNMENT.UNASSIGNED) { + this.trackAssignments.inputs.unassigned.push(input); + } else if (input.assignment === ASSIGNMENT.CHAT) { + this.trackAssignments.inputs.chat.push(input); + } else { + if (input.assignment > nextTrackNumber) { nextTrackNumber = input.assignment; } + + let found = false; + for (assigned of Array.from(this.trackAssignments.inputs.assigned)) { + if (assigned.assignment === input.assignment) { + assigned.push(input); + found = true; + } + } + + if (!found) { + const initial = [input]; + initial.assignment = input.assignment; + this.trackAssignments.inputs.assigned.push(initial); + } + } + } + for (let output of Array.from(this.musicPorts.outputs)) { + if (output.assignment === ASSIGNMENT.OUTPUT) { + this.trackAssignments.outputs.assigned.push(output); + } else { + this.trackAssignments.outputs.unassigned.push(output); + } + } + + return this.nextTrackNumber = nextTrackNumber + 1; + }` + + # loadTrackInstruments: (forceInputsToUnassign) -> + # for inputsForTrack in @trackAssignments.inputs.assigned + + # clientInstrument = context.jamClient.TrackGetInstrument(inputsForTrack.assignment) + + # if clientInstrument == 0 + # logger.debug("defaulting track instrument for assignment #{@trackNumber}") + # # ensure that we always have an instrument set (50 = electric guitar + # context.jamClient.TrackSetInstrument(inputsForTrack.assignment, 50) + # clientInstrument = 50 + + # instrument = context.JK.client_to_server_instrument_map[clientInstrument]; + + # inputsForTrack.instrument_id = instrument?.server_id + + loadTrackInstruments: `async function(forceInputsToUnassign) { + const result = []; + for (let inputsForTrack of Array.from(this.trackAssignments.inputs.assigned)) { + + let clientInstrument = await context.jamClient.TrackGetInstrument(inputsForTrack.assignment); + + if (clientInstrument === 0) { + logger.debug('defaulting track instrument for assignment '+ this.trackNumber); + await context.jamClient.TrackSetInstrument(inputsForTrack.assignment, 50); + clientInstrument = 50; + } + + const instrument = context.JK.client_to_server_instrument_map[clientInstrument]; + + result.push(inputsForTrack.instrument_id = instrument != null ? instrument.server_id : undefined); + } + return result; + + }` + + # onAssociateInputsWithTrack: (inputId1, inputId2) -> + # return unless @trackNumber? + + # for inputs in @editingTrack + # context.jamClient.TrackSetAssignment(inputs.id, true, ASSIGNMENT.UNASSIGNED) + + # if inputId1? + # logger.debug("setting input1 #{inputId1} to #{@trackNumber}") + # context.jamClient.TrackSetAssignment(inputId1, true, @trackNumber) + + # if inputId2? + # logger.debug("setting input2 #{inputId2} to #{@trackNumber}") + # context.jamClient.TrackSetAssignment(inputId2, true, @trackNumber) + + # result = context.jamClient.TrackSaveAssignments(); + + # if(!result || result.length == 0) + + # else + # context.JK.Banner.showAlert('Unable to save assignments. ' + result); + + onAssociateInputsWithTrack: `async function(inputId1, inputId2) { + if (this.trackNumber == null) { return; } + + for (let inputs of Array.from(this.editingTrack)) { + await context.jamClient.TrackSetAssignment(inputs.id, true, ASSIGNMENT.UNASSIGNED); + } + + if (inputId1 != null) { + logger.debug('setting input1 '+ inputId1 +' to ' + this.trackNumber); + await context.jamClient.TrackSetAssignment(inputId1, true, this.trackNumber); + } + + if (inputId2 != null) { + logger.debug('setting input2 '+ inputId2 +' to ' + this.trackNumber); + await context.jamClient.TrackSetAssignment(inputId2, true, this.trackNumber); + } + + const result = await context.jamClient.TrackSaveAssignments(); + + if(!result || (result.length === 0)) { + + } else { + return context.JK.Banner.showAlert('Unable to save assignments. ' + result); + } + }` + + # onAssociateInstrumentWithTrack: (instrumentId) -> + # return unless @trackNumber? + + # logger.debug("context.jamClient.TrackSetInstrument(trackNumber, track.instrument_id)", @trackNumber, instrumentId) + + # clientInstrumentId = null + # if instrumentId != null && instrumentId != '' + # clientInstrumentId = context.JK.instrument_id_to_instrument[instrumentId].client_id + # else + # clientInstrumentId = 0 + + # context.jamClient.TrackSetInstrument(@trackNumber, clientInstrumentId) + + # if @trackNumber == MIDI_TRACK + # logger.debug("checking midi track for track instrument synchronization") + # # keep artificial midi track in sync + # midi = @findMidiTrack() + # if midi? + # logger.debug("synced midi track with #{instrumentId}") + # midi.instrument_id = instrumentId - loadTrackInstruments: (forceInputsToUnassign) -> - for inputsForTrack in @trackAssignments.inputs.assigned + # if(!result || result.length == 0) - clientInstrument = context.jamClient.TrackGetInstrument(inputsForTrack.assignment) - - if clientInstrument == 0 - logger.debug("defaulting track instrument for assignment #{@trackNumber}") - # ensure that we always have an instrument set (50 = electric guitar - context.jamClient.TrackSetInstrument(inputsForTrack.assignment, 50) - clientInstrument = 50 - - instrument = context.JK.client_to_server_instrument_map[clientInstrument]; - - inputsForTrack.instrument_id = instrument?.server_id + # else + # context.JK.Banner.showAlert('Unable to save assignments. ' + result); - onAssociateInputsWithTrack: (inputId1, inputId2) -> - return unless @trackNumber? + # result = context.jamClient.TrackSaveAssignments() - for inputs in @editingTrack - context.jamClient.TrackSetAssignment(inputs.id, true, ASSIGNMENT.UNASSIGNED) + # if(!result || result.length == 0) - if inputId1? - logger.debug("setting input1 #{inputId1} to #{@trackNumber}") - context.jamClient.TrackSetAssignment(inputId1, true, @trackNumber) + # else + # context.JK.Banner.showAlert('Unable to save assignments. ' + result); - if inputId2? - logger.debug("setting input2 #{inputId2} to #{@trackNumber}") - context.jamClient.TrackSetAssignment(inputId2, true, @trackNumber) + onAssociateInstrumentWithTrack: `async function(instrumentId) { + if (this.trackNumber == null) { return; } - result = context.jamClient.TrackSaveAssignments(); + logger.debug("context.jamClient.TrackSetInstrument(trackNumber, track.instrument_id)", this.trackNumber, instrumentId); - if(!result || result.length == 0) + let clientInstrumentId = null; + if ((instrumentId !== null) && (instrumentId !== '')) { + clientInstrumentId = context.JK.instrument_id_to_instrument[instrumentId].client_id; + } else { + clientInstrumentId = 0; + } - else + await context.jamClient.TrackSetInstrument(this.trackNumber, clientInstrumentId); + + if (this.trackNumber === MIDI_TRACK) { + logger.debug("checking midi track for track instrument synchronization"); + // keep artificial midi track in sync + const midi = this.findMidiTrack(); + if (midi != null) { + logger.debug('synced midi track with ' + instrumentId); + midi.instrument_id = instrumentId; + } + } + + + if(!result || (result.length === 0)) { + + } else { context.JK.Banner.showAlert('Unable to save assignments. ' + result); - - onAssociateInstrumentWithTrack: (instrumentId) -> - return unless @trackNumber? - - logger.debug("context.jamClient.TrackSetInstrument(trackNumber, track.instrument_id)", @trackNumber, instrumentId) - - clientInstrumentId = null - if instrumentId != null && instrumentId != '' - clientInstrumentId = context.JK.instrument_id_to_instrument[instrumentId].client_id - else - clientInstrumentId = 0 - - context.jamClient.TrackSetInstrument(@trackNumber, clientInstrumentId) - - if @trackNumber == MIDI_TRACK - logger.debug("checking midi track for track instrument synchronization") - # keep artificial midi track in sync - midi = @findMidiTrack() - if midi? - logger.debug("synced midi track with #{instrumentId}") - midi.instrument_id = instrumentId + } - if(!result || result.length == 0) + var result = await context.jamClient.TrackSaveAssignments(); - else - context.JK.Banner.showAlert('Unable to save assignments. ' + result); + if(!result || (result.length === 0)) { + } else { + return context.JK.Banner.showAlert('Unable to save assignments. ' + result); + } + }` - result = context.jamClient.TrackSaveAssignments() + # onAssociateVSTWithTrack: (vst) -> - if(!result || result.length == 0) + # if !@hasVst + # logger.debug("onAssociateVSTWithTrack skipped due to no VST") + # return - else - context.JK.Banner.showAlert('Unable to save assignments. ' + result); + # if vst? + # logger.debug("associating track:#{@trackNumber - 1} with VST:#{vst.file}") - onAssociateVSTWithTrack: (vst) -> + # found = null + # for knownVst in @vstPluginList.vsts + # if knownVst.file == vst.file + # found = knownVst + # break + # if found? + # context.jamClient.VSTSetTrackAssignment(found, @trackNumber - 1) + # else + # logger.error("unable to locate vst for #{vst}") + # else + # logger.debug("unassociated track:#{@trackNumber} with VST") + # # no way to unset VST assignment yet - if !@hasVst - logger.debug("onAssociateVSTWithTrack skipped due to no VST") - return + # setTimeout((() => ( + # @listVsts() - if vst? - logger.debug("associating track:#{@trackNumber - 1} with VST:#{vst.file}") + # @changed() + # )), 250) - found = null - for knownVst in @vstPluginList.vsts - if knownVst.file == vst.file - found = knownVst - break - if found? - context.jamClient.VSTSetTrackAssignment(found, @trackNumber - 1) - else - logger.error("unable to locate vst for #{vst}") - else - logger.debug("unassociated track:#{@trackNumber} with VST") - # no way to unset VST assignment yet + onAssociateVSTWithTrack: `async function(vst) { - setTimeout((() => ( - @listVsts() + if (!this.hasVst) { + logger.debug("onAssociateVSTWithTrack skipped due to no VST"); + return; + } - @changed() - )), 250) + if (vst != null) { + logger.debug('associating track:'+this.trackNumber - 1+' with VST:'+vst.file); - onCancelEdit: () -> - if @newTrack - for input in @editingTrack - context.jamClient.TrackSetAssignment(input.id, true, ASSIGNMENT.UNASSIGNED) - result = context.jamClient.TrackSaveAssignments() - if(!result || result.length == 0) + let found = null; + for (let knownVst of Array.from(this.vstPluginList.vsts)) { + if (knownVst.file === vst.file) { + found = knownVst; + break; + } + } + if (found != null) { + await context.jamClient.VSTSetTrackAssignment(found, this.trackNumber - 1); + } else { + logger.error('unable to locate vst for '+ vst); + } + } else { + logger.debug('unassociated track:'+this.trackNumber+ ' with VST'); + } + // no way to unset VST assignment yet - else - context.JK.Banner.showAlert('Unable to save assignments. ' + result); - else - logger.error("unable to process cancel for an existing track") + return setTimeout((() => ( + this.listVsts(), - onDeleteTrack: (assignment) -> - logger.debug("deleting track with assignment #{assignment}") - if assignment != MIDI_TRACK - track = null - for inputsForTrack in @trackAssignments.inputs.assigned - if inputsForTrack.assignment == assignment - track = inputsForTrack - break + this.changed() + )), 250); + }` - if track? - for input in inputsForTrack - context.jamClient.TrackSetAssignment(input.id, true, ASSIGNMENT.UNASSIGNED) - result = context.jamClient.TrackSaveAssignments() + # onCancelEdit: () -> + # if @newTrack + # for input in @editingTrack + # context.jamClient.TrackSetAssignment(input.id, true, ASSIGNMENT.UNASSIGNED) + # result = context.jamClient.TrackSaveAssignments() + # if(!result || result.length == 0) - if(!result || result.length == 0) + # else + # context.JK.Banner.showAlert('Unable to save assignments. ' + result); + # else + # logger.error("unable to process cancel for an existing track") - else - context.JK.Banner.showAlert('Unable to save assignments. ' + result); - else - logger.error("unable to find track to delete") - else - logger.debug("deleting midi track") - @onAssociateMIDIWithTrack(null) - @removeMidiTrack() - @changed() + onCancelEdit: `async function() { + if (this.newTrack) { + const result1 = []; + for (let input of Array.from(this.editingTrack)) { + await context.jamClient.TrackSetAssignment(input.id, true, ASSIGNMENT.UNASSIGNED); + const result = await context.jamClient.TrackSaveAssignments(); + if(!result || (result.length === 0)) { + + } else { + result1.push(context.JK.Banner.showAlert('Unable to save assignments. ' + result)); + } + } + return result1; + } else { + return logger.error("unable to process cancel for an existing track"); + } + }` + + # onDeleteTrack: (assignment) -> + # logger.debug("deleting track with assignment #{assignment}") + # if assignment != MIDI_TRACK + # track = null + # for inputsForTrack in @trackAssignments.inputs.assigned + # if inputsForTrack.assignment == assignment + # track = inputsForTrack + # break + + # if track? + # for input in inputsForTrack + # context.jamClient.TrackSetAssignment(input.id, true, ASSIGNMENT.UNASSIGNED) + # result = context.jamClient.TrackSaveAssignments() + + # if(!result || result.length == 0) + + # else + # context.JK.Banner.showAlert('Unable to save assignments. ' + result); + # else + # logger.error("unable to find track to delete") + # else + # logger.debug("deleting midi track") + # @onAssociateMIDIWithTrack(null) + # @removeMidiTrack() + # @changed() + + onDeleteTrack: `async function(assignment) { + logger.debug('deleting track with assignment ' + assignment); + if (assignment !== MIDI_TRACK) { + let inputsForTrack; + let track = null; + for (inputsForTrack of Array.from(this.trackAssignments.inputs.assigned)) { + if (inputsForTrack.assignment === assignment) { + track = inputsForTrack; + break; + } + } + + if (track != null) { + const result1 = []; + for (let input of Array.from(inputsForTrack)) { + await context.jamClient.TrackSetAssignment(input.id, true, ASSIGNMENT.UNASSIGNED); + const result = await context.jamClient.TrackSaveAssignments(); + + if(!result || (result.length === 0)) { + + } else { + result1.push(context.JK.Banner.showAlert('Unable to save assignments. ' + result)); + } + } + return result1; + } else { + return logger.error("unable to find track to delete"); + } + } else { + logger.debug("deleting midi track"); + this.onAssociateMIDIWithTrack(null); + this.removeMidiTrack(); + return this.changed(); + } + }` onShowAddNewTrack: (type) -> @@ -509,36 +816,73 @@ _loadChannels = `async function(forceInputsToUnassign,inputChannelFilter){let as onShowEditTrack: (trackNumber) -> @openLiveTrackDialog(trackNumber) - openLiveTrackDialog: (trackNumber) -> - @trackNumber = trackNumber - logger.debug("opening live track dialog for track #{trackNumber}", @trackAssignments.inputs.assigned) + # openLiveTrackDialog: (trackNumber) -> + # @trackNumber = trackNumber + # logger.debug("opening live track dialog for track #{trackNumber}", @trackAssignments.inputs.assigned) - @newTrack = true - for inputsForTrack in @trackAssignments.inputs.assigned - logger.debug("inputsForTrack.assignment @trackNumber", inputsForTrack.assignment, @trackNumber ) - if inputsForTrack.assignment == @trackNumber - @newTrack = false - break + # @newTrack = true + # for inputsForTrack in @trackAssignments.inputs.assigned + # logger.debug("inputsForTrack.assignment @trackNumber", inputsForTrack.assignment, @trackNumber ) + # if inputsForTrack.assignment == @trackNumber + # @newTrack = false + # break - if @trackNumber == MIDI_TRACK - @trackType = 'midi' - else - @trackType = 'audio' + # if @trackNumber == MIDI_TRACK + # @trackType = 'midi' + # else + # @trackType = 'audio' - if @newTrack - assignment = context.jamClient.TrackGetInstrument(@trackNumber) + # if @newTrack + # assignment = context.jamClient.TrackGetInstrument(@trackNumber) - if assignment == 0 - logger.debug("defaulting track instrument for assignment #{@trackNumber}") - # ensure that we always have an instrument set (50 = electric guitar - context.jamClient.TrackSetInstrument(@trackNumber, 50) + # if assignment == 0 + # logger.debug("defaulting track instrument for assignment #{@trackNumber}") + # # ensure that we always have an instrument set (50 = electric guitar + # context.jamClient.TrackSetInstrument(@trackNumber, 50) - #@performVstScan() - @performMidiScan() + # #@performVstScan() + # @performMidiScan() - @changed() + # @changed() - @app.layout.showDialog('configure-live-tracks-dialog') + # @app.layout.showDialog('configure-live-tracks-dialog') + + openLiveTrackDialog: `async function(trackNumber) { + this.trackNumber = trackNumber; + logger.debug('opening live track dialog for track ' + trackNumber +', ' +this.trackAssignments.inputs.assigned); + + this.newTrack = true; + for (let inputsForTrack of Array.from(this.trackAssignments.inputs.assigned)) { + logger.debug("inputsForTrack.assignment @trackNumber", inputsForTrack.assignment, this.trackNumber ); + if (inputsForTrack.assignment === this.trackNumber) { + this.newTrack = false; + break; + } + } + + if (this.trackNumber === MIDI_TRACK) { + this.trackType = 'midi'; + } else { + this.trackType = 'audio'; + } + + if (this.newTrack) { + const assignment = await context.jamClient.TrackGetInstrument(this.trackNumber); + + if (assignment === 0) { + logger.debug('defaulting track instrument for assignment' + this.trackNumber); + // ensure that we always have an instrument set (50 = electric guitar + await context.jamClient.TrackSetInstrument(this.trackNumber, 50); + } + } + + //@performVstScan() + this.performMidiScan(); + + this.changed(); + + this.app.layout.showDialog('configure-live-tracks-dialog'); + }` onDesiredTrackType: (trackType) -> @trackType = trackType @@ -547,37 +891,70 @@ _loadChannels = `async function(forceInputsToUnassign,inputChannelFilter){let as @trackNumber = MIDI_TRACK @changed() - onUpdateOutputs: (outputId1, outputId2) -> + # onUpdateOutputs: (outputId1, outputId2) -> - context.jamClient.TrackSetAssignment(outputId1, true, ASSIGNMENT.OUTPUT); - context.jamClient.TrackSetAssignment(outputId2, true, ASSIGNMENT.OUTPUT); + # context.jamClient.TrackSetAssignment(outputId1, true, ASSIGNMENT.OUTPUT); + # context.jamClient.TrackSetAssignment(outputId2, true, ASSIGNMENT.OUTPUT); - result = context.jamClient.TrackSaveAssignments(); + # result = context.jamClient.TrackSaveAssignments(); - if(!result || result.length == 0) + # if(!result || result.length == 0) - else - context.JK.Banner.showAlert('Unable to save assignments. ' + result); + # else + # context.JK.Banner.showAlert('Unable to save assignments. ' + result); + + onUpdateOutputs: `async function(outputId1, outputId2) { + + await context.jamClient.TrackSetAssignment(outputId1, true, ASSIGNMENT.OUTPUT); + await context.jamClient.TrackSetAssignment(outputId2, true, ASSIGNMENT.OUTPUT); + + const result = await context.jamClient.TrackSaveAssignments(); + + if(!result || (result.length === 0)) { + + } else { + return context.JK.Banner.showAlert('Unable to save assignments. ' + result); + } + }` onShowEditOutputs: () -> @app.layout.showDialog('configure-outputs-dialog') - onAssociateMIDIWithTrack: (midiInterface) -> + # onAssociateMIDIWithTrack: (midiInterface) -> - @trackNumber = MIDI_TRACK + # @trackNumber = MIDI_TRACK - if !midiInterface? || midiInterface == '' - logger.debug("disabling midiInterface:#{midiInterface}, track:#{@trackNumber - 1}") - context.jamClient.VST_EnableMidiForTrack(@trackNumber - 1, false, 0) - else - logger.debug("enabling midiInterface:#{midiInterface}, track:#{@trackNumber - 1}") - context.jamClient.VST_EnableMidiForTrack(@trackNumber - 1, true, midiInterface) + # if !midiInterface? || midiInterface == '' + # logger.debug("disabling midiInterface:#{midiInterface}, track:#{@trackNumber - 1}") + # context.jamClient.VST_EnableMidiForTrack(@trackNumber - 1, false, 0) + # else + # logger.debug("enabling midiInterface:#{midiInterface}, track:#{@trackNumber - 1}") + # context.jamClient.VST_EnableMidiForTrack(@trackNumber - 1, true, midiInterface) - setTimeout((() => ( - @listVsts() + # setTimeout((() => ( + # @listVsts() - @changed() - )), 250) + # @changed() + # )), 250) + + onAssociateMIDIWithTrack: `async function(midiInterface) { + + this.trackNumber = MIDI_TRACK; + + if ((midiInterface == null) || (midiInterface === '')) { + logger.debug('disabling midiInterface:'+midiInterface+', track:' +this.trackNumber - 1); + await context.jamClient.VST_EnableMidiForTrack(this.trackNumber - 1, false, 0); + } else { + logger.debug('enabling midiInterface:'+midiInterface+', track:' +this.trackNumber - 1); + await context.jamClient.VST_EnableMidiForTrack(this.trackNumber - 1, true, midiInterface); + } + + return setTimeout((() => ( + this.listVsts(), + + this.changed() + )), 250); + }` } ) \ No newline at end of file diff --git a/web/app/assets/javascripts/react-components/stores/JamBlasterStore.js.coffee b/web/app/assets/javascripts/react-components/stores/JamBlasterStore.js.coffee index 505a03c46..83cde02b9 100644 --- a/web/app/assets/javascripts/react-components/stores/JamBlasterStore.js.coffee +++ b/web/app/assets/javascripts/react-components/stores/JamBlasterStore.js.coffee @@ -28,122 +28,257 @@ logger = context.JK.logger else context.JK.Banner.showAlert('unable to update the JamBlaster', msg) - onUpdateAudio: (name, value) -> - # input1_linemode - # input2_linemode - # input1_48V - # input2_48V - # has_chat - # track1 = {left, right, inst, stereo) - # track1 = {left, right, inst, stereo) + # onUpdateAudio: (name, value) -> + # # input1_linemode + # # input2_linemode + # # input1_48V + # # input2_48V + # # has_chat + # # track1 = {left, right, inst, stereo) + # # track1 = {left, right, inst, stereo) - if @pairedJamBlaster? && @pairedJamBlaster.tracks? - logger.debug("onUpdateAudio name=#{name} value=#{value}", @pairedJamBlaster.tracks) + # if @pairedJamBlaster? && @pairedJamBlaster.tracks? + # logger.debug("onUpdateAudio name=#{name} value=#{value}", @pairedJamBlaster.tracks) - if name == 'inputTypeTrack1' - result = context.jamClient.set48vAndLineInstState({input1_linemode: value}) - @postSimpleChange(result, 'Unable to set the line mode for Track 1') - return + # if name == 'inputTypeTrack1' + # result = context.jamClient.set48vAndLineInstState({input1_linemode: value}) + # @postSimpleChange(result, 'Unable to set the line mode for Track 1') + # return - else if name == 'inputTypeTrack2' - result = context.jamClient.set48vAndLineInstState({input2_linemode: value}) - @postSimpleChange(result, 'Unable to set the line mode for Track 2') - return + # else if name == 'inputTypeTrack2' + # result = context.jamClient.set48vAndLineInstState({input2_linemode: value}) + # @postSimpleChange(result, 'Unable to set the line mode for Track 2') + # return - else if name == 'track1Phantom' - result = context.jamClient.set48vAndLineInstState({input1_48V: value}) - @postSimpleChange(result, 'Unable to set the phantom power for Track 1') - return + # else if name == 'track1Phantom' + # result = context.jamClient.set48vAndLineInstState({input1_48V: value}) + # @postSimpleChange(result, 'Unable to set the phantom power for Track 1') + # return - else if name == 'track2Phantom' - result = context.jamClient.set48vAndLineInstState({input2_48V: value}) - @postSimpleChange(result, 'Unable to set the phantom power for Track 2') - return + # else if name == 'track2Phantom' + # result = context.jamClient.set48vAndLineInstState({input2_48V: value}) + # @postSimpleChange(result, 'Unable to set the phantom power for Track 2') + # return - #else if name == 'track1Instrument' - # result = context.jamClient.set48vAndLineInstState({input2_48V: value}) - # @postSimpleChange(result, 'Unable to set the phantom power for Track 2') - # return + # #else if name == 'track1Instrument' + # # result = context.jamClient.set48vAndLineInstState({input2_48V: value}) + # # @postSimpleChange(result, 'Unable to set the phantom power for Track 2') + # # return - #else if name == 'track1Instrument' - # result = context.jamClient.set48vAndLineInstState({input2_48V: value}) - # @postSimpleChange(result, 'Unable to set the phantom power for Track 2') - # return + # #else if name == 'track1Instrument' + # # result = context.jamClient.set48vAndLineInstState({input2_48V: value}) + # # @postSimpleChange(result, 'Unable to set the phantom power for Track 2') + # # return - audio = $.extend({}, @pairedJamBlaster.tracks) - if name == 'inputTypeTrack1' - audio.input1_linemode = value - else if name == 'inputTypeTrack2' - audio.input2_linemode = value - else if name == 'track1Phantom' - audio.input1_48V = value - else if name == 'track2Phantom' - audio.input2_48V = value - else if name == 'micActive' - audio.has_chat = value + # audio = $.extend({}, @pairedJamBlaster.tracks) + # if name == 'inputTypeTrack1' + # audio.input1_linemode = value + # else if name == 'inputTypeTrack2' + # audio.input2_linemode = value + # else if name == 'track1Phantom' + # audio.input1_48V = value + # else if name == 'track2Phantom' + # audio.input2_48V = value + # else if name == 'micActive' + # audio.has_chat = value - #track1Active = @pairedJamBlaster.tracks.track1Active - #if name == 'track1Active' - # track1Active = value + # #track1Active = @pairedJamBlaster.tracks.track1Active + # #if name == 'track1Active' + # # track1Active = value - #track2Active = @pairedJamBlaster.tracks.track2Active - #if name == 'track2Active' - # track2Active = value + # #track2Active = @pairedJamBlaster.tracks.track2Active + # #if name == 'track2Active' + # # track2Active = value - track1Active = true - track2Active = true - has_chat = true + # track1Active = true + # track2Active = true + # has_chat = true - audio.has_chat = true + # audio.has_chat = true - combined = @pairedJamBlaster.tracks.combined - if name == 'combined' - combined = value + # combined = @pairedJamBlaster.tracks.combined + # if name == 'combined' + # combined = value - track1Instrument = @pairedJamBlaster.tracks.track1Instrument - track2Instrument = @pairedJamBlaster.tracks.track2Instrument - if name == 'track1Instrument' - track1Instrument = @convertToClientInstrument(value) - if name == 'track2Instrument' - track2Instrument = @convertToClientInstrument(value) + # track1Instrument = @pairedJamBlaster.tracks.track1Instrument + # track2Instrument = @pairedJamBlaster.tracks.track2Instrument + # if name == 'track1Instrument' + # track1Instrument = @convertToClientInstrument(value) + # if name == 'track2Instrument' + # track2Instrument = @convertToClientInstrument(value) - if !track1Instrument - track1Instrument = context.JK.server_to_client_instrument_map.Other.client_id - if !track2Instrument - track2Instrument = context.JK.server_to_client_instrument_map.Other.client_id + # if !track1Instrument + # track1Instrument = context.JK.server_to_client_instrument_map.Other.client_id + # if !track2Instrument + # track2Instrument = context.JK.server_to_client_instrument_map.Other.client_id - if combined - # user has chosen to combine both inputs into one track. stereo=true is the key flag her + # if combined + # # user has chosen to combine both inputs into one track. stereo=true is the key flag her - audio.track1 = {stereo: true, left: true, inst: track1Instrument} - delete audio.track2 # backend will treat null as present + # audio.track1 = {stereo: true, left: true, inst: track1Instrument} + # delete audio.track2 # backend will treat null as present - else + # else - if track1Active && track2Active + # if track1Active && track2Active - audio.track1 = {stereo: false, left: true, inst: track1Instrument} - audio.track2 = {stereo: false, right: true, inst: track2Instrument} + # audio.track1 = {stereo: false, left: true, inst: track1Instrument} + # audio.track2 = {stereo: false, right: true, inst: track2Instrument} - else if track1Active #(means track) + # else if track1Active #(means track) - audio.track1 = {stereo: false, left: true, inst: track1Instrument} - delete audio.track2 # backend will treat null as present + # audio.track1 = {stereo: false, left: true, inst: track1Instrument} + # delete audio.track2 # backend will treat null as present - else # input2Active + # else # input2Active - audio.track2 = {stereo: false, right: true, inst: track2Instrument} - delete audio.track1 # backend will treat null as present + # audio.track2 = {stereo: false, right: true, inst: track2Instrument} + # delete audio.track1 # backend will treat null as present - logger.debug("updating JamBlaster track state", audio) - context.jamClient.setJbTrackState(audio); - @waitOnTracks() - else - context.JK.Banner.showAlert('no paired JamBlaster', 'it seems your JamBlaster has become disconnected. Please ensure it is powered on and connected via an ethernet cable.') + # logger.debug("updating JamBlaster track state", audio) + # context.jamClient.setJbTrackState(audio); + # @waitOnTracks() + # else + # context.JK.Banner.showAlert('no paired JamBlaster', 'it seems your JamBlaster has become disconnected. Please ensure it is powered on and connected via an ethernet cable.') + + onUpdateAudio: `async function(name, value) { + // input1_linemode + // input2_linemode + // input1_48V + // input2_48V + // has_chat + // track1 = {left, right, inst, stereo) + // track1 = {left, right, inst, stereo) + + if ((this.pairedJamBlaster != null) && (this.pairedJamBlaster.tracks != null)) { + let result; + logger.debug('onUpdateAudio name='+name+' value='+value, this.pairedJamBlaster.tracks); + + if (name === 'inputTypeTrack1') { + result = await context.jamClient.set48vAndLineInstState({input1_linemode: value}); + this.postSimpleChange(result, 'Unable to set the line mode for Track 1'); + return; + + } else if (name === 'inputTypeTrack2') { + result = await context.jamClient.set48vAndLineInstState({input2_linemode: value}); + this.postSimpleChange(result, 'Unable to set the line mode for Track 2'); + return; + + } else if (name === 'track1Phantom') { + result = await context.jamClient.set48vAndLineInstState({input1_48V: value}); + this.postSimpleChange(result, 'Unable to set the phantom power for Track 1'); + return; + + } else if (name === 'track2Phantom') { + result = await context.jamClient.set48vAndLineInstState({input2_48V: value}); + this.postSimpleChange(result, 'Unable to set the phantom power for Track 2'); + return; + } + + //else if name == 'track1Instrument' + // result = context.jamClient.set48vAndLineInstState({input2_48V: value}) + // @postSimpleChange(result, 'Unable to set the phantom power for Track 2') + // return + + //else if name == 'track1Instrument' + // result = context.jamClient.set48vAndLineInstState({input2_48V: value}) + // @postSimpleChange(result, 'Unable to set the phantom power for Track 2') + // return + + + const audio = $.extend({}, this.pairedJamBlaster.tracks); + if (name === 'inputTypeTrack1') { + audio.input1_linemode = value; + } else if (name === 'inputTypeTrack2') { + audio.input2_linemode = value; + } else if (name === 'track1Phantom') { + audio.input1_48V = value; + } else if (name === 'track2Phantom') { + audio.input2_48V = value; + } else if (name === 'micActive') { + audio.has_chat = value; + } + + + //track1Active = @pairedJamBlaster.tracks.track1Active + //if name == 'track1Active' + // track1Active = value + + //track2Active = @pairedJamBlaster.tracks.track2Active + //if name == 'track2Active' + // track2Active = value + + const track1Active = true; + const track2Active = true; + const has_chat = true; + + + audio.has_chat = true; + + let { + combined + } = this.pairedJamBlaster.tracks; + if (name === 'combined') { + combined = value; + } + + let { + track1Instrument + } = this.pairedJamBlaster.tracks; + let { + track2Instrument + } = this.pairedJamBlaster.tracks; + if (name === 'track1Instrument') { + track1Instrument = this.convertToClientInstrument(value); + } + if (name === 'track2Instrument') { + track2Instrument = this.convertToClientInstrument(value); + } + + if (!track1Instrument) { + track1Instrument = context.JK.server_to_client_instrument_map.Other.client_id; + } + if (!track2Instrument) { + track2Instrument = context.JK.server_to_client_instrument_map.Other.client_id; + } + + + if (combined) { + // user has chosen to combine both inputs into one track. stereo=true is the key flag her + + audio.track1 = {stereo: true, left: true, inst: track1Instrument}; + delete audio.track2; // backend will treat null as present + + } else { + + if (track1Active && track2Active) { + + audio.track1 = {stereo: false, left: true, inst: track1Instrument}; + audio.track2 = {stereo: false, right: true, inst: track2Instrument}; + + } else if (track1Active) { //(means track) + + audio.track1 = {stereo: false, left: true, inst: track1Instrument}; + delete audio.track2; // backend will treat null as present + + } else { // input2Active + + audio.track2 = {stereo: false, right: true, inst: track2Instrument}; + delete audio.track1; // backend will treat null as present + } + } + + logger.debug("updating JamBlaster track state", audio); + await context.jamClient.setJbTrackState(audio); + return this.waitOnTracks(); + } else { + context.JK.Banner.showAlert('no paired JamBlaster', 'it seems your JamBlaster has become disconnected. Please ensure it is powered on and connected via an ethernet cable.'); + } + }` waitOnTracks: () -> @lastClientTrackState = null @@ -177,28 +312,52 @@ logger = context.JK.logger clientInstrumentId = 10 clientInstrumentId - onSetAutoPair: (autopair) -> + # onSetAutoPair: (autopair) -> - if !autopair - context.jamClient.setJBAutoPair(autopair) - @lastClientAutoPair = null - JamBlasterActions.resyncBonjour() - setTimeout((() => context.JK.Banner.showNotice("autoconnect removed", - "To use the JamBlaster in the future, you will need to come to this screen and click the connect link.")), 1) - else + # if !autopair + # context.jamClient.setJBAutoPair(autopair) + # @lastClientAutoPair = null + # JamBlasterActions.resyncBonjour() + # setTimeout((() => context.JK.Banner.showNotice("autoconnect removed", + # "To use the JamBlaster in the future, you will need to come to this screen and click the connect link.")), 1) + # else + # context.JK.Banner.showYesNo({ + # title: "enable auto-connect", + # html: "If you would like to automatically connect to your JamBlaster whenever you start this app, click the AUTO CONNECT button below.", + # yes_text: 'AUTO CONNECT', + # yes: => + # context.jamClient.setJBAutoPair(autopair) + # @lastClientAutoPair = null + # JamBlasterActions.resyncBonjour() + # setTimeout((() => context.JK.Banner.showNotice("autoconnect enabled", + # "Your desktop JamKazam application will automatically reconnect to the JamBlaster .")), 1) + + # }) + + onSetAutoPair: `async function(autopair) { + if (!autopair) { + await context.jamClient.setJBAutoPair(autopair); + this.lastClientAutoPair = null; + JamBlasterActions.resyncBonjour(); + return setTimeout((() => context.JK.Banner.showNotice("autoconnect removed", + "To use the JamBlaster in the future, you will need to come to this screen and click the connect link.")), 1); + } else { context.JK.Banner.showYesNo({ title: "enable auto-connect", html: "If you would like to automatically connect to your JamBlaster whenever you start this app, click the AUTO CONNECT button below.", yes_text: 'AUTO CONNECT', - yes: => - context.jamClient.setJBAutoPair(autopair) - @lastClientAutoPair = null - JamBlasterActions.resyncBonjour() - setTimeout((() => context.JK.Banner.showNotice("autoconnect enabled", - "Your desktop JamKazam application will automatically reconnect to the JamBlaster .")), 1) + yes: async () => { + await context.jamClient.setJBAutoPair(autopair); + this.lastClientAutoPair = null; + JamBlasterActions.resyncBonjour(); + return setTimeout((() => context.JK.Banner.showNotice("autoconnect enabled", + "Your desktop JamKazam application will automatically reconnect to the JamBlaster .")), 1); + } - }) + }); + } + }` onPairState: (state) -> if state.client_pair_state == 10 @@ -206,20 +365,37 @@ logger = context.JK.logger logger.debug("backend indicates we are paired with a client") @onResyncBonjour() - onSaveNetworkSettings: (settings) -> - logger.debug("onSaveNetworkSettings", settings) + # onSaveNetworkSettings: (settings) -> + # logger.debug("onSaveNetworkSettings", settings) - result = context.jamClient.setJbNetworkState(settings) - if !result - context.JK.Banner.showAlert('unable to save network settings', 'Please double-check that your JamBlaster is online and paired.') - return - else - context.JK.Banner.showAlert('network settings updated', 'Please reboot the JamBlaster.') - # it will be refreshed by backend - setTimeout(()=> - @onClearNetworkState() - @onResyncBonjour() - , 1000) + # result = context.jamClient.setJbNetworkState(settings) + # if !result + # context.JK.Banner.showAlert('unable to save network settings', 'Please double-check that your JamBlaster is online and paired.') + # return + # else + # context.JK.Banner.showAlert('network settings updated', 'Please reboot the JamBlaster.') + # # it will be refreshed by backend + # setTimeout(()=> + # @onClearNetworkState() + # @onResyncBonjour() + # , 1000) + + onSaveNetworkSettings: `async function(settings) { + logger.debug("onSaveNetworkSettings", settings); + + const result = await context.jamClient.setJbNetworkState(settings); + if (!result) { + context.JK.Banner.showAlert('unable to save network settings', 'Please double-check that your JamBlaster is online and paired.'); + } else { + context.JK.Banner.showAlert('network settings updated', 'Please reboot the JamBlaster.'); + // it will be refreshed by backend + setTimeout(()=> { + this.onClearNetworkState(); + this.onResyncBonjour(); + } + , 1000); + } + }` onResyncBonjour: () -> @@ -277,28 +453,55 @@ logger = context.JK.logger else return @getJbPortBindState(client) - getJbPortBindState:(client) -> - @lastClientPortState = context.jamClient.getJbPortBindState() - console.log("context.jamClient.getJbPortBindState()", @lastClientPortState) - @lastClientPortState.ipv6_addr = client.ipv6_addr - return @lastClientPortState + # getJbPortBindState:(client) -> + # @lastClientPortState = context.jamClient.getJbPortBindState() + # console.log("context.jamClient.getJbPortBindState()", @lastClientPortState) + # @lastClientPortState.ipv6_addr = client.ipv6_addr + # return @lastClientPortState - getJbNetworkState:(client) -> - @lastClientNetworkState = context.jamClient.getJbNetworkState() - console.log("context.jamClient.getJbNetworkState()", @lastClientNetworkState) - @lastClientNetworkState.ipv6_addr = client.ipv6_addr - return @lastClientNetworkState + getJbPortBindState: `async function(client) { + this.lastClientPortState = await context.jamClient.getJbPortBindState(); + console.log("context.jamClient.getJbPortBindState()", this.lastClientPortState); + this.lastClientPortState.ipv6_addr = client.ipv6_addr; + return this.lastClientPortState; + }` - getJbAutoPair:() -> - @lastClientAutoPair = context.jamClient.getJBAutoPair() - console.log("context.jamClient.getJBAutoPair()", @lastClientAutoPair) - return @lastClientAutoPair + # getJbNetworkState:(client) -> + # @lastClientNetworkState = context.jamClient.getJbNetworkState() + # console.log("context.jamClient.getJbNetworkState()", @lastClientNetworkState) + # @lastClientNetworkState.ipv6_addr = client.ipv6_addr + # return @lastClientNetworkState - getJbTrackState:(client) -> - @lastClientTrackState = context.jamClient.getJbTrackState() - console.log("context.jamClient.getJbTrackState()", @lastClientTrackState) - @lastClientTrackState.ipv6_addr = client.ipv6_addr - return @lastClientTrackState + getJbNetworkState: `async function(client) { + this.lastClientNetworkState = await context.jamClient.getJbNetworkState(); + console.log("context.jamClient.getJbNetworkState()", this.lastClientNetworkState); + this.lastClientNetworkState.ipv6_addr = client.ipv6_addr; + return this.lastClientNetworkState; + }` + + # getJbAutoPair:() -> + # @lastClientAutoPair = context.jamClient.getJBAutoPair() + # console.log("context.jamClient.getJBAutoPair()", @lastClientAutoPair) + # return @lastClientAutoPair + + getJbAutoPair: `async function() { + this.lastClientAutoPair = await context.jamClient.getJBAutoPair(); + console.log("context.jamClient.getJBAutoPair()", this.lastClientAutoPair); + return this.lastClientAutoPair; + }` + + # getJbTrackState:(client) -> + # @lastClientTrackState = context.jamClient.getJbTrackState() + # console.log("context.jamClient.getJbTrackState()", @lastClientTrackState) + # @lastClientTrackState.ipv6_addr = client.ipv6_addr + # return @lastClientTrackState + + getJbTrackState: `async function(client) { + this.lastClientTrackState = await context.jamClient.getJbTrackState(); + console.log("context.jamClient.getJbTrackState()", this.lastClientTrackState); + this.lastClientTrackState.ipv6_addr = client.ipv6_addr; + return this.lastClientTrackState; + }` onClearPortBindState: () -> @lastClientPortState = null @@ -413,17 +616,31 @@ logger = context.JK.logger @clients = clients @changed() - getLocalClients: (userJamBlasters) -> - @localClients = context.jamClient.getLocalClients() + # getLocalClients: (userJamBlasters) -> + # @localClients = context.jamClient.getLocalClients() - @mergeBonjourClients(@localClients, userJamBlasters) + # @mergeBonjourClients(@localClients, userJamBlasters) - @refreshingBonjour = false - @changed() + # @refreshingBonjour = false + # @changed() - get48vAndLineState: () -> - @phantomAndLineState = context.jamClient.get48vAndLineInstState() - console.log("get48vAndLineInstState", @phantomAndLineState) + getLocalClients: `async function(userJamBlasters) { + this.localClients = await context.jamClient.getLocalClients(); + + this.mergeBonjourClients(this.localClients, userJamBlasters); + + this.refreshingBonjour = false; + return this.changed(); + }` + + # get48vAndLineState: () -> + # @phantomAndLineState = context.jamClient.get48vAndLineInstState() + # console.log("get48vAndLineInstState", @phantomAndLineState) + + get48vAndLineState: `async function() { + this.phantomAndLineState = await context.jamClient.get48vAndLineInstState(); + console.log("get48vAndLineInstState", this.phantomAndLineState); + }` changed: () -> diff --git a/web/app/assets/javascripts/react-components/stores/JamTrackStore.js.coffee b/web/app/assets/javascripts/react-components/stores/JamTrackStore.js.coffee index 46a095bb8..bdfec8b75 100644 --- a/web/app/assets/javascripts/react-components/stores/JamTrackStore.js.coffee +++ b/web/app/assets/javascripts/react-components/stores/JamTrackStore.js.coffee @@ -203,20 +203,35 @@ JamTrackActions = @JamTrackActions else logger.debug("JamTrackStore: already downloading") - attemptKeying: () -> - if @keyCheckTimeout? - logger.debug("JamTrackStore: attemptKeying: skipping because already keying") - return - else if @jamTrack.activeMixdown.client_state == 'keying_timeout' - # if we have timed out keying, we shouldn't automatically retry - logger.debug("JamTrackStore: attempKeying: skipping because we have timed out before and user hasn't requested RETRY") - return - else - @keyCheckTimeout = setTimeout(@onKeyCheckTimeout, 10000) - @keyCheckoutInterval = setInterval(@checkOnKeying, 1000) - @jamTrack.activeMixdown.client_state = 'keying' - logger.debug("JamTrackStore: initiating keying requested") - context.jamClient.JamTrackKeysRequest() + # attemptKeying: () -> + # if @keyCheckTimeout? + # logger.debug("JamTrackStore: attemptKeying: skipping because already keying") + # return + # else if @jamTrack.activeMixdown.client_state == 'keying_timeout' + # # if we have timed out keying, we shouldn't automatically retry + # logger.debug("JamTrackStore: attempKeying: skipping because we have timed out before and user hasn't requested RETRY") + # return + # else + # @keyCheckTimeout = setTimeout(@onKeyCheckTimeout, 10000) + # @keyCheckoutInterval = setInterval(@checkOnKeying, 1000) + # @jamTrack.activeMixdown.client_state = 'keying' + # logger.debug("JamTrackStore: initiating keying requested") + # context.jamClient.JamTrackKeysRequest() + + attemptKeying: `async function() { + if (this.keyCheckTimeout != null) { + logger.debug("JamTrackStore: attemptKeying: skipping because already keying"); + } else if (this.jamTrack.activeMixdown.client_state === 'keying_timeout') { + // if we have timed out keying, we should not automatically retry + logger.debug("JamTrackStore: attempKeying: skipping because we have timed out before and user hasn't requested RETRY"); + } else { + this.keyCheckTimeout = setTimeout(this.onKeyCheckTimeout, 10000); + this.keyCheckoutInterval = setInterval(this.checkOnKeying, 1000); + this.jamTrack.activeMixdown.client_state = 'keying'; + logger.debug("JamTrackStore: initiating keying requested"); + await context.jamClient.JamTrackKeysRequest(); + } + }` onKeyCheckTimeout: () -> @keyCheckTimeout = null @@ -262,19 +277,35 @@ JamTrackActions = @JamTrackActions this.trigger(@state) - onOpen: (jamTrack) -> - if @jamTrack? - @app.notify({text: 'Unable to open JamTrack because another one is already open.'}) - return + # onOpen: (jamTrack) -> + # if @jamTrack? + # @app.notify({text: 'Unable to open JamTrack because another one is already open.'}) + # return - @enqueuedMixdowns = {} - @jamTrack = jamTrack + # @enqueuedMixdowns = {} + # @jamTrack = jamTrack - # we can cache this because you can't switch gear while in a session (and possible change sample rate!) - sampleRate = context.jamClient.GetSampleRate() - @sampleRate = if sampleRate == 48 then 48 else 44 + # # we can cache this because you can't switch gear while in a session (and possible change sample rate!) + # sampleRate = context.jamClient.GetSampleRate() + # @sampleRate = if sampleRate == 48 then 48 else 44 - @changed() + # @changed() + + onOpen: `async function(jamTrack) { + if (this.jamTrack != null) { + this.app.notify({text: 'Unable to open JamTrack because another one is already open.'}); + return; + } + + this.enqueuedMixdowns = {}; + this.jamTrack = jamTrack; + + // we can cache this because you can not switch gear while in a session (and possible change sample rate!) + const sampleRate = await context.jamClient.GetSampleRate(); + this.sampleRate = sampleRate === 48 ? 48 : 44; + + return this.changed(); + }` onClose: () -> @jamTrack = null @@ -300,31 +331,59 @@ JamTrackActions = @JamTrackActions @requestedFilter = null requested - onCreateMixdown: (mixdown, done, fail) -> + # onCreateMixdown: (mixdown, done, fail) -> - volumeSettings = context.jamClient.GetJamTrackSettings(); + # volumeSettings = context.jamClient.GetJamTrackSettings(); - track_settings = [] + # track_settings = [] - for track in volumeSettings.tracks - track_settings.push({id: track.id, pan: track.pan, vol: track.vol_l, mute: track.mute}) + # for track in volumeSettings.tracks + # track_settings.push({id: track.id, pan: track.pan, vol: track.vol_l, mute: track.mute}) - mixdown.settings.tracks = track_settings + # mixdown.settings.tracks = track_settings - logger.debug("creating mixdown", mixdown) + # logger.debug("creating mixdown", mixdown) - rest.createMixdown(mixdown) - .done((created) => + # rest.createMixdown(mixdown) + # .done((created) => - @addMixdown(created) + # @addMixdown(created) - logger.debug("created mixdown", created) + # logger.debug("created mixdown", created) - @onEnqueueMixdown({id: created.id}, done, fail) - ) - .fail((jqxhr) => - fail(jqxhr) - ) + # @onEnqueueMixdown({id: created.id}, done, fail) + # ) + # .fail((jqxhr) => + # fail(jqxhr) + # ) + + onCreateMixdown: `async function(mixdown, done, fail) { + + const volumeSettings = await context.jamClient.GetJamTrackSettings(); + + const track_settings = []; + + for (let track of Array.from(volumeSettings.tracks)) { + track_settings.push({id: track.id, pan: track.pan, vol: track.vol_l, mute: track.mute}); + } + + mixdown.settings.tracks = track_settings; + + logger.debug("creating mixdown", mixdown); + + return rest.createMixdown(mixdown) + .done(created => { + + this.addMixdown(created); + + logger.debug("created mixdown", created); + + return this.onEnqueueMixdown({id: created.id}, done, fail); + }) + .fail(jqxhr => { + return fail(jqxhr); + }); + }` onEditMixdown: (mixdown) -> @@ -351,25 +410,46 @@ JamTrackActions = @JamTrackActions @app.layout.notify({title:'Unable to Deleted Custom Mix', text: 'The server was unable to delete this mix.'}) ) - onOpenMixdown: (mixdown) -> - logger.debug("opening mixdown", mixdown) + # onOpenMixdown: (mixdown) -> + # logger.debug("opening mixdown", mixdown) - # check if it's already available in the backend or not - rest.markMixdownActive({id: @jamTrack.id, mixdown_id: mixdown.id}) - .done((edited) => - logger.debug("marked mixdown as active") - @jamTrack = edited + # # check if it's already available in the backend or not + # rest.markMixdownActive({id: @jamTrack.id, mixdown_id: mixdown.id}) + # .done((edited) => + # logger.debug("marked mixdown as active") + # @jamTrack = edited - # unload any currently loaded JamTrack - context.jamClient.JamTrackStopPlay(); + # # unload any currently loaded JamTrack + # context.jamClient.JamTrackStopPlay(); - @changed() + # @changed() - SessionActions.mixdownActive(mixdown) - ) - .fail((jqxhr) => - @app.layout.notify({title:'Unable to Edit Mixdown', text: 'Unable to mark this mixdown as active.'}) - ) + # SessionActions.mixdownActive(mixdown) + # ) + # .fail((jqxhr) => + # @app.layout.notify({title:'Unable to Edit Mixdown', text: 'Unable to mark this mixdown as active.'}) + # ) + + onOpenMixdown: `function(mixdown) { + logger.debug("opening mixdown", mixdown); + + // check if it is already available in the backend or not + rest.markMixdownActive({id: this.jamTrack.id, mixdown_id: mixdown.id}) + .done(async (edited) => { + logger.debug("marked mixdown as active"); + this.jamTrack = edited; + + // unload any currently loaded JamTrack + await context.jamClient.JamTrackStopPlay(); + + this.changed(); + + SessionActions.mixdownActive(mixdown); + }) + .fail(jqxhr => { + this.app.layout.notify({title:'Unable to Edit Mixdown', text: 'Unable to mark this mixdown as active.'}); + }); + }` onActivateNoMixdown: (jamTrack) -> logger.debug("activating no mixdown") diff --git a/web/app/assets/javascripts/react-components/stores/MediaPlaybackStore.js.coffee b/web/app/assets/javascripts/react-components/stores/MediaPlaybackStore.js.coffee index 051e0047e..29efa7324 100644 --- a/web/app/assets/javascripts/react-components/stores/MediaPlaybackStore.js.coffee +++ b/web/app/assets/javascripts/react-components/stores/MediaPlaybackStore.js.coffee @@ -30,30 +30,62 @@ RecordingActions = @RecordingActions @isRecording = session.isRecording @sessionHelper = session - onMediaStartPlay: (data) -> - logger.debug("calling jamClient.SessionStartPlay"); - context.jamClient.SessionStartPlay(data.playbackMode); + # onMediaStartPlay: (data) -> + # logger.debug("calling jamClient.SessionStartPlay"); + # context.jamClient.SessionStartPlay(data.playbackMode); - onMediaStopPlay: (data) -> - # if a JamTrack is open, and the user hits 'pause' or 'stop', we need to automatically stop the recording - if @sessionHelper.jamTracks() && @isRecording - logger.debug("preemptive jamtrack stop") - @startStopRecording(); + onMediaStartPlay: `async function(data) { + logger.debug("calling jamClient.SessionStartPlay"); + await context.jamClient.SessionStartPlay(data.playbackMode); + }` - if !data.endReached - logger.debug("calling jamClient.SessionStopPlay. endReached:", data.endReached) - context.jamClient.SessionStopPlay() + # onMediaStopPlay: (data) -> + # # if a JamTrack is open, and the user hits 'pause' or 'stop', we need to automatically stop the recording + # if @sessionHelper.jamTracks() && @isRecording + # logger.debug("preemptive jamtrack stop") + # @startStopRecording(); - onMediaPausePlay: (data) -> - # if a JamTrack is open, and the user hits 'pause' or 'stop', we need to automatically stop the recording - if @sessionHelper.jamTracks() && @isRecording - logger.debug("preemptive jamtrack stop") - @startStopRecording(); + # if !data.endReached + # logger.debug("calling jamClient.SessionStopPlay. endReached:", data.endReached) + # context.jamClient.SessionStopPlay() + + onMediaStopPlay: `async function(data) { + // if a JamTrack is open, and the user hits 'pause' or 'stop', we need to automatically stop the recording + if (this.sessionHelper.jamTracks() && this.isRecording) { + logger.debug("preemptive jamtrack stop"); + this.startStopRecording(); + } + + if (!data.endReached) { + logger.debug("calling jamClient.SessionStopPlay. endReached:", data.endReached); + await context.jamClient.SessionStopPlay(); + } + }` + + # onMediaPausePlay: (data) -> + # # if a JamTrack is open, and the user hits 'pause' or 'stop', we need to automatically stop the recording + # if @sessionHelper.jamTracks() && @isRecording + # logger.debug("preemptive jamtrack stop") + # @startStopRecording(); - if !data.endReached - logger.debug("calling jamClient.SessionPausePlay. endReached:", data.endReached) - context.jamClient.SessionPausePlay() + # if !data.endReached + # logger.debug("calling jamClient.SessionPausePlay. endReached:", data.endReached) + # context.jamClient.SessionPausePlay() + + onMediaPausePlay: `async function(data) { + // if a JamTrack is open, and the user hits 'pause' or 'stop', we need to automatically stop the recording + if (this.sessionHelper.jamTracks() && this.isRecording) { + logger.debug("preemptive jamtrack stop"); + this.startStopRecording(); + } + + + if (!data.endReached) { + logger.debug("calling jamClient.SessionPausePlay. endReached:", data.endReached); + await context.jamClient.SessionPausePlay(); + } + }` startStopRecording: () -> if @isRecording @@ -61,22 +93,43 @@ RecordingActions = @RecordingActions else RecordingActions.startRecording.trigger() - onMediaChangePosition: (data) -> - seek = data.positionMs; + # onMediaChangePosition: (data) -> + # seek = data.positionMs; - if data.playbackMonitorMode == PLAYBACK_MONITOR_MODE.JAMTRACK - # if positionMs == 0, then seek it back to whatever the earliest play start is to catch all the prelude + # if data.playbackMonitorMode == PLAYBACK_MONITOR_MODE.JAMTRACK + # # if positionMs == 0, then seek it back to whatever the earliest play start is to catch all the prelude - if(seek == 0) - duration = context.jamClient.SessionGetJamTracksPlayDurationMs(); - seek = duration.start; + # if(seek == 0) + # duration = context.jamClient.SessionGetJamTracksPlayDurationMs(); + # seek = duration.start; - logger.debug("calling jamClient.SessionTrackSeekMs(" + seek + ")"); + # logger.debug("calling jamClient.SessionTrackSeekMs(" + seek + ")"); - if data.playbackMonitorMode == PLAYBACK_MONITOR_MODE.JAMTRACK - context.jamClient.SessionJamTrackSeekMs(seek); - else - context.jamClient.SessionTrackSeekMs(seek); + # if data.playbackMonitorMode == PLAYBACK_MONITOR_MODE.JAMTRACK + # context.jamClient.SessionJamTrackSeekMs(seek); + # else + # context.jamClient.SessionTrackSeekMs(seek); + + onMediaChangePosition: `async function(data) { + let seek = data.positionMs; + + if (data.playbackMonitorMode === PLAYBACK_MONITOR_MODE.JAMTRACK) { + // if positionMs == 0, then seek it back to whatever the earliest play start is to catch all the prelude + + if(seek === 0) { + const duration = await context.jamClient.SessionGetJamTracksPlayDurationMs(); + seek = duration.start; + } + } + + logger.debug("calling jamClient.SessionTrackSeekMs(" + seek + ")"); + + if (data.playbackMonitorMode === PLAYBACK_MONITOR_MODE.JAMTRACK) { + await context.jamClient.SessionJamTrackSeekMs(seek); + } else { + await context.jamClient.SessionTrackSeekMs(seek); + } + }` issueChange: () -> @@ -102,19 +155,35 @@ RecordingActions = @RecordingActions @issueChange() - onPositionUpdate: (playbackMode) -> - if playbackMode == PLAYBACK_MONITOR_MODE.JAMTRACK - @positionMs = context.jamClient.SessionCurrrentJamTrackPlayPosMs() - duration = context.jamClient.SessionGetJamTracksPlayDurationMs() - @durationMs = duration.media_len - else - @positionMs = context.jamClient.SessionCurrrentPlayPosMs() - @durationMs = context.jamClient.SessionGetTracksPlayDurationMs() + # onPositionUpdate: (playbackMode) -> + # if playbackMode == PLAYBACK_MONITOR_MODE.JAMTRACK + # @positionMs = context.jamClient.SessionCurrrentJamTrackPlayPosMs() + # duration = context.jamClient.SessionGetJamTracksPlayDurationMs() + # @durationMs = duration.media_len + # else + # @positionMs = context.jamClient.SessionCurrrentPlayPosMs() + # @durationMs = context.jamClient.SessionGetTracksPlayDurationMs() - @isPlaying = context.jamClient.isSessionTrackPlaying() + # @isPlaying = context.jamClient.isSessionTrackPlaying() - @positionUpdateChanged = true - @issueChange() + # @positionUpdateChanged = true + # @issueChange() + + onPositionUpdate: `async function(playbackMode) { + if (playbackMode === PLAYBACK_MONITOR_MODE.JAMTRACK) { + this.positionMs = await context.jamClient.SessionCurrrentJamTrackPlayPosMs(); + const duration = await context.jamClient.SessionGetJamTracksPlayDurationMs(); + this.durationMs = duration.media_len; + } else { + this.positionMs = await context.jamClient.SessionCurrrentPlayPosMs(); + this.durationMs = await context.jamClient.SessionGetTracksPlayDurationMs(); + } + + this.isPlaying = await context.jamClient.isSessionTrackPlaying(); + + this.positionUpdateChanged = true; + return this.issueChange(); + }` } ) diff --git a/web/app/assets/javascripts/react-components/stores/MixerStore.js.coffee b/web/app/assets/javascripts/react-components/stores/MixerStore.js.coffee index 8208f5368..954180ee4 100644 --- a/web/app/assets/javascripts/react-components/stores/MixerStore.js.coffee +++ b/web/app/assets/javascripts/react-components/stores/MixerStore.js.coffee @@ -113,13 +113,23 @@ rest = context.JK.Rest() handleBackingTrackSelectedCallback: () -> logger.debug("backing track selected") - onAppInit: (@app) -> - @gearUtils = context.JK.GearUtilsInstance - @sessionUtils = context.JK.SessionUtils + # onAppInit: (@app) -> + # @gearUtils = context.JK.GearUtilsInstance + # @sessionUtils = context.JK.SessionUtils - context.jamClient.SetVURefreshRate(150) - context.jamClient.RegisterVolChangeCallBack("JK.HandleVolumeChangeCallback2") - context.jamClient.setMetronomeOpenCallback("JK.HandleMetronomeCallback2") + # context.jamClient.SetVURefreshRate(150) + # context.jamClient.RegisterVolChangeCallBack("JK.HandleVolumeChangeCallback2") + # context.jamClient.setMetronomeOpenCallback("JK.HandleMetronomeCallback2") + + onAppInit: `async function(app) { + this.app = app; + this.gearUtils = context.JK.GearUtilsInstance; + this.sessionUtils = context.JK.SessionUtils; + + await context.jamClient.SetVURefreshRate(150); + await context.jamClient.RegisterVolChangeCallBack("JK.HandleVolumeChangeCallback2"); + await context.jamClient.setMetronomeOpenCallback("JK.HandleMetronomeCallback2"); + }` sessionEnded: () -> @@ -128,18 +138,32 @@ rest = context.JK.Rest() @missingMixerPeers = {} clearTimeout(@recheckTimeout) if @recheckTimeout? - onSessionChange: (session) -> + # onSessionChange: (session) -> - @sessionEnded() unless session.inSession() + # @sessionEnded() unless session.inSession() - @session = session + # @session = session - @masterMixers = context.jamClient.SessionGetAllControlState(true); - @personalMixers = context.jamClient.SessionGetAllControlState(false); + # @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) + # @mixers = new context.MixerHelper(@session, @masterMixers, @personalMixers, @metro, @noAudioUsers, @clientsWithAudioOverride, @mixers?.mixMode || MIX_MODES.PERSONAL) - @issueChange() + # @issueChange() + + onSessionChange: `async function(session) { + + if (!session.inSession()) { this.sessionEnded(); } + + this.session = session; + + this.masterMixers = await context.jamClient.SessionGetAllControlState(true); + this.personalMixers = await context.jamClient.SessionGetAllControlState(false); + + this.mixers = new context.MixerHelper(this.session, this.masterMixers, this.personalMixers, this.metro, this.noAudioUsers, this.clientsWithAudioOverride, (this.mixers != null ? this.mixers.mixMode : undefined) || MIX_MODES.PERSONAL); + + return this.issueChange(); + }` onMute: (mixers, muting) -> @@ -165,19 +189,35 @@ rest = context.JK.Rest() onLoopChanged: (mixer, shouldLoop) -> @mixers.loopChanged(mixer, shouldLoop) - onOpenMetronome: () -> - context.jamClient.SessionStopPlay() - context.jamClient.SessionOpenMetronome(@mixers.metro.tempo, @mixers.metro.sound, 1, 0) + # onOpenMetronome: () -> + # context.jamClient.SessionStopPlay() + # context.jamClient.SessionOpenMetronome(@mixers.metro.tempo, @mixers.metro.sound, 1, 0) - onMetronomeChanged: (tempo, sound) -> - logger.debug("onMetronomeChanged", tempo, sound) + onOpenMetronome: `async function() { + await context.jamClient.SessionStopPlay(); + await context.jamClient.SessionOpenMetronome(this.mixers.metro.tempo, this.mixers.metro.sound, 1, 0); + }` - @metro.tempo = tempo - @metro.sound = sound - context.jamClient.SessionSetMetronome(@metro.tempo, @metro.sound, 1, 0); + # onMetronomeChanged: (tempo, sound) -> + # logger.debug("onMetronomeChanged", tempo, sound) - @mixers = new context.MixerHelper(@session, @masterMixers, @personalMixers, @metro, @noAudioUsers, @clientsWithAudioOverride, @mixers?.mixMode || MIX_MODES.PERSONAL) - @issueChange() + # @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() + + onMetronomeChanged: `async function(tempo, sound) { + logger.debug("onMetronomeChanged", tempo, sound); + + this.metro.tempo = tempo; + this.metro.sound = sound; + await context.jamClient.SessionSetMetronome(this.metro.tempo, this.metro.sound, 1, 0); + + this.mixers = new context.MixerHelper(this.session, this.masterMixers, this.personalMixers, this.metro, this.noAudioUsers, this.clientsWithAudioOverride, (this.mixers != null ? this.mixers.mixMode : undefined) || MIX_MODES.PERSONAL); + return this.issueChange(); + }` # codeInitiated means the user did not initiate this onCloseMedia: (codeInitiated) -> @@ -259,23 +299,44 @@ rest = context.JK.Rest() 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 + # 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 = {} + # # 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() + # @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() + + recheckForMixers: `async function() { + // increment how many times we have checked for this particular peer + for (let clientId in this.checkingMissingPeers) { + const meh = this.checkingMissingPeers[clientId]; + let missingPeerAttempts = this.missingMixerPeers[clientId]; + if (missingPeerAttempts == null) { missingPeerAttempts = 0; } + missingPeerAttempts++; + this.missingMixerPeers[clientId] = missingPeerAttempts; + } + + // reset the peers we are looking for + this.checkingMissingPeers = {}; + + this.recheckTimeout = null; + this.masterMixers = await context.jamClient.SessionGetAllControlState(true); + this.personalMixers = await context.jamClient.SessionGetAllControlState(false); + logger.debug("MixerStore: recheckForMixers"); + this.mixers = new context.MixerHelper(this.session, this.masterMixers, this.personalMixers, this.metro, this.noAudioUsers, this.clientsWithAudioOverride, (this.mixers != null ? this.mixers.mixMode : undefined) || MIX_MODES.PERSONAL); + return this.issueChange(); + }` onInitGain: (mixer) -> @mixers.initGain(mixer) @@ -283,17 +344,30 @@ rest = context.JK.Rest() onInitPan: (mixer) -> @mixers.initPan(mixer) - onMixersChanged: (type, text) -> - @masterMixers = context.jamClient.SessionGetAllControlState(true); - @personalMixers = context.jamClient.SessionGetAllControlState(false); + # onMixersChanged: (type, text) -> + # @masterMixers = context.jamClient.SessionGetAllControlState(true); + # @personalMixers = context.jamClient.SessionGetAllControlState(false); - logger.debug("MixerStore: onMixersChanged") + # logger.debug("MixerStore: onMixersChanged") - @mixers = new context.MixerHelper(@session, @masterMixers, @personalMixers, @metro, @noAudioUsers, @clientsWithAudioOverride, @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()) + # SessionActions.mixersChanged.trigger(type, text, @mixers.getTrackInfo()) - @issueChange() + # @issueChange() + + onMixersChanged: `async function(type, text) { + this.masterMixers = await context.jamClient.SessionGetAllControlState(true); + this.personalMixers = await context.jamClient.SessionGetAllControlState(false); + + logger.debug("MixerStore: onMixersChanged"); + + this.mixers = new context.MixerHelper(this.session, this.masterMixers, this.personalMixers, this.metro, this.noAudioUsers, this.clientsWithAudioOverride, (this.mixers != null ? this.mixers.mixMode : undefined) || MIX_MODES.PERSONAL); + + SessionActions.mixersChanged.trigger(type, text, this.mixers.getTrackInfo()); + + return this.issueChange(); + }` onMixerModeChanged: (mode) -> if mode == MIX_MODES.MASTER diff --git a/web/app/assets/javascripts/react-components/stores/PlatformStore.js.coffee b/web/app/assets/javascripts/react-components/stores/PlatformStore.js.coffee index 84366fc7e..01a836636 100644 --- a/web/app/assets/javascripts/react-components/stores/PlatformStore.js.coffee +++ b/web/app/assets/javascripts/react-components/stores/PlatformStore.js.coffee @@ -11,21 +11,42 @@ logger = context.JK.logger init: -> this.listenTo(context.AppStore, this.onAppInit) - jamblasterSerialNo: () -> + # jamblasterSerialNo: () -> - if @serial_no? - return @serial_no + # if @serial_no? + # return @serial_no - if context.jamClient && context.jamClient.jamBlasterSerialNo - @serial_no = context.jamClient.jamBlasterSerialNo() - else - @serial_no= false + # if context.jamClient && context.jamClient.jamBlasterSerialNo + # @serial_no = context.jamClient.jamBlasterSerialNo() + # else + # @serial_no= false - @serial_no + # @serial_no - onAppInit: (@app) -> - @os = context.jamClient.GetOSAsString() - this.trigger({os: @os, isWindows: @isWindows()}) + jamblasterSerialNo: `async function() { + + if (this.serial_no != null) { + return this.serial_no; + } + + if (context.jamClient && await context.jamClient.jamBlasterSerialNo()) { + this.serial_no = await context.jamClient.jamBlasterSerialNo(); + } else { + this.serial_no= false; + } + + return this.serial_no; + }` + + # onAppInit: (@app) -> + # @os = context.jamClient.GetOSAsString() + # this.trigger({os: @os, isWindows: @isWindows()}) + + onAppInit: `async function(app) { + this.app = app; + this.os = await context.jamClient.GetOSAsString(); + this.trigger({os: this.os, isWindows: this.isWindows()}); + }` isWindows: -> @os == 'Win32' diff --git a/web/app/assets/javascripts/react-components/stores/RecordingStore.js.jsx.coffee b/web/app/assets/javascripts/react-components/stores/RecordingStore.js.jsx.coffee index 70e49ee33..1af07d80f 100644 --- a/web/app/assets/javascripts/react-components/stores/RecordingStore.js.jsx.coffee +++ b/web/app/assets/javascripts/react-components/stores/RecordingStore.js.jsx.coffee @@ -32,18 +32,33 @@ BackendToFrontendFPS = { @recordingModel = recordingModel this.trigger({isRecording: @recordingModel.isRecording()}) - onStartRecording: (recordVideo, recordChat) -> - frameRate = 0 - if recordVideo - if context.jamClient.GetCurrentVideoFrameRate? - frameRate = context.jamClient.GetCurrentVideoFrameRate() || 0; - frameRate = BackendToFrontendFPS[frameRate] + # onStartRecording: (recordVideo, recordChat) -> + # frameRate = 0 + # if recordVideo + # if context.jamClient.GetCurrentVideoFrameRate? + # frameRate = context.jamClient.GetCurrentVideoFrameRate() || 0; + # frameRate = BackendToFrontendFPS[frameRate] - NoVideoRecordActive = 0 - WebCamRecordActive = 1 - ScreenRecordActive = 2 - logger.debug("onStartRecording: recordVideo: #{recordVideo}, recordChat: #{recordChat} frameRate: #{frameRate}") - @recordingModel.startRecording(recordVideo, recordChat, frameRate) + # NoVideoRecordActive = 0 + # WebCamRecordActive = 1 + # ScreenRecordActive = 2 + # logger.debug("onStartRecording: recordVideo: #{recordVideo}, recordChat: #{recordChat} frameRate: #{frameRate}") + # @recordingModel.startRecording(recordVideo, recordChat, frameRate) + + onStartRecording: `async function(recordVideo, recordChat) { + let frameRate = 0; + if (recordVideo) { + //if (await context.jamClient.GetCurrentVideoFrameRate() != null) { + frameRate = await context.jamClient.GetCurrentVideoFrameRate() || 0; + frameRate = BackendToFrontendFPS[frameRate]; + //} + } + const NoVideoRecordActive = 0; + const WebCamRecordActive = 1; + const ScreenRecordActive = 2; + logger.debug('onStartRecording: recordVideo: '+recordVideo+' , recordChat:' +recordChat+' frameRate: '+frameRate); + this.recordingModel.startRecording(recordVideo, recordChat, frameRate); + }` onStopRecording: () -> @recordingModel.stopRecording() diff --git a/web/app/assets/javascripts/react-components/stores/SessionStore.js.coffee b/web/app/assets/javascripts/react-components/stores/SessionStore.js.coffee index 5d22eb376..235ae48a3 100644 --- a/web/app/assets/javascripts/react-components/stores/SessionStore.js.coffee +++ b/web/app/assets/javascripts/react-components/stores/SessionStore.js.coffee @@ -13,7 +13,6 @@ NotificationActions = @NotificationActions VideoActions = @VideoActions ConfigureTracksActions = @ConfigureTracksActions -_closeRecording = `async function(){logger.debug("closing recording");rest.stopPlayClaimedRecording({id:this.currentSessionId,claimed_recording_id:this.currentSession.claimed_recording.id}).done(response=>{this.onUpdateSession(response);}).fail(jqXHR=>{this.app.notify({"title":"Couldn't Stop Recording Playback","text":"Couldn't inform the server to stop playback. msg="+jqXHR.responseText,"icon_url":"/assets/content/icon_alert_big.png"});}); await context.jamClient.CloseRecording();}` @SessionStore = Reflux.createStore( { @@ -59,16 +58,29 @@ _closeRecording = `async function(){logger.debug("closing recording");rest.stopP RecordingActions.initModel(@recordingModel) @helper = new context.SessionHelper(@app, @currentSession, @participantsEverSeen, @isRecording, @downloadingJamTrack, @enableVstTimeout?, @sessionRules, @subscriptionRules) - onSessionJoinedByOther: (payload) -> - clientId = payload.client_id + # onSessionJoinedByOther: (payload) -> + # clientId = payload.client_id - #parentClientId = context.jamClient.getParentClientId() - #if parentClientId? && parentClientId != '' - #if parentClientId == clientId - # auto nav to session - if context.jamClient.getClientParentChildRole && context.jamClient.getClientParentChildRole() == CLIENT_ROLE.CHILD && payload.source_user_id == context.JK.currentUserId - logger.debug("autonav to session #{payload.session_id}") - context.SessionActions.navToSession(payload.session_id) + # #parentClientId = context.jamClient.getParentClientId() + # #if parentClientId? && parentClientId != '' + # #if parentClientId == clientId + # # auto nav to session + # if context.jamClient.getClientParentChildRole && context.jamClient.getClientParentChildRole() == CLIENT_ROLE.CHILD && payload.source_user_id == context.JK.currentUserId + # logger.debug("autonav to session #{payload.session_id}") + # context.SessionActions.navToSession(payload.session_id) + + onSessionJoinedByOther: `async function(payload) { + const clientId = payload.client_id; + + //parentClientId = context.jamClient.getParentClientId() + //if parentClientId? && parentClientId != '' + //if parentClientId == clientId + // auto nav to session + if (await context.jamClient.getClientParentChildRole() === CLIENT_ROLE.CHILD && (payload.source_user_id === context.JK.currentUserId)) { + logger.debug('autonav to session '+payload.session_id); + context.SessionActions.navToSession(payload.session_id); + } + }` onNavToSession: (sessionId) -> context.location = '/client#/session/' + sessionId @@ -142,8 +154,12 @@ _closeRecording = `async function(){logger.debug("closing recording");rest.stopP else logger.debug("unable to report source change because no mount seen on session") - onShowNativeMetronomeGui: () -> - context.jamClient.SessionShowMetronomeGui() + # onShowNativeMetronomeGui: () -> + # context.jamClient.SessionShowMetronomeGui() + + onShowNativeMetronomeGui: `async function() { + await context.jamClient.SessionShowMetronomeGui(); + }` onOpenMetronome: () -> unstable = @unstableNTPClocks() @@ -172,33 +188,66 @@ _closeRecording = `async function(){logger.debug("closing recording");rest.stopP }) ) - onMetronomeCricketChange: (isCricket) -> - context.jamClient.setMetronomeCricketTestState(isCricket); + # onMetronomeCricketChange: (isCricket) -> + # context.jamClient.setMetronomeCricketTestState(isCricket); - unstableNTPClocks: () -> - unstable = [] - # This should be handled in the below loop, actually: - myState = context.jamClient.getMyNetworkState() - map = null - for participant in @participants() - isSelf = participant.client_id == @app.clientId + onMetronomeCricketChange: `async function(isCricket) { + await context.jamClient.setMetronomeCricketTestState(isCricket); + }` - if isSelf - isStable = myState.ntp_stable - else - map = context.jamClient.getPeerState(participant.client_id) - isStable = map.ntp_stable + # unstableNTPClocks: () -> + # unstable = [] + # # This should be handled in the below loop, actually: + # myState = context.jamClient.getMyNetworkState() + # map = null + # for participant in @participants() + # isSelf = participant.client_id == @app.clientId - if !isStable - name = participant.user.name + # if isSelf + # isStable = myState.ntp_stable + # else + # map = context.jamClient.getPeerState(participant.client_id) + # isStable = map.ntp_stable - if isSelf - name += " (this computer)" + # if !isStable + # name = participant.user.name - unstable.push(name) - unstable + # if isSelf + # name += " (this computer)" + # unstable.push(name) + # unstable + unstableNTPClocks: `async function() { + const unstable = []; + // This should be handled in the below loop, actually: + const myState = await context.jamClient.getMyNetworkState(); + let map = null; + for (let participant of Array.from(this.participants())) { + var isStable; + const isSelf = participant.client_id === this.app.clientId; + + if (isSelf) { + isStable = myState.ntp_stable; + } else { + map = await context.jamClient.getPeerState(participant.client_id); + isStable = map.ntp_stable; + } + + if (!isStable) { + let { + name + } = participant.user; + + if (isSelf) { + name += " (this computer)"; + } + + unstable.push(name); + } + } + return unstable; + }` onDownloadingJamTrack: (downloading) -> @downloadingJamTrack = downloading @@ -217,14 +266,25 @@ _closeRecording = `async function(){logger.debug("closing recording");rest.stopP }) - onAudioResync: () -> - logger.debug("audio resyncing") - response = context.jamClient.SessionAudioResync() - if response? - @app.notify({ + # onAudioResync: () -> + # logger.debug("audio resyncing") + # response = context.jamClient.SessionAudioResync() + # if response? + # @app.notify({ + # "title": "Error", + # "text": response, + # "icon_url": "/assets/content/icon_alert_big.png"}) + + onAudioResync: `async function() { + logger.debug("audio resyncing"); + const response = await context.jamClient.SessionAudioResync(); + if (response != null) { + return this.app.notify({ "title": "Error", "text": response, - "icon_url": "/assets/content/icon_alert_big.png"}) + "icon_url": "/assets/content/icon_alert_big.png"}); + } + }` onSyncWithServer: () -> @refreshCurrentSession(true) @@ -253,64 +313,125 @@ _closeRecording = `async function(){logger.debug("closing recording");rest.stopP else logger.error("don't know how to close open media", @helper) unless codeInitiated + # closeJamTrack: () -> + # logger.debug("closing jam track"); - closeJamTrack: () -> + # if @isRecording + # logger.debug("can't close jamtrack while recording") + # @app.notify({title: 'Can Not Close JamTrack', text: 'A JamTrack can not be closed while recording.'}) + # return + + # unless @selfOpenedJamTracks() + # logger.debug("can't close jamtrack if not the opener") + # @app.notify({title: 'Can Not Close JamTrack', text: 'Only the person who opened the JamTrack can close it.'}) + # return + + # rest.closeJamTrack({id: @currentSessionId}) + # .done(() => + # @downloadingJamTrack = false + # @refreshCurrentSession(true) + # ) + # .fail((jqXHR) => + # @app.notify({ + # "title": "Couldn't Close JamTrack", + # "text": "Couldn't inform the server to close JamTrack. msg=" + jqXHR.responseText, + # "icon_url": "/assets/content/icon_alert_big.png" + # }) + # ) + + # context.jamClient.JamTrackStopPlay() + # JamTrackActions.close() + + closeJamTrack: `async function() { logger.debug("closing jam track"); - if @isRecording - logger.debug("can't close jamtrack while recording") - @app.notify({title: 'Can Not Close JamTrack', text: 'A JamTrack can not be closed while recording.'}) - return + if (this.isRecording) { + logger.debug("can't close jamtrack while recording"); + this.app.notify({title: 'Can Not Close JamTrack', text: 'A JamTrack can not be closed while recording.'}); + } - unless @selfOpenedJamTracks() - logger.debug("can't close jamtrack if not the opener") - @app.notify({title: 'Can Not Close JamTrack', text: 'Only the person who opened the JamTrack can close it.'}) - return + if (!this.selfOpenedJamTracks()) { + logger.debug("can't close jamtrack if not the opener"); + this.app.notify({title: 'Can Not Close JamTrack', text: 'Only the person who opened the JamTrack can close it.'}); + } - rest.closeJamTrack({id: @currentSessionId}) - .done(() => - @downloadingJamTrack = false - @refreshCurrentSession(true) - ) - .fail((jqXHR) => - @app.notify({ + rest.closeJamTrack({id: this.currentSessionId}) + .done(() => { + this.downloadingJamTrack = false; + return this.refreshCurrentSession(true); + }) + .fail(jqXHR => { + return this.app.notify({ "title": "Couldn't Close JamTrack", "text": "Couldn't inform the server to close JamTrack. msg=" + jqXHR.responseText, "icon_url": "/assets/content/icon_alert_big.png" - }) - ) + }); + }); - context.jamClient.JamTrackStopPlay() - JamTrackActions.close() + await context.jamClient.JamTrackStopPlay(); + JamTrackActions.close(); + }` - onOpenBackingTrack: (result) -> - unless @inSession() - logger.debug("ignoring backing track selected callback (not in session)") - return + # onOpenBackingTrack: (result) -> + # unless @inSession() + # logger.debug("ignoring backing track selected callback (not in session)") + # return - if result.success - logger.debug("backing track selected: " + result.file); + # if result.success + # logger.debug("backing track selected: " + result.file); - rest.openBackingTrack({id: @currentSessionId, backing_track_path: result.file}) - .done(() => + # rest.openBackingTrack({id: @currentSessionId, backing_track_path: result.file}) + # .done(() => - openResult = context.jamClient.SessionOpenBackingTrackFile(result.file, false); + # openResult = context.jamClient.SessionOpenBackingTrackFile(result.file, false); - if openResult - # storing session state in memory, not in response of Session server response. bad. - @openBackingTrack = result.file - else - @app.notify({ - "title": "Couldn't Open Backing Track", - "text": "Is the file a valid audio file?", - "icon_url": "/assets/content/icon_alert_big.png" - }); - @closeBackingTrack() - ) - .fail((jqXHR) => - @app.notifyServerError(jqXHR, "Unable to Open Backing Track For Playback"); - ) + # if openResult + # # storing session state in memory, not in response of Session server response. bad. + # @openBackingTrack = result.file + # else + # @app.notify({ + # "title": "Couldn't Open Backing Track", + # "text": "Is the file a valid audio file?", + # "icon_url": "/assets/content/icon_alert_big.png" + # }); + # @closeBackingTrack() + # ) + # .fail((jqXHR) => + # @app.notifyServerError(jqXHR, "Unable to Open Backing Track For Playback"); + # ) + + onOpenBackingTrack: `function(result) { + if (!this.inSession()) { + logger.debug("ignoring backing track selected callback (not in session)"); + return; + } + + if (result.success) { + logger.debug("backing track selected: " + result.file); + + return rest.openBackingTrack({id: this.currentSessionId, backing_track_path: result.file}) + .done(async () => { + + const openResult = await context.jamClient.SessionOpenBackingTrackFile(result.file, false); + + if (openResult) { + // storing session state in memory, not in response of Session server response. bad. + return this.openBackingTrack = result.file; + } else { + this.app.notify({ + "title": "Couldn't Open Backing Track", + "text": "Is the file a valid audio file?", + "icon_url": "/assets/content/icon_alert_big.png" + }); + return this.closeBackingTrack(); + } + }) + .fail(jqXHR => { + return this.app.notifyServerError(jqXHR, "Unable to Open Backing Track For Playback"); + }); + } + }` # closeRecording: () -> # logger.debug("closing recording"); @@ -331,43 +452,99 @@ _closeRecording = `async function(){logger.debug("closing recording");rest.stopP # context.jamClient.CloseRecording() - closeRecording: _closeRecording + closeRecording: `async function() { + logger.debug("closing recording"); - closeMetronomeTrack:() -> - logger.debug("SessionStore: closeMetronomeTrack") - rest.closeMetronome({id: @currentSessionId}) - .done(() => - context.jamClient.SessionCloseMetronome() - @refreshCurrentSession(true) - ) - .fail((jqXHR) => - @app.notify({ + rest.stopPlayClaimedRecording({id: this.currentSessionId, claimed_recording_id: this.currentSession.claimed_recording.id}) + .done(response => { + //sessionModel.refreshCurrentSession(true); + // update session info + return this.onUpdateSession(response); + }) + .fail(jqXHR => { + return this.app.notify({ + "title": "Couldn't Stop Recording Playback", + "text": "Couldn't inform the server to stop playback. msg=" + jqXHR.responseText, + "icon_url": "/assets/content/icon_alert_big.png" + }); + }); + + await context.jamClient.CloseRecording(); + }` + + # closeMetronomeTrack:() -> + # logger.debug("SessionStore: closeMetronomeTrack") + # rest.closeMetronome({id: @currentSessionId}) + # .done(() => + # context.jamClient.SessionCloseMetronome() + # @refreshCurrentSession(true) + # ) + # .fail((jqXHR) => + # @app.notify({ + # "title": "Couldn't Close MetronomeTrack", + # "text": "Couldn't inform the server to close MetronomeTrack. msg=" + jqXHR.responseText, + # "icon_url": "/assets/content/icon_alert_big.png" + # }) + # ) + + closeMetronomeTrack: `function() { + logger.debug("SessionStore: closeMetronomeTrack"); + return rest.closeMetronome({id: this.currentSessionId}) + .done(async() => { + await context.jamClient.SessionCloseMetronome(); + this.refreshCurrentSession(true); + }) + .fail(jqXHR => { + return this.app.notify({ "title": "Couldn't Close MetronomeTrack", "text": "Couldn't inform the server to close MetronomeTrack. msg=" + jqXHR.responseText, "icon_url": "/assets/content/icon_alert_big.png" - }) - ) - - closeBackingTrack: () -> - if @isRecording - logger.debug("can't close backing track while recording") - return - - - rest.closeBackingTrack({id: @currentSessionId}) - .done(() => - ) - .fail(() => - @app.notify({ - "title": "Couldn't Close Backing Track", - "text": "Couldn't inform the server to close Backing Track. msg=" + jqXHR.responseText, - "icon_url": "/assets/content/icon_alert_big.png" }); - ) + }); + }` - # '' closes all open backing tracks - context.jamClient.SessionStopPlay(); - context.jamClient.SessionCloseBackingTrackFile(''); + # closeBackingTrack: () -> + # if @isRecording + # logger.debug("can't close backing track while recording") + # return + + + # rest.closeBackingTrack({id: @currentSessionId}) + # .done(() => + # ) + # .fail(() => + # @app.notify({ + # "title": "Couldn't Close Backing Track", + # "text": "Couldn't inform the server to close Backing Track. msg=" + jqXHR.responseText, + # "icon_url": "/assets/content/icon_alert_big.png" + # }); + # ) + + # # '' closes all open backing tracks + # context.jamClient.SessionStopPlay(); + # context.jamClient.SessionCloseBackingTrackFile(''); + + closeBackingTrack: `async function() { + if (this.isRecording) { + logger.debug("can't close backing track while recording"); + return; + } + + rest.closeBackingTrack({id: this.currentSessionId}) + .done(() => { + }) + .fail(() => { + return this.app.notify({ + "title": "Couldn't Close Backing Track", + "text": "Couldn't inform the server to close Backing Track. msg=" + jqXHR.responseText, + "icon_url": "/assets/content/icon_alert_big.png" + }); + }); + + // '' closes all open backing tracks + await context.jamClient.SessionStopPlay(); + await context.jamClient.SessionCloseBackingTrackFile(''); + }` onMixersChanged: (type, text, trackInfo) -> @@ -430,106 +607,254 @@ _closeRecording = `async function(){logger.debug("closing recording");rest.stopP else if text == 'Local Peer Stream Mixer Mode' MixerActions.mixerModeChanged(MIX_MODES.PERSONAL) - onRecordingChanged: (details) -> - logger.debug("SessionStore.onRecordingChanged: " + details.cause) - @isRecording = details.isRecording + # onRecordingChanged: (details) -> + # logger.debug("SessionStore.onRecordingChanged: " + details.cause) + # @isRecording = details.isRecording - switch details.cause - when 'started' + # switch details.cause + # when 'started' - if details.reason - reason = details.reason; - detail = details.detail; - title = "Could Not Start Recording"; + # if details.reason + # reason = details.reason; + # detail = details.detail; + # title = "Could Not Start Recording"; - switch reason - when 'client-no-response' - @notifyWithUserInfo(title, 'did not respond to the start signal.', detail) - when 'empty-recording-id' - @app.notifyAlert(title, "No recording ID specified.") - when 'missing-client' - @notifyWithUserInfo(title, 'could not be signalled to start recording.', detail) - when 'already-recording' - @app.notifyAlert(title, 'Already recording. If this appears incorrect, try restarting JamKazam.') - when 'recording-engine-unspecified' - @notifyWithUserInfo(title, 'had a problem writing recording data to disk.', detail) - when 'recording-engine-create-directory' - @notifyWithUserInfo(title, 'had a problem creating a recording folder.', detail) - when 'recording-engine-create-file' - @notifyWithUserInfo(title, 'had a problem creating a recording file.', detail) - when 'recording-engine-sample-rate' - @notifyWithUserInfo(title, 'had a problem recording at the specified sample rate.', detail) - when 'rest' - jqXHR = detail[0]; - @app.notifyServerError(jqXHR); - else - @notifyWithUserInfo(title, 'Error Reason: ' + reason) - else - @displayWhoCreatedRecording(details.clientId) + # switch reason + # when 'client-no-response' + # @notifyWithUserInfo(title, 'did not respond to the start signal.', detail) + # when 'empty-recording-id' + # @app.notifyAlert(title, "No recording ID specified.") + # when 'missing-client' + # @notifyWithUserInfo(title, 'could not be signalled to start recording.', detail) + # when 'already-recording' + # @app.notifyAlert(title, 'Already recording. If this appears incorrect, try restarting JamKazam.') + # when 'recording-engine-unspecified' + # @notifyWithUserInfo(title, 'had a problem writing recording data to disk.', detail) + # when 'recording-engine-create-directory' + # @notifyWithUserInfo(title, 'had a problem creating a recording folder.', detail) + # when 'recording-engine-create-file' + # @notifyWithUserInfo(title, 'had a problem creating a recording file.', detail) + # when 'recording-engine-sample-rate' + # @notifyWithUserInfo(title, 'had a problem recording at the specified sample rate.', detail) + # when 'rest' + # jqXHR = detail[0]; + # @app.notifyServerError(jqXHR); + # else + # @notifyWithUserInfo(title, 'Error Reason: ' + reason) + # else + # @displayWhoCreatedRecording(details.clientId) - when 'stopped' - if @selfOpenedJamTracks() - timeline = context.jamClient.GetJamTrackTimeline(); + # when 'stopped' + # if @selfOpenedJamTracks() + # timeline = context.jamClient.GetJamTrackTimeline(); - rest.addRecordingTimeline(details.recordingId, timeline) - .fail(()=> - @app.notify({ - title: "Unable to Add JamTrack Volume Data", - text: "The volume of the JamTrack will not be correct in the recorded mix." - }, null, true) - ) + # rest.addRecordingTimeline(details.recordingId, timeline) + # .fail(()=> + # @app.notify({ + # title: "Unable to Add JamTrack Volume Data", + # text: "The volume of the JamTrack will not be correct in the recorded mix." + # }, null, true) + # ) - if details.reason - logger.warn("Recording Discarded: ", details) - reason = details.reason - detail = details.detail - title = "Recording Discarded" + # if details.reason + # logger.warn("Recording Discarded: ", details) + # reason = details.reason + # detail = details.detail + # title = "Recording Discarded" - switch reason - when 'client-no-response' - @notifyWithUserInfo(title, 'did not respond to the stop signal.', detail) - when 'missing-client' - @notifyWithUserInfo(title, 'could not be signalled to stop recording.', detail) - when 'empty-recording-id' - @app.notifyAlert(title, "No recording ID specified.") - when 'wrong-recording-id' - @app.notifyAlert(title, "Wrong recording ID specified.") - when 'not-recording' - @app.notifyAlert(title, "Not currently recording.") - when 'already-stopping' - @app.notifyAlert(title, "Already stopping the current recording.") - when 'start-before-stop' - @notifyWithUserInfo(title, 'asked that we start a new recording; cancelling the current one.', detail) - else - @app.notifyAlert(title, "Error reason: " + reason) - else - @promptUserToSave(details.recordingId, timeline); + # switch reason + # when 'client-no-response' + # @notifyWithUserInfo(title, 'did not respond to the stop signal.', detail) + # when 'missing-client' + # @notifyWithUserInfo(title, 'could not be signalled to stop recording.', detail) + # when 'empty-recording-id' + # @app.notifyAlert(title, "No recording ID specified.") + # when 'wrong-recording-id' + # @app.notifyAlert(title, "Wrong recording ID specified.") + # when 'not-recording' + # @app.notifyAlert(title, "Not currently recording.") + # when 'already-stopping' + # @app.notifyAlert(title, "Already stopping the current recording.") + # when 'start-before-stop' + # @notifyWithUserInfo(title, 'asked that we start a new recording; cancelling the current one.', detail) + # else + # @app.notifyAlert(title, "Error reason: " + reason) + # else + # @promptUserToSave(details.recordingId, timeline); - when 'abortedRecording' - reason = details.reason - detail = details.detail + # when 'abortedRecording' + # reason = details.reason + # detail = details.detail - title = "Recording Cancelled" + # title = "Recording Cancelled" - switch reason - when 'client-no-response' - @notifyWithUserInfo(title, 'did not respond to the start signal.', detail) - when 'missing-client' - @notifyWithUserInfo(title, 'could not be signalled to start recording.', detail) - when 'populate-recording-info' - @notifyWithUserInfo(title, 'could not synchronize with the server.', detail) - when 'recording-engine-unspecified' - @notifyWithUserInfo(title, 'had a problem writing recording data to disk.', detail) - when 'recording-engine-create-directory' - @notifyWithUserInfo(title, 'had a problem creating a recording folder.', detail) - when 'recording-engine-create-file' - @notifyWithUserInfo(title, 'had a problem creating a recording file.', detail) - when 'recording-engine-sample-rate' - @notifyWithUserInfo(title, 'had a problem recording at the specified sample rate.', detail) - else - @app.notifyAlert(title, "Error reason: " + reason) + # switch reason + # when 'client-no-response' + # @notifyWithUserInfo(title, 'did not respond to the start signal.', detail) + # when 'missing-client' + # @notifyWithUserInfo(title, 'could not be signalled to start recording.', detail) + # when 'populate-recording-info' + # @notifyWithUserInfo(title, 'could not synchronize with the server.', detail) + # when 'recording-engine-unspecified' + # @notifyWithUserInfo(title, 'had a problem writing recording data to disk.', detail) + # when 'recording-engine-create-directory' + # @notifyWithUserInfo(title, 'had a problem creating a recording folder.', detail) + # when 'recording-engine-create-file' + # @notifyWithUserInfo(title, 'had a problem creating a recording file.', detail) + # when 'recording-engine-sample-rate' + # @notifyWithUserInfo(title, 'had a problem recording at the specified sample rate.', detail) + # else + # @app.notifyAlert(title, "Error reason: " + reason) - @issueChange() + # @issueChange() + + onRecordingChanged: `async function(details) { + let detail, reason, timeline, title; + logger.debug("SessionStore.onRecordingChanged: " + details.cause); + this.isRecording = details.isRecording; + + switch (details.cause) { + case 'started': + + if (details.reason) { + ({ + reason + } = details); + ({ + detail + } = details); + title = "Could Not Start Recording"; + + switch (reason) { + case 'client-no-response': + this.notifyWithUserInfo(title, 'did not respond to the start signal.', detail); + break; + case 'empty-recording-id': + this.app.notifyAlert(title, "No recording ID specified."); + break; + case 'missing-client': + this.notifyWithUserInfo(title, 'could not be signalled to start recording.', detail); + break; + case 'already-recording': + this.app.notifyAlert(title, 'Already recording. If this appears incorrect, try restarting JamKazam.'); + break; + case 'recording-engine-unspecified': + this.notifyWithUserInfo(title, 'had a problem writing recording data to disk.', detail); + break; + case 'recording-engine-create-directory': + this.notifyWithUserInfo(title, 'had a problem creating a recording folder.', detail); + break; + case 'recording-engine-create-file': + this.notifyWithUserInfo(title, 'had a problem creating a recording file.', detail); + break; + case 'recording-engine-sample-rate': + this.notifyWithUserInfo(title, 'had a problem recording at the specified sample rate.', detail); + break; + case 'rest': + var jqXHR = detail[0]; + this.app.notifyServerError(jqXHR); + break; + default: + this.notifyWithUserInfo(title, 'Error Reason: ' + reason); + } + } else { + this.displayWhoCreatedRecording(details.clientId); + } + break; + + case 'stopped': + if (this.selfOpenedJamTracks()) { + timeline = await context.jamClient.GetJamTrackTimeline(); + + rest.addRecordingTimeline(details.recordingId, timeline) + .fail(()=> { + return this.app.notify({ + title: "Unable to Add JamTrack Volume Data", + text: "The volume of the JamTrack will not be correct in the recorded mix." + }, null, true); + }); + } + + if (details.reason) { + logger.warn("Recording Discarded: ", details); + ({ + reason + } = details); + ({ + detail + } = details); + title = "Recording Discarded"; + + switch (reason) { + case 'client-no-response': + this.notifyWithUserInfo(title, 'did not respond to the stop signal.', detail); + break; + case 'missing-client': + this.notifyWithUserInfo(title, 'could not be signalled to stop recording.', detail); + break; + case 'empty-recording-id': + this.app.notifyAlert(title, "No recording ID specified."); + break; + case 'wrong-recording-id': + this.app.notifyAlert(title, "Wrong recording ID specified."); + break; + case 'not-recording': + this.app.notifyAlert(title, "Not currently recording."); + break; + case 'already-stopping': + this.app.notifyAlert(title, "Already stopping the current recording."); + break; + case 'start-before-stop': + this.notifyWithUserInfo(title, 'asked that we start a new recording; cancelling the current one.', detail); + break; + default: + this.app.notifyAlert(title, "Error reason: " + reason); + } + } else { + this.promptUserToSave(details.recordingId, timeline); + } + break; + + case 'abortedRecording': + ({ + reason + } = details); + ({ + detail + } = details); + + title = "Recording Cancelled"; + + switch (reason) { + case 'client-no-response': + this.notifyWithUserInfo(title, 'did not respond to the start signal.', detail); + break; + case 'missing-client': + this.notifyWithUserInfo(title, 'could not be signalled to start recording.', detail); + break; + case 'populate-recording-info': + this.notifyWithUserInfo(title, 'could not synchronize with the server.', detail); + break; + case 'recording-engine-unspecified': + this.notifyWithUserInfo(title, 'had a problem writing recording data to disk.', detail); + break; + case 'recording-engine-create-directory': + this.notifyWithUserInfo(title, 'had a problem creating a recording folder.', detail); + break; + case 'recording-engine-create-file': + this.notifyWithUserInfo(title, 'had a problem creating a recording file.', detail); + break; + case 'recording-engine-sample-rate': + this.notifyWithUserInfo(title, 'had a problem recording at the specified sample rate.', detail); + break; + default: + this.app.notifyAlert(title, "Error reason: " + reason); + } + break; + } + + return this.issueChange(); + }` notifyWithUserInfo: (title , text, clientId) -> @findUserBy({clientId: clientId}) @@ -741,153 +1066,319 @@ _closeRecording = `async function(){logger.debug("closing recording");rest.stopP context.JK.popExternalLink("https://jamkazam.freshdesk.com/support/solutions/articles/66000122535-what-are-jamkazam-s-free-vs-premium-features-") return 'noclose' - joinSession: () -> - 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) + # joinSession: () -> + # 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 == 0 + # clientRole = 'child' + # else if clientRole == 1 + # clientRole = 'parent' - if clientRole == '' || !clientRole - clientRole = null + # if clientRole == '' || !clientRole + # clientRole = null - # subscribe to events from the recording model - @recordingRegistration() + # # subscribe to events from the recording model + # @recordingRegistration() - # tell the server we want to join + # # tell the server we want to join - @joinDeferred = rest.joinSession({ - client_id: @app.clientId, + # @joinDeferred = rest.joinSession({ + # client_id: @app.clientId, + # ip_address: context.JK.JamServer.publicIP, + # as_musician: true, + # tracks: @userTracks, + # session_id: @currentSessionId, + # client_role: clientRole, + # parent_client_id: parentClientId + # audio_latency: context.jamClient.FTUEGetExpectedLatency().latency + # }) + # .done((response) => + + # unless @inSession() + # # the user has left the session before they got joined. We need to issue a leave again to the server to make sure they are out + # logger.debug("user left before fully joined to session. telling server again that they have left") + # @leaveSessionRest(@currentSessionId) + # return + + # @updateSessionInfo(response, true) + # @issueChange() + + # logger.debug("calling jamClient.JoinSession"); + # # on temporary disconnect scenarios, a user may already be in a session when they enter this path + # # so we avoid double counting + # unless @alreadyInSession() + # if @participants().length == 1 + # context.JK.GA.trackSessionMusicians(context.JK.GA.SessionCreationTypes.create); + # else + # context.JK.GA.trackSessionMusicians(context.JK.GA.SessionCreationTypes.join); + + # @recordingModel.reset(@currentSessionId); + + # joinSessionMsg = {sessionID: @currentSessionId, music_session_id_int: response.music_session_id_int} + # context.jamClient.JoinSession(joinSessionMsg); + + # #@refreshCurrentSession(true); + + # context.JK.JamServer.registerMessageCallback(context.JK.MessageType.SESSION_JOIN, @trackChanges); + # context.JK.JamServer.registerMessageCallback(context.JK.MessageType.SESSION_DEPART, @trackChanges); + # context.JK.JamServer.registerMessageCallback(context.JK.MessageType.TRACKS_CHANGED, @trackChanges); + # context.JK.JamServer.registerMessageCallback(context.JK.MessageType.HEARTBEAT_ACK, @trackChanges); + + # $(document).trigger(EVENTS.SESSION_STARTED, {session: {id: @currentSessionId, lesson_session: response.lesson_session}}) if document + + # @handleAutoOpenJamTrack() + + # @watchBackendStats() + + # ConfigureTracksActions.reset(true) + # @delayEnableVst() + # ) + # .fail((xhr) => + # @updateCurrentSession(null) + + # if xhr.status == 404 + # # we tried to join the session, but it's already gone. kick user back to join session screen + # leaveBehavior = + # location: "/client#/findSession" + # notify: + # title: "Unable to Join Session", + # text: " The session you attempted to join is over." + # SessionActions.leaveSession.trigger(leaveBehavior) + # else if xhr.status == 422 + # response = JSON.parse(xhr.responseText); + # if response["errors"] && response["errors"]["tracks"] && response["errors"]["tracks"][0] == "Please select at least one track" + # @app.notifyAlert("No Inputs Configured", $('You will need to reconfigure your audio device.')) + + # else if response["errors"] && response["errors"]["music_session"] && response["errors"]["music_session"][0] == ["is currently recording"] + # leaveBehavior = + # location: "/client#/findSession" + # notify: + # title: "Unable to Join Session" + # text: "The session is currently recording." + # SessionActions.leaveSession.trigger(leaveBehavior) + # else if response["errors"] && response["errors"]["remaining_session_play_time"] + # leaveBehavior = + # location: "/client#/findSession" + # buttons = [] + # buttons.push({name: 'CLOSE', buttonStyle: 'button-grey'}) + # buttons.push({name: 'COMPARE PLANS', buttonStyle: 'button-grey', click: (() => (@openBrowserToPlanComparison()))}) + # buttons.push({ + # name: 'UPGRADE PLAN', + # buttonStyle: 'button-orange', + # click: (() => (@openBrowserToPayment())) + # }) + # context.JK.Banner.show({ + # title: "Out of Time For This Session", + # html: context._.template($('#template-no-remaining-session-play-time').html(), {}, { variable: 'data' }), + # buttons: buttons}); + # SessionActions.leaveSession.trigger(leaveBehavior) + # else if response["errors"] && response["errors"]["remaining_month_play_time"] + # leaveBehavior = + # location: "/client#/findSession" + # buttons = [] + # buttons.push({name: 'CLOSE', buttonStyle: 'button-grey'}) + # buttons.push({name: 'COMPARE PLANS', buttonStyle: 'button-grey', click: (() => (@openBrowserToPlanComparison()))}) + # buttons.push({ + # name: 'UPGRADE PLAN', + # buttonStyle: 'button-orange', + # click: (() => (@openBrowserToPayment())) + # }) + # context.JK.Banner.show({ + # title: "Out of Time for the Month", + # html: context._.template($('#template-no-remaining-month-play-time').html(), {}, { variable: 'data' }), + # buttons: buttons}); + # SessionActions.leaveSession.trigger(leaveBehavior) + # else + # @app.notifyServerError(xhr, 'Unable to Join Session'); + # else + # @app.notifyServerError(xhr, 'Unable to Join Session'); + # ) + + joinSession: `async function() { + await context.jamClient.SessionRegisterCallback("JK.HandleBridgeCallback2"); + await context.jamClient.RegisterRecordingCallbacks("JK.HandleRecordingStartResult", "JK.HandleRecordingStopResult", "JK.HandleRecordingStarted", "JK.HandleRecordingStopped", "JK.HandleRecordingAborted"); + await context.jamClient.SessionSetConnectionStatusRefreshRate(1000); + let clientRole = await context.jamClient.getClientParentChildRole(); + const parentClientId = await 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 + this.recordingRegistration(); + + // tell the server we want to join + + return this.joinDeferred = rest.joinSession({ + client_id: this.app.clientId, ip_address: context.JK.JamServer.publicIP, as_musician: true, - tracks: @userTracks, - session_id: @currentSessionId, + tracks: this.userTracks, + session_id: this.currentSessionId, client_role: clientRole, - parent_client_id: parentClientId - audio_latency: context.jamClient.FTUEGetExpectedLatency().latency + parent_client_id: parentClientId, + audio_latency: await context.jamClient.FTUEGetExpectedLatency().latency }) - .done((response) => + .done(async response => { - unless @inSession() - # the user has left the session before they got joined. We need to issue a leave again to the server to make sure they are out - logger.debug("user left before fully joined to session. telling server again that they have left") - @leaveSessionRest(@currentSessionId) - return + if (!this.inSession()) { + // the user has left the session before they got joined. We need to issue a leave again to the server to make sure they are out + logger.debug("user left before fully joined to session. telling server again that they have left"); + this.leaveSessionRest(this.currentSessionId); + return; + } - @updateSessionInfo(response, true) - @issueChange() + this.updateSessionInfo(response, true); + this.issueChange(); logger.debug("calling jamClient.JoinSession"); - # on temporary disconnect scenarios, a user may already be in a session when they enter this path - # so we avoid double counting - unless @alreadyInSession() - if @participants().length == 1 + // on temporary disconnect scenarios, a user may already be in a session when they enter this path + // so we avoid double counting + if (!this.alreadyInSession()) { + if (this.participants().length === 1) { context.JK.GA.trackSessionMusicians(context.JK.GA.SessionCreationTypes.create); - else + } else { context.JK.GA.trackSessionMusicians(context.JK.GA.SessionCreationTypes.join); + } + } - @recordingModel.reset(@currentSessionId); + this.recordingModel.reset(this.currentSessionId); - joinSessionMsg = {sessionID: @currentSessionId, music_session_id_int: response.music_session_id_int} - context.jamClient.JoinSession(joinSessionMsg); + const joinSessionMsg = {sessionID: this.currentSessionId, music_session_id_int: response.music_session_id_int}; + await context.jamClient.JoinSession(joinSessionMsg); - #@refreshCurrentSession(true); + //@refreshCurrentSession(true); - context.JK.JamServer.registerMessageCallback(context.JK.MessageType.SESSION_JOIN, @trackChanges); - context.JK.JamServer.registerMessageCallback(context.JK.MessageType.SESSION_DEPART, @trackChanges); - context.JK.JamServer.registerMessageCallback(context.JK.MessageType.TRACKS_CHANGED, @trackChanges); - context.JK.JamServer.registerMessageCallback(context.JK.MessageType.HEARTBEAT_ACK, @trackChanges); + context.JK.JamServer.registerMessageCallback(context.JK.MessageType.SESSION_JOIN, this.trackChanges); + context.JK.JamServer.registerMessageCallback(context.JK.MessageType.SESSION_DEPART, this.trackChanges); + context.JK.JamServer.registerMessageCallback(context.JK.MessageType.TRACKS_CHANGED, this.trackChanges); + context.JK.JamServer.registerMessageCallback(context.JK.MessageType.HEARTBEAT_ACK, this.trackChanges); - $(document).trigger(EVENTS.SESSION_STARTED, {session: {id: @currentSessionId, lesson_session: response.lesson_session}}) if document + if (document) { $(document).trigger(EVENTS.SESSION_STARTED, {session: {id: this.currentSessionId, lesson_session: response.lesson_session}}); } - @handleAutoOpenJamTrack() + this.handleAutoOpenJamTrack(); - @watchBackendStats() + this.watchBackendStats(); - ConfigureTracksActions.reset(true) - @delayEnableVst() - ) - .fail((xhr) => - @updateCurrentSession(null) + ConfigureTracksActions.reset(true); + return this.delayEnableVst(); + }) + .fail(xhr => { + let leaveBehavior; + this.updateCurrentSession(null); - if xhr.status == 404 - # we tried to join the session, but it's already gone. kick user back to join session screen - leaveBehavior = - location: "/client#/findSession" - notify: + if (xhr.status === 404) { + // we tried to join the session, but its already gone. kick user back to join session screen + leaveBehavior = { + location: "/client#/findSession", + notify: { title: "Unable to Join Session", text: " The session you attempted to join is over." - SessionActions.leaveSession.trigger(leaveBehavior) - else if xhr.status == 422 - response = JSON.parse(xhr.responseText); - if response["errors"] && response["errors"]["tracks"] && response["errors"]["tracks"][0] == "Please select at least one track" - @app.notifyAlert("No Inputs Configured", $('You will need to reconfigure your audio device.')) + } + }; + return SessionActions.leaveSession.trigger(leaveBehavior); + } else if (xhr.status === 422) { + let buttons; + const response = JSON.parse(xhr.responseText); + if (response["errors"] && response["errors"]["tracks"] && (response["errors"]["tracks"][0] === "Please select at least one track")) { + return this.app.notifyAlert("No Inputs Configured", $('You will need to reconfigure your audio device.')); - else if response["errors"] && response["errors"]["music_session"] && response["errors"]["music_session"][0] == ["is currently recording"] - leaveBehavior = - location: "/client#/findSession" - notify: - title: "Unable to Join Session" + } else if (response["errors"] && response["errors"]["music_session"] && (response["errors"]["music_session"][0] === ["is currently recording"])) { + leaveBehavior = { + location: "/client#/findSession", + notify: { + title: "Unable to Join Session", text: "The session is currently recording." - SessionActions.leaveSession.trigger(leaveBehavior) - else if response["errors"] && response["errors"]["remaining_session_play_time"] + } + }; + return SessionActions.leaveSession.trigger(leaveBehavior); + } else if (response["errors"] && response["errors"]["remaining_session_play_time"]) { leaveBehavior = - location: "/client#/findSession" - buttons = [] - buttons.push({name: 'CLOSE', buttonStyle: 'button-grey'}) - buttons.push({name: 'COMPARE PLANS', buttonStyle: 'button-grey', click: (() => (@openBrowserToPlanComparison()))}) + {location: "/client#/findSession"}; + buttons = []; + buttons.push({name: 'CLOSE', buttonStyle: 'button-grey'}); + buttons.push({name: 'COMPARE PLANS', buttonStyle: 'button-grey', click: (() => (this.openBrowserToPlanComparison()))}); buttons.push({ name: 'UPGRADE PLAN', buttonStyle: 'button-orange', - click: (() => (@openBrowserToPayment())) - }) + click: (() => (this.openBrowserToPayment())) + }); context.JK.Banner.show({ title: "Out of Time For This Session", html: context._.template($('#template-no-remaining-session-play-time').html(), {}, { variable: 'data' }), - buttons: buttons}); - SessionActions.leaveSession.trigger(leaveBehavior) - else if response["errors"] && response["errors"]["remaining_month_play_time"] + buttons}); + return SessionActions.leaveSession.trigger(leaveBehavior); + } else if (response["errors"] && response["errors"]["remaining_month_play_time"]) { leaveBehavior = - location: "/client#/findSession" - buttons = [] - buttons.push({name: 'CLOSE', buttonStyle: 'button-grey'}) - buttons.push({name: 'COMPARE PLANS', buttonStyle: 'button-grey', click: (() => (@openBrowserToPlanComparison()))}) + {location: "/client#/findSession"}; + buttons = []; + buttons.push({name: 'CLOSE', buttonStyle: 'button-grey'}); + buttons.push({name: 'COMPARE PLANS', buttonStyle: 'button-grey', click: (() => (this.openBrowserToPlanComparison()))}); buttons.push({ name: 'UPGRADE PLAN', buttonStyle: 'button-orange', - click: (() => (@openBrowserToPayment())) - }) + click: (() => (this.openBrowserToPayment())) + }); context.JK.Banner.show({ title: "Out of Time for the Month", html: context._.template($('#template-no-remaining-month-play-time').html(), {}, { variable: 'data' }), - buttons: buttons}); - SessionActions.leaveSession.trigger(leaveBehavior) - else - @app.notifyServerError(xhr, 'Unable to Join Session'); - else - @app.notifyServerError(xhr, 'Unable to Join Session'); - ) + buttons}); + return SessionActions.leaveSession.trigger(leaveBehavior); + } else { + return this.app.notifyServerError(xhr, 'Unable to Join Session'); + } + } else { + return this.app.notifyServerError(xhr, 'Unable to Join Session'); + } + }); + }` - delayEnableVst: () -> - if @enableVstTimeout? - clearTimeout(@enableVstTimeout) - @enableVstTimeout = null + # delayEnableVst: () -> + # if @enableVstTimeout? + # clearTimeout(@enableVstTimeout) + # @enableVstTimeout = null - isVstLoaded = context.jamClient.IsVstLoaded() - hasVstAssignment = context.jamClient.hasVstAssignment() + # isVstLoaded = context.jamClient.IsVstLoaded() + # hasVstAssignment = context.jamClient.hasVstAssignment() - if hasVstAssignment && !isVstLoaded - @enableVstTimeout = setTimeout((() => - @enableVst() - ), 5000) - @issueChange() + # if hasVstAssignment && !isVstLoaded + # @enableVstTimeout = setTimeout((() => + # @enableVst() + # ), 5000) + # @issueChange() + + delayEnableVst: `async function() { + if (this.enableVstTimeout != null) { + clearTimeout(this.enableVstTimeout); + this.enableVstTimeout = null; + } + + const isVstLoaded = await context.jamClient.IsVstLoaded(); + const hasVstAssignment = await context.jamClient.hasVstAssignment(); + + if (hasVstAssignment && !isVstLoaded) { + this.enableVstTimeout = setTimeout((() => { + return this.enableVst(); + } + ), 5000); + this.issueChange(); + } + }` enableVst: () -> @enableVstTimeout = null @@ -901,12 +1392,20 @@ _closeRecording = `async function(){logger.debug("closing recording");rest.stopP watchBackendStats: () -> @backendStatsInterval = window.setInterval((() => (@updateBackendStats())), 1000) - updateBackendStats: () -> - connectionStats = window.jamClient.getConnectionDetail('', false) - parentConnectionStats = window.jamClient.getConnectionDetail('', true) - #console.log("CONNECTION STATES", connectionStats) - #console.log("PARENT STATES", parentConnectionStats) - SessionStatsActions.pushStats(connectionStats, parentConnectionStats) + # updateBackendStats: () -> + # connectionStats = window.jamClient.getConnectionDetail('', false) + # parentConnectionStats = window.jamClient.getConnectionDetail('', true) + # #console.log("CONNECTION STATES", connectionStats) + # #console.log("PARENT STATES", parentConnectionStats) + # SessionStatsActions.pushStats(connectionStats, parentConnectionStats) + + updateBackendStats: `async function() { + const connectionStats = await window.jamClient.getConnectionDetail('', false); + const parentConnectionStats = await 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 @@ -919,25 +1418,48 @@ _closeRecording = `async function(){logger.debug("closing recording");rest.stopP # don't log if HEARTBEAT_ACK, or you will see this log all the time logger.info("track_changes_counter = fresh. skipping refresh...", header, payload) - handleAutoOpenJamTrack: () -> - jamTrack = @sessionUtils.grabAutoOpenJamTrack(); - if jamTrack - # give the session to settle just a little (call a timeout of 1 second) - setTimeout(()=> - # tell the server we are about to open a jamtrack - rest.openJamTrack({id: @currentSessionId, jam_track_id: jamTrack.id}) - .done((response) => - logger.debug("jamtrack opened") - # now actually load the jamtrack + # handleAutoOpenJamTrack: () -> + # jamTrack = @sessionUtils.grabAutoOpenJamTrack(); + # if jamTrack + # # give the session to settle just a little (call a timeout of 1 second) + # setTimeout(()=> + # # tell the server we are about to open a jamtrack + # rest.openJamTrack({id: @currentSessionId, jam_track_id: jamTrack.id}) + # .done((response) => + # logger.debug("jamtrack opened") + # # now actually load the jamtrack + # context.SessionActions.updateSession.trigger(response); + # # context.JK.CurrentSessionModel.updateSession(response); + # # loadJamTrack(jamTrack); + # JamTrackActions.open(jamTrack) + # ) + # .fail((jqXHR) => + # @app.notifyServerError(jqXHR, "Unable to Open JamTrack For Playback") + # ) + # , 1000) + + handleAutoOpenJamTrack: `async function() { + const jamTrack = this.sessionUtils.grabAutoOpenJamTrack(); + if (jamTrack) { + // give the session to settle just a little (call a timeout of 1 second) + setTimeout(()=> { + // tell the server we are about to open a jamtrack + rest.openJamTrack({id: this.currentSessionId, jam_track_id: jamTrack.id}) + .done(response => { + logger.debug("jamtrack opened"); + // now actually load the jamtrack context.SessionActions.updateSession.trigger(response); - # context.JK.CurrentSessionModel.updateSession(response); - # loadJamTrack(jamTrack); - JamTrackActions.open(jamTrack) - ) - .fail((jqXHR) => - @app.notifyServerError(jqXHR, "Unable to Open JamTrack For Playback") - ) - , 1000) + // context.JK.CurrentSessionModel.updateSession(response); + // loadJamTrack(jamTrack); + JamTrackActions.open(jamTrack); + }) + .fail(jqXHR => { + this.app.notifyServerError(jqXHR, "Unable to Open JamTrack For Playback"); + }); + } + , 1000); + } + }` inSession: () -> !!@currentSessionId @@ -1067,15 +1589,27 @@ _closeRecording = `async function(){logger.debug("closing recording");rest.stopP @participantLeft(newSession, v) @participantJoined(newSession, v) - participantJoined: (newSession, participant) -> - logger.debug("jamClient.ParticipantJoined", participant.client_id) - context.jamClient.ParticipantJoined(newSession, @toJamClientParticipant(participant)); - @currentParticipants[participant.client_id] = {server: participant, client: {audio_established: null}} + # participantJoined: (newSession, participant) -> + # logger.debug("jamClient.ParticipantJoined", participant.client_id) + # context.jamClient.ParticipantJoined(newSession, @toJamClientParticipant(participant)); + # @currentParticipants[participant.client_id] = {server: participant, client: {audio_established: null}} - participantLeft: (newSession, participant) -> - logger.debug("jamClient.ParticipantLeft", participant.client_id) - context.jamClient.ParticipantLeft(newSession, @toJamClientParticipant(participant)); - delete @currentParticipants[participant.client_id] + participantJoined: `async function(newSession, participant) { + logger.debug("jamClient.ParticipantJoined", participant.client_id); + await context.jamClient.ParticipantJoined(newSession, this.toJamClientParticipant(participant)); + this.currentParticipants[participant.client_id] = {server: participant, client: {audio_established: null}}; + }` + + # participantLeft: (newSession, participant) -> + # logger.debug("jamClient.ParticipantLeft", participant.client_id) + # context.jamClient.ParticipantLeft(newSession, @toJamClientParticipant(participant)); + # delete @currentParticipants[participant.client_id] + + participantLeft: `async function(newSession, participant) { + logger.debug("jamClient.ParticipantLeft", participant.client_id); + await context.jamClient.ParticipantLeft(newSession, this.toJamClientParticipant(participant)); + delete this.currentParticipants[participant.client_id]; + }` toJamClientParticipant: (participant) -> { @@ -1093,49 +1627,102 @@ _closeRecording = `async function(){logger.debug("closing recording");rest.stopP recordingRegistration: () -> logger.debug("recording registration not hooked up yet") - updateCurrentSession: (sessionData) -> - if sessionData != null - @currentOrLastSession = sessionData + # updateCurrentSession: (sessionData) -> + # if sessionData != null + # @currentOrLastSession = sessionData - if sessionData.session_rules - @sessionRules = sessionData.session_rules - # TESTING: - #@sessionRules.remaining_session_play_time = 60 * 15 + 15 # 15 minutes and 15 seconds + # if sessionData.session_rules + # @sessionRules = sessionData.session_rules + # # TESTING: + # #@sessionRules.remaining_session_play_time = 60 * 15 + 15 # 15 minutes and 15 seconds - # compute timestamp due time - if @sessionRules.remaining_session_play_time? - until_time = new Date() - until_time = new Date(until_time.getTime() + @sessionRules.remaining_session_play_time * 1000) - console.log("subscription: session has remaining play time", until_time) - @sessionRules.remaining_session_until = until_time + # # compute timestamp due time + # if @sessionRules.remaining_session_play_time? + # until_time = new Date() + # until_time = new Date(until_time.getTime() + @sessionRules.remaining_session_play_time * 1000) + # console.log("subscription: session has remaining play time", until_time) + # @sessionRules.remaining_session_until = until_time - if sessionData.subscription - # for the backend - it looks here - #sessionData.subscription = sessionData.subscription_rules - # let the backend know - #context.jamClient.applySubscriptionPolicy() - @subscriptionRules = sessionData.subscription - # TESTING: - #@subscriptionRules.remaining_month_play_time = 60 * 15 + 15 # 15 minutes and 15 seconds + # if sessionData.subscription + # # for the backend - it looks here + # #sessionData.subscription = sessionData.subscription_rules + # # let the backend know + # #context.jamClient.applySubscriptionPolicy() + # @subscriptionRules = sessionData.subscription + # # TESTING: + # #@subscriptionRules.remaining_month_play_time = 60 * 15 + 15 # 15 minutes and 15 seconds - if @subscriptionRules.remaining_month_play_time? - until_time = new Date() - until_time = new Date(until_time.getTime() + @subscriptionRules.remaining_month_play_time * 1000) - #until_time.setSeconds(until_time.getSeconds() + @subscriptionRules.remaining_month_play_time) - console.log("subscription: month has remaining play time", until_time) - @subscriptionRules.remaining_month_until = until_time + # if @subscriptionRules.remaining_month_play_time? + # until_time = new Date() + # until_time = new Date(until_time.getTime() + @subscriptionRules.remaining_month_play_time * 1000) + # #until_time.setSeconds(until_time.getSeconds() + @subscriptionRules.remaining_month_play_time) + # console.log("subscription: month has remaining play time", until_time) + # @subscriptionRules.remaining_month_until = until_time - @currentSession = sessionData - if context.jamClient.UpdateSessionInfo? - if @currentSession? - context.jamClient.UpdateSessionInfo(@currentSession) - else - context.jamClient.UpdateSessionInfo({}) - #logger.debug("session changed") + # @currentSession = sessionData + # if context.jamClient.UpdateSessionInfo? + # if @currentSession? + # context.jamClient.UpdateSessionInfo(@currentSession) + # else + # context.jamClient.UpdateSessionInfo({}) + # #logger.debug("session changed") - logger.debug("issue change") - @issueChange() + # logger.debug("issue change") + # @issueChange() + + updateCurrentSession: `async function(sessionData) { + if (sessionData !== null) { + let until_time; + this.currentOrLastSession = sessionData; + + if (sessionData.session_rules) { + this.sessionRules = sessionData.session_rules; + // TESTING: + //@sessionRules.remaining_session_play_time = 60 * 15 + 15 # 15 minutes and 15 seconds + + // compute timestamp due time + if (this.sessionRules.remaining_session_play_time != null) { + until_time = new Date(); + until_time = new Date(until_time.getTime() + (this.sessionRules.remaining_session_play_time * 1000)); + console.log("subscription: session has remaining play time", until_time); + this.sessionRules.remaining_session_until = until_time; + } + } + + + if (sessionData.subscription) { + // for the backend - it looks here + //sessionData.subscription = sessionData.subscription_rules + // let the backend know + //context.jamClient.applySubscriptionPolicy() + this.subscriptionRules = sessionData.subscription; + // TESTING: + //@subscriptionRules.remaining_month_play_time = 60 * 15 + 15 # 15 minutes and 15 seconds + + if (this.subscriptionRules.remaining_month_play_time != null) { + until_time = new Date(); + until_time = new Date(until_time.getTime() + (this.subscriptionRules.remaining_month_play_time * 1000)); + //until_time.setSeconds(until_time.getSeconds() + @subscriptionRules.remaining_month_play_time) + console.log("subscription: month has remaining play time", until_time); + this.subscriptionRules.remaining_month_until = until_time; + } + } + } + + this.currentSession = sessionData; + //if (context.jamClient.UpdateSessionInfo != null) { + if (this.currentSession != null) { + await context.jamClient.UpdateSessionInfo(this.currentSession); + } else { + await context.jamClient.UpdateSessionInfo({}); + } + //} + //logger.debug("session changed") + + logger.debug("issue change"); + return this.issueChange(); + }` ensureConnected: () -> unless context.JK.JamServer.connected @@ -1209,8 +1796,6 @@ _closeRecording = `async function(){logger.debug("closing recording");rest.stopP @sessionUtils.SessionPageLeave() - - leaveSession: () -> if !@joinDeferred? || @joinDeferred?.state() == 'resolved' @@ -1221,31 +1806,58 @@ _closeRecording = `async function(){logger.debug("closing recording");rest.stopP @performLeaveSession(deferred) ) - performLeaveSession: (deferred) -> + # performLeaveSession: (deferred) -> - logger.debug("SessionModel.leaveCurrentSession()") - # TODO - sessionChanged will be called with currentSession = null\ + # logger.debug("SessionModel.leaveCurrentSession()") + # # TODO - sessionChanged will be called with currentSession = null\ - # leave the session right away without waiting on REST. Why? If you can't contact the server, or if it takes a long - # time, for that entire duration you'll still be sending voice data to the other users. - # this may be bad if someone decides to badmouth others in the left-session during this time - logger.debug("performLeaveSession: calling jamClient.LeaveSession for clientId=" + @app.clientId) - context.jamClient.LeaveSession({ sessionID: @currentSessionId }) - @leaveSessionRest(@currentSessionId) - .done(=> - deferred.resolve(arguments[0], arguments[1], arguments[2])) - .fail(=> - deferred.reject(arguments[0], arguments[1], arguments[2]); - ) + # # leave the session right away without waiting on REST. Why? If you can't contact the server, or if it takes a long + # # time, for that entire duration you'll still be sending voice data to the other users. + # # this may be bad if someone decides to badmouth others in the left-session during this time + # logger.debug("performLeaveSession: calling jamClient.LeaveSession for clientId=" + @app.clientId) + # context.jamClient.LeaveSession({ sessionID: @currentSessionId }) + # @leaveSessionRest(@currentSessionId) + # .done(=> + # deferred.resolve(arguments[0], arguments[1], arguments[2])) + # .fail(=> + # deferred.reject(arguments[0], arguments[1], arguments[2]); + # ) - # 'unregister' for callbacks - context.jamClient.SessionRegisterCallback(""); - #context.jamClient.SessionSetAlertCallback(""); - context.jamClient.SessionSetConnectionStatusRefreshRate(0); + # # 'unregister' for callbacks + # context.jamClient.SessionRegisterCallback(""); + # #context.jamClient.SessionSetAlertCallback(""); + # context.jamClient.SessionSetConnectionStatusRefreshRate(0); - @sessionEnded() + # @sessionEnded() - @issueChange() + # @issueChange() + + performLeaveSession: `async function(deferred) { + + logger.debug("SessionModel.leaveCurrentSession()"); + // TODO - sessionChanged will be called with currentSession = null\ + + // leave the session right away without waiting on REST. Why? If you can't contact the server, or if it takes a long + // time, for that entire duration you'll still be sending voice data to the other users. + // this may be bad if someone decides to badmouth others in the left-session during this time + logger.debug("performLeaveSession: calling jamClient.LeaveSession for clientId=" + this.app.clientId); + await context.jamClient.LeaveSession({ sessionID: this.currentSessionId }); + this.leaveSessionRest(this.currentSessionId) + .done(function() { + return deferred.resolve(arguments[0], arguments[1], arguments[2]);}.bind(this)) + .fail(function() { + return deferred.reject(arguments[0], arguments[1], arguments[2]); + }.bind(this)); + + // 'unregister' for callbacks + await context.jamClient.SessionRegisterCallback(""); + //context.jamClient.SessionSetAlertCallback(""); + await context.jamClient.SessionSetConnectionStatusRefreshRate(0); + + this.sessionEnded(); + + this.issueChange(); + }` selfOpenedJamTracks: () -> @currentSession && (@currentSession.jam_track_initiator_id == context.JK.currentUserId) diff --git a/web/app/assets/javascripts/react-components/stores/VideoLiveStreamStore.js.coffee b/web/app/assets/javascripts/react-components/stores/VideoLiveStreamStore.js.coffee index 7535dd5e1..a13f91ab5 100644 --- a/web/app/assets/javascripts/react-components/stores/VideoLiveStreamStore.js.coffee +++ b/web/app/assets/javascripts/react-components/stores/VideoLiveStreamStore.js.coffee @@ -17,15 +17,27 @@ VideoLiveStreamActions = @VideoLiveStreamActions onAppInit: (@app) -> - onPopupClosed: () -> + # onPopupClosed: () -> - if @childWindow? - @childWindow = null + # if @childWindow? + # @childWindow = null - logger.debug("Popup closed") - context.jamClient.StopLiveStreaming() - @streaming = false - @onRefresh() + # logger.debug("Popup closed") + # context.jamClient.StopLiveStreaming() + # @streaming = false + # @onRefresh() + + onPopupClosed: `async function() { + + if (this.childWindow != null) { + this.childWindow = null; + } + + logger.debug("Popup closed"); + await context.jamClient.StopLiveStreaming(); + this.streaming = false; + return this.onRefresh(); + }` onRefresh: () -> @@ -116,186 +128,391 @@ VideoLiveStreamActions = @VideoLiveStreamActions @onRefresh() ) - createLiveStream: () -> + # createLiveStream: () -> - @creatingBroadcast = true + # @creatingBroadcast = true - rest.createLiveStream(context.SessionStore.id()) - .done((broadcast) => - @creatingBroadcast = false - @broadcast = broadcast - @onRefresh() - success = context.jamClient.StartLiveStreaming(broadcast.stream_name) + # rest.createLiveStream(context.SessionStore.id()) + # .done((broadcast) => + # @creatingBroadcast = false + # @broadcast = broadcast + # @onRefresh() + # success = context.jamClient.StartLiveStreaming(broadcast.stream_name) - if success - @createdStream = true - @waitingForReady = true - @transitionTimeout = new Date().getTime() + 60000 # die in 10 seconds - @onRefresh() - setTimeout(() => - @waitForReady() - , 1000) + # if success + # @createdStream = true + # @waitingForReady = true + # @transitionTimeout = new Date().getTime() + 60000 # die in 10 seconds + # @onRefresh() + # setTimeout(() => + # @waitForReady() + # , 1000) - else - @createStreamError = true - @onRefresh() - ) - .fail(() => - @creatingBroadcast = false - @onRefresh() - ) + # else + # @createStreamError = true + # @onRefresh() + # ) + # .fail(() => + # @creatingBroadcast = false + # @onRefresh() + # ) - waitForReady: () -> - rest.getLiveStream(context.SessionStore.id()) - .done((broadcast) => - @broadcast = broadcast - if broadcast.broadcast_status == 'ready' || broadcast.broadcast_status == 'live' - @waitingForReady = false - @transitionTimeout = new Date().getTime() + 60000 # die in 20 seconds - @waitForActiveStream() - else - if new Date().getTime() > @transitionTimeout - # uh oh. waited fo ra while; broadcast never becam ready - @errorMessage = 'YouTube never indicated broadcast is ready' - @waitingForReady = false - @onRefresh() - else - setTimeout(() => - @waitForReady() - , 1000) - ) - .fail(() => - @waitingForReady = false - @errorMessage = 'Could not check status of YouTube broadcast' - context.jamClient.StopLiveStreaming() - @streaming = false - @onRefresh() - ) + createLiveStream: `function() { - transitionTesting: () -> - @transitioningTesting = true - @onRefresh() + this.creatingBroadcast = true; - rest.liveStreamTransition(context.SessionStore.id(), 'testing') - .done((broadcast) => - @broadcast = broadcast - @transitioningTesting = false - @waitingOnTesting = true - @transitionTimeout = new Date().getTime() + 60000 # die in 20 seconds - setTimeout(() => - @waitForTesting() - , 1000) - ) - .fail(() => - @transitioningTesting = false - @errorMessage = 'Could not transition live stream to "testing"' - context.jamClient.StopLiveStreaming() - @streaming = false - @onRefresh() - ) + rest.createLiveStream(context.SessionStore.id()) + .done(async broadcast => { + this.creatingBroadcast = false; + this.broadcast = broadcast; + this.onRefresh(); + const success = await context.jamClient.StartLiveStreaming(broadcast.stream_name); - transitionLive: () -> - @transitioningLive = true - @onRefresh() + if (success) { + this.createdStream = true; + this.waitingForReady = true; + this.transitionTimeout = new Date().getTime() + 60000; // die in 10 seconds + this.onRefresh(); + return setTimeout(() => { + return this.waitForReady(); + } + , 1000); - rest.liveStreamTransition(context.SessionStore.id(), 'live') - .done((broadcast) => - @broadcast = broadcast - @transitioningLive = false - @waitingOnLive = true - @transitionTimeout = new Date().getTime() + 60000 # die in 20 seconds - setTimeout(() => - @waitForLive() - , 1000) - ) - .fail(() => - @transitioningLive = false - @errorMessage = 'Could not transition live stream to "live"' - context.jamClient.StopLiveStreaming() - @streaming = false - @onRefresh() - ) + } else { + this.createStreamError = true; + return this.onRefresh(); + } + }) + .fail(() => { + this.creatingBroadcast = false; + return this.onRefresh(); + }); + }` + + # waitForReady: () -> + # rest.getLiveStream(context.SessionStore.id()) + # .done((broadcast) => + # @broadcast = broadcast + # if broadcast.broadcast_status == 'ready' || broadcast.broadcast_status == 'live' + # @waitingForReady = false + # @transitionTimeout = new Date().getTime() + 60000 # die in 20 seconds + # @waitForActiveStream() + # else + # if new Date().getTime() > @transitionTimeout + # # uh oh. waited fo ra while; broadcast never becam ready + # @errorMessage = 'YouTube never indicated broadcast is ready' + # @waitingForReady = false + # @onRefresh() + # else + # setTimeout(() => + # @waitForReady() + # , 1000) + # ) + # .fail(() => + # @waitingForReady = false + # @errorMessage = 'Could not check status of YouTube broadcast' + # context.jamClient.StopLiveStreaming() + # @streaming = false + # @onRefresh() + # ) + + waitForReady: `function() { + rest.getLiveStream(context.SessionStore.id()) + .done(broadcast => { + this.broadcast = broadcast; + if ((broadcast.broadcast_status === 'ready') || (broadcast.broadcast_status === 'live')) { + this.waitingForReady = false; + this.transitionTimeout = new Date().getTime() + 60000; // die in 20 seconds + this.waitForActiveStream(); + } else { + if (new Date().getTime() > this.transitionTimeout) { + // uh oh. waited fo ra while; broadcast never becam ready + this.errorMessage = 'YouTube never indicated broadcast is ready'; + this.waitingForReady = false; + this.onRefresh(); + } else { + return setTimeout(() => { + return this.waitForReady(); + } + , 1000); + } + } + }) + .fail(async () => { + this.waitingForReady = false; + this.errorMessage = 'Could not check status of YouTube broadcast'; + await context.jamClient.StopLiveStreaming(); + this.streaming = false; + return this.onRefresh(); + }); + }` + + # transitionTesting: () -> + # @transitioningTesting = true + # @onRefresh() + + # rest.liveStreamTransition(context.SessionStore.id(), 'testing') + # .done((broadcast) => + # @broadcast = broadcast + # @transitioningTesting = false + # @waitingOnTesting = true + # @transitionTimeout = new Date().getTime() + 60000 # die in 20 seconds + # setTimeout(() => + # @waitForTesting() + # , 1000) + # ) + # .fail(() => + # @transitioningTesting = false + # @errorMessage = 'Could not transition live stream to "testing"' + # context.jamClient.StopLiveStreaming() + # @streaming = false + # @onRefresh() + # ) + + transitionTesting: `function() { + this.transitioningTesting = true; + this.onRefresh(); + + rest.liveStreamTransition(context.SessionStore.id(), 'testing') + .done(broadcast => { + this.broadcast = broadcast; + this.transitioningTesting = false; + this.waitingOnTesting = true; + this.transitionTimeout = new Date().getTime() + 60000; // die in 20 seconds + setTimeout(() => { + this.waitForTesting(); + } + , 1000); + }) + .fail(async () => { + this.transitioningTesting = false; + this.errorMessage = 'Could not transition live stream to "testing"'; + await context.jamClient.StopLiveStreaming(); + this.streaming = false; + this.onRefresh(); + }); + }` + + # transitionLive: () -> + # @transitioningLive = true + # @onRefresh() + + # rest.liveStreamTransition(context.SessionStore.id(), 'live') + # .done((broadcast) => + # @broadcast = broadcast + # @transitioningLive = false + # @waitingOnLive = true + # @transitionTimeout = new Date().getTime() + 60000 # die in 20 seconds + # setTimeout(() => + # @waitForLive() + # , 1000) + # ) + # .fail(() => + # @transitioningLive = false + # @errorMessage = 'Could not transition live stream to "live"' + # context.jamClient.StopLiveStreaming() + # @streaming = false + # @onRefresh() + # ) + + transitionLive: `function() { + this.transitioningLive = true; + this.onRefresh(); + + rest.liveStreamTransition(context.SessionStore.id(), 'live') + .done(broadcast => { + this.broadcast = broadcast; + this.transitioningLive = false; + this.waitingOnLive = true; + this.transitionTimeout = new Date().getTime() + 60000; // die in 20 seconds + setTimeout(() => { + this.waitForLive(); + } + , 1000); + }) + .fail(async() => { + this.transitioningLive = false; + this.errorMessage = 'Could not transition live stream to "live"'; + await context.jamClient.StopLiveStreaming(); + this.streaming = false; + this.onRefresh(); + }); + }` - waitForActiveStream: () -> - rest.getLiveStream(context.SessionStore.id()) - .done((broadcast) => - @broadcast = broadcast - if broadcast.stream_status == 'active' - @waitingOnActiveStream = false - @transitionTimeout = new Date().getTime() + 60000 # die in 20 seconds - @transitionTesting() - else - if new Date().getTime() > @transitionTimeout - # uh oh. waited fo ra while; stream never became ready - @errorMessage = 'YouTube never indicated stream came from the JamKazam application' - @waitingOnActiveStream = false - @onRefresh() - else - setTimeout(() => - @waitForActiveStream() - , 1000) - ) - .fail(() => - @waitingOnActiveStream = false - @errorMessage = 'Could not check status of YouTube broadcast' - context.jamClient.StopLiveStreaming() - @streaming = false - @onRefresh() - ) + # waitForActiveStream: () -> + # rest.getLiveStream(context.SessionStore.id()) + # .done((broadcast) => + # @broadcast = broadcast + # if broadcast.stream_status == 'active' + # @waitingOnActiveStream = false + # @transitionTimeout = new Date().getTime() + 60000 # die in 20 seconds + # @transitionTesting() + # else + # if new Date().getTime() > @transitionTimeout + # # uh oh. waited fo ra while; stream never became ready + # @errorMessage = 'YouTube never indicated stream came from the JamKazam application' + # @waitingOnActiveStream = false + # @onRefresh() + # else + # setTimeout(() => + # @waitForActiveStream() + # , 1000) + # ) + # .fail(() => + # @waitingOnActiveStream = false + # @errorMessage = 'Could not check status of YouTube broadcast' + # context.jamClient.StopLiveStreaming() + # @streaming = false + # @onRefresh() + # ) - waitForTesting: () -> - rest.getLiveStream(context.SessionStore.id()) - .done((broadcast) => - @broadcast = broadcast - if broadcast.broadcast_status == 'testing' || broadcast.broadcast_status == 'live' - @waitingOnTesting = false - @transitionTimeout = new Date().getTime() + 60000 # die in 20 seconds - @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() - ) + waitForActiveStream: `function() { + rest.getLiveStream(context.SessionStore.id()) + .done(broadcast => { + this.broadcast = broadcast; + if (broadcast.stream_status === 'active') { + this.waitingOnActiveStream = false; + this.transitionTimeout = new Date().getTime() + 60000; // die in 20 seconds + this.transitionTesting(); + } else { + if (new Date().getTime() > this.transitionTimeout) { + // uh oh. waited fo ra while; stream never became ready + this.errorMessage = 'YouTube never indicated stream came from the JamKazam application'; + this.waitingOnActiveStream = false; + this.onRefresh(); + } else { + setTimeout(() => { + this.waitForActiveStream(); + } + , 1000); + } + } + }) + .fail(async() => { + this.waitingOnActiveStream = false; + this.errorMessage = 'Could not check status of YouTube broadcast'; + await context.jamClient.StopLiveStreaming(); + this.streaming = false; + this.onRefresh(); + }); + }` - waitForLive: () -> - rest.getLiveStream(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() - ) + # waitForTesting: () -> + # rest.getLiveStream(context.SessionStore.id()) + # .done((broadcast) => + # @broadcast = broadcast + # if broadcast.broadcast_status == 'testing' || broadcast.broadcast_status == 'live' + # @waitingOnTesting = false + # @transitionTimeout = new Date().getTime() + 60000 # die in 20 seconds + # @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() + # ) + + waitForTesting: `function() { + rest.getLiveStream(context.SessionStore.id()) + .done(broadcast => { + this.broadcast = broadcast; + if ((broadcast.broadcast_status === 'testing') || (broadcast.broadcast_status === 'live')) { + this.waitingOnTesting = false; + this.transitionTimeout = new Date().getTime() + 60000; // die in 20 seconds + this.transitionLive(); + } else { + if (new Date().getTime() > this.transitionTimeout) { + // uh oh. waited fo ra while; stream never became ready + this.errorMessage = 'YouTube never indicated stream converted to testing'; + this.waitingOnTesting = false; + this.onRefresh(); + } else { + setTimeout(() => { + this.waitForTesting(); + } + , 1000); + } + } + }) + .fail(async() => { + this.waitingForTesting = false; + this.errorMessage = 'Could not check status of YouTube broadcast'; + await context.jamClient.StopLiveStreaming(); + this.streaming = false; + this.onRefresh(); + }); + }` + + # waitForLive: () -> + # rest.getLiveStream(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() + # ) + + waitForLive: `function() { + rest.getLiveStream(context.SessionStore.id()) + .done(broadcast => { + if (broadcast.broadcast_status === 'live') { + this.waitingOnLive = false; + this.streaming = true; + console.log("BROADCAST TIME", broadcast); + this.onRefresh(); + } else { + if (new Date().getTime() > this.transitionTimeout) { + // uh oh. waited fo ra while; stream never became ready + this.errorMessage = 'YouTube never indicated stream converted to live'; + this.waitingOnLive = false; + this.onRefresh(); + } else { + setTimeout(() => { + this.waitForLive(); + } + , 1000); + } + } + }) + .fail(async() => { + this.waitingForLive = false; + this.errorMessage = 'Could not check status of YouTube broadcast'; + await context.jamClient.StopLiveStreaming(); + this.streaming = false; + this.onRefresh(); + }); + }` + } ) \ No newline at end of file diff --git a/web/app/assets/javascripts/react-components/stores/VideoStore.js.coffee b/web/app/assets/javascripts/react-components/stores/VideoStore.js.coffee index 7e877f421..a0c17a854 100644 --- a/web/app/assets/javascripts/react-components/stores/VideoStore.js.coffee +++ b/web/app/assets/javascripts/react-components/stores/VideoStore.js.coffee @@ -15,8 +15,6 @@ BackendToFrontendFPS = { 4: 10 } -_onBringVideoToFront = `async function() { if (this.videoShared) { this.logger.debug("BringVideoToFront"); await context.jamClient.BringVideoWindowToFront(); }}` - @VideoStore = Reflux.createStore( { listenables: VideoActions @@ -32,98 +30,190 @@ _onBringVideoToFront = `async function() { if (this.videoShared) { this.logger.d onAppInit: (@app) -> - - # someone has requested us to refresh our config - onRefresh: -> + + # onRefresh: -> - # don't do any check if this is a client with no video enabled - return unless context.jamClient.FTUECurrentSelectedVideoDevice? + # # don't do any check if this is a client with no video enabled + # return unless context.jamClient.FTUECurrentSelectedVideoDevice? - videoEnabled = context.jamClient.FTUEGetVideoShareEnable() + # videoEnabled = context.jamClient.FTUEGetVideoShareEnable() - @videoEnabled = videoEnabled + # @videoEnabled = videoEnabled - if videoEnabled - currentDevice = context.jamClient.FTUECurrentSelectedVideoDevice() - deviceNames = context.jamClient.FTUEGetVideoCaptureDeviceNames() - #deviceCaps = context.jamClient.FTUEGetVideoCaptureDeviceCapabilities() - captureResolutions = context.jamClient.FTUEGetCaptureResolution() - currentCaptureResolution = context.jamClient.FTUEGetCurrentCaptureResolution() + # if videoEnabled + # currentDevice = context.jamClient.FTUECurrentSelectedVideoDevice() + # deviceNames = context.jamClient.FTUEGetVideoCaptureDeviceNames() + # #deviceCaps = context.jamClient.FTUEGetVideoCaptureDeviceCapabilities() + # captureResolutions = context.jamClient.FTUEGetCaptureResolution() + # currentCaptureResolution = context.jamClient.FTUEGetCurrentCaptureResolution() - logger.debug("captureResolutions, currentCaptureResolution", captureResolutions, currentCaptureResolution) - else - @everDisabled = true - # don't talk to the backend when video is disabled; avoiding crashes - currentDevice = null - deviceNames = {} - captureResolutions: {} - currentCaptureResolution: null - frameRates: {} + # logger.debug("captureResolutions, currentCaptureResolution", captureResolutions, currentCaptureResolution) + # else + # @everDisabled = true + # # don't talk to the backend when video is disabled; avoiding crashes + # currentDevice = null + # deviceNames = {} + # captureResolutions: {} + # currentCaptureResolution: null + # frameRates: {} - #deviceCaps: deviceCaps, + # #deviceCaps: deviceCaps, - @state = { - currentDevice: currentDevice, - deviceNames: deviceNames, - captureResolutions: captureResolutions, - currentCaptureResolution: currentCaptureResolution, - videoShared: @videoShared - videoOpen: @videoOpen, - videoEnabled: videoEnabled, - everDisabled: @everDisabled + # @state = { + # currentDevice: currentDevice, + # deviceNames: deviceNames, + # captureResolutions: captureResolutions, + # currentCaptureResolution: currentCaptureResolution, + # videoShared: @videoShared + # videoOpen: @videoOpen, + # videoEnabled: videoEnabled, + # everDisabled: @everDisabled + # } + # this.trigger(@state) + + onRefresh: `async function() { + let captureResolutions, currentCaptureResolution, currentDevice, deviceNames; + if (await context.jamClient.FTUECurrentSelectedVideoDevice() == null) { return; } + + const videoEnabled = await context.jamClient.FTUEGetVideoShareEnable(); + + this.videoEnabled = videoEnabled; + + if (videoEnabled) { + currentDevice = await context.jamClient.FTUECurrentSelectedVideoDevice(); + deviceNames = await context.jamClient.FTUEGetVideoCaptureDeviceNames(); + //deviceCaps = await context.jamClient.FTUEGetVideoCaptureDeviceCapabilities() + captureResolutions = await context.jamClient.FTUEGetCaptureResolution(); + currentCaptureResolution = await context.jamClient.FTUEGetCurrentCaptureResolution(); + + logger.debug("captureResolutions, currentCaptureResolution", captureResolutions, currentCaptureResolution); + } else { + this.everDisabled = true; + currentDevice = null; + deviceNames = {}; + ({ + captureResolutions: {}, + currentCaptureResolution: null, + frameRates: {} + }); + } + + this.state = { + currentDevice, + deviceNames, + captureResolutions, + currentCaptureResolution, + videoShared: this.videoShared, + videoOpen: this.videoOpen, + videoEnabled, + everDisabled: this.everDisabled + }; + this.trigger(this.state); + }` + + # onSetVideoEnabled: (enable) -> + + # return unless context.jamClient.FTUESetVideoShareEnable? + + # context.jamClient.FTUESetVideoShareEnable(enable) + + # # keep state in sync + # @state.videoEnabled = enable + # @onRefresh() + + onSetVideoEnabled: `async function(enable) { + + if (await context.jamClient.FTUESetVideoShareEnable() == null) { return; } + + await context.jamClient.FTUESetVideoShareEnable(enable); + + // keep state in sync + this.state.videoEnabled = enable; + return this.onRefresh(); + }` + + # onStartVideo: -> + # return unless context.jamClient.SessStartVideoSharing? + + # if @howtoWindow? + # @howtoWindow.close() + # @howtoWindow = null + # #else # TESTING + # # @howtoWindow = window.open("/popups/how-to-use-video", 'How to Use Video', 'scrollbars=yes,toolbar=no,status=no,height=315,width=320') + + # @logger.debug("SessStartVideoSharing()") + # context.jamClient.SessStartVideoSharing(0) + # @videoShared = true + + # @state.videoShared = @videoShared + # this.trigger(@state) + + onStartVideo: `async function() { + if (await context.jamClient.SessStartVideoSharing() == null) { return; } + + if (this.howtoWindow != null) { + this.howtoWindow.close(); + this.howtoWindow = null; } - this.trigger(@state) + //else # TESTING + // @howtoWindow = window.open("/popups/how-to-use-video", 'How to Use Video', 'scrollbars=yes,toolbar=no,status=no,height=315,width=320') - onSetVideoEnabled: (enable) -> + this.logger.debug("SessStartVideoSharing()"); + await context.jamClient.SessStartVideoSharing(0); + this.videoShared = true; - return unless context.jamClient.FTUESetVideoShareEnable? + this.state.videoShared = this.videoShared; + return this.trigger(this.state); + }` - context.jamClient.FTUESetVideoShareEnable(enable) + # onStopVideo: -> + # if @videoShared + # @logger.debug("SessStopVideoSharing()") + # context.jamClient.SessStopVideoSharing() + # @videoShared = false + # @state.videoShared = @videoShared + # this.trigger(@state) - # keep state in sync - @state.videoEnabled = enable - @onRefresh() - - onStartVideo: -> - return unless context.jamClient.SessStartVideoSharing? - - if @howtoWindow? - @howtoWindow.close() - @howtoWindow = null - #else # TESTING - # @howtoWindow = window.open("/popups/how-to-use-video", 'How to Use Video', 'scrollbars=yes,toolbar=no,status=no,height=315,width=320') - - @logger.debug("SessStartVideoSharing()") - context.jamClient.SessStartVideoSharing(0) - @videoShared = true - - @state.videoShared = @videoShared - this.trigger(@state) - - onStopVideo: -> - if @videoShared - @logger.debug("SessStopVideoSharing()") - context.jamClient.SessStopVideoSharing() - @videoShared = false - @state.videoShared = @videoShared - this.trigger(@state) + onStopVideo: `async function() { + if (this.videoShared) { + this.logger.debug("SessStopVideoSharing()"); + await context.jamClient.SessStopVideoSharing(); + this.videoShared = false; + this.state.videoShared = this.videoShared; + return this.trigger(this.state); + } + }` # onBringVideoToFront: -> # if @videoShared # @logger.debug("BringVideoToFront") # context.jamClient.BringVideoWindowToFront(); - onBringVideoToFront: _onBringVideoToFront + onBringVideoToFront: `async function() { + if (this.videoShared) { + this.logger.debug("BringVideoToFront"); + await context.jamClient.BringVideoWindowToFront(); } + }` - onTestVideo: () -> + # onTestVideo: () -> - return unless context.jamClient.testVideoRender? - result = context.jamClient.testVideoRender() + # return unless context.jamClient.testVideoRender? + # result = context.jamClient.testVideoRender() - if !result - @app.layout.notify({title: 'Unable to initialize video window', text: "Please contact support@jamkazam.com"}) + # if !result + # @app.layout.notify({title: 'Unable to initialize video window', text: "Please contact support@jamkazam.com"}) + + onTestVideo: `async function() { + const videoRender = await context.jamClient.testVideoRender(); + if (videoRender == null) { return; } + const result = videoRender; + + if (!result) { + return this.app.layout.notify({title: 'Unable to initialize video window', text: "Please contact support@jamkazam.com"}); + } + }` onToggleVideo: () -> if @videoShared @@ -131,46 +221,92 @@ _onBringVideoToFront = `async function() { if (this.videoShared) { this.logger.d else @onStartVideo() - onSetCaptureResolution: (resolution) -> - @logger.debug("set capture resolution: #{resolution}") - context.jamClient.FTUESetCaptureResolution(resolution) - @state.currentCaptureResolution = resolution - this.trigger(@state) + # onSetCaptureResolution: (resolution) -> + # @logger.debug("set capture resolution: #{resolution}") + # context.jamClient.FTUESetCaptureResolution(resolution) + # @state.currentCaptureResolution = resolution + # this.trigger(@state) - onSetSendFrameRate: (frameRates) -> - @logger.debug("set capture frame rate: #{frameRates}") - context.jamClient.FTUESetSendFrameRates(frameRates) - @state.currentFrameRate = frameRates - this.trigger(@state) + onSetCaptureResolution: `async function(resolution) { + this.logger.debug('set capture resolution: '+resolution); + await context.jamClient.FTUESetCaptureResolution(resolution); + this.state.currentCaptureResolution = resolution; + this.trigger(this.state); + }` - onRefreshVideoState:()-> - @logger.debug("onRefreshVideoState") - openVideoSources = context.jamClient.getOpenVideoSources() - @logger.debug("onRefreshVideoState", openVideoSources) + # onSetSendFrameRate: (frameRates) -> + # @logger.debug("set capture frame rate: #{frameRates}") + # context.jamClient.FTUESetSendFrameRates(frameRates) + # @state.currentFrameRate = frameRates + # this.trigger(@state) - # possible keys, all bool values - #"session_window", "webcam1", "webcam2", "screen_capture" + onSetSendFrameRate: `async function(frameRates) { + this.logger.debug('set capture frame rate: '+frameRates); + await context.jamClient.FTUESetSendFrameRates(frameRates); + this.state.currentFrameRate = frameRates; + this.trigger(this.state); + }` - # ex: with mac webcam open only: session_window: 2, webcam1: 1} - # no webcam open: Object {} + # onRefreshVideoState:()-> + # @logger.debug("onRefreshVideoState") + # openVideoSources = context.jamClient.getOpenVideoSources() + # @logger.debug("onRefreshVideoState", openVideoSources) - @openVideoSources = openVideoSources - @anyVideoOpen = Object.keys(openVideoSources).length > 0 - @state.anyVideoOpen = Object.keys(openVideoSources).length > 0 - this.trigger(@state) + # # possible keys, all bool values + # #"session_window", "webcam1", "webcam2", "screen_capture" - onSelectDevice: (device, caps) -> + # # ex: with mac webcam open only: session_window: 2, webcam1: 1} + # # no webcam open: Object {} - # don't do anything if no video capabilities - return unless context.jamClient.FTUESelectVideoCaptureDevice? + # @openVideoSources = openVideoSources + # @anyVideoOpen = Object.keys(openVideoSources).length > 0 + # @state.anyVideoOpen = Object.keys(openVideoSources).length > 0 + # this.trigger(@state) - result = context.jamClient.FTUESelectVideoCaptureDevice(device, caps) - if(!result) - @logger.error("onSelectDevice failed with device #{device}") - @app.layout.notify({title: 'Unable to select webcam', text: "Please try reconnecting webcam."}) - else - @state.currentDevice = context.jamClient.FTUECurrentSelectedVideoDevice(); - this.trigger(@state) + onRefreshVideoState: `async function(){ + this.logger.debug("onRefreshVideoState"); + const openVideoSources = await context.jamClient.getOpenVideoSources(); + this.logger.debug("onRefreshVideoState", openVideoSources); + + // possible keys, all bool values + //"session_window", "webcam1", "webcam2", "screen_capture" + + // ex: with mac webcam open only: session_window: 2, webcam1: 1} + // no webcam open: Object {} + + this.openVideoSources = openVideoSources; + this.anyVideoOpen = Object.keys(openVideoSources).length > 0; + this.state.anyVideoOpen = Object.keys(openVideoSources).length > 0; + return this.trigger(this.state); + }` + + # onSelectDevice: (device, caps) -> + + # # don't do anything if no video capabilities + # return unless context.jamClient.FTUESelectVideoCaptureDevice? + + # result = context.jamClient.FTUESelectVideoCaptureDevice(device, caps) + # if(!result) + # @logger.error("onSelectDevice failed with device #{device}") + # @app.layout.notify({title: 'Unable to select webcam', text: "Please try reconnecting webcam."}) + # else + # @state.currentDevice = context.jamClient.FTUECurrentSelectedVideoDevice(); + # this.trigger(@state) + + onSelectDevice: `async function(device, caps) { + + //do not do anything if no video capabilities + //if (await context.jamClient.FTUESelectVideoCaptureDevice() == null) { return; } + + const result = await context.jamClient.FTUESelectVideoCaptureDevice(device, caps); + if(!result) { + this.logger.error('onSelectDevice failed with device '+ device); + return this.app.layout.notify({title: 'Unable to select webcam', text: "Please try reconnecting webcam."}); + } else { + this.state.currentDevice = await context.jamClient.FTUECurrentSelectedVideoDevice(); + this.trigger(this.state); + } + }` onVideoWindowOpened: () -> @onRefresh() unless @state? @@ -221,23 +357,44 @@ _onBringVideoToFront = `async function() { if (this.videoShared) { this.logger.d @configureWindow = null # if the user passes all the safeguards, let's see if we should get them to configure video - onCheckPromptConfigureVideo: () -> - # don't do any check if this is a client with no video enabled - return unless context.jamClient.FTUECurrentSelectedVideoDevice? + # onCheckPromptConfigureVideo: () -> + # # don't do any check if this is a client with no video enabled + # return unless context.jamClient.FTUECurrentSelectedVideoDevice? - @onRefresh() unless @state? + # @onRefresh() unless @state? - @logger.debug("checkPromptConfigureVideo", @state.currentDevice, @state.deviceNames) + # @logger.debug("checkPromptConfigureVideo", @state.currentDevice, @state.deviceNames) - # if no device configured and this is the native client and if you have at least 1 video - # currentDevice, from the backend, is '{'':''}' in the case of no device configured. But we also check for an empty object, or null object. - if (!@state.currentDevice? || Object.keys(@state.currentDevice).length == 0 || (Object.keys(@state.currentDevice).length == 1 && @state.currentDevice[''] == '')) && gon?.isNativeClient && Object.keys(@state.deviceNames).length > 0 - # and if they haven't said stop bothering me about this - context.JK.ModUtils.shouldShow(NAMED_MESSAGES.CONFIGURE_VIDEO_NOSHOW).done((shouldShow) => - @logger.debug("checking if user has 'should show' on video config: #{shouldShow}") - if shouldShow - @configureWindow = window.open("/popups/configure-video", 'Configure Video', 'scrollbars=yes,toolbar=no,status=no,height=395,width=444') - ) + # # if no device configured and this is the native client and if you have at least 1 video + # # currentDevice, from the backend, is '{'':''}' in the case of no device configured. But we also check for an empty object, or null object. + # if (!@state.currentDevice? || Object.keys(@state.currentDevice).length == 0 || (Object.keys(@state.currentDevice).length == 1 && @state.currentDevice[''] == '')) && gon?.isNativeClient && Object.keys(@state.deviceNames).length > 0 + # # and if they haven't said stop bothering me about this + # context.JK.ModUtils.shouldShow(NAMED_MESSAGES.CONFIGURE_VIDEO_NOSHOW).done((shouldShow) => + # @logger.debug("checking if user has 'should show' on video config: #{shouldShow}") + # if shouldShow + # @configureWindow = window.open("/popups/configure-video", 'Configure Video', 'scrollbars=yes,toolbar=no,status=no,height=395,width=444') + # ) + + onCheckPromptConfigureVideo: `async function() { + // do not do any check if this is a client with no video enabled + if (await context.jamClient.FTUECurrentSelectedVideoDevice() == null) { return; } + + if (this.state == null) { this.onRefresh(); } + + this.logger.debug("checkPromptConfigureVideo", this.state.currentDevice, this.state.deviceNames); + + // if no device configured and this is the native client and if you have at least 1 video + // currentDevice, from the backend, is '{'':''}' in the case of no device configured. But we also check for an empty object, or null object. + if (((this.state.currentDevice == null) || (Object.keys(this.state.currentDevice).length === 0) || ((Object.keys(this.state.currentDevice).length === 1) && (this.state.currentDevice[''] === ''))) && (typeof gon !== 'undefined' && gon !== null ? gon.isNativeClient : undefined) && (Object.keys(this.state.deviceNames).length > 0)) { + // and if they have not said stop bothering me about this + context.JK.ModUtils.shouldShow(NAMED_MESSAGES.CONFIGURE_VIDEO_NOSHOW).done(shouldShow => { + this.logger.debug("checking if user has 'should show' on video config: " + shouldShow); + if (shouldShow) { + return this.configureWindow = window.open("/popups/configure-video", 'Configure Video', 'scrollbars=yes,toolbar=no,status=no,height=395,width=444'); + } + }); + } + }` isVideoEnabled:() -> return @videoEnabled diff --git a/web/app/assets/javascripts/react-components/stores/VideoUploaderStore.js.coffee b/web/app/assets/javascripts/react-components/stores/VideoUploaderStore.js.coffee index ef7d34798..85854e0ca 100644 --- a/web/app/assets/javascripts/react-components/stores/VideoUploaderStore.js.coffee +++ b/web/app/assets/javascripts/react-components/stores/VideoUploaderStore.js.coffee @@ -5,10 +5,6 @@ rest = context.JK.Rest(); VideoUploaderActions = @VideoUploaderActions -_onCancel = `async function(){if(this.uploading){this.uploading=false;await context.jamClient.cancelVideoUpload();this.triggerState();}}` - -_onDelete = `async function(recordingId) {await context.jamClient.deleteVideo(recordingId);}` - @VideoUploaderStore = Reflux.createStore( { listenables: VideoUploaderActions @@ -40,24 +36,48 @@ _onDelete = `async function(recordingId) {await context.jamClient.deleteVideo(re getState: () -> @state - onPause: () -> - if @uploading - @uploading = false - @paused = true - context.jamClient.pauseVideoUpload() - @triggerState() + # onPause: () -> + # if @uploading + # @uploading = false + # @paused = true + # context.jamClient.pauseVideoUpload() + # @triggerState() - onResume: () -> - if @paused && @recordingId? - @uploading = true - @paused = false - context.jamClient.resumeVideoUpload() - @triggerState() - else - if @uploading - @app.layout.notify({title: 'Already uploading', text: "A video is already being uploaded."}) - else - @app.layout.notify({title: 'Nothing to resume', text: "No upload to resume."}) + onPause: `async function() { + if (this.uploading) { + this.uploading = false; + this.paused = true; + await context.jamClient.pauseVideoUpload(); + this.triggerState(); + } + }` + + # onResume: () -> + # if @paused && @recordingId? + # @uploading = true + # @paused = false + # context.jamClient.resumeVideoUpload() + # @triggerState() + # else + # if @uploading + # @app.layout.notify({title: 'Already uploading', text: "A video is already being uploaded."}) + # else + # @app.layout.notify({title: 'Nothing to resume', text: "No upload to resume."}) + + onResume: `async function() { + if (this.paused && (this.recordingId != null)) { + this.uploading = true; + this.paused = false; + await context.jamClient.resumeVideoUpload(); + this.triggerState(); + } else { + if (this.uploading) { + this.app.layout.notify({title: 'Already uploading', text: "A video is already being uploaded."}); + } else { + this.app.layout.notify({title: 'Nothing to resume', text: "No upload to resume."}); + } + } + }` # onCancel: () -> # if @uploading @@ -65,12 +85,20 @@ _onDelete = `async function(recordingId) {await context.jamClient.deleteVideo(re # context.jamClient.cancelVideoUpload() # @triggerState() - onCancel: _onCancel + onCancel: `async function(){ + if(this.uploading){ + this.uploading=false; + await context.jamClient.cancelVideoUpload(); + this.triggerState(); + } + }` # onDelete: (recordingId) -> # context.jamClient.deleteVideo(recordingId); - onDelete: _onDelete + onDelete: `async function(recordingId) { + await context.jamClient.deleteVideo(recordingId); + }` onNewVideo: (recordingId) -> @@ -99,89 +127,180 @@ _onDelete = `async function(recordingId) {await context.jamClient.deleteVideo(re if @childWindow? @childWindow = null - onUploadVideo: (recordingId) -> + # onUploadVideo: (recordingId) -> - if @uploading || @preparingUpload - logger.debug("ignoring upload request") - return + # if @uploading || @preparingUpload + # logger.debug("ignoring upload request") + # return - @preparingUpload = true - @onNewVideo() + # @preparingUpload = true + # @onNewVideo() - rest.getRecording({id:recordingId}) - .done((response) => - claim = response.my + # rest.getRecording({id:recordingId}) + # .done((response) => + # claim = response.my - privateStatus = 'private' - privateStatus = 'public' if claim.is_public + # privateStatus = 'private' + # privateStatus = 'public' if claim.is_public - if claim? - videoInfo = { - "snippet": { - "title": claim.name, - "description": claim.description, - "tags": ["JamKazam"], - "categoryId": 10 # music - }, - "status": { - "privacyStatus": privateStatus, - "embeddable": true, - "license": "youtube" - } + # if claim? + # videoInfo = { + # "snippet": { + # "title": claim.name, + # "description": claim.description, + # "tags": ["JamKazam"], + # "categoryId": 10 # music + # }, + # "status": { + # "privacyStatus": privateStatus, + # "embeddable": true, + # "license": "youtube" + # } + # } + + # rest.getUserAuthorizations() + # .done((response) => + + # # http://localhost:3000/popups/video/upload/d25dbe8e-a066-4ea0-841d-16872c713fc9 + # youtube_auth = null + # for authorization in response.authorizations + # if authorization.provider == 'google_login' + # youtube_auth = authorization.token + # break + + # if youtube_auth? + # logger.debug("calling uploadVideo(#{recordingId}, #{youtube_auth}, #{videoInfo})") + # result = context.jamClient.uploadVideo(recordingId, youtube_auth, JSON.stringify(videoInfo), + # "VideoUploaderStore.clientUploadCallback", + # "VideoUploaderStore.clientDoneCallback", + # "VideoUploaderStore.clientFailCallback") + + # if result.error + # @preparingUpload = false + # @triggerState() + # @app.layout.notify({title: 'Unable to upload video', text: 'Application error: ' + result.error}) + # else + # @preparingUpload = false + # @videoUrl = null + # @uploading = true + # @recordingId = recordingId + # @triggerState() + + + # else + # @preparingUpload = false + # @triggerState() + # @app.layout.notify({title: 'No Authorization Yet for YouTube', text: 'Youtube authorization still needed'}) + + # ) + # .fail((jqXHR) => + # @preparingUpload = false + # @triggerState() + # @app.layout.notifyServerError(jqXHR, 'Unable to fetch user authorizations') + # ) + + # else + # @preparingUpload = false + # @triggerState() + # @app.layout.notify({title: "You do not have a claim to this recording", text: "If this is in error, contact support@jamkazam.com."}) + + # ) + # .fail((jqXHR) => + # @preparingUpload = false + # @triggerState() + # @app.layout.notifyServerError(jqXHR, 'Unable to fetch recording information') + # ) + + onUploadVideo: `function(recordingId) { + + if (this.uploading || this.preparingUpload) { + logger.debug("ignoring upload request"); + return; + } + + this.preparingUpload = true; + this.onNewVideo(); + + return rest.getRecording({id:recordingId}) + .done(response => { + const claim = response.my; + + let privateStatus = 'private'; + if (claim.is_public) { privateStatus = 'public'; } + + if (claim != null) { + const videoInfo = { + "snippet": { + "title": claim.name, + "description": claim.description, + "tags": ["JamKazam"], + "categoryId": 10 // music + }, + "status": { + "privacyStatus": privateStatus, + "embeddable": true, + "license": "youtube" + } + }; + + return rest.getUserAuthorizations() + .done(async response => { + + // http://localhost:3000/popups/video/upload/d25dbe8e-a066-4ea0-841d-16872c713fc9 + let youtube_auth = null; + for (let authorization of Array.from(response.authorizations)) { + if (authorization.provider === 'google_login') { + youtube_auth = authorization.token; + break; + } + } + + if (youtube_auth != null) { + logger.debug('calling uploadVideo('+recordingId+', '+youtube_auth+', ' +videoInfo); + const result = await context.jamClient.uploadVideo(recordingId, youtube_auth, JSON.stringify(videoInfo), + "VideoUploaderStore.clientUploadCallback", + "VideoUploaderStore.clientDoneCallback", + "VideoUploaderStore.clientFailCallback"); + + if (result.error) { + this.preparingUpload = false; + this.triggerState(); + return this.app.layout.notify({title: 'Unable to upload video', text: 'Application error: ' + result.error}); + } else { + this.preparingUpload = false; + this.videoUrl = null; + this.uploading = true; + this.recordingId = recordingId; + return this.triggerState(); + } + + + } else { + this.preparingUpload = false; + this.triggerState(); + return this.app.layout.notify({title: 'No Authorization Yet for YouTube', text: 'Youtube authorization still needed'}); + } + + }) + .fail(jqXHR => { + this.preparingUpload = false; + this.triggerState(); + return this.app.layout.notifyServerError(jqXHR, 'Unable to fetch user authorizations'); + }); + + } else { + this.preparingUpload = false; + this.triggerState(); + return this.app.layout.notify({title: "You do not have a claim to this recording", text: "If this is in error, contact support@jamkazam.com."}); } - rest.getUserAuthorizations() - .done((response) => - - # http://localhost:3000/popups/video/upload/d25dbe8e-a066-4ea0-841d-16872c713fc9 - youtube_auth = null - for authorization in response.authorizations - if authorization.provider == 'google_login' - youtube_auth = authorization.token - break - - if youtube_auth? - logger.debug("calling uploadVideo(#{recordingId}, #{youtube_auth}, #{videoInfo})") - result = context.jamClient.uploadVideo(recordingId, youtube_auth, JSON.stringify(videoInfo), - "VideoUploaderStore.clientUploadCallback", - "VideoUploaderStore.clientDoneCallback", - "VideoUploaderStore.clientFailCallback") - - if result.error - @preparingUpload = false - @triggerState() - @app.layout.notify({title: 'Unable to upload video', text: 'Application error: ' + result.error}) - else - @preparingUpload = false - @videoUrl = null - @uploading = true - @recordingId = recordingId - @triggerState() - - - else - @preparingUpload = false - @triggerState() - @app.layout.notify({title: 'No Authorization Yet for YouTube', text: 'Youtube authorization still needed'}) - - ) - .fail((jqXHR) => - @preparingUpload = false - @triggerState() - @app.layout.notifyServerError(jqXHR, 'Unable to fetch user authorizations') - ) - - else - @preparingUpload = false - @triggerState() - @app.layout.notify({title: "You do not have a claim to this recording", text: "If this is in error, contact support@jamkazam.com."}) - - ) - .fail((jqXHR) => - @preparingUpload = false - @triggerState() - @app.layout.notifyServerError(jqXHR, 'Unable to fetch recording information') - ) + }) + .fail(jqXHR => { + this.preparingUpload = false; + this.triggerState(); + return this.app.layout.notifyServerError(jqXHR, 'Unable to fetch recording information'); + }); + }` clientUploadCallback: (bytesSent, bytesTotal) -> logger.debug("bytesSent: #{bytesSent} bytesTotal: #{bytesTotal}") diff --git a/web/app/assets/javascripts/sync_viewer.js.coffee b/web/app/assets/javascripts/sync_viewer.js.coffee index b452eb4f8..6d35e6baa 100644 --- a/web/app/assets/javascripts/sync_viewer.js.coffee +++ b/web/app/assets/javascripts/sync_viewer.js.coffee @@ -124,28 +124,55 @@ context.JK.SyncViewer = class SyncViewer ) - renderHeader: () => - recordingManagerState = context.jamClient.GetRecordingManagerState() - if recordingManagerState.running - @uploadProgress.removeClass('quiet paused busy') - @downloadProgress.removeClass('quiet paused busy') + # renderHeader: () => + # recordingManagerState = context.jamClient.GetRecordingManagerState() + # if recordingManagerState.running + # @uploadProgress.removeClass('quiet paused busy') + # @downloadProgress.removeClass('quiet paused busy') - if recordingManagerState.current_download - @downloadProgress.addClass('busy') - else - @downloadProgress.addClass('quiet') - @downloadProgress.find('.busy').empty() + # if recordingManagerState.current_download + # @downloadProgress.addClass('busy') + # else + # @downloadProgress.addClass('quiet') + # @downloadProgress.find('.busy').empty() - if recordingManagerState.current_upload - @uploadProgress.addClass('busy') - else - @uploadProgress.addClass('quiet') - @uploadProgress.find('.busy').empty() - else - @downloadProgress.removeClass('quiet paused busy').addClass('paused') - @uploadProgress.removeClass('quiet paused busy').addClass('paused') - @downloadProgress.find('.busy').empty() - @uploadProgress.find('.busy').empty() + # if recordingManagerState.current_upload + # @uploadProgress.addClass('busy') + # else + # @uploadProgress.addClass('quiet') + # @uploadProgress.find('.busy').empty() + # else + # @downloadProgress.removeClass('quiet paused busy').addClass('paused') + # @uploadProgress.removeClass('quiet paused busy').addClass('paused') + # @downloadProgress.find('.busy').empty() + # @uploadProgress.find('.busy').empty() + + renderHeader: `async function(){ + const recordingManagerState = await context.jamClient.GetRecordingManagerState(); + if (recordingManagerState.running) { + this.uploadProgress.removeClass('quiet paused busy'); + this.downloadProgress.removeClass('quiet paused busy'); + + if (recordingManagerState.current_download) { + this.downloadProgress.addClass('busy'); + } else { + this.downloadProgress.addClass('quiet'); + this.downloadProgress.find('.busy').empty(); + } + + if (recordingManagerState.current_upload) { + return this.uploadProgress.addClass('busy'); + } else { + this.uploadProgress.addClass('quiet'); + this.uploadProgress.find('.busy').empty(); + } + } else { + this.downloadProgress.removeClass('quiet paused busy').addClass('paused'); + this.uploadProgress.removeClass('quiet paused busy').addClass('paused'); + this.downloadProgress.find('.busy').empty(); + this.uploadProgress.find('.busy').empty(); + } + }` updateMixState: ($mix) => serverInfo = $mix.data('server-info') @@ -670,14 +697,22 @@ context.JK.SyncViewer = class SyncViewer resetUploadProgress: () => @uploadProgress - sendCommand: ($retry, cmd) => + # sendCommand: ($retry, cmd) => - if context.SessionStore.inSession() - context.JK.ackBubble($retry, 'sync-viewer-paused', {}, {offsetParent: $retry.closest('.dialog')}) - else - context.jamClient.OnTrySyncCommand(cmd) - context.JK.ackBubble($retry, 'sync-viewer-retry', {}, {offsetParent: $retry.closest('.dialog')}) + # if context.SessionStore.inSession() + # context.JK.ackBubble($retry, 'sync-viewer-paused', {}, {offsetParent: $retry.closest('.dialog')}) + # else + # context.jamClient.OnTrySyncCommand(cmd) + # context.JK.ackBubble($retry, 'sync-viewer-retry', {}, {offsetParent: $retry.closest('.dialog')}) + sendCommand: `async function($retry, cmd){ + if (context.SessionStore.inSession()) { + context.JK.ackBubble($retry, 'sync-viewer-paused', {}, {offsetParent: $retry.closest('.dialog')}); + } else { + await context.jamClient.OnTrySyncCommand(cmd); + context.JK.ackBubble($retry, 'sync-viewer-retry', {}, {offsetParent: $retry.closest('.dialog')}); + } + }` retryDownloadRecordedTrack: (e) => $retry = $(e.target) @@ -815,77 +850,159 @@ context.JK.SyncViewer = class SyncViewer $uploadState.addClass('is-native-client') if gon.isNativeClient $track - openVideo: (e) => - $link = $(e.target) - recordingId = $link.closest('.details').attr('data-recording-id') + # openVideo: (e) => + # $link = $(e.target) + # recordingId = $link.closest('.details').attr('data-recording-id') - if !context.jamClient.openVideo(recordingId) - @app.layout.notify({title: 'No Video Found', text: 'Did you delete this recording earlier from your computer?'}) - return false + # if !context.jamClient.openVideo(recordingId) + # @app.layout.notify({title: 'No Video Found', text: 'Did you delete this recording earlier from your computer?'}) + # return false - exportRecording: (e) => - $export = $(e.target) - if context.SessionStore.inSession() - context.JK.ackBubble($export, 'sync-viewer-paused', {}, {offsetParent: $export.closest('.dialog')}) - return + openVideo: `async function(e){ + const $link = $(e.target); + const recordingId = $link.closest('.details').attr('data-recording-id'); + const openVid = await context.jamClient.openVideo(recordingId) + if (!openVid) { + this.app.layout.notify({title: 'No Video Found', text: 'Did you delete this recording earlier from your computer?'}); + } + return false; + }` - recordingId = $export.closest('.details').attr('data-recording-id') - if !recordingId? or recordingId == "" - throw "exportRecording can't find data-recording-id" + # exportRecording: (e) => + # $export = $(e.target) + # if context.SessionStore.inSession() + # context.JK.ackBubble($export, 'sync-viewer-paused', {}, {offsetParent: $export.closest('.dialog')}) + # return - cmd = - { type: 'export_recording', - action: 'export', - queue: 'upload', - recording_id: recordingId} + # recordingId = $export.closest('.details').attr('data-recording-id') + # if !recordingId? or recordingId == "" + # throw "exportRecording can't find data-recording-id" - logger.debug("enqueueing export") - context.jamClient.OnTrySyncCommand(cmd) - return false; + # cmd = + # { type: 'export_recording', + # action: 'export', + # queue: 'upload', + # recording_id: recordingId} - deleteRecording: (e) => - $delete = $(e.target) - if context.SessionStore.inSession() - context.JK.ackBubble($delete, 'sync-viewer-paused', {}, {offsetParent: $delete.closest('.dialog')}) - return + # logger.debug("enqueueing export") + # context.jamClient.OnTrySyncCommand(cmd) + # return false; - $details = $delete.closest('.details') - recordingId = $details.attr('data-recording-id') + exportRecording: `async function(e){ + const $export = $(e.target); + if (context.SessionStore.inSession()) { + context.JK.ackBubble($export, 'sync-viewer-paused', {}, {offsetParent: $export.closest('.dialog')}); + return; + } - if !recordingId? or recordingId == "" - throw "deleteRecording can't find data-recording-id" + const recordingId = $export.closest('.details').attr('data-recording-id'); + if ((recordingId == null) || (recordingId === "")) { + throw "exportRecording can't find data-recording-id"; + } - context.JK.Banner.showYesNo({ - title: "Confirm Deletion", - html: "Are you sure you want to delete this recording?", - yes: => - @rest.deleteRecordingClaim(recordingId).done((response)=> - cmd = - { type: 'recording_directory', - action: 'delete', - queue: 'cleanup', - recording_id: recordingId} + const cmd = + { type: 'export_recording', + action: 'export', + queue: 'upload', + recording_id: recordingId}; - # now check if the sync is gone entirely, allowing us to delete it from the UI - @rest.getUserSync({user_sync_id: recordingId}).done((userSync) => - # the user sync is still here. tell user it'll be done as soon as they've uploaded their files - context.JK.ackBubble($delete, 'file-sync-delayed-deletion', {}, {offsetParent: $delete.closest('.dialog')}) - ) - .fail((xhr) => - if xhr.status == 404 - # the userSync is gone; remove from file manager dynamically - $recordingHolder = $details.closest('.recording-holder') - $recordingHolder.slideUp() - else - @app.ajaxError(arguments) - ) + logger.debug("enqueueing export"); + await context.jamClient.OnTrySyncCommand(cmd); + return false; + }` - context.jamClient.OnTrySyncCommand(cmd) - ) - .fail(@app.ajaxError) - }) + # deleteRecording: (e) => + # $delete = $(e.target) + # if context.SessionStore.inSession() + # context.JK.ackBubble($delete, 'sync-viewer-paused', {}, {offsetParent: $delete.closest('.dialog')}) + # return - return false; + # $details = $delete.closest('.details') + # recordingId = $details.attr('data-recording-id') + + # if !recordingId? or recordingId == "" + # throw "deleteRecording can't find data-recording-id" + + # context.JK.Banner.showYesNo({ + # title: "Confirm Deletion", + # html: "Are you sure you want to delete this recording?", + # yes: => + # @rest.deleteRecordingClaim(recordingId).done((response)=> + # cmd = + # { type: 'recording_directory', + # action: 'delete', + # queue: 'cleanup', + # recording_id: recordingId} + + # # now check if the sync is gone entirely, allowing us to delete it from the UI + # @rest.getUserSync({user_sync_id: recordingId}).done((userSync) => + # # the user sync is still here. tell user it'll be done as soon as they've uploaded their files + # context.JK.ackBubble($delete, 'file-sync-delayed-deletion', {}, {offsetParent: $delete.closest('.dialog')}) + # ) + # .fail((xhr) => + # if xhr.status == 404 + # # the userSync is gone; remove from file manager dynamically + # $recordingHolder = $details.closest('.recording-holder') + # $recordingHolder.slideUp() + # else + # @app.ajaxError(arguments) + # ) + + # context.jamClient.OnTrySyncCommand(cmd) + # ) + # .fail(@app.ajaxError) + # }) + + # return false; + + deleteRecording: `function(e){ + const $delete = $(e.target); + if (context.SessionStore.inSession()) { + context.JK.ackBubble($delete, 'sync-viewer-paused', {}, {offsetParent: $delete.closest('.dialog')}); + return; + } + + const $details = $delete.closest('.details'); + const recordingId = $details.attr('data-recording-id'); + + if ((recordingId == null) || (recordingId === "")) { + throw "deleteRecording can't find data-recording-id"; + } + + context.JK.Banner.showYesNo({ + title: "Confirm Deletion", + html: "Are you sure you want to delete this recording?", + yes: () => { + this.rest.deleteRecordingClaim(recordingId).done(async response=> { + const cmd = + { type: 'recording_directory', + action: 'delete', + queue: 'cleanup', + recording_id: recordingId}; + + // now check if the sync is gone entirely, allowing us to delete it from the UI + this.rest.getUserSync({user_sync_id: recordingId}).done(userSync => { + // the user sync is still here. tell user it'll be done as soon as they've uploaded their files + return context.JK.ackBubble($delete, 'file-sync-delayed-deletion', {}, {offsetParent: $delete.closest('.dialog')}); + }) + .fail(function(xhr) { + if (xhr.status === 404) { + // the userSync is gone; remove from file manager dynamically + const $recordingHolder = $details.closest('.recording-holder'); + return $recordingHolder.slideUp(); + } else { + return this.app.ajaxError(arguments); + } + }.bind(this)); + + await context.jamClient.OnTrySyncCommand(cmd); + }) + .fail(this.app.ajaxError); + } + }); + + return false; + }` displaySize: (size) => # size is in bytes. divide by million, anxosd round to one decimal place @@ -935,48 +1052,103 @@ context.JK.SyncViewer = class SyncViewer if queue.length > 0 this.createRecordingWrapper(queue, $(queue.get(0)).data('server-info').recording) - processUserSyncs: (response) => + # processUserSyncs: (response) => - @list.empty() + # @list.empty() - # check if no entries - if @since == 0 and response.entries.length == 0 - @list.append(context._.template(@templateNoSyncs.html(), {}, {variable: 'data'})) - else - recordings = {} # collect all unique recording - for userSync in response.entries - if userSync.type == 'recorded_track' - @list.append(this.createTrack(userSync)) - if userSync.type == 'recorded_backing_track' - @list.append(this.createBackingTrack(userSync)) - else if userSync.type == 'mix' - @list.append(this.createMix(userSync)) - else if userSync.type == 'stream_mix' - @list.append(this.createStreamMix(userSync)) + # # check if no entries + # if @since == 0 and response.entries.length == 0 + # @list.append(context._.template(@templateNoSyncs.html(), {}, {variable: 'data'})) + # else + # recordings = {} # collect all unique recording + # for userSync in response.entries + # if userSync.type == 'recorded_track' + # @list.append(this.createTrack(userSync)) + # if userSync.type == 'recorded_backing_track' + # @list.append(this.createBackingTrack(userSync)) + # else if userSync.type == 'mix' + # @list.append(this.createMix(userSync)) + # else if userSync.type == 'stream_mix' + # @list.append(this.createStreamMix(userSync)) - recordings[userSync.recording_id] = userSync.recording - recordingsToResolve = [] - # resolve each track against backend data: - for recording_id, recording of recordings - recordingsToResolve.push(recording) + # recordings[userSync.recording_id] = userSync.recording + # recordingsToResolve = [] + # # resolve each track against backend data: + # for recording_id, recording of recordings + # recordingsToResolve.push(recording) - clientRecordings = context.jamClient.GetLocalRecordingState(recordings: recordingsToResolve) + # clientRecordings = context.jamClient.GetLocalRecordingState(recordings: recordingsToResolve) - if clientRecordings.error? - alert(clientRecordings.error) - else - this.associateClientInfo(turp) for turp in clientRecordings.recordings + # if clientRecordings.error? + # alert(clientRecordings.error) + # else + # this.associateClientInfo(turp) for turp in clientRecordings.recordings - for track in @list.find('.recorded-track.sync') - this.updateTrackState($(track)) - for track in @list.find('.recorded-backing-track.sync') - this.updateBackingTrackState($(track)) - for streamMix in @list.find('.stream-mix.sync') - this.updateStreamMixState($(streamMix)) + # for track in @list.find('.recorded-track.sync') + # this.updateTrackState($(track)) + # for track in @list.find('.recorded-backing-track.sync') + # this.updateBackingTrackState($(track)) + # for streamMix in @list.find('.stream-mix.sync') + # this.updateStreamMixState($(streamMix)) - this.separateByRecording() + # this.separateByRecording() - @since = response.next + # @since = response.next + + processUserSyncs: `async function(response){ + + this.list.empty(); + + // check if no entries + if ((this.since === 0) && (response.entries.length === 0)) { + this.list.append(context._.template(this.templateNoSyncs.html(), {}, {variable: 'data'})); + } else { + let track; + const recordings = {}; // collect all unique recording + for (let userSync of Array.from(response.entries)) { + if (userSync.type === 'recorded_track') { + this.list.append(this.createTrack(userSync)); + } + if (userSync.type === 'recorded_backing_track') { + this.list.append(this.createBackingTrack(userSync)); + } else if (userSync.type === 'mix') { + this.list.append(this.createMix(userSync)); + } else if (userSync.type === 'stream_mix') { + this.list.append(this.createStreamMix(userSync)); + } + + recordings[userSync.recording_id] = userSync.recording; + } + const recordingsToResolve = []; + // resolve each track against backend data: + for (let recording_id in recordings) { + const recording = recordings[recording_id]; + recordingsToResolve.push(recording); + } + + const clientRecordings = await context.jamClient.GetLocalRecordingState({recordings: recordingsToResolve}); + + if (clientRecordings.error != null) { + alert(clientRecordings.error); + } else { + for (let turp of Array.from(clientRecordings.recordings)) { this.associateClientInfo(turp); } + } + + for (track of Array.from(this.list.find('.recorded-track.sync'))) { + this.updateTrackState($(track)); + } + for (track of Array.from(this.list.find('.recorded-backing-track.sync'))) { + this.updateBackingTrackState($(track)); + } + for (let streamMix of Array.from(this.list.find('.stream-mix.sync'))) { + this.updateStreamMixState($(streamMix)); + } + } + + this.separateByRecording(); + + return this.since = response.next; + }` resolveTrack: (commandMetadata) => recordingId = commandMetadata['recording_id'] @@ -1075,81 +1247,170 @@ context.JK.SyncViewer = class SyncViewer @logger.error("unknown category #{category}") - renderStartCommand: (commandId, commandType, commandMetadata) => + # renderStartCommand: (commandId, commandType, commandMetadata) => - #console.log("renderStartCommand", arguments) - unless commandMetadata? - managerState = context.jamClient.GetRecordingManagerState() - if commandType == 'download' - commandMetadata = managerState.current_download - else if commandType == 'upload' - commandMetadata = managerState.current_upload - else - @logger.error("unknown commandType #{commandType}") + # #console.log("renderStartCommand", arguments) + # unless commandMetadata? + # managerState = context.jamClient.GetRecordingManagerState() + # if commandType == 'download' + # commandMetadata = managerState.current_download + # else if commandType == 'upload' + # commandMetadata = managerState.current_upload + # else + # @logger.error("unknown commandType #{commandType}") - unless commandMetadata? - # we still have no metadata. we have to give up - @logger.error("no metadata found for current command #{commandId} #{commandType}. bailing out") - return + # unless commandMetadata? + # # we still have no metadata. we have to give up + # @logger.error("no metadata found for current command #{commandId} #{commandType}. bailing out") + # return - if commandMetadata.queue == 'download' - @downloadCommandId = commandId - @downloadMetadata = commandMetadata - @downloadProgress.removeClass('quiet paused busy') - @downloadProgress.addClass('busy') - if commandMetadata.type == 'recorded_track' and commandMetadata.action == 'download' - this.renderDownloadRecordedTrack(commandId, commandMetadata) - else if commandMetadata.type == 'recorded_backing_track' and commandMetadata.action == 'download' - this.renderDownloadRecordedBackingTrack(commandId, commandMetadata) - else - this.renderGeneric(commandId, 'download', commandMetadata) - else if commandMetadata.queue == 'upload' - @uploadCommandId = commandId - @uploadMetadata = commandMetadata - @uploadProgress.removeClass('quiet paused busy') - @uploadProgress.addClass('busy') - if commandMetadata.type == 'recorded_track' and commandMetadata.action == 'upload' - this.renderUploadRecordedTrack(commandId, commandMetadata) - else if commandMetadata.type == 'recorded_backing_track' and commandMetadata.action == 'upload' - this.renderUploadRecordedBackingTrack(commandId, commandMetadata) - else - this.renderGeneric(commandId, 'upload', commandMetadata) - else if commandMetadata.queue == 'cleanup' - @cleanupCommandId = commandId - @cleanupMetadata = commandMetadata + # if commandMetadata.queue == 'download' + # @downloadCommandId = commandId + # @downloadMetadata = commandMetadata + # @downloadProgress.removeClass('quiet paused busy') + # @downloadProgress.addClass('busy') + # if commandMetadata.type == 'recorded_track' and commandMetadata.action == 'download' + # this.renderDownloadRecordedTrack(commandId, commandMetadata) + # else if commandMetadata.type == 'recorded_backing_track' and commandMetadata.action == 'download' + # this.renderDownloadRecordedBackingTrack(commandId, commandMetadata) + # else + # this.renderGeneric(commandId, 'download', commandMetadata) + # else if commandMetadata.queue == 'upload' + # @uploadCommandId = commandId + # @uploadMetadata = commandMetadata + # @uploadProgress.removeClass('quiet paused busy') + # @uploadProgress.addClass('busy') + # if commandMetadata.type == 'recorded_track' and commandMetadata.action == 'upload' + # this.renderUploadRecordedTrack(commandId, commandMetadata) + # else if commandMetadata.type == 'recorded_backing_track' and commandMetadata.action == 'upload' + # this.renderUploadRecordedBackingTrack(commandId, commandMetadata) + # else + # this.renderGeneric(commandId, 'upload', commandMetadata) + # else if commandMetadata.queue == 'cleanup' + # @cleanupCommandId = commandId + # @cleanupMetadata = commandMetadata + renderStartCommand: `async function(commandId, commandType, commandMetadata) { - renderSingleRecording: (userSyncs) => - return if userSyncs.entries.length == 0 - clientRecordings = context.jamClient.GetLocalRecordingState(recordings: [userSyncs.entries[0].recording]) - for userSync in userSyncs.entries - if userSync.type == 'recorded_track' - $track = @list.find(".sync[data-id='#{userSync.id}']") - continue if $track.length == 0 - $track.data('server-info', userSync) - this.associateClientInfo(clientRecordings.recordings[0]) - this.updateTrackState($track) - else if userSync.type == 'recorded_backing_track' - $track = @list.find(".sync[data-id='#{userSync.id}']") - continue if $track.length == 0 - $track.data('server-info', userSync) - this.associateClientInfo(clientRecordings.recordings[0]) - this.updateBackingTrackState($track) - else if userSync.type == 'mix' - # check if there is a virtual mix 1st; if so, update it - $mix = @list.find(".mix.virtual[data-recording-id='#{userSync.recording.id}']") - if $mix.length == 0 - $mix = @list.find(".sync[data-id='#{userSync.id}']") - continue if $mix.length == 0 - $newMix = this.createMix(userSync) - this.associateClientInfo(clientRecordings.recordings[0]) - $mix.replaceWith($newMix) - else if userSync.type == 'stream_mix' - $streamMix = @list.find(".sync[data-id='#{userSync.id}']") - continue if $streamMix.length == 0 - $streamMix.data('server-info', userSync) - this.associateClientInfo(clientRecordings.recordings[0]) - this.updateStreamMixState($streamMix) + //console.log("renderStartCommand", arguments) + if (commandMetadata == null) { + const managerState = await context.jamClient.GetRecordingManagerState(); + if (commandType === 'download') { + commandMetadata = managerState.current_download; + } else if (commandType === 'upload') { + commandMetadata = managerState.current_upload; + } else { + this.logger.error('unknown commandType '+ commandType); + } + } + + if (commandMetadata == null) { + // we still have no metadata. we have to give up + this.logger.error('no metadata found for current command '+ commandId + ' '+commandType+'. bailing out'); + } + + if (commandMetadata.queue === 'download') { + this.downloadCommandId = commandId; + this.downloadMetadata = commandMetadata; + this.downloadProgress.removeClass('quiet paused busy'); + this.downloadProgress.addClass('busy'); + if ((commandMetadata.type === 'recorded_track') && (commandMetadata.action === 'download')) { + return this.renderDownloadRecordedTrack(commandId, commandMetadata); + } else if ((commandMetadata.type === 'recorded_backing_track') && (commandMetadata.action === 'download')) { + return this.renderDownloadRecordedBackingTrack(commandId, commandMetadata); + } else { + return this.renderGeneric(commandId, 'download', commandMetadata); + } + } else if (commandMetadata.queue === 'upload') { + this.uploadCommandId = commandId; + this.uploadMetadata = commandMetadata; + this.uploadProgress.removeClass('quiet paused busy'); + this.uploadProgress.addClass('busy'); + if ((commandMetadata.type === 'recorded_track') && (commandMetadata.action === 'upload')) { + return this.renderUploadRecordedTrack(commandId, commandMetadata); + } else if ((commandMetadata.type === 'recorded_backing_track') && (commandMetadata.action === 'upload')) { + return this.renderUploadRecordedBackingTrack(commandId, commandMetadata); + } else { + return this.renderGeneric(commandId, 'upload', commandMetadata); + } + } else if (commandMetadata.queue === 'cleanup') { + this.cleanupCommandId = commandId; + return this.cleanupMetadata = commandMetadata; + } + }` + + # renderSingleRecording: (userSyncs) => + # return if userSyncs.entries.length == 0 + # clientRecordings = context.jamClient.GetLocalRecordingState(recordings: [userSyncs.entries[0].recording]) + # for userSync in userSyncs.entries + # if userSync.type == 'recorded_track' + # $track = @list.find(".sync[data-id='#{userSync.id}']") + # continue if $track.length == 0 + # $track.data('server-info', userSync) + # this.associateClientInfo(clientRecordings.recordings[0]) + # this.updateTrackState($track) + # else if userSync.type == 'recorded_backing_track' + # $track = @list.find(".sync[data-id='#{userSync.id}']") + # continue if $track.length == 0 + # $track.data('server-info', userSync) + # this.associateClientInfo(clientRecordings.recordings[0]) + # this.updateBackingTrackState($track) + # else if userSync.type == 'mix' + # # check if there is a virtual mix 1st; if so, update it + # $mix = @list.find(".mix.virtual[data-recording-id='#{userSync.recording.id}']") + # if $mix.length == 0 + # $mix = @list.find(".sync[data-id='#{userSync.id}']") + # continue if $mix.length == 0 + # $newMix = this.createMix(userSync) + # this.associateClientInfo(clientRecordings.recordings[0]) + # $mix.replaceWith($newMix) + # else if userSync.type == 'stream_mix' + # $streamMix = @list.find(".sync[data-id='#{userSync.id}']") + # continue if $streamMix.length == 0 + # $streamMix.data('server-info', userSync) + # this.associateClientInfo(clientRecordings.recordings[0]) + # this.updateStreamMixState($streamMix) + + renderSingleRecording: `async function(userSyncs){ + if (userSyncs.entries.length === 0) { return; } + const clientRecordings = await context.jamClient.GetLocalRecordingState({recordings: [userSyncs.entries[0].recording]}); + const result = []; + for (let userSync of Array.from(userSyncs.entries)) { + var $track; + if (userSync.type === 'recorded_track') { + $track = this.list.find('.sync[data-id='+userSync.id+']'); + if ($track.length === 0) { continue; } + $track.data('server-info', userSync); + this.associateClientInfo(clientRecordings.recordings[0]); + result.push(this.updateTrackState($track)); + } else if (userSync.type === 'recorded_backing_track') { + $track = this.list.find(".sync[data-id='"+userSync.id+"']"); + if ($track.length === 0) { continue; } + $track.data('server-info', userSync); + this.associateClientInfo(clientRecordings.recordings[0]); + result.push(this.updateBackingTrackState($track)); + } else if (userSync.type === 'mix') { + // check if there is a virtual mix 1st; if so, update it + let $mix = this.list.find(".mix.virtual[data-recording-id='"+userSync.recording.id+"']"); + if ($mix.length === 0) { + $mix = this.list.find(".sync[data-id='"+userSync.id+"']"); + } + if ($mix.length === 0) { continue; } + const $newMix = this.createMix(userSync); + this.associateClientInfo(clientRecordings.recordings[0]); + result.push($mix.replaceWith($newMix)); + } else if (userSync.type === 'stream_mix') { + const $streamMix = this.list.find(".sync[data-id='"+userSync.id+"']"); + if ($streamMix.length === 0) { continue; } + $streamMix.data('server-info', userSync); + this.associateClientInfo(clientRecordings.recordings[0]); + result.push(this.updateStreamMixState($streamMix)); + } else { + result.push(undefined); + } + } + return result; + }` updateSingleRecording: (recording_id) => @rest.getUserSyncs({recording_id: recording_id}).done(this.renderSingleRecording) diff --git a/web/app/assets/javascripts/webcam_viewer.js.coffee b/web/app/assets/javascripts/webcam_viewer.js.coffee index 5d5ac96ab..9ab016687 100644 --- a/web/app/assets/javascripts/webcam_viewer.js.coffee +++ b/web/app/assets/javascripts/webcam_viewer.js.coffee @@ -33,8 +33,6 @@ BackendToFrontendFPS = { 5: 10 } -_selectedDeviceName = `async function(){let webcamName="None Configured";const webcam=(this.client.FTUECurrentSelectedVideoDevice!=null)?await this.client.FTUECurrentSelectedVideoDevice():null;logger.debug("currently selected video device",webcam);if((webcam!=null)&&(Object.keys(webcam).length>0)){webcamName=Object.keys(webcam)[0];}return webcamName;}` - #_loadResolutions = `async function(){const resolutions = (this.client.FTUEGetCaptureResolution != null) ? this.client.FTUEGetCaptureResolution() : {};const selectControl = this.resolutionSelect;this.logger.debug('FOUND THESE RESOLUTIONS', resolutions); context._.each(resolutions, function(resolution, resolutionKey, obj) { const frontendResolution = BackendToFrontend[resolutionKey];if (!frontendResolution) { this.logger.error('unknown resolution!' + resolution); const value = `${resolutionKey}`; const option = $('