From 9f4a54afa2fa3ec60d2b0946dabfcc198b43b44f Mon Sep 17 00:00:00 2001 From: s-ol Date: Tue, 22 Mar 2022 00:45:16 +0100 Subject: move MIDI settings in toolbar, reorganize --- app/app.js | 286 +++++++++++++++++++++---------------------------------------- 1 file changed, 98 insertions(+), 188 deletions(-) (limited to 'app/app.js') diff --git a/app/app.js b/app/app.js index 5074285..9af30ee 100644 --- a/app/app.js +++ b/app/app.js @@ -1,6 +1,7 @@ -import React from 'react'; +import React, { useState, useEffect } from 'react'; import { css, pos, width, height } from './style'; import * as notes from './notes'; +import { useAppState, useMIDI, Toolbar } from './config'; const statbyte = (stat, chan) => (stat << 4) | chan; const CHANNEL = 0b1011; @@ -36,9 +37,8 @@ const Hexagon = ({ x, y, children, state, note, major, scale, noteon, noteoff }) style={pos([x, y], major)} >
noteon(note)} - onMouseUp ={() => noteoff(note)} + onMouseUp={() => noteoff(note)} > {children}
@@ -60,7 +60,7 @@ const layouts = { // B = 7 // C = 2 = x // A + B = 12 = y - let note = 41 + 2 * x + 6 * y; + let note = 5 + 2 * x + 6 * y; if (y % 2 == 0) note += 1; return note; }, @@ -128,7 +128,7 @@ const tallyup = (steps, offset=0) => { }; }; -const Keyboard = ({ w, h, layout: { major, map }, state, scale, labels, noteon, noteoff }) => ( +const Keyboard = ({ w, h, layout: { major, map }, state, scale, transpose, labels, noteon, noteoff }) => (
{range(w).map((_, x) => ( range(h).map((_, y) => { - const note = map([x, y], [w, h]); + const note = map([x, y], [w, h]) + transpose; const onCore = scale && scale.notes.indexOf(note) >= 0; const onScale = scale && scale.modulo.indexOf(note % 12) >= 0; return ( @@ -182,30 +182,7 @@ const ChordView = ({ chord }) => {
); }; - -css(` -nav { - display: flex; - flex-wrap: wrap; - justfiy-content: space-between; -} - -nav > .group, nav > .spacer { - display: flex; - align-items: baseline; - padding: 0.25em 1em; - gap: 1em; - - border: 0 solid #363636; - border-width: 1px 0 1px 0; -} - -nav > .group:nth-child(2n) { - background: #363636; -} - -nav > .spacer { flex: 1; } -`); +; css(` main { @@ -240,190 +217,123 @@ main:focus-within .focus-msg { } `); -export default class App extends React.Component { - state = { +export default () => { + const [settings, setSettings] = useAppState({ layout: 'wicki_hayden', scale: 'major', labels: 'english', offset: 60, - state: {}, + transpose: 3*12, w: 12, h: 4, - }; - - ref = React.createRef(); - - componentDidMount() { - this.ref.current.addEventListener("keydown", this.onkeydown); - this.ref.current.addEventListener("keyup", this.onkeyup); - } - - componentDidUpdate(prevProps) { - this.send(CHANNEL, ALL_SOUND_OFF, 0); - this.send(CHANNEL, ALL_NOTES_OFF, 0); - - if (prevProps.midiin) - prevProps.midiin.onmidimessage = null; - - if (this.props.midiin) - this.props.midiin.onmidimessage = this.onmessage; - } + }); + const [state, setState] = useState({}); + const midi = useMIDI(); - blink = (note) => { - this.onmessage({ cmd: NOTE_ON, note }); - setTimeout(() => this.onmessage({ cmd: NOTE_OFF, note }), 250); - } + const ref = React.createRef(); - send(command, note, vel=127) { - if (command === NOTE_ON && this.state.offset === null) - this.setState({ offset: note }); + const midiin = midi.inputs.get(settings.midiin); + const midiout = midi.outputs.get(settings.midiout); - if (!this.props.midiout) - return; + const send = (command, note, vel=127) => { + if (!midiout) return; const msg = [statbyte(command, 0), note, vel]; - this.props.midiout.send(msg); - } + midiout.send(msg); + }; - noteon(note) { - if (this.state.offset === null) - this.setState({ offset: note }); + const noteon = (note) => { + if (settings.offset === null) { + setSettings((s) => ({ ...s, offset: note })); + } - this.setState(({ state }) => ({ state: { ...state, [note]: true } })); - this.send(NOTE_ON, note); + setState((s) => ({ ...s, [note]: true })); + send(NOTE_ON, note); } - noteoff(note) { - this.setState(({ state }) => ({ state: { ...state, [note]: false } })); - this.send(NOTE_OFF, note); + const noteoff = (note) => { + setState((s) => ({ ...s, [note]: false })); + send(NOTE_OFF, note); } - set = (e) => { - const key = e.target.name; - let value = e.target.value; - if (key === 'w' || key === 'h') value = +value; - this.setState({ [key]: value }); - }; + useEffect(() => { + ref.current.onkeydown = (e) => { + if (e.repeat) return; - onoffset = (offset) => (e) => this.setState({ offset }); + const note = notes.key2midi[e.code]; + if (!note) return; + e.preventDefault(); + noteon(note); + } - onmessage = (e) => { - const message = parse(e); + ref.current.onkeyup = (e) => { + if (e.repeat) return; - switch (message.cmd) { - case NOTE_ON: - console.info(message.note); - break; + const note = notes.key2midi[e.code]; + if (!note) return; + e.preventDefault(); + noteoff(note); } + }); - switch (message.cmd) { - case NOTE_ON: - this.setState(({ state }) => ({ state: { ...state, [message.note]: true } })); - break; + useEffect(() => { + send(CHANNEL, ALL_SOUND_OFF, 0); + send(CHANNEL, ALL_NOTES_OFF, 0); + }, [midiout]); - case NOTE_OFF: - this.setState(({ state }) => ({ state: { ...state, [message.note]: false } })); - break; - } - } + useEffect(() => { + if (!midiin) return; - onkeydown = (e) => { - if (e.repeat) return; + midiin.onmidimessage = (e) => { + const message = parse(e); - const note = notes.key2midi[e.code]; - if (!note) return; - e.preventDefault(); - this.noteon(note); - } + switch (message.cmd) { + case NOTE_ON: + if (settings.offset === null) { + setSettings((s) => ({ ...s, offset: note })); + } - onkeyup = (e) => { - if (e.repeat) return; + setState((s) => ({ ...s, [message.note]: true })); + break; - const note = notes.key2midi[e.code]; - if (!note) return; - e.preventDefault(); - this.noteoff(note); - } + case NOTE_OFF: + setState((s) => ({ ...s, [message.note]: false })); + break; + } + } - render() { - const { configure } = this.props; - const { w, h, scale, layout, labels, offset, state } = this.state; - - const chord = Object.entries(state).filter(([note, on]) => on).map(([k, _]) => k); - chord.sort(); - - return ( -
- - -
- - -
- click here to activate
keyboard input
-
-
-
- ); - } + return () => { + midiin.onmidimessage = null; + }; + }, [midiin]); + + const { scale, layout, labels, offset } = settings; + const chord = Object.entries(state).filter(([note, on]) => on).map(([k, _]) => k); + chord.sort(); + + return ( +
+ + +
+ + +
+ click here to activate
keyboard input
+
+
+
+ ); }; -- cgit v1.2.3