Add debug logging for audio source handling and API initialization; improve error handling in AudioPlayer and AudioPlayerContext
This commit is contained in:
@@ -248,8 +248,71 @@ export const AudioPlayer: React.FC = () => {
|
|||||||
// Always clear current track time when changing tracks
|
// Always clear current track time when changing tracks
|
||||||
localStorage.removeItem('navidrome-current-track-time');
|
localStorage.removeItem('navidrome-current-track-time');
|
||||||
|
|
||||||
|
console.log('🔄 Setting audio source:', currentTrack.url);
|
||||||
|
|
||||||
|
// Debug: Check if URL is valid
|
||||||
|
if (!currentTrack.url || currentTrack.url === 'undefined' || currentTrack.url === '') {
|
||||||
|
console.error('❌ Invalid audio URL:', currentTrack.url);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debug: Log current audio element state
|
||||||
|
console.log('🔍 Audio element state before loading:', {
|
||||||
|
src: audioCurrent.src,
|
||||||
|
readyState: audioCurrent.readyState,
|
||||||
|
networkState: audioCurrent.networkState,
|
||||||
|
crossOrigin: audioCurrent.crossOrigin,
|
||||||
|
canPlayType_mp3: audioCurrent.canPlayType('audio/mpeg'),
|
||||||
|
canPlayType_mp4: audioCurrent.canPlayType('audio/mp4'),
|
||||||
|
canPlayType_webm: audioCurrent.canPlayType('audio/webm'),
|
||||||
|
canPlayType_ogg: audioCurrent.canPlayType('audio/ogg'),
|
||||||
|
canPlayType_flac: audioCurrent.canPlayType('audio/flac'),
|
||||||
|
canPlayType_wav: audioCurrent.canPlayType('audio/wav')
|
||||||
|
});
|
||||||
|
|
||||||
|
// Clear any previous error handlers
|
||||||
|
audioCurrent.onerror = null;
|
||||||
|
audioCurrent.onloadstart = null;
|
||||||
|
audioCurrent.oncanplay = null;
|
||||||
|
|
||||||
|
// Simple error handling
|
||||||
|
audioCurrent.onerror = (e) => {
|
||||||
|
const event = e as Event;
|
||||||
|
const error = event.target as HTMLAudioElement;
|
||||||
|
console.error('❌ Audio element error:', {
|
||||||
|
error: error.error,
|
||||||
|
networkState: error.networkState,
|
||||||
|
readyState: error.readyState,
|
||||||
|
src: error.src
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
audioCurrent.onloadstart = () => {
|
||||||
|
console.log('📥 Audio load started');
|
||||||
|
};
|
||||||
|
|
||||||
|
audioCurrent.oncanplay = () => {
|
||||||
|
console.log('✅ Audio can play');
|
||||||
|
};
|
||||||
|
|
||||||
|
// Set source without any CORS configuration
|
||||||
|
audioCurrent.removeAttribute('crossorigin');
|
||||||
audioCurrent.src = currentTrack.url;
|
audioCurrent.src = currentTrack.url;
|
||||||
|
|
||||||
|
// Force load and log state after setting source
|
||||||
|
audioCurrent.load();
|
||||||
|
|
||||||
|
// Log state after load
|
||||||
|
setTimeout(() => {
|
||||||
|
console.log('🔍 Audio element state after load:', {
|
||||||
|
src: audioCurrent.src,
|
||||||
|
readyState: audioCurrent.readyState,
|
||||||
|
networkState: audioCurrent.networkState,
|
||||||
|
error: audioCurrent.error,
|
||||||
|
duration: audioCurrent.duration
|
||||||
|
});
|
||||||
|
}, 100);
|
||||||
|
|
||||||
// For iOS, ensure audio element is properly loaded
|
// For iOS, ensure audio element is properly loaded
|
||||||
if (isMobile) {
|
if (isMobile) {
|
||||||
audioCurrent.load();
|
audioCurrent.load();
|
||||||
@@ -721,10 +784,7 @@ export const AudioPlayer: React.FC = () => {
|
|||||||
<button
|
<button
|
||||||
className="p-4 hover:bg-muted/50 rounded-full transition-all duration-200 active:scale-95 bg-primary/10 touch-manipulation"
|
className="p-4 hover:bg-muted/50 rounded-full transition-all duration-200 active:scale-95 bg-primary/10 touch-manipulation"
|
||||||
onClick={togglePlayPause}
|
onClick={togglePlayPause}
|
||||||
onTouchStart={(e) => {
|
style={{ touchAction: 'manipulation' }}
|
||||||
// Prevent iOS double-tap zoom on the play button
|
|
||||||
e.preventDefault();
|
|
||||||
}}
|
|
||||||
type="button"
|
type="button"
|
||||||
data-testid="play-pause-button"
|
data-testid="play-pause-button"
|
||||||
aria-label={isPlaying ? 'Pause' : 'Play'}
|
aria-label={isPlaying ? 'Pause' : 'Play'}
|
||||||
@@ -746,11 +806,8 @@ export const AudioPlayer: React.FC = () => {
|
|||||||
{/* Single audio element - shared across all UI states */}
|
{/* Single audio element - shared across all UI states */}
|
||||||
<audio
|
<audio
|
||||||
ref={audioRef}
|
ref={audioRef}
|
||||||
hidden
|
|
||||||
playsInline
|
playsInline
|
||||||
preload={isMobile ? "none" : "auto"}
|
preload="metadata"
|
||||||
controls={false}
|
|
||||||
crossOrigin="anonymous"
|
|
||||||
style={{ display: 'none' }}
|
style={{ display: 'none' }}
|
||||||
/>
|
/>
|
||||||
<audio ref={preloadAudioRef} hidden preload="metadata" />
|
<audio ref={preloadAudioRef} hidden preload="metadata" />
|
||||||
@@ -814,11 +871,8 @@ export const AudioPlayer: React.FC = () => {
|
|||||||
{/* Single audio element - shared across all UI states */}
|
{/* Single audio element - shared across all UI states */}
|
||||||
<audio
|
<audio
|
||||||
ref={audioRef}
|
ref={audioRef}
|
||||||
hidden
|
|
||||||
playsInline
|
playsInline
|
||||||
preload={isMobile ? "none" : "auto"}
|
preload="metadata"
|
||||||
controls={false}
|
|
||||||
crossOrigin="anonymous"
|
|
||||||
style={{ display: 'none' }}
|
style={{ display: 'none' }}
|
||||||
/>
|
/>
|
||||||
<audio ref={preloadAudioRef} hidden preload="metadata" />
|
<audio ref={preloadAudioRef} hidden preload="metadata" />
|
||||||
@@ -929,11 +983,8 @@ export const AudioPlayer: React.FC = () => {
|
|||||||
{/* Single audio element - shared across all UI states with mobile support */}
|
{/* Single audio element - shared across all UI states with mobile support */}
|
||||||
<audio
|
<audio
|
||||||
ref={audioRef}
|
ref={audioRef}
|
||||||
hidden
|
|
||||||
playsInline
|
playsInline
|
||||||
preload={isMobile ? "none" : "auto"}
|
preload="metadata"
|
||||||
controls={false}
|
|
||||||
crossOrigin="anonymous"
|
|
||||||
style={{ display: 'none' }}
|
style={{ display: 'none' }}
|
||||||
/>
|
/>
|
||||||
<audio ref={preloadAudioRef} hidden preload="metadata" />
|
<audio ref={preloadAudioRef} hidden preload="metadata" />
|
||||||
|
|||||||
@@ -53,7 +53,15 @@ export const AudioPlayerProvider: React.FC<{ children: React.ReactNode }> = ({ c
|
|||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [shuffle, setShuffle] = useState(false);
|
const [shuffle, setShuffle] = useState(false);
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const api = useMemo(() => getNavidromeAPI(), []);
|
const api = useMemo(() => {
|
||||||
|
const navidromeApi = getNavidromeAPI();
|
||||||
|
if (!navidromeApi) {
|
||||||
|
console.warn('⚠️ Navidrome API not configured');
|
||||||
|
} else {
|
||||||
|
console.log('✅ Navidrome API initialized');
|
||||||
|
}
|
||||||
|
return navidromeApi;
|
||||||
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const savedQueue = localStorage.getItem('navidrome-audioQueue');
|
const savedQueue = localStorage.getItem('navidrome-audioQueue');
|
||||||
@@ -98,10 +106,14 @@ export const AudioPlayerProvider: React.FC<{ children: React.ReactNode }> = ({ c
|
|||||||
if (!api) {
|
if (!api) {
|
||||||
throw new Error('Navidrome API not configured');
|
throw new Error('Navidrome API not configured');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const streamUrl = api.getStreamUrl(song.id);
|
||||||
|
console.log('🎵 Creating track with stream URL:', streamUrl);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: song.id,
|
id: song.id,
|
||||||
name: song.title,
|
name: song.title,
|
||||||
url: api.getStreamUrl(song.id),
|
url: streamUrl,
|
||||||
artist: song.artist,
|
artist: song.artist,
|
||||||
album: song.album,
|
album: song.album,
|
||||||
duration: song.duration,
|
duration: song.duration,
|
||||||
|
|||||||
Reference in New Issue
Block a user