diff --git a/Assets/_Client/Scripts/ApiClient.cs b/Assets/_Client/Scripts/ApiClient.cs index 3865fb1..e303978 100644 --- a/Assets/_Client/Scripts/ApiClient.cs +++ b/Assets/_Client/Scripts/ApiClient.cs @@ -1,5 +1,6 @@ using System; using System.Collections; +using System.IO; using System.Text; using UnityEngine; @@ -115,6 +116,41 @@ Response Body: {body}"; yield return CallEndpointCoroutine( url, "DELETE", null, timeoutInSeconds, callbackOnSuccess); } + + internal static IEnumerator ReadAudioResponseCoroutine( + UnityWebRequest request, + Action callbackOnSuccess) + { + byte[] audioBytes = request.downloadHandler.data; + if (audioBytes == null || audioBytes.Length == 0) + { + Debug.LogError("No audio data received."); + yield break; + } + + // Save temporarily to file for loading as AudioClip + string tempPath = Path.Combine(Application.persistentDataPath, "tts_temp.ogg"); + File.WriteAllBytes(tempPath, audioBytes); + + using (var file = UnityWebRequestMultimedia.GetAudioClip( + "file://" + tempPath, AudioType.OGGVORBIS)) + { + yield return file.SendWebRequest(); + + if (file.result == UnityWebRequest.Result.Success) + { + AudioClip clip = DownloadHandlerAudioClip.GetContent(file); + callbackOnSuccess?.Invoke(clip); + } + else + { + Debug.LogError($"Error loading AudioClip: {file.error}"); + } + } + + // Remove temporary file + File.Delete(tempPath); + } } internal enum Environment diff --git a/Assets/_Client/Scripts/ApiClientManager.cs b/Assets/_Client/Scripts/ApiClientManager.cs index c089031..5420ec4 100644 --- a/Assets/_Client/Scripts/ApiClientManager.cs +++ b/Assets/_Client/Scripts/ApiClientManager.cs @@ -5,6 +5,7 @@ using UnityEngine; namespace PPGIA.X540.Project3.API { + [RequireComponent(typeof(AudioSource))] public class ApiClientManager : MonoBehaviour { #region -- Inspector Fields ------------------------------------------- @@ -53,6 +54,9 @@ namespace PPGIA.X540.Project3.API #endregion ------------------------------------------------------------ #region -- Other Properties & Methods --------------------------------- + [SerializeField] + private AudioSource _audioSource; + // Property to get the appropriate API base URL private string ApiBaseUrl => _environment == Environment.Development ? @@ -64,7 +68,11 @@ namespace PPGIA.X540.Project3.API string.Join("/", parts.Select(p => p.Trim('/'))); #endregion ------------------------------------------------------------ - + void Awake() + { + _audioSource = GetComponent(); + } + #region -- API Calls -------------------------------------------------- [ContextMenu("Test API Availability")] public void TestApiAvailability() @@ -115,22 +123,34 @@ namespace PPGIA.X540.Project3.API [ContextMenu("Send Chat Message")] public void SendChatMessage() { + // Ensure there is an active session if (_session == null) { Debug.LogWarning("No active session. Please initiate a session first."); return; } + // Build the endpoint URL and payload var url = EndpointUrl(_chatEndpoint, _session.SessionId); var payload = new ChatServicePayload { message = _query }; + // Make the API call. Expect an audio response. StartCoroutine(ApiClient.CallEndpointWithPostCoroutine( url, _timeoutInSeconds, payload, (request) => { - var body = request.downloadHandler?.text ?? string.Empty; - Debug.Log($"Chat response: {body}"); + StartCoroutine(ApiClient.ReadAudioResponseCoroutine( + request, (audioClip) => + { + if (audioClip == null) + { + Debug.LogError("AudioClip is null after download."); + return; + } + + _audioSource?.PlayOneShot(audioClip); + })); })); } #endregion -- API Calls ------------------------------------------------ } -} +}