Skip to content

Commit

Permalink
Settings saving
Browse files Browse the repository at this point in the history
the settings will now be saved in config.json for local edition
  • Loading branch information
spessasus committed May 19, 2024
1 parent 9c58d82 commit b3af371
Show file tree
Hide file tree
Showing 6 changed files with 462 additions and 180 deletions.
28 changes: 23 additions & 5 deletions server.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import open from "open";
import express from "express";
import fs from "fs";
import path from 'path';
import {fileURLToPath} from 'url';
import open from 'open'
import express from 'express'
import fs from 'fs'
import path from 'path'
import { fileURLToPath } from 'url'

const app = express();
const PORT = 8181;
Expand All @@ -14,6 +14,7 @@ const __dirname = path.dirname(__filename);

app.use(express.static("src"));
app.use(express.static("soundfonts"));
app.use(express.json());

fs.writeFile("config.json", "{}", {flag: "wx"}, () => {});

Expand Down Expand Up @@ -56,6 +57,23 @@ app.get("/setlastsf2", (req) => {
fs.writeFile("config.json", JSON.stringify(config), { flag: "w"}, () => {});
});

app.post("/savesettings", (req) => {
const config = JSON.parse(fs.readFileSync("config.json", "utf-8"));
config.settings = req.body;
fs.writeFile("config.json", JSON.stringify(config), { flag: "w"}, () => {});
})

app.get("/getsettings", (req, res) => {
/**
* @type {{
* lastUsedSf2: string,
* settings: SavedSettings
* }}
*/
const config = JSON.parse(fs.readFileSync("config.json", "utf-8"));
res.send(config.settings);
})

