diff --git a/public/index.html b/public/index.html index 7ac5506..e6c6051 100644 --- a/public/index.html +++ b/public/index.html @@ -526,6 +526,7 @@ + @@ -1313,51 +1314,84 @@ let audioPlaying = false; function startAlarmSound() { + console.log('Starting alarm sound...'); const audioElement = document.getElementById('timerAudio'); + + // Force load the audio + audioElement.load(); + + // Set volume to max + audioElement.volume = 1.0; audioElement.loop = true; - audioElement.play().catch(error => { - console.log('Audio playback failed:', error); - // Fallback - try to create a beep sound - createBeepSound(); - }); - audioPlaying = true; + + // Try to play + const playPromise = audioElement.play(); + + if (playPromise !== undefined) { + playPromise + .then(() => { + console.log('Audio playing successfully'); + audioPlaying = true; + }) + .catch(error => { + console.error('Audio playback failed:', error); + console.log('Audio src:', audioElement.src); + console.log('Audio readyState:', audioElement.readyState); + console.log('Audio error:', audioElement.error); + + // Try fallback beep + createBeepSound(); + }); + } } function stopAlarmSound() { + console.log('Stopping alarm sound...'); const audioElement = document.getElementById('timerAudio'); audioElement.pause(); audioElement.currentTime = 0; audioPlaying = false; + + // Stop any fallback beep + if (window.audioContext) { + window.audioContext.close(); + window.audioContext = null; + } } function playCompletionSound() { - // Single play for non-alarm situations + console.log('Playing completion sound (single)...'); const audioElement = document.getElementById('timerAudio'); audioElement.loop = false; + audioElement.volume = 1.0; audioElement.play().catch(error => { - console.log('Audio playback failed:', error); + console.error('Single play failed:', error); }); } function createBeepSound() { - // Fallback beep using Web Audio API + console.log('Creating fallback beep sound...'); try { - const audioContext = new (window.AudioContext || window.webkitAudioContext)(); - const oscillator = audioContext.createOscillator(); - const gainNode = audioContext.createGain(); + window.audioContext = new (window.AudioContext || window.webkitAudioContext)(); + const oscillator = window.audioContext.createOscillator(); + const gainNode = window.audioContext.createGain(); oscillator.connect(gainNode); - gainNode.connect(audioContext.destination); + gainNode.connect(window.audioContext.destination); oscillator.frequency.value = 800; // Frequency in Hz + oscillator.type = 'sine'; gainNode.gain.value = 0.3; // Volume oscillator.start(); + audioPlaying = true; // Create beeping pattern const beepPattern = () => { if (!audioPlaying) { oscillator.stop(); + window.audioContext.close(); + window.audioContext = null; return; } gainNode.gain.value = gainNode.gain.value > 0 ? 0 : 0.3; @@ -1365,16 +1399,63 @@ }; beepPattern(); + console.log('Beep sound started'); } catch (e) { - console.log('Web Audio API not supported'); + console.error('Web Audio API error:', e); + // Last resort - use notification API if available + if ('Notification' in window && Notification.permission === 'granted') { + new Notification('Timer Complete!', { + body: 'Your timer has finished.', + requireInteraction: true + }); + } } } + // Test audio on page load + window.addEventListener('load', () => { + const audioElement = document.getElementById('timerAudio'); + console.log('Audio element found:', audioElement); + console.log('Audio sources:', audioElement.getElementsByTagName('source').length); + + // Check if audio can play + audioElement.addEventListener('canplay', () => { + console.log('Audio can play'); + }); + + audioElement.addEventListener('error', (e) => { + console.error('Audio error event:', e); + }); + + // Request notification permission for fallback + if ('Notification' in window && Notification.permission === 'default') { + Notification.requestPermission(); + } + }); + function dismissTimerComplete() { stopAlarmSound(); closeModal('timerCompleteModal'); } + // Test audio function + function testAudio() { + console.log('Testing audio...'); + startAlarmSound(); + + // Show test modal + showAlert('Testing audio alarm. Click OK to stop.', 'Audio Test'); + + // Override OK button to stop sound + setTimeout(() => { + const okButton = document.querySelector('#alertModal button'); + okButton.onclick = () => { + stopAlarmSound(); + closeModal('alertModal'); + }; + }, 100); + } + // Close modals when clicking outside (except for no-close modals) window.onclick = function(event) { const modals = document.querySelectorAll('.modal:not(.no-close)'); diff --git a/public/timer-complete.mp3 b/public/timer-complete.mp3 new file mode 100644 index 0000000..c8e2866 Binary files /dev/null and b/public/timer-complete.mp3 differ