Skip to content

Commit 2943bc7

Browse files
committed
fix(player): 操作双轨时结束波形试听
1 parent 4c48d63 commit 2943bc7

6 files changed

Lines changed: 82 additions & 8 deletions

‎src/renderer/src/components/HorizontalBrowseModeShell.vue‎

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -196,10 +196,11 @@ const {
196196
waveformPresentation.state.top.visualPending === true ||
197197
waveformPresentation.state.bottom.visualPending === true
198198
})
199-
useHorizontalBrowseWaveformPreviewSuspension({
199+
const { handlePlayerInteraction } = useHorizontalBrowseWaveformPreviewSuspension({
200200
nativeTransport,
201201
syncDeckRenderState,
202-
setAuditionPresentationSuspended
202+
setAuditionPresentationSuspended,
203+
playerInteractionEnabled: () => !isEditMode.value
203204
})
204205
const notifyDeckSeekPresentationIntent = (deck: DeckKey, seconds: number) => {
205206
waveformPresentation.markSeek(deck, seconds)
@@ -218,7 +219,6 @@ const resolveDeckDurationSeconds = (deck: DeckKey) =>
218219
)
219220
const topDeckUiPlaying = computed(() => resolveDeckPlaying('top'))
220221
const bottomDeckUiPlaying = computed(() => resolveDeckPlaying('bottom'))
221-
const HORIZONTAL_BROWSE_NEGATIVE_PLAYBACK_EPSILON_SEC = 0.0001
222222
const resolveDeckWaveformPlaybackActive = (deck: DeckKey) =>
223223
resolveHorizontalBrowseDeckWaveformPlaybackActive({
224224
deck,
@@ -227,7 +227,7 @@ const resolveDeckWaveformPlaybackActive = (deck: DeckKey) =>
227227
auditionPresentationSuspended.value || nativeTransport.state.auditionSuspended,
228228
topRenderCurrentSeconds: topDeckRenderCurrentSeconds,
229229
bottomRenderCurrentSeconds: bottomDeckRenderCurrentSeconds,
230-
negativePlaybackEpsilonSec: HORIZONTAL_BROWSE_NEGATIVE_PLAYBACK_EPSILON_SEC
230+
negativePlaybackEpsilonSec: 0.0001
231231
})
232232
const topDeckWaveformPlaybackActive = computed(() => resolveDeckWaveformPlaybackActive('top'))
233233
const bottomDeckWaveformPlaybackActive = computed(() => resolveDeckWaveformPlaybackActive('bottom'))
@@ -734,6 +734,7 @@ const resolveDeckToolbarState = (deck: DeckKey) => {
734734
735735
useHorizontalBrowseModeShellHotkeys({
736736
runtime,
737+
onPlayerInteraction: handlePlayerInteraction,
737738
touchDeckInteraction,
738739
resolveDeckSong,
739740
ejectDeckSong: handleDeckEjectSong,
@@ -998,6 +999,10 @@ onUnmounted(() => {
998999
'is-light-theme': isLightTheme,
9991000
'is-fader-controls-expanded': faderControlsExpanded && !isEditMode
10001001
}"
1002+
@pointerdown.capture="handlePlayerInteraction"
1003+
@wheel.capture="handlePlayerInteraction"
1004+
@keydown.capture="handlePlayerInteraction"
1005+
@drop.capture="handlePlayerInteraction"
10011006
>
10021007
<div class="controls" :class="{ 'controls--edit': isEditMode }">
10031008
<HorizontalBrowseEditDeckControls

‎src/renderer/src/composables/horizontalBrowse/useHorizontalBrowseHotkeys.ts‎

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ type CrossfaderDirection = -1 | 0 | 1
1313

1414
type UseHorizontalBrowseHotkeysParams = {
1515
runtime: ReturnType<typeof useRuntimeStore>
16+
onPlayerInteraction?: () => void
1617
onTogglePlayPause: (deck: HorizontalBrowseDeckKey) => void
1718
onCueKeyDown: (deck: HorizontalBrowseDeckKey) => boolean
1819
onCueKeyUp: (deck: HorizontalBrowseDeckKey) => void
@@ -73,6 +74,26 @@ const resolvePercentByCode = (code: string) => {
7374
const isHorizontalBrowsePhraseJumpHotkey = (event: KeyboardEvent) =>
7475
event.altKey && (event.code === 'KeyA' || event.code === 'KeyD')
7576

77+
const isHorizontalBrowsePlayerControlHotkey = (event: KeyboardEvent) => {
78+
if (isHorizontalBrowsePhraseJumpHotkey(event)) return true
79+
if (
80+
event.code === 'Space' ||
81+
event.code === 'KeyC' ||
82+
event.code === 'KeyA' ||
83+
event.code === 'KeyD' ||
84+
event.code === 'ArrowLeft' ||
85+
event.code === 'ArrowRight' ||
86+
event.code === 'KeyW' ||
87+
event.code === 'KeyS' ||
88+
event.code === 'ArrowUp' ||
89+
event.code === 'ArrowDown' ||
90+
event.code === 'KeyF'
91+
) {
92+
return true
93+
}
94+
return resolvePercentByCode(event.code) !== null
95+
}
96+
7697
export const useHorizontalBrowseHotkeys = (params: UseHorizontalBrowseHotkeysParams) => {
7798
const activeCueDeckByCode = new Map<string, HorizontalBrowseDeckKey>()
7899
const activeCrossfaderKeys = new Set<string>()
@@ -175,9 +196,13 @@ export const useHorizontalBrowseHotkeys = (params: UseHorizontalBrowseHotkeysPar
175196
emitPreviewMoveRequest('CuratedLibrary')
176197
return
177198
}
178-
stopKeyboardEvent(event)
179-
return
199+
if (!isHorizontalBrowsePlayerControlHotkey(event)) {
200+
stopKeyboardEvent(event)
201+
return
202+
}
180203
}
204+
const playerControlHotkey = isHorizontalBrowsePlayerControlHotkey(event)
205+
if (playerControlHotkey) params.onPlayerInteraction?.()
181206
const deck = resolveDeckByShiftState(event)
182207

183208
if (isHorizontalBrowsePhraseJumpHotkey(event)) {

‎src/renderer/src/composables/horizontalBrowse/useHorizontalBrowseModeShellHotkeys.ts‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ type CrossfaderKeyboardTarget = {
1414

1515
type UseHorizontalBrowseModeShellHotkeysParams = {
1616
runtime: ReturnType<typeof useRuntimeStore>
17+
onPlayerInteraction?: () => void
1718
touchDeckInteraction: (deck: DeckKey) => void
1819
resolveDeckSong: (deck: DeckKey) => ISongInfo | null
1920
ejectDeckSong: (deck: DeckKey) => Promise<unknown>
@@ -55,6 +56,7 @@ export const useHorizontalBrowseModeShellHotkeys = (
5556

5657
useHorizontalBrowseHotkeys({
5758
runtime: params.runtime,
59+
onPlayerInteraction: params.onPlayerInteraction,
5860
onTogglePlayPause: params.onTogglePlayPause,
5961
onCueKeyDown: params.onCueKeyDown,
6062
onCueKeyUp: params.onCueKeyUp,

‎src/renderer/src/composables/horizontalBrowse/useHorizontalBrowseWaveformPreviewSuspension.spec.ts‎

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ describe('useHorizontalBrowseWaveformPreviewSuspension', () => {
3030
useHorizontalBrowseWaveformPreviewSuspension({
3131
nativeTransport: { state, setAuditionSuspended },
3232
syncDeckRenderState,
33-
setAuditionPresentationSuspended
33+
setAuditionPresentationSuspended,
34+
playerInteractionEnabled: () => true
3435
})
3536
})
3637

@@ -63,7 +64,8 @@ describe('useHorizontalBrowseWaveformPreviewSuspension', () => {
6364
useHorizontalBrowseWaveformPreviewSuspension({
6465
nativeTransport: { state, setAuditionSuspended },
6566
syncDeckRenderState: vi.fn(),
66-
setAuditionPresentationSuspended
67+
setAuditionPresentationSuspended,
68+
playerInteractionEnabled: () => true
6769
})
6870
})
6971

@@ -82,4 +84,31 @@ describe('useHorizontalBrowseWaveformPreviewSuspension', () => {
8284
expect(setAuditionPresentationSuspended).toHaveBeenLastCalledWith(false)
8385
scope.stop()
8486
})
87+
88+
it('冻结期间的双轨播放器操作会请求结束波形试听', async () => {
89+
const state = reactive({ auditionSuspended: false })
90+
const stopListener = vi.fn()
91+
emitter.on('waveform-preview:stop', stopListener)
92+
const scope = effectScope()
93+
const suspension = scope.run(() =>
94+
useHorizontalBrowseWaveformPreviewSuspension({
95+
nativeTransport: {
96+
state,
97+
setAuditionSuspended: async (suspended) => {
98+
state.auditionSuspended = suspended
99+
}
100+
},
101+
syncDeckRenderState: vi.fn(),
102+
setAuditionPresentationSuspended: vi.fn(),
103+
playerInteractionEnabled: () => true
104+
})
105+
)
106+
107+
await emitGate(WAVEFORM_PREVIEW_TRANSPORT_SUSPEND_EVENT, 'session-player-input')
108+
suspension?.handlePlayerInteraction()
109+
110+
expect(stopListener).toHaveBeenCalledWith({ reason: 'manual-play' })
111+
emitter.off('waveform-preview:stop', stopListener)
112+
scope.stop()
113+
})
85114
})

‎src/renderer/src/composables/horizontalBrowse/useHorizontalBrowseWaveformPreviewSuspension.ts‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { onScopeDispose } from 'vue'
22
import emitter from '@renderer/utils/mitt'
33
import type { HorizontalBrowseRenderSyncOptions } from '@renderer/composables/horizontalBrowse/useHorizontalBrowseRenderSync'
44
import {
5+
stopWaveformPreviewForTransportInteraction,
56
WAVEFORM_PREVIEW_TRANSPORT_RESUME_EVENT,
67
WAVEFORM_PREVIEW_TRANSPORT_SUSPEND_EVENT,
78
type WaveformPreviewTransportGatePayload
@@ -16,6 +17,7 @@ type UseHorizontalBrowseWaveformPreviewSuspensionParams = {
1617
}
1718
syncDeckRenderState: (input?: number | HorizontalBrowseRenderSyncOptions) => void
1819
setAuditionPresentationSuspended: (suspended: boolean) => void
20+
playerInteractionEnabled: () => boolean
1921
}
2022

2123
const isGatePayload = (payload: unknown): payload is WaveformPreviewTransportGatePayload => {
@@ -77,6 +79,11 @@ export const useHorizontalBrowseWaveformPreviewSuspension = (
7779
emitter.on(WAVEFORM_PREVIEW_TRANSPORT_SUSPEND_EVENT, handleSuspend)
7880
emitter.on(WAVEFORM_PREVIEW_TRANSPORT_RESUME_EVENT, handleResume)
7981

82+
const handlePlayerInteraction = () => {
83+
if (!activeSessionId || !params.playerInteractionEnabled()) return
84+
stopWaveformPreviewForTransportInteraction()
85+
}
86+
8087
onScopeDispose(() => {
8188
disposed = true
8289
emitter.off(WAVEFORM_PREVIEW_TRANSPORT_SUSPEND_EVENT, handleSuspend)
@@ -89,4 +96,6 @@ export const useHorizontalBrowseWaveformPreviewSuspension = (
8996
activeSessionId = ''
9097
}).catch(() => undefined)
9198
})
99+
100+
return { handlePlayerInteraction }
92101
}

‎src/renderer/src/utils/exclusivePlayback.ts‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,7 @@ export const suspendTransportForWaveformPreview = async (sessionId: string) => {
6969
export const resumeTransportAfterWaveformPreview = async (sessionId: string) => {
7070
await runWaveformPreviewTransportGate(WAVEFORM_PREVIEW_TRANSPORT_RESUME_EVENT, sessionId)
7171
}
72+
73+
export const stopWaveformPreviewForTransportInteraction = () => {
74+
emitter.emit('waveform-preview:stop', { reason: 'manual-play' })
75+
}

0 commit comments

Comments
 (0)