diff --git a/components/topbar.js b/components/topbar.js index 94f9546..2723f34 100644 --- a/components/topbar.js +++ b/components/topbar.js @@ -1,7 +1,7 @@ import { BiCoffeeTogo, BiShare, BiMoon, BiSun, BiHelpCircle } from 'react-icons/bi' import { SiAboutdotme, SiMidi } from 'react-icons/si' -import { sectionsToQuery } from '../lib/serialization' +import { stateToQuery } from '../lib/serialization' import { copyTextToClipboard } from '../lib/clipboard' import { useDarkMode } from 'next-dark-mode' import { useTheme } from '../hooks/useTheme' @@ -135,7 +135,7 @@ export default function Social(){ let state = useStore.getState(); let val = window.location.origin + window.location.pathname - + sectionsToQuery(state.sections, state.bpm); + + stateToQuery(state.sections, state.bpm, state.instrumentIDs); copyTextToClipboard(val); setTimeout(()=>alert('copied the url to clipboard! '), 100); }) diff --git a/lib/serialization.js b/lib/serialization.js index a9bdc61..fcff669 100644 --- a/lib/serialization.js +++ b/lib/serialization.js @@ -2,8 +2,9 @@ const d1 = '_'; const d2 = 'a'; -export function sectionsToQuery(sections, bpm){ - return '?' + Object.entries({ +export function stateToQuery(sections, bpm, instrumentIDs){ + const number_of_tracks = sections.reduce((s, v) => Math.max(s, v.ratios.length), -1); + const params = { lengths: sections.map(x=>x.length).join(d1), repeats: sections.map(x=>x.repeat).join(d1), swings: sections.map(x=>x.swing).join(d1), @@ -11,13 +12,21 @@ export function sectionsToQuery(sections, bpm){ subdivides: sections.map(x=>x.subdivide.join(d2)).join(d1), offsets: sections.map(x=>x.offsets.join(d2)).join(d1), bpm: bpm, - }) + }; + if (instrumentIDs && number_of_tracks > 0) { + params.instruments = instrumentIDs.slice(0, number_of_tracks).join(d1); + } + return '?' + Object.entries(params) .map(([k, v])=>`&${k}=${v}`) .join('') .slice(1); } -export function queryToSections(query){ +function parseInstruments(str) { + return str.split(d1).map(Number); +} + +export function queryToState(query){ const lens = query.lengths.split(d1).map(Number); const reps = query.repeats.split(d1).map(Number); const swins = query.swings.split(d1).map(Number); @@ -26,7 +35,7 @@ export function queryToSections(query){ const subs = query.subdivides.split(d1).map(x=>x.split(d2).map(Number)); const offs = query.offsets.split(d1).map(x=>x.split(d2).map(Number)); - return lens.map((len, i)=>({ + const sections = lens.map((len, i)=>({ length: len, repeat: reps[i], swing: swins[i], @@ -34,4 +43,13 @@ export function queryToSections(query){ subdivide: subs[i], offsets: offs[i], })); + + return { + sections, + instrumentIDs: query.instruments ? parseInstruments(query.instruments) : null, + }; +} + +export function queryToSections(query){ + return queryToState(query).sections; } \ No newline at end of file diff --git a/pages/index.js b/pages/index.js index 0e1a120..707aa5d 100644 --- a/pages/index.js +++ b/pages/index.js @@ -6,11 +6,12 @@ import { useTheme } from "../hooks/useTheme"; import useStore from "../hooks/useStore"; import shallow from "zustand/shallow"; -import { queryToSections } from "../lib/serialization"; +import { queryToState } from "../lib/serialization"; import { sectionsToImgURL } from "../lib/sectionsToImgURL"; import { init as initSynths, getInstruments, + getNewInstrument, } from "../lib/instruments"; const Tone = require("tone"); @@ -22,7 +23,7 @@ import HitTracker from "../components/hittracker"; export default function Home() { const styles = useTheme(require("../styles/Home.module.sass")); - const [paused, bpm, setBpm, sections, setSections, instrumentIDs, pause, play] = useStore( + const [paused, bpm, setBpm, sections, setSections, setInstrumentIDs, instrumentIDs, pause, play] = useStore( useCallback( (state) => [ state.paused, @@ -30,6 +31,7 @@ export default function Home() { state.setBpm, state.sections, state.setSections, + state.setInstrumentIDs, state.instrumentIDs, state.pause, state.play, @@ -119,12 +121,19 @@ export default function Home() { if(Object.keys(router.query).length <= 0) return; console.log('found state in url, proceeding to load...'); - setSections(queryToSections(router.query)); + const { sections: loadedSections, instrumentIDs: loadedInstruments } = queryToState(router.query); + setSections(loadedSections); setBpm(Number(router.query.bpm)); + if (loadedInstruments) { + const base = Array.from({ length: 10 }, (v, i) => getNewInstrument(i)); + loadedInstruments.forEach((id, i) => { base[i] = id; }); + setInstrumentIDs(base); + } + // remove query params window.history.replaceState({}, document.title, window.location.pathname); - }, [router.query]); + }, [router.query, setSections, setBpm, setInstrumentIDs]); return (