feat: add jukebox player engine for server-side playback (#2109)

* feat: add jukebox player engine for server-side playback

---------

Co-authored-by: jeffvli <jeffvictorli@gmail.com>
This commit is contained in:
mannansainidev
2026-07-10 09:59:22 +05:30
committed by GitHub
parent dd136f91e6
commit 0c89fea1ea
15 changed files with 743 additions and 31 deletions
@@ -7,13 +7,14 @@ import {
SettingOption,
SettingsSection,
} from '/@/renderer/features/settings/components/settings-section';
import { usePlaybackType, usePlayerStatus } from '/@/renderer/store';
import { useCurrentServer, usePlaybackType, usePlayerStatus } from '/@/renderer/store';
import { usePlaybackSettings, useSettingsStoreActions } from '/@/renderer/store/settings.store';
import { hasFeature } from '/@/shared/api/utils';
import { Select } from '/@/shared/components/select/select';
import { Switch } from '/@/shared/components/switch/switch';
import { toast } from '/@/shared/components/toast/toast';
import { ServerFeature } from '/@/shared/types/features-types';
import { PlayerStatus, PlayerType } from '/@/shared/types/types';
const ipc = isElectron() ? window.api.ipc : null;
const mpvPlayer = isElectron() ? window.api.mpvPlayer : null;
@@ -91,22 +92,33 @@ export const AudioSettings = memo(() => {
const status = usePlayerStatus();
const playbackType = usePlaybackType();
// Cleaned up server feature logic via requested hooks/utilities
const currentServer = useCurrentServer();
const isJukeboxSupported = hasFeature(currentServer, ServerFeature.JUKEBOX);
const audioDevices = useAudioDevices(playbackType);
const audioDeviceId =
playbackType === PlayerType.LOCAL ? settings.mpvAudioDeviceId : settings.audioDeviceId;
// Dynamically build the options for the dropdown
const selectData = [
{
disabled: !isElectron(),
label: 'MPV',
value: PlayerType.LOCAL,
},
{ label: 'Web', value: PlayerType.WEB },
];
if (isJukeboxSupported) {
selectData.push({ label: 'Jukebox', value: PlayerType.JUKEBOX });
}
const audioOptions: SettingOption[] = [
{
control: (
<Select
data={[
{
disabled: !isElectron(),
label: 'MPV',
value: PlayerType.LOCAL,
},
{ label: 'Web', value: PlayerType.WEB },
]}
data={selectData}
defaultValue={settings.type}
disabled={status === PlayerStatus.PLAYING}
onChange={(e) => {
@@ -115,10 +127,8 @@ export const AudioSettings = memo(() => {
}}
/>
),
description: t('setting.audioPlayer', {
context: 'description',
}),
isHidden: !isElectron(),
description: t('setting.audioPlayer', { context: 'description' }),
isHidden: !isElectron() && !isJukeboxSupported,
note: status === PlayerStatus.PLAYING ? t('common.playerMustBePaused') : undefined,
title: t('setting.audioPlayer'),
},
@@ -139,9 +149,7 @@ export const AudioSettings = memo(() => {
}
/>
),
description: t('setting.audioDevice', {
context: 'description',
}),
description: t('setting.audioDevice', { context: 'description' }),
isHidden: !isElectron(),
title: t('setting.audioDevice'),
},
@@ -156,9 +164,7 @@ export const AudioSettings = memo(() => {
}}
/>
),
description: t('setting.webAudio', {
context: 'description',
}),
description: t('setting.webAudio', { context: 'description' }),
isHidden: settings.type !== PlayerType.WEB,
note: t('common.restartRequired'),
title: t('setting.webAudio'),
@@ -174,9 +180,7 @@ export const AudioSettings = memo(() => {
}}
/>
),
description: t('setting.preservePitch', {
context: 'description',
}),
description: t('setting.preservePitch', { context: 'description' }),
isHidden: settings.type !== PlayerType.WEB,
title: t('setting.preservePitch'),
},
@@ -186,16 +190,12 @@ export const AudioSettings = memo(() => {
defaultChecked={settings.audioFadeOnStatusChange}
onChange={(e) => {
setSettings({
playback: {
audioFadeOnStatusChange: e.currentTarget.checked,
},
playback: { audioFadeOnStatusChange: e.currentTarget.checked },
});
}}
/>
),
description: t('setting.audioFadeOnStatusChange', {
context: 'description',
}),
description: t('setting.audioFadeOnStatusChange', { context: 'description' }),
title: t('setting.audioFadeOnStatusChange'),
},
];