diff --git a/src/renderer/features/artists/components/album-artist-list-paginated-grid.tsx b/src/renderer/features/artists/components/album-artist-list-paginated-grid.tsx
index ac6251722..b5f1ef8ec 100644
--- a/src/renderer/features/artists/components/album-artist-list-paginated-grid.tsx
+++ b/src/renderer/features/artists/components/album-artist-list-paginated-grid.tsx
@@ -1,5 +1,4 @@
import { UseSuspenseQueryOptions } from '@tanstack/react-query';
-import { ref } from 'process';
import { api } from '/@/renderer/api';
import { useItemListPaginatedLoader } from '/@/renderer/components/item-list/helpers/item-list-paginated-loader';
@@ -77,7 +76,6 @@ export const AlbumArtistListPaginatedGrid = ({
itemsPerRow={itemsPerRow}
itemType={LibraryItem.ALBUM_ARTIST}
onScrollEnd={handleOnScrollEnd}
- ref={ref}
rows={rows}
/>
diff --git a/src/renderer/features/player/audio-player/engine/web-player-engine.tsx b/src/renderer/features/player/audio-player/engine/web-player-engine.tsx
index cf81cb25f..f2824d7f0 100644
--- a/src/renderer/features/player/audio-player/engine/web-player-engine.tsx
+++ b/src/renderer/features/player/audio-player/engine/web-player-engine.tsx
@@ -1,6 +1,6 @@
import type { RefObject } from 'react';
-import { useEffect, useImperativeHandle, useRef, useState } from 'react';
+import { useCallback, useEffect, useImperativeHandle, useRef, useState } from 'react';
import ReactPlayer from 'react-player';
import { AudioPlayer, PlayerOnProgressProps } from '/@/renderer/features/player/audio-player/types';
@@ -153,15 +153,37 @@ export const WebPlayerEngine = (props: WebPlayerEngineProps) => {
useEffect(() => {
const player1 = player1Ref.current?.getInternalPlayer();
- if (player1) {
+ if (player1 && player1 instanceof HTMLAudioElement) {
player1.preservesPitch = preservesPitch;
}
const player2 = player2Ref.current?.getInternalPlayer();
- if (player2) {
+ if (player2 && player2 instanceof HTMLAudioElement) {
player2.preservesPitch = preservesPitch;
}
}, [preservesPitch]);
+ const handleOnReadyPlayer1 = useCallback(
+ (player: ReactPlayer) => {
+ const internal = player.getInternalPlayer();
+ if (internal && internal instanceof HTMLAudioElement) {
+ internal.preservesPitch = preservesPitch;
+ }
+ onStartedPlayer1(player);
+ },
+ [onStartedPlayer1, preservesPitch],
+ );
+
+ const handleOnReadyPlayer2 = useCallback(
+ (player: ReactPlayer) => {
+ const internal = player.getInternalPlayer();
+ if (internal && internal instanceof HTMLAudioElement) {
+ internal.preservesPitch = preservesPitch;
+ }
+ onStartedPlayer2(player);
+ },
+ [onStartedPlayer2, preservesPitch],
+ );
+
return (
{
onEnded={src1 ? () => onEndedPlayer1() : undefined}
onError={handleOnError(player1Ref, () => onEndedPlayer1())}
onProgress={onProgressPlayer1}
- onReady={onStartedPlayer1}
+ onReady={handleOnReadyPlayer1}
playbackRate={speed || 1}
playing={playerNum === 1 && playerStatus === PlayerStatus.PLAYING}
progressInterval={isTransitioning ? 10 : 250}
@@ -195,7 +217,7 @@ export const WebPlayerEngine = (props: WebPlayerEngineProps) => {
onEnded={src2 ? () => onEndedPlayer2() : undefined}
onError={handleOnError(player2Ref, () => onEndedPlayer2())}
onProgress={onProgressPlayer2}
- onReady={onStartedPlayer2}
+ onReady={handleOnReadyPlayer2}
playbackRate={speed || 1}
playing={playerNum === 2 && playerStatus === PlayerStatus.PLAYING}
progressInterval={isTransitioning ? 10 : 250}
diff --git a/src/renderer/features/player/components/player-config.tsx b/src/renderer/features/player/components/player-config.tsx
index 907d2c23a..2af16223f 100644
--- a/src/renderer/features/player/components/player-config.tsx
+++ b/src/renderer/features/player/components/player-config.tsx
@@ -1,5 +1,5 @@
import isElectron from 'is-electron';
-import { useEffect, useMemo, useState } from 'react';
+import { useCallback, useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { ListConfigTable } from '/@/renderer/features/shared/components/list-config-menu';
@@ -11,12 +11,17 @@ import {
usePlayerSpeed,
usePlayerStatus,
} from '/@/renderer/store';
-import { usePlaybackSettings, useSettingsStoreActions } from '/@/renderer/store/settings.store';
+import {
+ usePlaybackSettings,
+ useSettingsStore,
+ useSettingsStoreActions,
+} from '/@/renderer/store/settings.store';
import { ActionIcon } from '/@/shared/components/action-icon/action-icon';
import { Popover } from '/@/shared/components/popover/popover';
import { SegmentedControl } from '/@/shared/components/segmented-control/segmented-control';
import { Select } from '/@/shared/components/select/select';
import { Slider } from '/@/shared/components/slider/slider';
+import { Switch } from '/@/shared/components/switch/switch';
import { toast } from '/@/shared/components/toast/toast';
import {
CrossfadeStyle,
@@ -42,9 +47,20 @@ export const PlayerConfig = () => {
const { crossfadeDuration, crossfadeStyle, transitionType } = usePlayerProperties();
const { setCrossfadeDuration, setCrossfadeStyle, setQueueType, setSpeed, setTransitionType } =
usePlayerActions();
+ const preservePitch = useSettingsStore((state) => state.playback.preservePitch);
+
const playbackSettings = usePlaybackSettings();
const { setSettings } = useSettingsStoreActions();
+ const setPreservePitch = useCallback(
+ (value: boolean) => {
+ setSettings({
+ playback: { ...playbackSettings, preservePitch: value },
+ });
+ },
+ [playbackSettings, setSettings],
+ );
+
const [audioDevices, setAudioDevices] = useState<{ label: string; value: string }[]>([]);
useEffect(() => {
@@ -288,26 +304,38 @@ export const PlayerConfig = () => {
id: 'playbackSpeed',
label: t('player.playbackSpeed', { postProcess: 'titleCase' }),
},
+ {
+ component: (
+ setPreservePitch(e.currentTarget.checked)}
+ />
+ ),
+ id: 'preservePitch',
+ label: t('setting.preservePitch', { postProcess: 'titleCase' }),
+ },
];
return allOptions;
}, [
- playbackSettings,
- audioDevices,
- status,
- setSettings,
- currentSong,
- speed,
- setSpeed,
+ t,
queueType,
- setQueueType,
+ playbackSettings,
+ status,
+ audioDevices,
transitionType,
- setTransitionType,
+ crossfadeStyle,
crossfadeDuration,
setCrossfadeDuration,
- crossfadeStyle,
+ speed,
+ setSpeed,
+ preservePitch,
+ currentSong?.bpm,
+ setQueueType,
+ setSettings,
+ setTransitionType,
setCrossfadeStyle,
- t,
+ setPreservePitch,
]);
return (