Skip to content

Commit

Permalink
fix for stemhandler
Browse files Browse the repository at this point in the history
  • Loading branch information
jgentes committed May 22, 2024
1 parent 0c2f215 commit 0251079
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 43 deletions.
13 changes: 7 additions & 6 deletions app/api/handlers/fileHandlers.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import { ref } from 'valtio'
import {
type Stem,
type Track,
type TrackCache,
addToMix,
db,
storeTrackCache
storeTrackCache,
} from '~/api/handlers/dbHandlers'
import type { StemState } from '~/api/models/appModels'
import {
audioState,
mixState,
uiState,
userState
userState,
} from '~/api/models/appState.client'
import { errorHandler } from '~/utils/notifications'
import { processTracks } from './audioHandlers.client'
Expand All @@ -33,7 +34,7 @@ function showOpenFilePickerPolyfill(options: OpenFilePickerOptions) {
getFile: async () =>
new Promise(resolve => {
resolve(file)
})
}),
}
})
)
Expand Down Expand Up @@ -159,14 +160,14 @@ const getStemsDirHandle = async (): Promise<
const newStemsDirHandle = await window.showDirectoryPicker({
startIn: stemsDirHandle,
id: 'stemsDir',
mode: 'readwrite'
mode: 'readwrite',
})

if (
(await newStemsDirHandle.queryPermission({ mode: 'readwrite' })) ===
'granted'
) {
userState.stemsDirHandle = newStemsDirHandle
userState.stemsDirHandle = ref(newStemsDirHandle)
return newStemsDirHandle
}
}
Expand All @@ -190,7 +191,7 @@ const validateTrackStemAccess = async (
// do we have access to the stem dir?
try {
const stemDirAccess = await stemsDirHandle.queryPermission({
mode: 'readwrite'
mode: 'readwrite',
})
if (stemDirAccess !== 'granted') return 'grantStemDirAccess'
} catch (e) {
Expand Down
58 changes: 29 additions & 29 deletions app/api/models/appModels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class MixpointDb extends Dexie {
mixes: '++id, tracks',
sets: '++id, mixes',
trackCache: 'id',
appState: ''
appState: '',
})
// example migration:
//
Expand Down Expand Up @@ -120,40 +120,20 @@ type TrackCache = {
}>
}

// AppState provides persistence for Valtio state, which has much simpler get/set than Dexie
type AppState = Partial<{
userState: UserState
mixState: MixState
}>

type TrackState = Partial<{
adjustedBpm: Track['bpm']
beatResolution: '1:1' | '1:2' | '1:4'
stemZoom: Stem
mixpointTime: number // seconds
}>

type MixState = {
tracks: Track['id'][]
trackState: {
[trackId: Track['id']]: TrackState
}
}

type UserState = Partial<{
sortDirection: 'ascending' | 'descending'
sortColumn: Key
visibleColumns: Set<Key> // track table visible columns
stemsDirHandle: FileSystemDirectoryHandle // local folder on file system to store stems
}>

// AudioState is the working state of the mix, limited to the # of tracks in use, thereby not storing waveforms for all tracks
// AudioState is the working state of the mix, should not be persisted due to time/volumeMeter!
type AudioState = Partial<{
waveform: WaveSurfer // must be a valtio ref()
waveform: WaveSurfer // ref()
playing: boolean
time: number
gainNode?: GainNode // gain controls actual loudness of track, must be a ref()
analyserNode?: AnalyserNode // analyzerNode is used for volumeMeter, must be a ref()
gainNode?: GainNode // ref() gain controls actual loudness of track
analyserNode?: AnalyserNode // ref() analyzerNode is used for volumeMeter
volume: number // volume is the crossfader value
volumeMeter?: number // value between 0 and 1
stems: Stems
Expand All @@ -163,9 +143,9 @@ type AudioState = Partial<{

type Stems = {
[key in Stem]: Partial<{
waveform: WaveSurfer // must be a valtio ref()
gainNode?: GainNode // gain controls actual loudness of stem, must be a ref()
analyserNode?: AnalyserNode // analyzerNode is used for volumeMeter, must be a ref()
waveform: WaveSurfer // ref()
gainNode?: GainNode // ref() gain controls actual loudness of stem
analyserNode?: AnalyserNode // ref() analyzerNode is used for volumeMeter
volume: number // volume is the crossfader value
volumeMeter: number
mute: boolean
Expand Down Expand Up @@ -211,6 +191,26 @@ type UiState = {
modal: ModalState
}

// AppState provides persistence for Valtio state, which has much simpler get/set than Dexie
type AppState = Partial<{
userState: UserState
mixState: MixState
}>

type MixState = {
tracks: Track['id'][]
trackState: {
[trackId: Track['id']]: TrackState
}
}

type UserState = {
sortDirection: 'ascending' | 'descending'
sortColumn: Key
visibleColumns: Set<Key> // track table visible columns
stemsDirHandle: FileSystemDirectoryHandle // ref() local folder on file system to store stems
}

// Avoid having two files export same type names
export type {
Track,
Expand All @@ -226,6 +226,6 @@ export type {
MixState,
TrackState,
AudioState,
UiState
UiState,
}
export { db, STEMS, EFFECTS }
20 changes: 12 additions & 8 deletions app/api/models/appState.client.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
// This file handles application state that may be persisted to local storage.
import { proxy, snapshot } from 'valtio'
import { proxy, ref, snapshot } from 'valtio'
import { devtools, proxySet, watch } from 'valtio/utils'
import { db } from '~/api/handlers/dbHandlers'
import type {
AudioState,
MixState,
Track,
UiState,
UserState
UserState,
} from '~/api/models/appModels'
import { Env } from '~/utils/env'

Expand All @@ -29,24 +29,28 @@ const uiState = proxy<UiState>({
stemsAnalyzing: proxySet(),
syncTimer: undefined,
userEmail: '',
modal: { openState: false }
modal: { openState: false },
})

// Pull latest persistent state from Dexie and populate Valtio store
let seeded = false
const initialMixState = (await db.appState.get('mixState')) as MixState
const mixState = proxy<MixState>(
initialMixState || { tracks: [], trackState: {} }
)
const mixState = proxy<MixState>(initialMixState)

watch(async get => {
get(mixState)
//@ts-ignore dexie typescript failure
if (seeded) db.appState.put(snapshot(mixState), 'mixState')
})

const initialUserState = (await db.appState.get('userState')) as UserState
const userState = proxy<UserState>(initialUserState || {})
let initialUserState = (await db.appState.get('userState')) as UserState
// ensure that we ref the stemsDirHandle
if (initialUserState?.stemsDirHandle)
initialUserState = {
...initialUserState,
stemsDirHandle: ref(initialUserState.stemsDirHandle),
}
const userState = proxy<UserState>(initialUserState)

watch(async get => {
get(userState)
Expand Down

0 comments on commit 0251079

Please sign in to comment.