{"version":3,"sources":["src/common.speech/RequestSession.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAKH,YAAY,EACZ,aAAa,EACb,OAAO,EACV,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAKH,sBAAsB,EACzB,MAAM,qBAAqB,CAAC;AAG7B,qBAAa,cAAc;IACvB,OAAO,CAAC,cAAc,CAAkB;IACxC,OAAO,CAAC,4BAA4B,CAA2B;IAC/D,OAAO,CAAC,eAAe,CAA2C;IAClE,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,aAAa,CAAsB;IAC3C,OAAO,CAAC,oBAAoB,CAAS;IACrC,OAAO,CAAC,uBAAuB,CAAkB;IACjD,OAAO,CAAC,iBAAiB,CAAkB;IAC3C,OAAO,CAAC,6BAA6B,CAAoB;IACzD,OAAO,CAAC,iBAAiB,CAAkB;IAC3C,OAAO,CAAC,wBAAwB,CAAa;IAC7C,OAAO,CAAC,kBAAkB,CAAa;IACvC,OAAO,CAAC,sBAAsB,CAAkB;IAChD,OAAO,CAAC,aAAa,CAAa;IAClC,OAAO,CAAC,eAAe,CAAa;IACpC,OAAO,CAAC,aAAa,CAAS;gBAElB,aAAa,EAAE,MAAM;aAOtB,SAAS,EAAI,MAAM;aAInB,SAAS,EAAI,MAAM;aAInB,WAAW,EAAI,MAAM;aAIrB,iBAAiB,EAAI,OAAO,CAAC,OAAO,CAAC;aAIrC,aAAa,EAAI,OAAO;aAIxB,aAAa,EAAI,OAAO;aAIxB,sBAAsB,EAAI,MAAM;aAIhC,WAAW,EAAI,MAAM;aAMrB,SAAS,EAAI,MAAM;IAGvB,yBAAyB,CAAC,WAAW,EAAE,YAAY,CAAC,aAAa,CAAC,GAAG,IAAI;IAMzE,mBAAmB,IAAI,IAAI;IAW3B,4BAA4B,6EASlC;IAEM,oBAAoB,2DAI1B;IAEM,eAAe,6CAIrB;IAEM,8BAA8B,gDAYpC;IAEM,wBAAwB,2CAS9B;IAEM,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAOlC,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAKxC,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAMzC,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAIpC,OAAO,2BAUb;IAEM,YAAY,eAMlB;IAEM,iBAAiB,IAAI,IAAI;IAKzB,aAAa,IAAI,IAAI;IAI5B,SAAS,CAAC,OAAO,0CAKhB;IAED,OAAO,CAAC,UAAU,CAKjB;IAED,OAAO,CAAC,eAAe,CAOtB;CACJ","file":"RequestSession.d.ts","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT license.\n\nimport { ReplayableAudioNode } from \"../common.browser/Exports\";\nimport {\n    createNoDashGuid,\n    Deferred,\n    Events,\n    IDetachable,\n    IEventSource,\n    PlatformEvent,\n    Promise,\n} from \"../common/Exports\";\nimport {\n    ConnectingToServiceEvent,\n    ListeningStartedEvent,\n    RecognitionStartedEvent,\n    RecognitionTriggeredEvent,\n    SpeechRecognitionEvent,\n} from \"./RecognitionEvents\";\nimport { ServiceTelemetryListener } from \"./ServiceTelemetryListener.Internal\";\n\nexport class RequestSession {\n    private privIsDisposed: boolean = false;\n    private privServiceTelemetryListener: ServiceTelemetryListener;\n    private privDetachables: IDetachable[] = new Array<IDetachable>();\n    private privRequestId: string;\n    private privAudioSourceId: string;\n    private privAudioNodeId: string;\n    private privAudioNode: ReplayableAudioNode;\n    private privAuthFetchEventId: string;\n    private privIsAudioNodeDetached: boolean = false;\n    private privIsRecognizing: boolean = false;\n    private privRequestCompletionDeferral: Deferred<boolean>;\n    private privIsSpeechEnded: boolean = false;\n    private privTurnStartAudioOffset: number = 0;\n    private privLastRecoOffset: number = 0;\n    private privHypothesisReceived: boolean = false;\n    private privBytesSent: number = 0;\n    private privRecogNumber: number = 0;\n    private privSessionId: string;\n\n    constructor(audioSourceId: string) {\n        this.privAudioSourceId = audioSourceId;\n        this.privRequestId = createNoDashGuid();\n        this.privAudioNodeId = createNoDashGuid();\n        this.privRequestCompletionDeferral = new Deferred<boolean>();\n    }\n\n    public get sessionId(): string {\n        return this.privSessionId;\n    }\n\n    public get requestId(): string {\n        return this.privRequestId;\n    }\n\n    public get audioNodeId(): string {\n        return this.privAudioNodeId;\n    }\n\n    public get completionPromise(): Promise<boolean> {\n        return this.privRequestCompletionDeferral.promise();\n    }\n\n    public get isSpeechEnded(): boolean {\n        return this.privIsSpeechEnded;\n    }\n\n    public get isRecognizing(): boolean {\n        return this.privIsRecognizing;\n    }\n\n    public get currentTurnAudioOffset(): number {\n        return this.privTurnStartAudioOffset;\n    }\n\n    public get recogNumber(): number {\n        return this.privRecogNumber;\n    }\n\n    // The number of bytes sent for the current connection.\n    // Counter is reset to 0 each time a connection is established.\n    public get bytesSent(): number {\n        return this.privBytesSent;\n    }\n    public listenForServiceTelemetry(eventSource: IEventSource<PlatformEvent>): void {\n        if (!!this.privServiceTelemetryListener) {\n            this.privDetachables.push(eventSource.attachListener(this.privServiceTelemetryListener));\n        }\n    }\n\n    public startNewRecognition(): void {\n        this.privIsSpeechEnded = false;\n        this.privIsRecognizing = true;\n        this.privTurnStartAudioOffset = 0;\n        this.privLastRecoOffset = 0;\n        this.privRequestId = createNoDashGuid();\n        this.privRecogNumber++;\n        this.privServiceTelemetryListener = new ServiceTelemetryListener(this.privRequestId, this.privAudioSourceId, this.privAudioNodeId);\n        this.onEvent(new RecognitionTriggeredEvent(this.requestId, this.privSessionId, this.privAudioSourceId, this.privAudioNodeId));\n    }\n\n    public onAudioSourceAttachCompleted = (audioNode: ReplayableAudioNode, isError: boolean, error?: string): void => {\n        this.privAudioNode = audioNode;\n        this.privIsAudioNodeDetached = false;\n\n        if (isError) {\n            this.onComplete();\n        } else {\n            this.onEvent(new ListeningStartedEvent(this.privRequestId, this.privSessionId, this.privAudioSourceId, this.privAudioNodeId));\n        }\n    }\n\n    public onPreConnectionStart = (authFetchEventId: string, connectionId: string): void => {\n        this.privAuthFetchEventId = authFetchEventId;\n        this.privSessionId = connectionId;\n        this.onEvent(new ConnectingToServiceEvent(this.privRequestId, this.privAuthFetchEventId, this.privSessionId));\n    }\n\n    public onAuthCompleted = (isError: boolean, error?: string): void => {\n        if (isError) {\n            this.onComplete();\n        }\n    }\n\n    public onConnectionEstablishCompleted = (statusCode: number, reason?: string): void => {\n        if (statusCode === 200) {\n            this.onEvent(new RecognitionStartedEvent(this.requestId, this.privAudioSourceId, this.privAudioNodeId, this.privAuthFetchEventId, this.privSessionId));\n            if (!!this.privAudioNode) {\n                this.privAudioNode.replay();\n            }\n            this.privTurnStartAudioOffset = this.privLastRecoOffset;\n            this.privBytesSent = 0;\n            return;\n        } else if (statusCode === 403) {\n            this.onComplete();\n        }\n    }\n\n    public onServiceTurnEndResponse = (continuousRecognition: boolean): void => {\n        if (!continuousRecognition || this.isSpeechEnded) {\n            this.onComplete();\n        } else {\n            // Start a new request set.\n            this.privTurnStartAudioOffset = this.privLastRecoOffset;\n            this.privRequestId = createNoDashGuid();\n            this.privAudioNode.replay();\n        }\n    }\n\n    public onHypothesis(offset: number): void {\n        if (!this.privHypothesisReceived) {\n            this.privHypothesisReceived = true;\n            this.privServiceTelemetryListener.hypothesisReceived(this.privAudioNode.findTimeAtOffset(offset));\n        }\n    }\n\n    public onPhraseRecognized(offset: number): void {\n        this.privServiceTelemetryListener.phraseReceived(this.privAudioNode.findTimeAtOffset(offset));\n        this.onServiceRecognized(offset);\n    }\n\n    public onServiceRecognized(offset: number): void {\n        this.privLastRecoOffset = offset;\n        this.privHypothesisReceived = false;\n        this.privAudioNode.shrinkBuffers(offset);\n    }\n\n    public onAudioSent(bytesSent: number): void {\n        this.privBytesSent += bytesSent;\n    }\n\n    public dispose = (error?: string): void => {\n        if (!this.privIsDisposed) {\n            // we should have completed by now. If we did not its an unknown error.\n            this.privIsDisposed = true;\n            for (const detachable of this.privDetachables) {\n                detachable.detach();\n            }\n\n            this.privServiceTelemetryListener.dispose();\n        }\n    }\n\n    public getTelemetry = (): string => {\n        if (this.privServiceTelemetryListener.hasTelemetry) {\n            return this.privServiceTelemetryListener.getTelemetry();\n        } else {\n            return null;\n        }\n    }\n\n    public onStopRecognizing(): void {\n        this.onComplete();\n    }\n\n    // Should be called with the audioNode for this session has indicated that it is out of speech.\n    public onSpeechEnded(): void {\n        this.privIsSpeechEnded = true;\n    }\n\n    protected onEvent = (event: SpeechRecognitionEvent): void => {\n        if (!!this.privServiceTelemetryListener) {\n            this.privServiceTelemetryListener.onEvent(event);\n        }\n        Events.instance.onEvent(event);\n    }\n\n    private onComplete = (): void => {\n        if (!!this.privIsRecognizing) {\n            this.privIsRecognizing = false;\n            this.detachAudioNode();\n        }\n    }\n\n    private detachAudioNode = (): void => {\n        if (!this.privIsAudioNodeDetached) {\n            this.privIsAudioNodeDetached = true;\n            if (this.privAudioNode) {\n                this.privAudioNode.detach();\n            }\n        }\n    }\n}\n"]}