Spaces:
Sleeping
Sleeping
File size: 2,599 Bytes
f23825d |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
import { DocumentReference } from "firebase/firestore"
import pullAt from "lodash/pullAt"
import {
action,
computed,
makeObservable,
observable,
reaction,
transaction,
} from "mobx"
import { createModelSchema, list, object, primitive } from "serializr"
import { TIME_BASE } from "../../main/Constants"
import { isNotUndefined } from "../helpers/array"
import { Measure } from "../measure/Measure"
import { getMeasuresFromConductorTrack } from "../measure/MeasureList"
import { collectAllEvents, PlayerEvent } from "../player/PlayerEvent"
import Track from "../track"
const END_MARGIN = 480 * 30
export default class Song {
tracks: Track[] = []
filepath: string = ""
timebase: number = TIME_BASE
name: string = ""
fileHandle: FileSystemFileHandle | null = null
isSaved = true
constructor() {
makeObservable(this, {
addTrack: action,
removeTrack: action,
insertTrack: action,
conductorTrack: computed,
measures: computed,
endOfSong: computed,
allEvents: computed({ keepAlive: true }),
tracks: observable.shallow,
filepath: observable,
timebase: observable,
name: observable,
isSaved: observable,
})
reaction(
() => [
this.tracks.map((t) => ({ channel: t.channel, events: t.events })),
this.name,
],
() => (this.isSaved = false),
)
}
insertTrack(t: Track, index: number) {
// 最初のトラックは Conductor Track なので channel を設定しない
if (t.channel === undefined && this.tracks.length > 0) {
t.channel = t.channel || this.tracks.length - 1
}
this.tracks.splice(index, 0, t)
}
addTrack(t: Track) {
this.insertTrack(t, this.tracks.length)
}
removeTrack(id: number) {
transaction(() => {
pullAt(this.tracks, id)
})
}
get conductorTrack(): Track | undefined {
return this.tracks.find((t) => t.isConductorTrack)
}
getTrack(id: number): Track | undefined {
return this.tracks[id]
}
get measures(): Measure[] {
const conductorTrack = this.conductorTrack
if (conductorTrack === undefined) {
return []
}
return getMeasuresFromConductorTrack(conductorTrack, this.timebase)
}
get endOfSong(): number {
const eos = Math.max(
...this.tracks.map((t) => t.endOfTrack).filter(isNotUndefined),
)
return (eos ?? 0) + END_MARGIN
}
get allEvents(): PlayerEvent[] {
return collectAllEvents(this.tracks)
}
}
createModelSchema(Song, {
tracks: list(object(Track)),
filepath: primitive(),
timebase: primitive(),
})
|