use existing web player engine for radio playback (#1543)

This commit is contained in:
jeffvli
2026-01-14 20:01:30 -08:00
parent 41054ed819
commit c676f5b91f
3 changed files with 159 additions and 112 deletions
@@ -1,19 +1,10 @@
import console from 'console';
import IcecastMetadataStats from 'icecast-metadata-stats';
import isElectron from 'is-electron';
import { useEffect, useRef } from 'react';
import { useEffect } from 'react';
import { createWithEqualityFn } from 'zustand/traditional';
import { usePlayerEvents } from '/@/renderer/features/player/audio-player/hooks/use-player-events';
import { convertToLogVolume } from '/@/renderer/features/player/audio-player/utils/player-utils';
import {
usePlaybackType,
usePlayerMuted,
usePlayerStoreBase,
usePlayerVolume,
useSettingsStore,
} from '/@/renderer/store';
import { toast } from '/@/shared/components/toast/toast';
import { usePlaybackType, usePlayerStoreBase, useSettingsStore } from '/@/renderer/store';
import { PlayerStatus, PlayerType } from '/@/shared/types/types';
export interface RadioMetadata {
@@ -132,10 +123,6 @@ export const useRadioAudioInstance = () => {
const currentStreamUrl = useRadioStore((state) => state.currentStreamUrl);
const isPlaying = useRadioStore((state) => state.isPlaying);
const playbackType = usePlaybackType();
const volume = usePlayerVolume();
const isMuted = usePlayerMuted();
const audioRef = useRef<HTMLAudioElement | null>(null);
const activeAudioRef = useRef<HTMLAudioElement | null>(null);
const isUsingMpv = playbackType === PlayerType.LOCAL && mpvPlayer;
// Handle mpv playback
@@ -188,102 +175,6 @@ export const useRadioAudioInstance = () => {
};
}, [isUsingMpv, setIsPlaying, setCurrentStreamUrl, setStationName]);
// Handle web playback
useEffect(() => {
if (isUsingMpv) {
if (audioRef.current) {
audioRef.current.pause();
audioRef.current.src = '';
audioRef.current = null;
}
return;
}
if (currentStreamUrl && isPlaying) {
if (audioRef.current) {
audioRef.current.pause();
audioRef.current.src = '';
}
const audio = new Audio(currentStreamUrl);
audioRef.current = audio;
activeAudioRef.current = audio;
const linearVolume = volume / 100;
const logVolume = convertToLogVolume(linearVolume);
audio.volume = logVolume;
audio.muted = isMuted;
audio.addEventListener('play', () => {
setIsPlaying(true);
});
audio.addEventListener('pause', () => {
setIsPlaying(false);
});
audio.addEventListener('ended', () => {
setIsPlaying(false);
setCurrentStreamUrl(null);
setStationName(null);
});
audio.addEventListener('error', (error) => {
console.error('Radio stream error:', error);
});
// Attempt to play
audio.play().catch((error) => {
if (activeAudioRef.current !== audio) {
return;
}
console.error('Failed to play audio:', error);
setIsPlaying(false);
setCurrentStreamUrl(null);
setStationName(null);
toast.error({ message: 'Failed to play radio stream' });
});
} else if (!currentStreamUrl || !isPlaying) {
if (audioRef.current) {
audioRef.current.pause();
audioRef.current.src = '';
audioRef.current = null;
}
activeAudioRef.current = null;
}
return () => {
if (audioRef.current) {
if (activeAudioRef.current === audioRef.current) {
activeAudioRef.current = null;
}
audioRef.current.pause();
audioRef.current.src = '';
audioRef.current = null;
}
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [
currentStreamUrl,
isPlaying,
isUsingMpv,
setIsPlaying,
setCurrentStreamUrl,
setStationName,
]);
useEffect(() => {
if (isUsingMpv || !audioRef.current) {
return;
}
const linearVolume = volume / 100;
const logVolume = convertToLogVolume(linearVolume);
audioRef.current.volume = logVolume;
audioRef.current.muted = isMuted;
}, [volume, isMuted, isUsingMpv]);
usePlayerEvents(
{
onPlayerStatus: (properties, prev) => {