aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDevine Lu Linvega <[email protected]>2019-04-15 09:15:48 +0900
committerDevine Lu Linvega <[email protected]>2019-04-15 09:15:48 +0900
commitc76707358b0819bcd213bb0da2bd680edf35f3e1 (patch)
tree8ab22f91a18234fdcf9f366d289886edd313f545
parentf676fbc8be18cd3c61fdca90904054ee65f596cc (diff)
downloadOrca-c76707358b0819bcd213bb0da2bd680edf35f3e1.tar.gz
Orca-c76707358b0819bcd213bb0da2bd680edf35f3e1.zip
Rebuilt Midi input/outputs
-rw-r--r--desktop/core/io/midi.js154
-rw-r--r--desktop/sources/index.html2
-rw-r--r--desktop/sources/scripts/clock.js8
-rw-r--r--desktop/sources/scripts/lib/controller.js8
4 files changed, 117 insertions, 55 deletions
diff --git a/desktop/core/io/midi.js b/desktop/core/io/midi.js
index 91296cc..9e568df 100644
--- a/desktop/core/io/midi.js
+++ b/desktop/core/io/midi.js
@@ -1,11 +1,11 @@
'use strict'
function Midi (terminal) {
- this.index = 0
- this.devices = []
- this.stack = []
+ this.mode = 0
- this.sendClock = false
+ this.outputs = []
+ this.inputs = []
+ this.stack = []
this.start = function () {
console.info('Midi Starting..')
@@ -16,30 +16,59 @@ function Midi (terminal) {
}
+ this.update = function () {
+ terminal.controller.clearCat('default', 'Midi')
+ terminal.controller.add('default', 'Midi', `Refresh Device List`, () => { terminal.io.midi.setup(); terminal.io.midi.update() })
+
+ terminal.controller.addSpacer('default', 'Midi', 'spacer1')
+
+ // Outputs
+ if (this.outputs.length < 1) {
+ terminal.controller.add('default', 'Midi', `No Midi Outputs`)
+ } else {
+ for (const id in this.outputs) {
+ terminal.controller.add('default', 'Midi', `${this.outputs[id].name} ${terminal.io.midi.outputIndex === parseInt(id) ? ' — Output' : ''}`, () => { terminal.io.midi.selectOutput(id) }, '')
+ }
+ terminal.controller.add('default', 'Midi', `No Output`, () => { terminal.io.midi.selectOutput(-1) }, '')
+ terminal.controller.addSpacer('default', 'Midi', 'spacer2')
+ }
+
+ // Inputs
+ if (this.inputs.length < 1) {
+ terminal.controller.add('default', 'Midi', `No Midi Inputs`)
+ } else {
+ for (const id in this.inputs) {
+ terminal.controller.add('default', 'Midi', `${this.inputs[id].name} ${terminal.io.midi.inputIndex === parseInt(id) ? ' — Input' : ''}`, () => { terminal.io.midi.selectInput(id) }, '')
+ }
+ terminal.controller.add('default', 'Midi', `No Input`, () => { terminal.io.midi.selectInput(-1) }, '')
+ terminal.controller.addSpacer('default', 'Midi', 'spacer1')
+ }
+
+ terminal.controller.commit()
+ }
+
this.run = function () {
- const device = this.device()
this.stack = this.stack.filter((item) => {
const alive = item[4] > 0
const played = item[5]
if (alive !== true) {
- this.trigger(item, device, false)
+ this.trigger(item, false)
} else if (played !== true) {
- this.trigger(item, device, true)
+ this.trigger(item, true)
}
item[4]--
return alive
})
- this.clock(device)
}
- this.trigger = function (item, device, down) {
- if (!device) { console.warn('No midi device!'); return }
+ this.trigger = function (item, down) {
+ if (!this.device()) { console.warn('No midi device!'); return }
const channel = down === true ? 0x90 + item[0] : 0x80 + item[0]
const note = 24 + (item[1] * 12) + item[2]
const velocity = item[3]
- device.send([channel, note, velocity])
+ this.device().send([channel, note, velocity])
item[5] = true
}
@@ -57,36 +86,18 @@ function Midi (terminal) {
}
this.silence = function () {
- const device = this.device()
this.stack = this.stack.filter((item) => {
- this.trigger(item, device, false)
+ this.trigger(item, false)
return false
})
}
- this.update = function () {
- terminal.controller.clearCat('default', 'Midi')
- terminal.controller.add('default', 'Midi', `Refresh Device List`, () => { terminal.io.midi.setup(); terminal.io.midi.update() })
- const devices = terminal.io.midi.list()
- if (devices.length < 1) {
- terminal.controller.add('default', 'Midi', `No Device Available`)
- }
- if (devices.length > 1) {
- terminal.controller.add('default', 'Midi', `Next Device`, () => { terminal.io.midi.next(id) }, 'CmdOrCtrl+Shift+M')
- }
- for (const id in devices) {
- terminal.controller.add('default', 'Midi', `${devices[id].name} ${terminal.io.midi.index === parseInt(id) ? ' — Active' : ''}`, () => { terminal.io.midi.select(id) }, '')
- }
- terminal.controller.add('default', 'Midi', this.sendClock === true ? 'Mute Clock' : 'Send Clock', () => { terminal.io.midi.toggleClock() }, '')
- terminal.controller.commit()
- }
-
// Clock
this.ticks = []
-
- this.clock = function (device) {
- if (!device) { return }
+ // TODO
+ this.sendClock = function () {
+ if (!this.device()) { return }
if (this.sendClock !== true) { return }
const bpm = terminal.clock.speed.value
@@ -95,57 +106,94 @@ function Midi (terminal) {
for (let id = 0; id < 6; id++) {
if (this.ticks[id]) { clearTimeout(this.ticks[id]) }
- this.ticks[id] = setTimeout(() => { device.send([0xF8], 0) }, parseInt(id) * frameFrag)
+ this.ticks[id] = setTimeout(() => { this.device().send([0xF8], 0) }, parseInt(id) * frameFrag)
}
}
- this.toggleClock = function () {
- this.sendClock = !this.sendClock
- this.update()
+ this.count = 0
+ this.started = false
+
+ this.receive = function (msg) {
+ switch (msg.data[0]) {
+ case 0xF8:
+ this.count = (this.count + 1) % 6
+ if (this.count === 0 && this.started) {
+ terminal.clock.tap()
+ }
+ break
+ case 0xFA:
+ console.log('Midi', 'Clock start.')
+ this.started = true
+ break
+ case 0xFC:
+ console.log('Midi', 'Clock stop.')
+ this.started = false
+ break
+ }
}
// Tools
- this.select = function (id) {
- if (!this.devices[id]) { return }
- this.index = parseInt(id)
+ this.selectOutput = function (id) {
+ if (!this.outputs[id]) { return }
+
+ this.outputIndex = id
+
this.update()
- console.log(`Midi Device: ${this.device().name}`)
- return this.device()
+ console.log('Midi', `Output Device: ${this.outputDevice().name}`)
+ }
+
+ this.selectInput = function (id) {
+ if (!this.inputs[id]) { return }
+ if (this.inputDevice()) { this.inputDevice().onmidimessage = null }
+
+ this.inputIndex = id
+ this.inputDevice().onmidimessage = (msg) => { this.receive(msg) }
+
+ this.update()
+ console.log('Midi', `Input Device: ${this.inputDevice().name}`)
}
this.device = function () {
- return this.devices[this.index]
+ return this.outputs[this.outputIndex]
}
- this.list = function () {
- return this.devices
+ this.outputDevice = function () {
+ return this.outputs[this.outputIndex]
}
- this.next = function () {
- this.select((this.index + 1) % this.devices.length)
+ this.inputDevice = function () {
+ return this.inputs[this.inputIndex]
}
// Setup
this.setup = function () {
if (!navigator.requestMIDIAccess) { return }
- this.devices = []
+ this.outputs = []
navigator.requestMIDIAccess({ sysex: false }).then(this.access, (err) => {
console.warn('No Midi', err)
})
}
this.access = function (midiAccess) {
- const iter = midiAccess.outputs.values()
- for (let i = iter.next(); i && !i.done; i = iter.next()) {
- terminal.io.midi.devices.push(i.value)
+ const outputs = midiAccess.outputs.values()
+ for (let i = outputs.next(); i && !i.done; i = outputs.next()) {
+ terminal.io.midi.outputs.push(i.value)
+ }
+ terminal.io.midi.selectOutput(0)
+
+ const inputs = midiAccess.inputs.values()
+ for (let i = inputs.next(); i && !i.done; i = inputs.next()) {
+ terminal.io.midi.inputs.push(i.value)
}
- terminal.io.midi.select(0)
+ terminal.io.midi.selectInput(0)
}
+ // UI
+
this.toString = function () {
- return this.devices.length > 0 ? `${this.devices[this.index].name}` : 'No Midi'
+ return this.outputs.length > 0 ? `${this.outputDevice().name}` : 'No Midi'
}
function clamp (v, min, max) { return v < min ? min : v > max ? max : v }
diff --git a/desktop/sources/index.html b/desktop/sources/index.html
index 7437182..e3532e1 100644
--- a/desktop/sources/index.html
+++ b/desktop/sources/index.html
@@ -55,6 +55,7 @@
terminal.controller.add("default","View","Zoom Out",() => { terminal.modZoom(-0.25) },"CmdOrCtrl+-")
terminal.controller.add("default","View","Zoom Reset",() => { terminal.modZoom(1,true) },"CmdOrCtrl+0")
terminal.controller.add("default","View","Toggle Retina",() => { terminal.toggleRetina() },"`")
+ terminal.controller.addSpacer('default', 'View', 'commander')
terminal.controller.add("default","View","Toggle Commander",() => { terminal.commander.start() },"CmdOrCtrl+K")
terminal.controller.add("default","View","Run Commander",() => { terminal.commander.run() },"Enter")
@@ -64,6 +65,7 @@
terminal.controller.add("default","Theme","Open Theme",() => { terminal.theme.open() },"CmdOrCtrl+Shift+O")
terminal.controller.add("default","Theme","Reset Theme",() => { terminal.theme.reset() },"CmdOrCtrl+Shift+Backspace")
+ terminal.controller.addSpacer('default', 'Theme', 'Download')
terminal.controller.add("default","Theme","Download Themes..",() => { require('electron').shell.openExternal('https://github.com/hundredrabbits/Themes') })
terminal.controller.commit()
diff --git a/desktop/sources/scripts/clock.js b/desktop/sources/scripts/clock.js
index fe6f9e3..6607fcf 100644
--- a/desktop/sources/scripts/clock.js
+++ b/desktop/sources/scripts/clock.js
@@ -47,19 +47,23 @@ function Clock (terminal) {
this.play = function () {
if (!this.isPaused) { console.warn('Already playing'); return }
- console.log('Play')
+ console.log('Clock', 'Play')
this.isPaused = false
this.set(this.speed.target, this.speed.target, true)
}
this.stop = function () {
if (this.isPaused) { console.warn('Already stopped'); return }
- console.log('Stop')
+ console.log('Clock', 'Stop')
terminal.io.midi.silence()
this.isPaused = true
this.clearTimer()
}
+ this.tap = function () {
+ console.log('Clock', 'Tapped..')
+ }
+
// Timer
this.clearTimer = function () {
diff --git a/desktop/sources/scripts/lib/controller.js b/desktop/sources/scripts/lib/controller.js
index 3140e49..cc6dfef 100644
--- a/desktop/sources/scripts/lib/controller.js
+++ b/desktop/sources/scripts/lib/controller.js
@@ -24,6 +24,12 @@ function Controller () {
this.menu[mode][cat][label] = { role: label }
}
+ this.addSpacer = function (mode, cat, label, type = 'separator') {
+ if (!this.menu[mode]) { this.menu[mode] = {} }
+ if (!this.menu[mode][cat]) { this.menu[mode][cat] = {} }
+ this.menu[mode][cat][label] = { type: type }
+ }
+
this.clearCat = function (mode, cat) {
if (this.menu[mode]) { this.menu[mode][cat] = {} }
}
@@ -42,6 +48,8 @@ function Controller () {
const option = m[cat][name]
if (option.role) {
submenu.push({ role: option.role })
+ } else if (option.type) {
+ submenu.push({ type: option.type })
} else {
submenu.push({ label: name, accelerator: option.accelerator, click: option.fn })
}