/** * TTS Player Module * Manages text-to-speech playback integration with animation queue. */ export class TtsPlayer { /** * Create a new TtsPlayer * @param {Object} config - Configuration options * @param {string} config.apiKey - API key for TTS service (if applicable) * @param {Object} config.animationQueue - AnimationQueue instance for synchronization */ constructor(config = {}) { this.config = config; this.animationQueue = config.animationQueue; this.ttsHandler = null; this.enabled = false; // Start with TTS disabled by default this.currentAudio = null; // Bind methods to ensure 'this' context this.speak = this.speak.bind(this); this.stop = this.stop.bind(this); } /** * Set the TTS handler * @param {Object} ttsHandler - The TTS handler instance */ setTtsHandler(ttsHandler) { if (!ttsHandler) { console.warn("TtsPlayer: No valid TTS handler provided."); return; } console.log("TtsPlayer: Handler set to", ttsHandler.constructor.name); this.ttsHandler = ttsHandler; // Make sure the window.ttsHandler is also set for global access if (!window.ttsHandler) { window.ttsHandler = ttsHandler; } } /** * Enable or disable TTS * @param {boolean} enabled - Whether TTS should be enabled */ setEnabled(enabled = true) { this.enabled = enabled; console.log(`TtsPlayer: TTS ${enabled ? 'enabled' : 'disabled'}`); // If disabling while audio is playing, stop it if (!enabled && this.currentAudio) { this.stop(); } // Also set the handler's state if available if (this.ttsHandler && typeof this.ttsHandler.setEnabled === 'function') { this.ttsHandler.setEnabled(enabled); } else if (window.ttsHandler && typeof window.ttsHandler.setEnabled === 'function') { window.ttsHandler.setEnabled(enabled); } } /** * Toggle TTS state * @returns {boolean} The new enabled state */ toggle() { this.setEnabled(!this.enabled); return this.enabled; } /** * Check if TTS is enabled * @returns {boolean} Whether TTS is enabled */ isEnabled() { return this.enabled; } /** * Speak text * @param {string} text - The text to speak */ speak(text) { if (!this.enabled || !text) return; // Stop any current speech this.stop(); console.log(`TtsPlayer: Speaking - "${text.substring(0, 50)}${text.length > 50 ? '...' : ''}"`); // Try to use our handler first if (this.ttsHandler && typeof this.ttsHandler.speak === 'function') { this.ttsHandler.speak(text); } // Fall back to window.ttsHandler if available else if (window.ttsHandler && typeof window.ttsHandler.speak === 'function') { window.ttsHandler.speak(text); } else { console.warn("TtsPlayer: No TTS handler available to speak text"); } } /** * Stop current speech */ stop() { // Try to use our handler first if (this.ttsHandler && typeof this.ttsHandler.stop === 'function') { this.ttsHandler.stop(); } // Fall back to window.ttsHandler if available else if (window.ttsHandler && typeof window.ttsHandler.stop === 'function') { window.ttsHandler.stop(); } } /** * Fast forward current speech (may skip or speed up) */ fastForward() { // Try to use our handler first if (this.ttsHandler && typeof this.ttsHandler.fastForward === 'function') { this.ttsHandler.fastForward(); } // Fall back to window.ttsHandler if available else if (window.ttsHandler && typeof window.ttsHandler.fastForward === 'function') { window.ttsHandler.fastForward(); } // If no fastForward method, just stop the speech else { this.stop(); } } }