/// <summary> /// Initializes a new instance of the <see cref="DialogManager{TInputType}"/> class. /// </summary> /// <param name="dialogBackend"> The dialog backend for the manager to use. </param> /// <param name="keywordRegistration"> The keyword registration with the current keyword file information.</param> /// <param name="dialogAudioInput"> The input audio provider. </param> /// <param name="agentSessionManager"> The manager that provides the instance of agent session wrapper. </param> /// <param name="dialogAudioOutput"> The dialog audio output sink to use. </param> public DialogManager( IDialogBackend <TInputType> dialogBackend, IKeywordRegistration keywordRegistration, IDialogAudioInputProvider <TInputType> dialogAudioInput, IAgentSessionManager agentSessionManager, IDialogAudioOutputAdapter dialogAudioOutput = null) { Contract.Requires(dialogBackend != null); Contract.Requires(agentSessionManager != null); this.logger = LogRouter.GetClassLogger(); this.dialogBackend = dialogBackend; this.dialogBackend.SessionStarted += (id) => this.logger.Log($"DialogManager: Session start: {id}"); this.dialogBackend.SessionStopped += (id) => this.logger.Log($"DialogManager: Session stop: {id}"); this.dialogBackend.KeywordRecognizing += this.OnKeywordRecognizing; this.dialogBackend.KeywordRecognized += this.OnKeywordRecognized; this.dialogBackend.SpeechRecognizing += this.OnSpeechRecognizing; this.dialogBackend.SpeechRecognized += async(text) => await this.OnSpeechRecognizedAsync(text); this.dialogBackend.DialogResponseReceived += this.OnActivityReceived; this.dialogBackend.ErrorReceived += async(errorInformation) => await this.OnErrorReceivedAsync(errorInformation); this.dialogAudioInput = dialogAudioInput; this.keywordRegistration = keywordRegistration; this.agentSessionManager = agentSessionManager; this.agentSessionManager.SignalDetected += (sender, args) => this.HandleSignalDetection(args); this.InitializeSignalDetectionHelper(); _ = this.InitializeAsync(dialogAudioOutput); }
/// <summary> /// Completes async initialization for dialog manager, including initialization of dialog output. /// </summary> /// <param name="dialogAudioOutput"> The dialog audio output sink to use. </param> /// <returns> A task that completes once the state is updated and consumers are notified. </returns> public async Task InitializeAsync(IDialogAudioOutputAdapter dialogAudioOutput = null) { this.dialogAudioOutput = dialogAudioOutput ?? await DialogAudioOutputAdapter.CreateAsync(); this.dialogResponseQueue = new DialogResponseQueue(this.dialogAudioOutput); this.dialogResponseQueue.ExecutingResponse += async(DialogResponse response) => { if (response.MessageMedia != null) { await this.ChangeAgentStateAsync(ConversationalAgentState.Speaking); } if (response.TurnEndIndicated) { await this.FinishTurnAsync(); } }; if (this.dialogAudioOutput != null) { this.dialogAudioOutput.OutputEnded += async() => { var session = await this.agentSessionManager.GetSessionAsync(); if (session.AgentState == ConversationalAgentState.Speaking) { await this.ChangeAgentStateAsync(ConversationalAgentState.Inactive); } }; } }
/// <summary> /// Free disposable resources per the IDisposable interface. /// </summary> /// <param name="disposing"> Whether managed state is being disposed. </param> protected virtual async void Dispose(bool disposing) { if (!this.AlreadyDisposed) { if (disposing) { await this.StopAudioCaptureAsync(); await this.StopAudioPlaybackAsync(); this.dialogBackend?.Dispose(); this.dialogAudioInput?.Dispose(); this.dialogAudioOutput?.Dispose(); } this.dialogBackend = null; this.dialogAudioInput = null; this.dialogAudioOutput = null; this.AlreadyDisposed = true; } }
/// <summary> /// Initializes a new instance of the <see cref="DialogResponseQueue"/> class. /// </summary> /// <param name="outputAdapter">Output adapter to play audio from dialog responses.</param> public DialogResponseQueue(IDialogAudioOutputAdapter outputAdapter) { this.dialogResponseQueue = new ConcurrentQueue <DialogResponse>(); this.outputAdapter = outputAdapter; this.actionQueueLock = new object(); }