diff --git a/app/renderer/editor.js b/app/renderer/editor.js index 3820615..8a5f9ed 100644 --- a/app/renderer/editor.js +++ b/app/renderer/editor.js @@ -3,8 +3,8 @@ //would like to use same listeners but with some extra parameters to identify //which sound/program was being edited. //user sets these. all midi functions must use them. -var midiIn -var midiOut +var midiIn = -1 +var midiOut = -1 var isMidiConfigured = false var isEditorLoaded = false @@ -15,6 +15,7 @@ var currentSound = -1 var currentBank = "empty" //range 1 -4 var program = 1 +var isLowerProgram = true //track editor changes var isDirty = false //default values. range from 0- 6; 0 is for relaod. @@ -192,6 +193,7 @@ function updateMode(trigger) { function loadEditorFromDump() { //since from a dump, the editor has no changes setDirtyFlag(false) + isEditorLoaded = true loadEditor() } @@ -199,6 +201,16 @@ function loadEditorFromDump() { * Load the UI editor with data from the program selected or just loaded from mirage. */ function loadEditor() { + + //check if editor is loaded or not (can't load editor unless midi also configured) + if (!isEditorLoaded) { + //reset UI to default value + document.getElementById("program").value = program + //pop warning + window.alert("Please load a sound to edit first.") + return + } + //just changing the program does not change if dirty or not (unless I switch to tracking at program level vice globally) program = parseInt(document.getElementById("program").value) //get program info from allPrograms (since already loaded from Mirage and in sync)s) @@ -277,13 +289,6 @@ function setDirtyFlag(status) { function configureMidi() { //load the midi ports into the UI window.api.send('getMidiPorts') - isMidiConfigured = true - //enable UI to use save button and selectors - document.getElementById("program").removeAttribute('disabled') - document.getElementById("savesoundbank").removeAttribute('disabled') - document.getElementById("savesound").removeAttribute('disabled') - document.getElementById("loadsoundbank").removeAttribute('disabled') - document.getElementById("loadsound").removeAttribute('disabled') } @@ -296,6 +301,7 @@ function loadSound() { var data = new Object() data["midiIn"] = midiIn data["midiOut"] = midiOut + data["isLowerProgram"] = isLowerProgram //0 means reload from current sound and bank without saving if (loadSoundBank != 0) { @@ -342,6 +348,7 @@ function loadSound() { //update internal state variables (a reload does not change these, but regular load will) currentBank = bank currentSound = data["sound"] + isLowerProgram = data["isLower"] //update the savesound option list. Recall you can only save to whatever bank you loaded. var legalBank = document.getElementById("savesoundbank") //remove old options @@ -395,9 +402,29 @@ function selectMidi(direction) { midiOut = document.getElementById("midi_out").value } + if (midiIn > -1 & midiOut > -1) { + //verify mirage comms + verifyComms() + //means user has selected in and out ports; does NOT mean it is correct + isMidiConfigured = true + //enable UI to use save button and selectors + document.getElementById("program").removeAttribute('disabled') + document.getElementById("savesoundbank").removeAttribute('disabled') + document.getElementById("savesound").removeAttribute('disabled') + document.getElementById("loadsoundbank").removeAttribute('disabled') + document.getElementById("loadsound").removeAttribute('disabled') + } } +function verifyComms() { + var data = new Object() + data["midiIn"] = midiIn + data["midiOut"] = midiOut + data["parameter"] = "36" + window.api.send('readParameter', data) +} + /** * This tells the Mirage to save the current sound/programs to disk. It DOES NOT send the program data * since that is already in the Mirage since the UI is in sync with the Mirage. @@ -458,6 +485,32 @@ function showLogs(message){ console.log(message) } + +window.api.receive('parameterValue', (event, args) => { + /* + returns: F0 0F 01 0D 10 25 00 05 F7 + 0d = value requested + 10 = program (program is zero based. Lower 1,2,3,4 = 00, 01, 02, 03; Upper 1,2,3,4 = 10, 11, 12, 13 - note extra bit flipped to mean upper) + + just reading parameter 21 to get a string back that identifies: + 1) did midi comms work + 2) what program and bank is being edited as indicated by byte 4 (0-based) + */ + if (args[4] < 4) { + //lower bank + showLogs(`lower bank ${args[4] + 1} being edited`) + isLowerProgram = true + } + else { + //upper bank + showLogs(`upper bank ${args[4] - 15} being edited`) + isLowerProgram = false + } + + +}) + + /** * Call back for recieving a program dump. Must parse it and SAVE it to all 4 programData objects * and put them into allPrograms. (global soo callback can access them). Note this is coming after a @@ -520,11 +573,16 @@ window.api.receive('midiPorts', (event, arg) => { } //read the inputs + var inputList = document.getElementById("midi_in") + var option = document.createElement("option"); + option.value = -1 + option.text = "select input" + inputList.appendChild(option); for (var i = 0; i < arg["inputs"].length; i++) { //load the dropdown lists - var inputList = document.getElementById("midi_in") //Create and append the options - var option = document.createElement("option"); + option = document.createElement("option"); + //I know there is only one 'k' for (var k in arg["inputs"][i]) { option.value = arg["inputs"][i][k] option.text = k @@ -532,10 +590,14 @@ window.api.receive('midiPorts', (event, arg) => { inputList.appendChild(option); } + var outputList = document.getElementById("midi_out") + option = document.createElement("option"); + option.value = -1 + option.text = "select output" + outputList.appendChild(option); //now read the outputs and load for (i = 0; i < arg["outputs"].length; i++) { //load the dropdown lists - var outputList = document.getElementById("midi_out") //Create and append the options option = document.createElement("option"); for (k in arg["outputs"][i]) { diff --git a/main.js b/main.js index 448e913..889e152 100644 --- a/main.js +++ b/main.js @@ -182,6 +182,7 @@ ipcMain.on("saveSound", (event, args) => { let midiIn = args["midiIn"] let midiOut = args["midiOut"] let isLower = args["isLower"] + let isLowerProgram = args["isLowerProgram"] let sound = args["sound"] midiOutput = new midi.Output(); midiInput = new midi.Input(); @@ -197,7 +198,7 @@ ipcMain.on("saveSound", (event, args) => { mainWindow.webContents.send("programDump", Buffer.from(message)); } else { - //other midi received. hmm. + //other midi received. console.log(`data received: ${message}`); } }); @@ -214,7 +215,20 @@ ipcMain.on("saveSound", (event, args) => { var prefix = [240, 15, 1, 1] var suffix = [127, 247] var fullSysex = [...prefix, ...sysex, ...suffix] - console.log(`sending sysex command ${fullSysex}`) + console.log(`sending sysex command loadSound ${fullSysex}`) + midiOutput.sendMessage(fullSysex) + + //now change the program bank to match. Always setting to program 1 after a loadsound + if (isLowerProgram == isLower) { + //no bank change + sysex = [0, 1 ] + } + else { + //bank change + sysex = [0, 0, 1] + } + fullSysex = [...prefix, ...sysex, ...suffix] + console.log(`sending sysex command changeProgram ${fullSysex}`) midiOutput.sendMessage(fullSysex) midiOutput.closePort() }) @@ -223,29 +237,46 @@ ipcMain.on("saveSound", (event, args) => { ipcMain.on("readParameter", (event, args) => { /** data["midiIn"] = midiIn data["midiOut"] = midiOut - data["isLower"] = isLower - data["sound"] = sound - data["programs"] = program data["parameter"] = parameter - send syex to Mirage to read a parameter*/ - //need parameters as two digits- decimal integers - let d1 = parseInt(args["parameter"].charAt[0]) - let d2 = parseInt(args["parameter"].charAt[1]) - //the command means (12) for parameter d1d2 (13) read the value (since none is given) - sendSysex(args["midiIn"], args["midiOut"], [12, d1, d2, 13] ) + let d1 = parseInt(args["parameter"].charAt(0)) + let d2 = parseInt(args["parameter"].charAt(1)) + // Set up a new output. + midiOutput = new midi.Output(); + midiInput = new midi.Input(); + // Configure a callback. + midiInput.on('message', (deltaTime, message) => { + mainWindow.webContents.send("parameterValue", Buffer.from(message)); + console.log(`readParameter received: ${message} d: ${deltaTime}`); + midiInput.closePort() + }); + + midiInput.openPort(parseInt(args["midiIn"])); + //turn on listening for sysex messages (ignores timing and active sensing) + midiInput.ignoreTypes(false, true, true); + midiOutput.openPort(parseInt(args["midiOut"])); + //the command means (12) for parameter d1d2 (13) read the value (since none is given) + //f0 0f 01 01 0c 03 07 0d 7f f7 + let sx = [240, 15, 1, 1, 12, d1, d2, 13, 127, 247] + console.log(`sending readParameter sysex ${sx}`) + midiOutput.sendMessage(sx) + // Close the port when done. + midiOutput.closePort(); }) + /** + * since setting the program bank in the loadSound command, this command NEVER has to change the bank, + * simplifying the logic. + */ ipcMain.on("changeProgram", (event, args) => { /** data["midiIn"] = midiIn data["midiOut"] = midiOut data["program"] = program */ - - //the command is simply prog X. returns 07 X - sendSysex(args["midiIn"], args["midiOut"], [0, args["program"] ] ) + console.log(`sending changeProgram sysex; changing to program ${args["program"]}`) + sendSysex(args["midiIn"], args["midiOut"], [0, args["program"] ] ) }) @@ -306,7 +337,7 @@ ipcMain.on("changeProgram", (event, args) => { //now send it. we only send a single up or down arrow at a time midiOutput.sendMessage(fullSysex) - console.log(`sent ${fullSysex}`) + console.log(`send writeParameter ${fullSysex}`) //close output and input midiOutput.closePort() //closing here since multiple messages were sent and there may be several callbacks diff --git a/package-lock.json b/package-lock.json index 1299f62..240b27d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "wavsyn", - "version": "1.0.5", + "version": "1.0.7", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "wavsyn", - "version": "1.0.5", + "version": "1.0.7", "license": "MIT", "dependencies": { "electron-log": "^4.3.5", diff --git a/package.json b/package.json index aececcf..8629ca6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wavsyn", - "version": "1.0.6", + "version": "1.0.7", "description": "Tools for creating disk images and editing sounds on the Ensoniq Mirage", "main": "main.js", "scripts": {