Skip to content

Commit

Permalink
feat: basic midi event listeners
Browse files Browse the repository at this point in the history
  • Loading branch information
dicagno committed Jan 1, 2025
1 parent 45c817f commit 8a6b1f6
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 107 deletions.
78 changes: 1 addition & 77 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
# Created by https://www.toptal.com/developers/gitignore/api/webstorm+iml,node,macos,dotenv
# Edit at https://www.toptal.com/developers/gitignore?templates=webstorm+iml,node,macos,dotenv

### dotenv ###
.env

Expand Down Expand Up @@ -181,86 +178,13 @@ dist
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839

# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf

# AWS User-specific
.idea/**/aws.xml

# Generated files
.idea/**/contentModel.xml

# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml

# Gradle
.idea/**/gradle.xml
.idea/**/libraries

# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
.idea

# CMake
cmake-build-*/

# Mongo Explorer plugin
.idea/**/mongoSettings.xml

# File-based project format
*.iws

# IntelliJ
out/

# mpeltonen/sbt-idea plugin
.idea_modules/

# JIRA plugin
atlassian-ide-plugin.xml

# Cursive Clojure plugin
.idea/replstate.xml

# SonarLint plugin
.idea/sonarlint/

# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties

# Editor-based Rest Client
.idea/httpRequests

# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser

### WebStorm+iml Patch ###
# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023

*.iml
modules.xml
.idea/misc.xml
*.ipr

# End of https://www.toptal.com/developers/gitignore/api/webstorm+iml,node,macos,dotenv
8 changes: 0 additions & 8 deletions .idea/.gitignore

This file was deleted.

6 changes: 0 additions & 6 deletions .idea/vcs.xml

This file was deleted.

5 changes: 3 additions & 2 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@
</head>
<body>
<h1>Web MIDI Example</h1>
<button id="connectBtn">Connect MIDI Device</button>
<button id="startSequenceBtn">StartSequence</button>
<button class="connect">Connect MIDI Device</button>
<button class="startSequence">StartSequence</button>
<button class="stopSequence">StopSequence</button>

<script src="main.js"></script>
</body>
Expand Down
51 changes: 37 additions & 14 deletions main.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
let launchpads = [];
window.launchpads = [];
window.isRunning = false;
window.mode = 2;

// reference: https://fael-downloads-prod.focusrite.com/customer/prod/downloads/launchpad-programmers-reference.pdf
const LED_VALUES = {
Expand Down Expand Up @@ -30,10 +32,12 @@ document.addEventListener('DOMContentLoaded', () => {
// Check if Web MIDI is supported
if (navigator.requestMIDIAccess) {
// Prompt the user to connect a MIDI device
const connectBtn = document.getElementById('connectBtn');
const startSequenceBtn = document.getElementById('startSequenceBtn');
const connectBtn = document.querySelector('button.connect');
const startSequenceBtn = document.querySelector('button.startSequence');
const stopSequenceBtn = document.querySelector('button.stopSequence');
connectBtn.addEventListener('click', connectMIDI);
startSequenceBtn.addEventListener('click', onClick);
startSequenceBtn.addEventListener('click', startSequencer);
stopSequenceBtn.addEventListener('click', stopSequencer);
} else {
console.log('Web MIDI is not supported in this browser.');
}
Expand All @@ -57,39 +61,50 @@ function connectMIDI() {

const stepPos = [0, 0, 0, 0, 0, 0, 0, 0];

async function runSequenceAtRowId([rowFrom, rowTo], color, interval = 100) {
async function runSequenceAtRowId([rowFrom, rowTo], color, interval = 500) {
for (let colId = 0; colId < 8; colId++) {
for (let rowId = rowFrom; rowId <= rowTo; rowId++) {
const row = launchpadMap[rowId];
const midiOutput = launchpads[0].output;
let midiOutput = window.launchpads[0].output;
if (midiOutput.connection === 'closed') {
midiOutput.open();
}
const pixelId = row[colId];
midiOutput.send([0x90, pixelId, color]);
}
await sleep(interval);
for (let rowId = rowFrom; rowId <= rowTo; rowId++) {
const row = launchpadMap[rowId];
const midiOutput = launchpads[0].output;
const midiOutput = window.launchpads[0].output;
const pixelId = row[colId];
midiOutput.send([0x90, pixelId, LED_VALUES.OFF]);
}
}
}

async function onClick() {
for (; ;) {
async function startSequencer() {
while (window.isRunning) {
await runSequenceAtRowId([0, 7], LED_VALUES.RED, 500);
}
}

function stopSequencer() {
window.isRunning = false;
}

function onMIDISuccess(midiAccess) {
const outputs = midiAccess.outputs.values();
const inputs = midiAccess.inputs.values();
let i = 0;
for (let output of outputs) {
console.log(output.name)
console.log(outputs)
console.log(output.name);
console.log(outputs);
if (output.name === 'Launchpad') {
//TODO: add respective input
launchpads.push({output});
const input = Array.from(inputs)[i];
window.launchpads.push({ output, input });
input.addEventListener('midimessage', onMIDIMessage);
}
i++;
}

console.log('MIDI connection established.');
Expand All @@ -102,5 +117,13 @@ function onMIDIFailure(error) {
function onMIDIMessage(event) {
// Handle MIDI messages here
// For example:
console.log('MIDI Message:', event.data);
let midiOutput = window.launchpads[0].output;
if (midiOutput.connection === 'closed') {
midiOutput.open();
}
midiOutput.send([0x90, event.data[1], event.data]);
if(window.mode === 2) {
console.log('output', window.launchpads[0].output);
window.launchpads[0].output.send([0x90, event.data[1], event.data]);
}
}

0 comments on commit 8a6b1f6

Please sign in to comment.