app.listen(PORT, HOST, undefined, () =>{
let url = `http://localhost:${PORT}`;
open(url).then(() => {
Expand Down
14 changes: 14 additions & 0 deletions src/spessasynth_lib/midi_handler/midi_handler.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
import { Synthetizer } from '../synthetizer/synthetizer.js'
import { consoleColors } from '../utils/other.js';

const NO_INPUT = null;

export class MIDIDeviceHandler
{
constructor()
{}
async createMIDIDeviceHandler()
{
/**
* @type {MIDIInput}
*/
this.selectedInput = NO_INPUT;
/**
* @type {MIDIOutput}
*/
this.selectedOutput = NO_INPUT;
if(navigator.requestMIDIAccess) {
// prepare the midi access
try
Expand Down Expand Up @@ -37,6 +46,7 @@ export class MIDIDeviceHandler
*/
connectMIDIOutputToSeq(output, seq)
{
this.selectedOutput = output;
seq.connectMidiOutput(output);
console.log(`%cPlaying MIDI to %c${output.name}`,
consoleColors.info,
Expand All @@ -49,6 +59,7 @@ export class MIDIDeviceHandler
*/
disconnectSeqFromMIDI(seq)
{
this.selectedOutput = NO_INPUT;
seq.connectMidiOutput(undefined);
console.log("%cDisconnected from MIDI out.",
consoleColors.info);
Expand All @@ -61,6 +72,7 @@ export class MIDIDeviceHandler
*/
connectDeviceToSynth(input, synth)
{
this.selectedInput = input;
input.onmidimessage = event => {
synth.sendMessage(event.data);
}
Expand All @@ -74,6 +86,7 @@ export class MIDIDeviceHandler
*/
disconnectDeviceFromSynth(input)
{
this.selectedInput = NO_INPUT;
input.onmidimessage = undefined;
console.log(`%cDisconnected from %c${input.name}`,
consoleColors.info,
Expand All @@ -82,6 +95,7 @@ export class MIDIDeviceHandler

disconnectAllDevicesFromSynth()
{
this.selectedInput = NO_INPUT;
for(const i of this.inputs)
{
i[1].onmidimessage = undefined;
Expand Down
2 changes: 1 addition & 1 deletion src/spessasynth_lib/synthetizer/synthetizer.js
Original file line number Diff line number Diff line change
Expand Up @@ -645,7 +645,7 @@ export class Synthetizer {

/**
* sends a raw MIDI message to the synthesizer
* @param message {Array<number>} the midi message, each number is a byte
* @param message {ArrayLike<number>} the midi message, each number is a byte
*/
sendMessage(message)
{
Expand Down
41 changes: 39 additions & 2 deletions src/website/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,13 @@ fetch("soundfonts").then(async r => {
for(let sf of soundFonts)
{
const option = document.createElement("option");
option.innerText = sf.name;
option.value = sf.name;
let displayName = sf.name
if(displayName.length > 20)
{
displayName = displayName.substring(0, 21) + "...";
}
option.innerText = displayName;
sfSelector.appendChild(option);
}

Expand Down Expand Up @@ -277,4 +283,35 @@ fetch("soundfonts").then(async r => {
}
startMidi(fileInput.files);
};
})
});

/**
* saves the settings (settings.js) selected data to config.json
* (only on local edition that's why it's here and not in the demo_main.js)
* @param settingsData {Object}
*/
function saveSettings(settingsData)
{
fetch("/savesettings", {
method: "POST",
body: JSON.stringify(settingsData),
headers: {
"Content-type": "application/json; charset=UTF-8"
}
}).then();
console.log("saved as", settingsData)
}

// expose the function
window.saveSettings = saveSettings;

/**
* reads the settings
* @type {Promise<SavedSettings>}
*/
window.savedSettings = new Promise(resolve => {
fetch("/getsettings").then(response => response.json().then(
parsedSettings => {
resolve(parsedSettings);
}));
});
173 changes: 97 additions & 76 deletions src/website/ui/midi_keyboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,98 @@ export class MidiKeyboard
});
}

/**
* @param midiNote {number}
* @returns {HTMLDivElement}
* @private
*/
_createKey(midiNote)
{
function isBlackNoteNumber(noteNumber) {
let pitchClass = noteNumber % 12;
return pitchClass === 1 || pitchClass === 3 || pitchClass === 6 || pitchClass === 8 || pitchClass === 10;
}
let keyElement = document.createElement("div");
keyElement.classList.add("key");
keyElement.id = `note${midiNote}`;

// MOUSE HANDLING
keyElement.onpointerover = e => {
if(!this.mouseHeld)
{
return
}
e.stopPropagation();

// user note on
this.heldKeys.push(midiNote);
// determine velocity. lower = more velocity
const rect = keyElement.getBoundingClientRect();
const relativeMouseY = e.clientY - rect.top;
const keyHeight = rect.height;
const velocity = Math.floor(relativeMouseY / keyHeight * 127);
this.synth.noteOn(this.channel, midiNote, velocity, this.enableDebugging);
}
keyElement.onpointerdown = e =>
{
e.stopPropagation();
this.mouseHeld = true;
// user note on
this.heldKeys.push(midiNote);
// determine velocity. lower = more velocity
const rect = keyElement.getBoundingClientRect();
const relativeMouseY = e.clientY - rect.top;
const keyHeight = rect.height;
const velocity = Math.floor(relativeMouseY / keyHeight * 127);
this.synth.noteOn(this.channel, midiNote, velocity, this.enableDebugging);
}
keyElement.onpointerout = () => {
// user note off
this.heldKeys.splice(this.heldKeys.indexOf(midiNote), 1);
this.releaseNote(midiNote, this.channel);
this.synth.noteOff(this.channel, midiNote);
};
keyElement.onpointerleave = keyElement.onpointerup;


let isBlack = isBlackNoteNumber(midiNote);
if(isBlack)
{
// short note
keyElement.classList.add("sharp_key");
}
else
{
// long note
keyElement.classList.add("flat_key");
let blackNoteLeft = false;
let blackNoteRight = false;
if(midiNote >= 0)
{
blackNoteLeft = isBlackNoteNumber(midiNote - 1);
}
if(midiNote < 127) {
blackNoteRight = isBlackNoteNumber(midiNote + 1);
}

if(blackNoteRight && blackNoteLeft)
{
keyElement.classList.add("between_sharps");
}
else if(blackNoteLeft)
{
keyElement.classList.add("left_sharp");
}
else if(blackNoteRight)
{
keyElement.classList.add("right_sharp");
}


}
return keyElement;
}

/**
* @private
*/
Expand All @@ -102,84 +194,9 @@ export class MidiKeyboard
*/
this.keyColors = [];
// create keyboard
function isBlackNoteNumber(noteNumber) {
let pitchClass = noteNumber % 12;
return pitchClass === 1 || pitchClass === 3 || pitchClass === 6 || pitchClass === 8 || pitchClass === 10;
}
for (let midiNote = this._keyRange.min; midiNote < this._keyRange.max + 1; midiNote++) {
let keyElement = document.createElement("div");
keyElement.classList.add("key");
keyElement.id = `note${midiNote}`;
keyElement.onpointerover = e => {
if(!this.mouseHeld)
{
return
}

// user note on
this.heldKeys.push(midiNote);
// determine velocity. lower = more velocity
const rect = keyElement.getBoundingClientRect();
const relativeMouseY = e.clientY - rect.top;
const keyHeight = rect.height;
const velocity = Math.floor(relativeMouseY / keyHeight * 127);
this.synth.noteOn(this.channel, midiNote, velocity, this.enableDebugging);
}

keyElement.onpointerdown = e =>
{
// user note on
this.heldKeys.push(midiNote);
// determine velocity. lower = more velocity
const rect = keyElement.getBoundingClientRect();
const relativeMouseY = e.clientY - rect.top;
const keyHeight = rect.height;
const velocity = Math.floor(relativeMouseY / keyHeight * 127);
this.synth.noteOn(this.channel, midiNote, velocity, this.enableDebugging);
}

keyElement.onpointerout = () => {
// user note off
this.heldKeys.splice(this.heldKeys.indexOf(midiNote), 1);
this.releaseNote(midiNote, this.channel);
this.synth.noteOff(this.channel, midiNote);
};
keyElement.onpointerleave = keyElement.onpointerup;
let isBlack = isBlackNoteNumber(midiNote);
if(isBlack)
{
// short note
keyElement.classList.add("sharp_key");
}
else
{
// long note
keyElement.classList.add("flat_key");
let blackNoteLeft = false;
let blackNoteRight = false;
if(midiNote >= 0)
{
blackNoteLeft = isBlackNoteNumber(midiNote - 1);
}
if(midiNote < 127) {
blackNoteRight = isBlackNoteNumber(midiNote + 1);
}

if(blackNoteRight && blackNoteLeft)
{
keyElement.classList.add("between_sharps");
}
else if(blackNoteLeft)
{
keyElement.classList.add("left_sharp");
}
else if(blackNoteRight)
{
keyElement.classList.add("right_sharp");
}


}
const keyElement = this._createKey(midiNote);
this.keyColors.push([]);
this.keyboard.appendChild(keyElement);
this.keys.push(keyElement);
Expand Down Expand Up @@ -246,6 +263,10 @@ export class MidiKeyboard
*/
selectChannel(channel)
{
if(channel >= this.synth.midiChannels.length)
{
channel = 0;
}
this.channel = channel;
}

Expand Down
Loading

0 comments on commit b3af371

Please sign in to comment.