(function (context, $) { "use strict"; context.JK = context.JK || {}; class Deferred { constructor(request_id) { var self = this; this.request_id = request_id; this.promise = new Promise(function (resolve, reject) { self.reject = reject; self.resolve = resolve; }); } } context.JK.AsyncJamClient = function (app) { const self = this; const logger = context.JK.logger; let deferredQueue = []; let jkfrontendchannel = null; let enumAppCounter = 1000; let request_id = 1; const JKFrontendMethods = Object.freeze({ UnknownJKAppMessage: enumAppCounter++, AbortRecording: enumAppCounter++, addUserBackingTracksToJamkazamAsset: enumAppCounter++, applySubscriptionPolicy: enumAppCounter++, BringVideoWindowToFront: enumAppCounter++, browseForUserBackingTracksCandidate: enumAppCounter++, cancelVideoUpload: enumAppCounter++, clientID: enumAppCounter++, ClientJoinedSession: enumAppCounter++, ClientLeftSession: enumAppCounter++, ClientUpdateStartDownload: enumAppCounter++, ClientUpdateStartUpdate: enumAppCounter++, ClientUpdateVersion: enumAppCounter++, ClosePreviewRecording: enumAppCounter++, CloseRecording: enumAppCounter++, deleteVideo: enumAppCounter++, DownloadFileStatus: enumAppCounter++, endPairing: enumAppCounter++, FTUEAudioResync: enumAppCounter++, FTUECancel: enumAppCounter++, FTUEChatFrameSize: enumAppCounter++, FTUEClearChannelAssignments: enumAppCounter++, FTUEClearChatInput: enumAppCounter++, FTUECreateUpdatePlayBackProfile: enumAppCounter++, FTUECurrentSelectedVideoDevice: enumAppCounter++, FTUEGetAllAudioConfigurations: enumAppCounter++, FTUEGetAllConfigurationList: enumAppCounter++, FTUEGetAudioConfigurationsMissingDevice: enumAppCounter++, FTUEGetAudioDevices: enumAppCounter++, FTUEGetAutoSelectVideoLayout: enumAppCounter++, FTUEGetAvailableEncodeVideoResolutions: enumAppCounter++, FTUEGetAvailableVideoLayoutGroupStyles: enumAppCounter++, FTUEGetBadConfigurationMissingDev: enumAppCounter++, FTUEGetCaptureResolution: enumAppCounter++, FTUEGetChannels: enumAppCounter++, FTUEGetChatInputs: enumAppCounter++, FTUEGetChatInputVolume: enumAppCounter++, FTUEGetChatLatency: enumAppCounter++, FTUEGetConfigurationDevice: enumAppCounter++, FTUEGetConfigurationDevs: enumAppCounter++, FTUEGetCurrentCaptureResolution: enumAppCounter++, FTUEGetCurrentVideoCaptureDeviceCapability: enumAppCounter++, FTUEGetDefaultAudioConfigurations: enumAppCounter++, FTUEGetDevices: enumAppCounter++, FTUEGetExpectedLatency: enumAppCounter++, FTUEGetFrameSize: enumAppCounter++, FTUEGetGoodAudioConfigurations: enumAppCounter++, FTUEGetGoodConfigurationList: enumAppCounter++, FTUEgetInputDeviceSampleRate: enumAppCounter++, FTUEGetInputLatency: enumAppCounter++, FTUEGetInputMusicDevice: enumAppCounter++, FTUEGetInputVolume: enumAppCounter++, FTUEGetIoPerfData: enumAppCounter++, FTUEGetMapUserCntPreferredVideoLayoutGroupStyle: enumAppCounter++, FTUEGetMusicInputs: enumAppCounter++, FTUEGetMusicOutputs: enumAppCounter++, FTUEGetMusicProfileName: enumAppCounter++, FTUEgetOutputDeviceSampleRate: enumAppCounter++, FTUEGetOutputLatency: enumAppCounter++, FTUEGetOutputMusicDevice: enumAppCounter++, FTUEGetOutputVolume: enumAppCounter++, FTUEGetPreferredChatSampleRate: enumAppCounter++, FTUEGetPreferredMixerSampleRate: enumAppCounter++, FTUEGetPreferredOutputSampleRate: enumAppCounter++, FTUEGetSendFrameRates: enumAppCounter++, FTUEGetStatus: enumAppCounter++, FTUEGetUserCountPreferredVideoLayoutGroupStyle: enumAppCounter++, FTUEGetVideoCaptureDeviceCapabilities: enumAppCounter++, FTUEGetVideoCaptureDeviceNames: enumAppCounter++, FTUEGetVideoShareEnable: enumAppCounter++, FTUEGetVolumeRanges: enumAppCounter++, FTUEHasControlPanel: enumAppCounter++, FTUEInit: enumAppCounter++, FTUEIsMusicDeviceWDM: enumAppCounter++, FTUELoadAudioConfiguration: enumAppCounter++, FTUEOpenControlPanel: enumAppCounter++, FTUEPageEnter: enumAppCounter++, FTUEPageLeave: enumAppCounter++, FTUERefreshDevices: enumAppCounter++, FTUERegisterLatencyCallback: enumAppCounter++, FTUERegisterVUCallbacks: enumAppCounter++, FTUESave: enumAppCounter++, FTUESelectVideoCaptureDevice: enumAppCounter++, FTUESetAutoSelectVideoLayout: enumAppCounter++, FTUESetCaptureResolution: enumAppCounter++, FTUESetChatInput: enumAppCounter++, FTUESetChatInputVolume: enumAppCounter++, FTUESetChatLatency: enumAppCounter++, FTUESetFrameSize: enumAppCounter++, FTUESetInputLatency: enumAppCounter++, FTUESetInputMusicDevice: enumAppCounter++, FTUESetInputVolume: enumAppCounter++, FTUESetLatencySamples: enumAppCounter++, FTUESetMusicDevice: enumAppCounter++, FTUESetMusicInput: enumAppCounter++, FTUESetMusicInput2: enumAppCounter++, FTUESetMusicOutput: enumAppCounter++, FTUESetMusicProfileName: enumAppCounter++, FTUESetOutputLatency: enumAppCounter++, FTUESetOutputMusicDevice: enumAppCounter++, FTUESetOutputVolume: enumAppCounter++, FTUESetPreferredChatSampleRate: enumAppCounter++, FTUESetPreferredMixerSampleRate: enumAppCounter++, FTUESetPreferredOutputSampleRate: enumAppCounter++, FTUESetPreferredVideoLayoutGroupStyle: enumAppCounter++, FTUESetSendFrameRates: enumAppCounter++, FTUESetStatus: enumAppCounter++, FTUESetUserCountPreferredVideoLayoutGroupStyle: enumAppCounter++, FTUESetVideoEncodeResolution: enumAppCounter++, FTUESetVideoShareEnable: enumAppCounter++, FTUEStartIoPerfTest: enumAppCounter++, FTUEStartLatency: enumAppCounter++, FTUEUnsetMusicInput2: enumAppCounter++, get48vAndLineInstState: enumAppCounter++, getABLoopState: enumAppCounter++, getAllClientsStateMap: enumAppCounter++, getAllClientsStateStr: enumAppCounter++, GetASIODevices: enumAppCounter++, GetAutoStart: enumAppCounter++, getAvailableMetronomeClickNames: enumAppCounter++, getBackingTrackList: enumAppCounter++, getClientParentChildRole: enumAppCounter++, getConnectionDetail: enumAppCounter++, GetCurrentVideoFrameRate: enumAppCounter++, GetCurrentVideoResolution: enumAppCounter++, GetDetailedOS: enumAppCounter++, GetFTUE: enumAppCounter++, GetJamTrackSettings: enumAppCounter++, GetJamTrackTimeline: enumAppCounter++, getJBAutoPair: enumAppCounter++, getJbNetworkState: enumAppCounter++, getJbPortBindState: enumAppCounter++, getJbPreampState: enumAppCounter++, getJbStaticPortFlag: enumAppCounter++, getJbStaticPortValue: enumAppCounter++, getJbTrackState: enumAppCounter++, getJbUsbState: enumAppCounter++, GetLastLatencyTestTimes: enumAppCounter++, getLatencyServerState: enumAppCounter++, getLocalClients: enumAppCounter++, GetLocalRecordingState: enumAppCounter++, getLogLevel: enumAppCounter++, getMetronomeCricketTestState: enumAppCounter++, GetMixerIDs: enumAppCounter++, GetMixerMode: enumAppCounter++, GetMixerVolume: enumAppCounter++, getMyChildren: enumAppCounter++, getMyNetworkState: enumAppCounter++, getMyParentState: enumAppCounter++, GetNetworkTestScore: enumAppCounter++, getOpenVideoSources: enumAppCounter++, getOperatingMode: enumAppCounter++, GetOS: enumAppCounter++, GetOSAsString: enumAppCounter++, getParentClientId: enumAppCounter++, getPeerState: enumAppCounter++, GetRecordingManagerState: enumAppCounter++, GetSampleRate: enumAppCounter++, GetScoreWorkTimingInterval: enumAppCounter++, getSessionSetCompressorState: enumAppCounter++, GetStaticPort: enumAppCounter++, GetUseStaticPort: enumAppCounter++, GetVideoNetworkTestScore: enumAppCounter++, hasBonjour: enumAppCounter++, hasVstAssignment: enumAppCounter++, hasVstHost: enumAppCounter++, hasWebrtc: enumAppCounter++, InitiateScoringSession: enumAppCounter++, InvalidateJamTrack: enumAppCounter++, IsAppInWritableVolume: enumAppCounter++, IsAudioStarted: enumAppCounter++, IsFrontendVisible: enumAppCounter++, isJamBlaster: enumAppCounter++, isLatencyTestBlocked: enumAppCounter++, IsMyNetworkWireless: enumAppCounter++, IsNativeClient: enumAppCounter++, IsSessionLiveBroadCastRunning: enumAppCounter++, isSessionTrackPaused: enumAppCounter++, isSessionTrackPlaying: enumAppCounter++, isSessVideoRecording: enumAppCounter++, isSessVideoShared: enumAppCounter++, isSessYouTubeVideoBroadcasting: enumAppCounter++, isVideoRecordingAllowed: enumAppCounter++, isVideoWindowOpen: enumAppCounter++, IsVstLoaded: enumAppCounter++, isWebCamOpen: enumAppCounter++, jamBlasterSerialNo: enumAppCounter++, JamTrackDownload: enumAppCounter++, JamTrackGetImage: enumAppCounter++, JamTrackGetTrackDetail: enumAppCounter++, JamTrackGetTracks: enumAppCounter++, JamTrackIsPlayable: enumAppCounter++, JamTrackIsPlaying: enumAppCounter++, JamTrackKeysRequest: enumAppCounter++, JamTrackLoadJmep: enumAppCounter++, JamTrackPlay: enumAppCounter++, JamTrackStopPlay: enumAppCounter++, JoinSession: enumAppCounter++, LastUsedProfileName: enumAppCounter++, LeaveSession: enumAppCounter++, LeaveSessionAndMinimize: enumAppCounter++, log: enumAppCounter++, NetworkTest: enumAppCounter++, NetworkTestResult: enumAppCounter++, OnDownloadAvailable: enumAppCounter++, OnLoggedIn: enumAppCounter++, OnLoggedInUserName: enumAppCounter++, OnLoggedOut: enumAppCounter++, OnTrySyncCommand: enumAppCounter++, openBackingTrackFile: enumAppCounter++, OpenBackingTracksDirectory: enumAppCounter++, OpenRecording: enumAppCounter++, OpenSystemBrowser: enumAppCounter++, openVideo: enumAppCounter++, P2PMessageReceived: enumAppCounter++, ParticipantJoined: enumAppCounter++, ParticipantLeft: enumAppCounter++, pauseVideoUpload: enumAppCounter++, PerformQuit: enumAppCounter++, PostTaskBarMessage: enumAppCounter++, PreviewRecording: enumAppCounter++, rebootJamBlaster: enumAppCounter++, RegisterGenericCallBack: enumAppCounter++, registerMasterClippingCallback: enumAppCounter++, RegisterMixerInterfaceModeChangeCallback: enumAppCounter++, RegisterMuteChangeCallBack: enumAppCounter++, RegisterQuitCallback: enumAppCounter++, RegisterRecordingCallbacks: enumAppCounter++, RegisterRecordingManagerCallbacks: enumAppCounter++, RegisterSessionJoinLeaveRequestCallBack: enumAppCounter++, RegisterVolChangeCallBack: enumAppCounter++, ReloadAudioSystem: enumAppCounter++, removeBackingTrackFiles: enumAppCounter++, ResetPageCounters: enumAppCounter++, RestartApplication: enumAppCounter++, restartParentClient: enumAppCounter++, resumeVideoUpload: enumAppCounter++, SaveSettings: enumAppCounter++, SaveToClipboard: enumAppCounter++, SendP2PMessage: enumAppCounter++, SessGetInsetPosition: enumAppCounter++, SessGetListOfPeersSharingVideo: enumAppCounter++, SessGetPeersVideoPosition: enumAppCounter++, SessGetVideoDisplayLayoutGroup: enumAppCounter++, SessGetVideoReceiveEnable: enumAppCounter++, SessGetVideoRecordings: enumAppCounter++, SessionAddPlayTrack: enumAppCounter++, SessionAddTrack: enumAppCounter++, SessionAudioResync: enumAppCounter++, SessionCloseBackingTrackFile: enumAppCounter++, SessionCloseMetronome: enumAppCounter++, SessionCurrentPlaybackMode: enumAppCounter++, SessionCurrrentJamTrackPlayPosMs: enumAppCounter++, SessionCurrrentPlayPosMs: enumAppCounter++, SessionFirstGet: enumAppCounter++, SessionFirstSet: enumAppCounter++, SessionGetAllControlState: enumAppCounter++, SessionGetControlState: enumAppCounter++, SessionGetDeviceLatency: enumAppCounter++, SessionGetIDs: enumAppCounter++, SessionGetJamTracksPlayDurationMs: enumAppCounter++, SessionGetMacHash: enumAppCounter++, SessionGetMasterLocalMix: enumAppCounter++, SessionGetTracksPlayDurationMs: enumAppCounter++, SessionJamTrackSeekMs: enumAppCounter++, SessionLiveBroadcastStart: enumAppCounter++, SessionLiveBroadcastStop: enumAppCounter++, SessionOpenBackingTrackFile: enumAppCounter++, SessionOpenMetronome: enumAppCounter++, SessionPageEnter: enumAppCounter++, SessionPageLeave: enumAppCounter++, SessionPausePlay: enumAppCounter++, SessionRegisterCallback: enumAppCounter++, SessionRemoveAllPlayTracks: enumAppCounter++, SessionRemovePlayTrack: enumAppCounter++, SessionRemoveTrack: enumAppCounter++, SessionRequestUserControlUpdate: enumAppCounter++, SessionSetAlertCallback: enumAppCounter++, SessionSetAlertPeriod: enumAppCounter++, SessionSetConnectionStatusRefreshRate: enumAppCounter++, SessionSetControlState: enumAppCounter++, SessionSetMasterLocalMix: enumAppCounter++, SessionSetMetronome: enumAppCounter++, SessionSetRecordingFilename: enumAppCounter++, SessionSetRecordingFolder: enumAppCounter++, SessionSetTrackVolumeData: enumAppCounter++, SessionSetUserData: enumAppCounter++, SessionSetUserName: enumAppCounter++, SessionShowMetronomeGui: enumAppCounter++, SessionStartPlay: enumAppCounter++, SessionStopPlay: enumAppCounter++, SessionTrackSeekMs: enumAppCounter++, SessionTracksSeek: enumAppCounter++, SessPlayVideoRecording: enumAppCounter++, SessRotatePeerVideoPositions: enumAppCounter++, SessSelectVideoDisplayLayoutGroup: enumAppCounter++, SessSetInsetPosition: enumAppCounter++, SessSetInsetSize: enumAppCounter++, SessSetPeersVideoPosition: enumAppCounter++, SessSetVideoReceiveEnable: enumAppCounter++, SessStartVideoRecordAndReturnFileName: enumAppCounter++, SessStartVideoSharing: enumAppCounter++, SessStartWebcamVideoRecordAndReturnFileName: enumAppCounter++, SessStartYouTubeVideoBroadcast: enumAppCounter++, SessStopVideoRecord: enumAppCounter++, SessStopVideoSharing: enumAppCounter++, SessStopYouTubeVideoBroadcast: enumAppCounter++, SessSubscribePeerVideo: enumAppCounter++, SessUnsubscribePeerVideo: enumAppCounter++, set48vAndLineInstState: enumAppCounter++, setABLoopState: enumAppCounter++, SetAutoStart: enumAppCounter++, setBackingTrackOpenCallback: enumAppCounter++, SetFakeRecordingImpl: enumAppCounter++, SetFTUE: enumAppCounter++, setJBAutoPair: enumAppCounter++, setJBName: enumAppCounter++, setJbNetworkState: enumAppCounter++, setJbPortBindState: enumAppCounter++, setJbPreampState: enumAppCounter++, setJbStaticPortFlag: enumAppCounter++, setJbStaticPortValue: enumAppCounter++, setJbTrackState: enumAppCounter++, setJbUsbState: enumAppCounter++, setJmepMetronomeVolume: enumAppCounter++, SetLastUsedProfileName: enumAppCounter++, SetLatencyTestBlocked: enumAppCounter++, setMetronomeCricketTestState: enumAppCounter++, setMetronomeOpenCallback: enumAppCounter++, SetMixerMode: enumAppCounter++, SetNetworkTestScore: enumAppCounter++, SetRecordingFilename: enumAppCounter++, SetRecordingFolder: enumAppCounter++, SetScoreWorkTimingInterval: enumAppCounter++, setSessionMixerCategoryPlayoutState: enumAppCounter++, setSessionSetCompressorState: enumAppCounter++, SetStaticPort: enumAppCounter++, SetUseStaticPort: enumAppCounter++, SetVideoNetworkTestScore: enumAppCounter++, SetVURefreshRate: enumAppCounter++, ShowSelectBackingTrackDialog: enumAppCounter++, ShowSelectVSTScanDialog: enumAppCounter++, ShutdownApplication: enumAppCounter++, StartLiveStreaming: enumAppCounter++, startPairing: enumAppCounter++, StartRecording: enumAppCounter++, StopAudio: enumAppCounter++, StopLiveStreaming: enumAppCounter++, StopNetworkTest: enumAppCounter++, StopRecording: enumAppCounter++, TestLatency: enumAppCounter++, TestNetworkPktBwRate: enumAppCounter++, testVideoRender: enumAppCounter++, TrackDeleteProfile: enumAppCounter++, TrackGetAssignment: enumAppCounter++, TrackGetChannels: enumAppCounter++, TrackGetChatEnable: enumAppCounter++, TrackGetChatUsesMusic: enumAppCounter++, TrackGetCount: enumAppCounter++, TrackGetDevices: enumAppCounter++, TrackGetInstrument: enumAppCounter++, TrackGetMusicDeviceID: enumAppCounter++, TrackGetMusicDeviceNames: enumAppCounter++, TrackHasControlPanel: enumAppCounter++, TrackIsMusicDeviceType: enumAppCounter++, TrackLoadAssignments: enumAppCounter++, TrackLoadAudioProfile: enumAppCounter++, TrackOpenControlPanel: enumAppCounter++, TrackRefreshDevices: enumAppCounter++, TrackSaveAssignments: enumAppCounter++, TrackSetAssignment: enumAppCounter++, TrackSetChatEnable: enumAppCounter++, TrackSetChatInput: enumAppCounter++, TrackSetChatUsesMusic: enumAppCounter++, TrackSetCount: enumAppCounter++, TrackSetInstrument: enumAppCounter++, TrackSetMusicDevice: enumAppCounter++, UpdateMixer: enumAppCounter++, UpdateSessionInfo: enumAppCounter++, uploadVideo: enumAppCounter++, UserAttention: enumAppCounter++, VideoDecision: enumAppCounter++, VSTAddSearchPath: enumAppCounter++, VSTClearAll: enumAppCounter++, VSTListSearchPaths: enumAppCounter++, VSTListTrackAssignments: enumAppCounter++, VSTListVsts: enumAppCounter++, VSTLoad: enumAppCounter++, VSTRemoveSearchPath: enumAppCounter++, VSTScan: enumAppCounter++, VSTSetTrackAssignment: enumAppCounter++, VSTShowHideGui: enumAppCounter++, VST_EnableMidiForTrack: enumAppCounter++, VST_GetMidiDeviceList: enumAppCounter++, VST_ScanForMidiDevices: enumAppCounter++, IsOBSAvailable: enumAppCounter++, StartMediaRecording: enumAppCounter++, LaunchBroadcastSettings: enumAppCounter++, }); function setupWebSocketConnection() { const baseUrl = "ws://localhost:3060"; logger.log( "[asyncJamClient] connecting to WebSocket server at " + baseUrl + "." ); const socket = new WebSocket(baseUrl); socket.onclose = function (event) { logger.error("[asyncJamClient] QWebChannel websocket closed"); if (event.code != 1000) { // Error code 1000 means that the connection was closed normally. // Try to reconnect. if (!navigator.onLine) { //alert("You are offline. Please connect to the Internet and try again."); } } }; socket.onerror = function (error) { logger.error("[asyncJamClient] QWebChannel websocket error: " + error); }; socket.onopen = function () { logger.log( "[asyncJamClient] WebSocket connected, setting up QWebChannel." ); const skipLogMethods = [ 'getConnectionDetail' ] const displayLogMethod = [ ] new QWebChannel(socket, function (channel) { jkfrontendchannel = channel.objects.jkfrontendchannel; if (jkfrontendchannel) { window.isWebChannelReady = true; let deferred; try { jkfrontendchannel.sendText.connect(function (message) { // logger.log( // "[asyncJamClient] Message received via QWebChannel: " + // message // ); //handle Method Not Implemented" if ( typeof resp === "object" && resp[0] === "Method Not Implemented" ) { //throw new Error("Method Not Implemented"); deferred.resolve(null); //return null value } else { let msg = JSON.parse(message); let req_id = msg.request_id; //frontend originated request let response = msg.response; let evt_id = msg.event_id; //backend originated async event let methodName = msg.method_name; deferred = deferredQueue.find((d) => { return d.request_id === req_id; }); if (deferred) { if(skipLogMethods.length > 0 && skipLogMethods.includes(methodName)){ }else{ if(displayLogMethod.includes(methodName)){ logger.log( "[asyncJamClient] Message received via QWebChannel: " + msg ); } } deferred.resolve(response); //remove this deferred object from queue deferredQueue = deferredQueue.filter( (d) => d.request_id !== deferred.request_id ); } else if (evt_id) { let method = Object.keys(response)[0] logger.log("[asyncJamClient] event received:", evt_id.toString(), Object.keys(response)[0]) // if(evt_id.toString() === '3012'){ // alert(evt_id.toString()) // } switch (evt_id.toString()) { case '3006': //execute_script if(!response['execute_script'].match('HandleBridgeCallback2')){ logger.log(`[asyncJamClient] 3006 execute_script: ${response['execute_script']}`); } try { eval(response['execute_script']); } catch (error) { logger.log(`[asyncJamClient] error: execute_script: ${response['execute_script']}`); logger.log(error); } break; case '3007': //message logger.log(`[asyncJamClient] 3007 message: ${response['message']}`); try { const msg = response['message']; const clientId = response['targetClientID']; context.JK.JamServer.sendP2PMessage(clientId, msg) } catch (error) { logger.log(`[asyncJamClient] error: sendP2PMessage: ${response['message']}`); logger.log(error); } break; case '3010': //JKVideoSession logger.log(`[asyncJamClient] 3010 JKVideoSession: ${response['JKVideoSession']['connect']}`); const vidConnect = response['JKVideoSession']['connect']; context.ExternalVideoActions.setVideoEnabled(vidConnect); context.JK.videoIsOngoing = vidConnect; break; case '3011': //AudioFormatChangeEvent logger.log(`[asyncJamClient] 3011 AudioFormatChangeEvent: ${response['AudioFormat']}`); const audioFormat = response['AudioFormat'] context.RecordingActions.audioRecordingFormatChanged(`.${audioFormat}`) break; case '3012': //customUrl logger.log(`[asyncJamClient] 3012 CustomUrl: ${response['CustomUrl']}`); const customUrl = response['CustomUrl'] //window.location.href = "http://www.jamkazam.local:3000/client#/createSession/custom~yes|privacy~2|description~hello|inviteeIds~27bd4a30-d1b8-4eea-8454-01a104d59381" //window.location.href = "http://www.jamkazam.local:3000/client#/joinSession/custom~yes|joinSessionId~2" window.location.href = customUrl break; // case '3013': //JKJoinSessionFromCustomUrlEvent // logger.log(`[asyncJamClient] 3013 JKJoinSessionFromCustomUrlEvent: ${response['JKJoinSessionFromCustomUrlEvent']['CustomUrl']}`); // if(context.JK.FindSessionScreen){ // const customUrl = response['JKJoinSessionFromCustomUrlEvent']['CustomUrl'] // context.JK.SessionUtils.joinSessionFromCustomUrlScheme(customUrl) // } // break; default: break; } } } }); //TODO: handle method does not exist } catch (e) { logger.log( "[asyncJamClient] Error when receving message via QWebChannel" ); if (deferred) { deferred.reject(e.message); deferred = null; } Bugsnag.notify(e, function(event){ event.severity = 'info' event.context = 'asyncJamClient' event.setUser(gon.user_id, gon.user_email, gon.user_name) }); } } }); }; } function waitForOpenConnection(){ return new Promise((resolve, reject) => { const maxNumberOfAttempts = 10 const intervalTime = 200 //ms let currentAttempt = 0 const interval = setInterval(() => { if (currentAttempt > maxNumberOfAttempts - 1) { clearInterval(interval) reject(new Error('Maximum number of attempts exceeded')) } else if (jkfrontendchannel) { clearInterval(interval) resolve() } currentAttempt++ }, intervalTime) }) } async function sendWhenReady(prop, args){ if (jkfrontendchannel) { return sendMessage(prop, args) }else{ try { await waitForOpenConnection() return sendMessage(prop, args) } catch (err) { console.error(err) } } } function sendMessage(prop, args){ let appMessage = new Object(); appMessage.request_id = ++request_id; appMessage.arguments = Array.from(args) || []; let method = JKFrontendMethods[prop]; appMessage.method = method; let deferred = new Deferred(appMessage.request_id); const skipLogMethods = [ ] const displayLogMethod = [ 'SessionSetTrackVolumeData' ] if(skipLogMethods.length > 0 && skipLogMethods.includes(prop)){ }else{ if(displayLogMethod.includes(prop)){ logger.log( "[asyncJamClient] diverting to backend:", prop, appMessage ); } } if (jkfrontendchannel) { try { jkfrontendchannel.receiveText(JSON.stringify(appMessage)); deferredQueue.push(deferred); return deferred.promise; } catch (e) { logger.error( "[asyncJamClient] Native app not connected", e.message ); deferred.reject('Native app not connected') return deferred.promise; } } else { logger.info( "[asyncJamClient] jkfrontendchannel is not ready yet" ); deferred.reject('frontendchannel is not ready yet') return deferred.promise; } } function setupAsyncProxy() { let proxy; const handler = { get(target, prop, receiver) { //const origMethod = target[prop]; //console.log('[asyncJamClient] get:', target, prop); return function (...args) { // let result = origMethod.apply(this, args); // console.log(prop + JSON.stringify(args)+ ' -> ' + JSON.stringify(result)); // return result; return sendWhenReady(prop, arguments) }; }, }; proxy = new Proxy(self, handler); logger.log( "[asyncJamClient] Connected to WebChannel, ready to send/receive messages!" ); return proxy; } setupWebSocketConnection(); return setupAsyncProxy(); }; })(window, jQuery);