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