import * as Sentry from '@sentry/react'; import { Note, Pad, ProjectRawData } from '../../types/types'; import { getSampleName } from '../exporters/utils'; import { noteNumberToName } from '../parsers'; import { findPad, findSoundByPad, findSoundIdByPad } from '../utils'; export type ViewNote = Note & { name: string }; export type ViewPattern = { pad: string; bars: number; soundName: string; notes: ViewNote[]; group: string; padNumber: number; midiChannel: number; soundId: number; }; export type ViewScene = { name: string; patterns: ViewPattern[]; maxBars: number; }; export type ViewPad = Pad; export type ViewData = { pads: Record; scenes: ViewScene[]; scenesSettings: ProjectRawData['scenesSettings']; }; function webViewTransformer(data: ProjectRawData): ViewData { const { pads, scenes } = data; const newScenes: ViewScene[] = []; const usedPads = new Set(); if (import.meta.env.DEV) { console.log(data); } // construct new scenes array // and collect the used pads scenes.forEach((scene, idx) => { newScenes[idx] = { name: scene.name, maxBars: Math.max( 1, ...scene.patterns.map((pattern) => pattern.bars), ...Object.values(scene.patternEvents).map((pattern) => pattern?.bars || 0), ), patterns: [], }; for (const pattern of scene.patterns) { if (pattern.notes.length > 0) { usedPads.add(pattern.pad); } } }); // also add pads that have samples assigned (even without patterns) for (const group in pads) { pads[group].forEach((pad, index) => { if (pad.soundId > 0) { usedPads.add(`${group}${index}`); } }); } newScenes.forEach((scene, idx) => { // make sure each scene have the same tracks/pads usedPads.forEach((pad) => { const patternByPad = scene.patterns.find((p) => p.pad === pad); if (!patternByPad) { const group = pad[0]; const padNumber = parseInt(pad.slice(1), 10); const soundId = findSoundIdByPad(pad, pads) || 0; const sound = findSoundByPad(pad, pads, data.sounds); const padObject = findPad(pad, pads); scene.patterns.push({ pad, notes: [], bars: 0, group, padNumber, soundName: getSampleName(sound?.meta?.name, soundId, false), midiChannel: padObject?.midiChannel || 0, soundId, }); } }); // copy notes to exiting patterns scenes[idx].patterns.forEach((pattern) => { const patternInScene = scene.patterns.find((p) => p.pad === pattern.pad); if (!patternInScene) { return; } patternInScene.notes = pattern.notes .map((note) => ({ ...note, name: noteNumberToName(note.note), })) .reduce((acc, note) => { const existingNoteInThisPosition = acc.find((n) => n.position === note.position); if (existingNoteInThisPosition) { existingNoteInThisPosition.name = `${existingNoteInThisPosition.name},${note.name}`; return acc; } acc.push({ ...note }); return acc; }, [] as ViewNote[]); patternInScene.bars = pattern.bars; }); scene.patterns.sort((a, b) => a.pad.localeCompare(b.pad, undefined, { numeric: true, sensitivity: 'base' }), ); }); Sentry.setContext('webViewData', { pads, scenes: newScenes, scenesSettings: data.scenesSettings, }); return { pads, scenes: newScenes, scenesSettings: data.scenesSettings, }; } export default webViewTransformer;