mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-21 23:05:46 +00:00
refactor(player): E.37 — extract updateReplayGainForCurrentTrack (#601)
Move the ~50-LOC `updateReplayGainForCurrentTrack` action body into `runUpdateReplayGainForCurrentTrack(set, get)` in a dedicated module, following the helper-with-thin-wrapper pattern from `applyQueueHistorySnapshot` (E.30) rather than a single-action factory. The action recomputes the normalization snapshot + pushes fresh ReplayGain/loudness state to the engine when mode toggles change or the loudness cache fills mid-playback. Pure code-move. playerStore.ts: 991 → 938 LOC (−53).
This commit is contained in:
committed by
GitHub
parent
55b2b12fa5
commit
14346d1482
@@ -11,8 +11,6 @@ import { useHotCacheStore } from './hotCacheStore';
|
|||||||
import { orbitBulkGuard } from '../utils/orbitBulkGuard';
|
import { orbitBulkGuard } from '../utils/orbitBulkGuard';
|
||||||
import { useOrbitStore } from './orbitStore';
|
import { useOrbitStore } from './orbitStore';
|
||||||
import { estimateLivePosition } from '../api/orbit';
|
import { estimateLivePosition } from '../api/orbit';
|
||||||
import { loudnessGainPlaceholderUntilCacheDb } from '../utils/loudnessPlaceholder';
|
|
||||||
import { effectiveLoudnessPreAnalysisAttenuationDb } from '../utils/loudnessPreAnalysisSlider';
|
|
||||||
import { resolveReplayGainDb } from '../utils/resolveReplayGainDb';
|
import { resolveReplayGainDb } from '../utils/resolveReplayGainDb';
|
||||||
import { shuffleArray } from '../utils/shuffleArray';
|
import { shuffleArray } from '../utils/shuffleArray';
|
||||||
import { songToTrack } from '../utils/songToTrack';
|
import { songToTrack } from '../utils/songToTrack';
|
||||||
@@ -37,16 +35,12 @@ import {
|
|||||||
import { deriveNormalizationSnapshot } from './normalizationSnapshot';
|
import { deriveNormalizationSnapshot } from './normalizationSnapshot';
|
||||||
import { isInOrbitSession } from './orbitSession';
|
import { isInOrbitSession } from './orbitSession';
|
||||||
import {
|
import {
|
||||||
getCachedLoudnessGain,
|
|
||||||
hasStableLoudness,
|
|
||||||
isReplayGainActive,
|
isReplayGainActive,
|
||||||
loudnessCacheStateKeysForTrackId,
|
|
||||||
loudnessGainDbForEngineBind,
|
loudnessGainDbForEngineBind,
|
||||||
} from './loudnessGainCache';
|
} from './loudnessGainCache';
|
||||||
import {
|
import {
|
||||||
clearAllPlaybackScheduleTimers,
|
clearAllPlaybackScheduleTimers,
|
||||||
} from './scheduleTimers';
|
} from './scheduleTimers';
|
||||||
import { invokeAudioUpdateReplayGainDeduped } from './normalizationIpcDedupe';
|
|
||||||
import { touchHotCacheOnPlayback } from './hotCacheTouch';
|
import { touchHotCacheOnPlayback } from './hotCacheTouch';
|
||||||
import { applySkipStarOnManualNext } from './skipStarRating';
|
import { applySkipStarOnManualNext } from './skipStarRating';
|
||||||
import { resetLoudnessBackfillStateForTrackId } from './loudnessBackfillState';
|
import { resetLoudnessBackfillStateForTrackId } from './loudnessBackfillState';
|
||||||
@@ -149,6 +143,7 @@ import type { PlayerState, Track } from './playerStoreTypes';
|
|||||||
export type { PlayerState, Track };
|
export type { PlayerState, Track };
|
||||||
import { createLastfmActions } from './lastfmActions';
|
import { createLastfmActions } from './lastfmActions';
|
||||||
import { createMiscActions } from './miscActions';
|
import { createMiscActions } from './miscActions';
|
||||||
|
import { runUpdateReplayGainForCurrentTrack } from './updateReplayGainAction';
|
||||||
import { createQueueMutationActions } from './queueMutationActions';
|
import { createQueueMutationActions } from './queueMutationActions';
|
||||||
import { createScheduleActions } from './scheduleActions';
|
import { createScheduleActions } from './scheduleActions';
|
||||||
import { createTransportLightActions } from './transportLightActions';
|
import { createTransportLightActions } from './transportLightActions';
|
||||||
@@ -902,55 +897,7 @@ export const usePlayerStore = create<PlayerState>()(
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
updateReplayGainForCurrentTrack: () => {
|
updateReplayGainForCurrentTrack: () => runUpdateReplayGainForCurrentTrack(set, get),
|
||||||
const { currentTrack, queue, queueIndex, volume } = get();
|
|
||||||
if (!currentTrack || !currentTrack.id) return;
|
|
||||||
const authState = useAuthStore.getState();
|
|
||||||
const prev = queueIndex > 0 ? queue[queueIndex - 1] : null;
|
|
||||||
const next = queueIndex + 1 < queue.length ? queue[queueIndex + 1] : null;
|
|
||||||
const replayGainDb = resolveReplayGainDb(
|
|
||||||
currentTrack, prev, next,
|
|
||||||
isReplayGainActive(), authState.replayGainMode,
|
|
||||||
);
|
|
||||||
const replayGainPeak = isReplayGainActive()
|
|
||||||
? (currentTrack.replayGainPeak ?? null)
|
|
||||||
: null;
|
|
||||||
|
|
||||||
const normalization = deriveNormalizationSnapshot(currentTrack, queue, queueIndex);
|
|
||||||
const cachedLoud = getCachedLoudnessGain(currentTrack.id);
|
|
||||||
const cachedLoudDb = Number.isFinite(cachedLoud) ? cachedLoud! : null;
|
|
||||||
const haveStableLoud = hasStableLoudness(currentTrack.id);
|
|
||||||
const preEffForNorm = effectiveLoudnessPreAnalysisAttenuationDb(
|
|
||||||
authState.loudnessPreAnalysisAttenuationDb,
|
|
||||||
authState.loudnessTargetLufs,
|
|
||||||
);
|
|
||||||
const preAnalysisPlaceholderDb =
|
|
||||||
normalization.normalizationEngineLive === 'loudness'
|
|
||||||
&& cachedLoudDb == null
|
|
||||||
&& !haveStableLoud
|
|
||||||
&& Number.isFinite(preEffForNorm)
|
|
||||||
? loudnessGainPlaceholderUntilCacheDb(
|
|
||||||
authState.loudnessTargetLufs,
|
|
||||||
preEffForNorm,
|
|
||||||
)
|
|
||||||
: null;
|
|
||||||
set(prevState => ({
|
|
||||||
normalizationNowDb:
|
|
||||||
normalization.normalizationEngineLive === 'loudness'
|
|
||||||
? (cachedLoudDb ?? preAnalysisPlaceholderDb ?? prevState.normalizationNowDb)
|
|
||||||
: normalization.normalizationNowDb,
|
|
||||||
normalizationTargetLufs: normalization.normalizationTargetLufs,
|
|
||||||
normalizationEngineLive: normalization.normalizationEngineLive,
|
|
||||||
}));
|
|
||||||
invokeAudioUpdateReplayGainDeduped({
|
|
||||||
volume,
|
|
||||||
replayGainDb,
|
|
||||||
replayGainPeak,
|
|
||||||
loudnessGainDb: currentTrack ? (getCachedLoudnessGain(currentTrack.id) ?? null) : null,
|
|
||||||
preGainDb: authState.replayGainPreGainDb,
|
|
||||||
fallbackDb: authState.replayGainFallbackDb,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,83 @@
|
|||||||
|
import { effectiveLoudnessPreAnalysisAttenuationDb } from '../utils/loudnessPreAnalysisSlider';
|
||||||
|
import { loudnessGainPlaceholderUntilCacheDb } from '../utils/loudnessPlaceholder';
|
||||||
|
import { resolveReplayGainDb } from '../utils/resolveReplayGainDb';
|
||||||
|
import { useAuthStore } from './authStore';
|
||||||
|
import {
|
||||||
|
getCachedLoudnessGain,
|
||||||
|
hasStableLoudness,
|
||||||
|
isReplayGainActive,
|
||||||
|
} from './loudnessGainCache';
|
||||||
|
import { deriveNormalizationSnapshot } from './normalizationSnapshot';
|
||||||
|
import { invokeAudioUpdateReplayGainDeduped } from './normalizationIpcDedupe';
|
||||||
|
import type { PlayerState } from './playerStoreTypes';
|
||||||
|
|
||||||
|
type SetState = (
|
||||||
|
partial: Partial<PlayerState> | ((state: PlayerState) => Partial<PlayerState>),
|
||||||
|
) => void;
|
||||||
|
type GetState = () => PlayerState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recompute and push fresh ReplayGain + loudness state to the engine
|
||||||
|
* for the currently-playing track. Called when ReplayGain mode /
|
||||||
|
* pre-gain / fallback toggles change while a track is mid-playback,
|
||||||
|
* or when the loudness cache for the current track resolves later
|
||||||
|
* than the initial play.
|
||||||
|
*
|
||||||
|
* - Re-derives the normalization snapshot (target LUFS, engine-live
|
||||||
|
* mode) from the current queue context.
|
||||||
|
* - Picks a placeholder loudness gain when in loudness mode and the
|
||||||
|
* real cached gain isn't ready yet, so the UI's "now playing -X dB"
|
||||||
|
* readout doesn't drop to zero between the cache miss and the
|
||||||
|
* eventual cache fill.
|
||||||
|
* - Pushes the new audio parameters to the Rust engine via the
|
||||||
|
* deduplicated IPC channel.
|
||||||
|
*/
|
||||||
|
export function runUpdateReplayGainForCurrentTrack(set: SetState, get: GetState): void {
|
||||||
|
const { currentTrack, queue, queueIndex, volume } = get();
|
||||||
|
if (!currentTrack || !currentTrack.id) return;
|
||||||
|
const authState = useAuthStore.getState();
|
||||||
|
const prev = queueIndex > 0 ? queue[queueIndex - 1] : null;
|
||||||
|
const next = queueIndex + 1 < queue.length ? queue[queueIndex + 1] : null;
|
||||||
|
const replayGainDb = resolveReplayGainDb(
|
||||||
|
currentTrack, prev, next,
|
||||||
|
isReplayGainActive(), authState.replayGainMode,
|
||||||
|
);
|
||||||
|
const replayGainPeak = isReplayGainActive()
|
||||||
|
? (currentTrack.replayGainPeak ?? null)
|
||||||
|
: null;
|
||||||
|
|
||||||
|
const normalization = deriveNormalizationSnapshot(currentTrack, queue, queueIndex);
|
||||||
|
const cachedLoud = getCachedLoudnessGain(currentTrack.id);
|
||||||
|
const cachedLoudDb = Number.isFinite(cachedLoud) ? cachedLoud! : null;
|
||||||
|
const haveStableLoud = hasStableLoudness(currentTrack.id);
|
||||||
|
const preEffForNorm = effectiveLoudnessPreAnalysisAttenuationDb(
|
||||||
|
authState.loudnessPreAnalysisAttenuationDb,
|
||||||
|
authState.loudnessTargetLufs,
|
||||||
|
);
|
||||||
|
const preAnalysisPlaceholderDb =
|
||||||
|
normalization.normalizationEngineLive === 'loudness'
|
||||||
|
&& cachedLoudDb == null
|
||||||
|
&& !haveStableLoud
|
||||||
|
&& Number.isFinite(preEffForNorm)
|
||||||
|
? loudnessGainPlaceholderUntilCacheDb(
|
||||||
|
authState.loudnessTargetLufs,
|
||||||
|
preEffForNorm,
|
||||||
|
)
|
||||||
|
: null;
|
||||||
|
set(prevState => ({
|
||||||
|
normalizationNowDb:
|
||||||
|
normalization.normalizationEngineLive === 'loudness'
|
||||||
|
? (cachedLoudDb ?? preAnalysisPlaceholderDb ?? prevState.normalizationNowDb)
|
||||||
|
: normalization.normalizationNowDb,
|
||||||
|
normalizationTargetLufs: normalization.normalizationTargetLufs,
|
||||||
|
normalizationEngineLive: normalization.normalizationEngineLive,
|
||||||
|
}));
|
||||||
|
invokeAudioUpdateReplayGainDeduped({
|
||||||
|
volume,
|
||||||
|
replayGainDb,
|
||||||
|
replayGainPeak,
|
||||||
|
loudnessGainDb: getCachedLoudnessGain(currentTrack.id) ?? null,
|
||||||
|
preGainDb: authState.replayGainPreGainDb,
|
||||||
|
fallbackDb: authState.replayGainFallbackDb,
|
||||||
|
});
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user