protected async receiveMessage()

in src/common.speech/SynthesisAdapterBase.ts [302:466]


    protected async receiveMessage(): Promise<void> {
        try {
            const connection: IConnection = await this.fetchConnection();
            const message: ConnectionMessage = await connection.read();

            if (this.receiveMessageOverride !== undefined) {
                return this.receiveMessageOverride();
            }
            if (this.privIsDisposed) {
                // We're done.
                return;
            }

            // indicates we are draining the queue and it came with no message;
            if (!message) {
                if (!this.privSynthesisTurn.isSynthesizing) {
                    return;
                } else {
                    return this.receiveMessage();
                }
            }

            this.privServiceHasSentMessage = true;

            const connectionMessage = SpeechConnectionMessage.fromConnectionMessage(message);

            if (connectionMessage.requestId.toLowerCase() === this.privSynthesisTurn.requestId.toLowerCase()) {
                switch (connectionMessage.path.toLowerCase()) {
                    case "turn.start":
                        this.privSynthesisTurn.onServiceTurnStartResponse();
                        break;
                    case "response":
                        this.privSynthesisTurn.onServiceResponseMessage(connectionMessage.textBody);
                        break;
                    case "audio":
                        if (this.privSynthesisTurn.streamId.toLowerCase() === connectionMessage.streamId.toLowerCase()
                            && !!connectionMessage.binaryBody) {
                            this.privSynthesisTurn.onAudioChunkReceived(connectionMessage.binaryBody);
                            if (!!this.privSpeechSynthesizer.synthesizing) {
                                try {
                                    const audioWithHeader = SynthesisAdapterBase.addHeader(connectionMessage.binaryBody, this.privSynthesisTurn.audioOutputFormat);
                                    const ev: SpeechSynthesisEventArgs = new SpeechSynthesisEventArgs(
                                        new SpeechSynthesisResult(
                                            this.privSynthesisTurn.requestId,
                                            ResultReason.SynthesizingAudio,
                                            audioWithHeader));
                                    this.privSpeechSynthesizer.synthesizing(this.privSpeechSynthesizer, ev);
                                } catch (error) {
                                    // Not going to let errors in the event handler
                                    // trip things up.
                                }
                            }
                            if (this.privSessionAudioDestination !== undefined) {
                                this.privSessionAudioDestination.write(connectionMessage.binaryBody);
                            }
                        }
                        break;
                    case "audio.metadata":
                        const metadataList = SynthesisAudioMetadata.fromJSON(connectionMessage.textBody).Metadata;
                        for (const metadata of metadataList) {
                            switch (metadata.Type) {
                                case MetadataType.WordBoundary:
                                    this.privSynthesisTurn.onWordBoundaryEvent(metadata.Data.text.Text);

                                    const wordBoundaryEventArgs: SpeechSynthesisWordBoundaryEventArgs = new SpeechSynthesisWordBoundaryEventArgs(
                                        metadata.Data.Offset,
                                        metadata.Data.text.Text,
                                        metadata.Data.text.Length,
                                        this.privSynthesisTurn.currentTextOffset);

                                    if (!!this.privSpeechSynthesizer.wordBoundary) {
                                        try {
                                            this.privSpeechSynthesizer.wordBoundary(this.privSpeechSynthesizer, wordBoundaryEventArgs);
                                        } catch (error) {
                                            // Not going to let errors in the event handler
                                            // trip things up.
                                        }
                                    }
                                    break;
                                case MetadataType.Bookmark:
                                    const bookmarkEventArgs: SpeechSynthesisBookmarkEventArgs = new SpeechSynthesisBookmarkEventArgs(
                                        metadata.Data.Offset,
                                        metadata.Data.Bookmark);

                                    if (!!this.privSpeechSynthesizer.bookmarkReached) {
                                        try {
                                            this.privSpeechSynthesizer.bookmarkReached(this.privSpeechSynthesizer, bookmarkEventArgs);
                                        } catch (error) {
                                            // Not going to let errors in the event handler
                                            // trip things up.
                                        }
                                    }
                                    break;
                                case MetadataType.Viseme:

                                    this.privSynthesisTurn.onVisemeMetadataReceived(metadata);

                                    if (metadata.Data.IsLastAnimation) {
                                        const visemeEventArgs: SpeechSynthesisVisemeEventArgs = new SpeechSynthesisVisemeEventArgs(
                                            metadata.Data.Offset,
                                            metadata.Data.VisemeId,
                                            this.privSynthesisTurn.getAndClearVisemeAnimation());

                                        if (!!this.privSpeechSynthesizer.visemeReceived) {
                                            try {
                                                this.privSpeechSynthesizer.visemeReceived(this.privSpeechSynthesizer, visemeEventArgs);
                                            } catch (error) {
                                                // Not going to let errors in the event handler
                                                // trip things up.
                                            }
                                        }
                                    }
                                    break;
                            }
                        }
                        break;
                    case "turn.end":
                        this.privSynthesisTurn.onServiceTurnEndResponse();
                        let result: SpeechSynthesisResult;
                        try {
                            const audioBuffer: ArrayBuffer = await this.privSynthesisTurn.getAllReceivedAudioWithHeader();
                            result = new SpeechSynthesisResult(
                                this.privSynthesisTurn.requestId,
                                ResultReason.SynthesizingAudioCompleted,
                                audioBuffer
                            );
                            if (!!this.privSuccessCallback) {
                                this.privSuccessCallback(result);
                            }
                        } catch (error) {
                            if (!!this.privErrorCallback) {
                                this.privErrorCallback(error);
                            }
                        }
                        if (this.privSpeechSynthesizer.synthesisCompleted) {
                            try {
                                this.privSpeechSynthesizer.synthesisCompleted(
                                    this.privSpeechSynthesizer,
                                    new SpeechSynthesisEventArgs(result)
                                );
                            } catch (e) {
                                // Not going to let errors in the event handler
                                // trip things up.
                            }
                        }
                        break;

                    default:

                        if (!this.processTypeSpecificMessages(connectionMessage)) {
                            // here are some messages that the derived class has not processed, dispatch them to connect class
                            if (!!this.privServiceEvents) {
                                this.serviceEvents.onEvent(new ServiceEvent(connectionMessage.path.toLowerCase(), connectionMessage.textBody));
                            }
                        }

                }
            }

            return this.receiveMessage();

        } catch (e) {
            // TODO: What goes here?
        }
    }