diff options
68 files changed, 1298 insertions, 1529 deletions
diff --git a/browser/mock/buffer.js b/browser/mock/buffer.js deleted file mode 100644 index 5aa0b69..0000000 --- a/browser/mock/buffer.js +++ /dev/null @@ -1,3 +0,0 @@ -export default class Buffer { - static from (str) { return str } -} diff --git a/browser/mock/dgram.js b/browser/mock/dgram.js deleted file mode 100644 index 18ffeb8..0000000 --- a/browser/mock/dgram.js +++ /dev/null @@ -1,10 +0,0 @@ -class Socket { - on () {} - bind () {} - close () {} - send () {} -} - -export function createSocket () { - return new Socket() -} diff --git a/browser/mock/electron.js b/browser/mock/electron.js deleted file mode 100644 index 4b2e8e6..0000000 --- a/browser/mock/electron.js +++ /dev/null @@ -1,5 +0,0 @@ -export let remote = { - app: { - injectMenu () {} - } -} diff --git a/browser/mock/fs.js b/browser/mock/fs.js deleted file mode 100644 index e69de29..0000000 --- a/browser/mock/fs.js +++ /dev/null diff --git a/browser/mock/osc.js b/browser/mock/osc.js deleted file mode 100644 index 7a2906f..0000000 --- a/browser/mock/osc.js +++ /dev/null @@ -1,3 +0,0 @@ -export class Client { - close () {} -} diff --git a/browser/mock/path.js b/browser/mock/path.js deleted file mode 100644 index e69de29..0000000 --- a/browser/mock/path.js +++ /dev/null diff --git a/browser/mock/require.js b/browser/mock/require.js deleted file mode 100644 index 7fcc38b..0000000 --- a/browser/mock/require.js +++ /dev/null @@ -1,19 +0,0 @@ -import * as fs from './fs.js' -import * as path from './path.js' -import * as osc from './osc.js' -import * as electron from './electron.js' -import * as dgram from './dgram.js' - -import Buffer from './buffer.js' -window.Buffer = Buffer - -window.require = function (what) { - switch (what) { - case 'dgram': return dgram; break - case 'fs': return fs; break - case 'path': return path; break - case 'node-osc': return osc; break - case 'electron': return electron; break - default: console.log(what); break - } -} diff --git a/desktop/core/io/udp.js b/desktop/core/io/udp.js deleted file mode 100644 index f438ac5..0000000 --- a/desktop/core/io/udp.js +++ /dev/null @@ -1,72 +0,0 @@ -'use strict' - -const dgram = require('dgram') - -export default function Udp (terminal) { - this.stack = [] - this.port = null - this.options = { default: 49161, orca: 49160 } - - this.start = function () { - console.info('UDP', 'Starting..') - this.select() - } - - this.clear = function () { - this.stack = [] - } - - this.run = function () { - for (const id in this.stack) { - this.play(this.stack[id]) - } - } - - this.push = function (msg) { - this.stack.push(msg) - } - - this.play = function (data) { - this.client.send(Buffer.from(`${data}`), this.port, terminal.io.ip, (err) => { - if (err) { console.warn(err) } - }) - } - - this.select = function (port = this.options.default) { - if (parseInt(port) === this.port) { console.warn('UDP', 'Already selected'); return } - if (isNaN(port) || port < 1000) { console.warn('UDP', 'Unavailable port'); return } - console.info('UDP', `Selected port: ${port}`) - this.port = parseInt(port) - this.update() - } - - this.update = function () { - terminal.controller.clearCat('default', 'UDP') - for (const id in this.options) { - terminal.controller.add('default', 'UDP', `${id.charAt(0).toUpperCase() + id.substr(1)}(${this.options[id]}) ${this.port === this.options[id] ? ' — Active' : ''}`, () => { terminal.io.udp.select(this.options[id]) }, '') - } - terminal.controller.add('default', 'UDP', 'Choose Custom Port', () => { terminal.commander.start('udp:') }, '') - terminal.controller.commit() - } - - this.client = dgram.createSocket('udp4') - this.listener = dgram.createSocket('udp4') - - // Input - - this.listener.on('message', (msg, rinfo) => { - terminal.commander.trigger(`${msg}`, false) - }) - - this.listener.on('listening', () => { - const address = this.listener.address() - console.info('UDP', `Started client at ${address.address}:${address.port}`) - }) - - this.listener.on('error', (err) => { - console.warn('UDP', `Server error:\n ${err.stack}`) - this.listener.close() - }) - - this.listener.bind(49160) -} diff --git a/desktop/core/library.js b/desktop/core/library.js deleted file mode 100644 index 4eb92e0..0000000 --- a/desktop/core/library.js +++ /dev/null @@ -1,86 +0,0 @@ -'use strict' - -import _null from './library/_null.js' -import a from './library/a.js' -import b from './library/b.js' -import c from './library/c.js' -import d from './library/d.js' -import e from './library/e.js' -import f from './library/f.js' -import g from './library/g.js' -import h from './library/h.js' -import i from './library/i.js' -import j from './library/j.js' -import k from './library/k.js' -import l from './library/l.js' -import m from './library/m.js' -import n from './library/n.js' -import o from './library/o.js' -import p from './library/p.js' -import q from './library/q.js' -import r from './library/r.js' -import s from './library/s.js' -import t from './library/t.js' -import u from './library/u.js' -import v from './library/v.js' -import w from './library/w.js' -import x from './library/x.js' -import y from './library/y.js' -import z from './library/z.js' -import _bang from './library/_bang.js' -import _comment from './library/_comment.js' -import _midi from './library/_midi.js' -import _mono from './library/_mono.js' -import _cc from './library/_cc.js' -import _pb from './library/_pb.js' -import _udp from './library/_udp.js' -import _osc from './library/_osc.js' -import _self from './library/_self.js' - -export default { - 0: _null, - 1: _null, - 2: _null, - 3: _null, - 4: _null, - 5: _null, - 6: _null, - 7: _null, - 8: _null, - 9: _null, - a, - b, - c, - d, - e, - f, - g, - h, - i, - j, - k, - l, - m, - n, - o, - p, - q, - r, - s, - t, - u, - v, - w, - x, - y, - z, - '*': _bang, - '#': _comment, - ':': _midi, - '%': _mono, - '!': _cc, - '?': _pb, - ';': _udp, - '=': _osc, - $: _self -} diff --git a/desktop/core/library/_bang.js b/desktop/core/library/_bang.js deleted file mode 100644 index 1599cca..0000000 --- a/desktop/core/library/_bang.js +++ /dev/null @@ -1,16 +0,0 @@ -'use strict' - -import Operator from '../operator.js' - -export default function OperatorBang (orca, x, y, passive) { - Operator.call(this, orca, x, y, '*', true) - - this.name = 'bang' - this.info = 'Bangs neighboring operands' - this.draw = false - - this.run = function (force = false) { - this.draw = false - this.erase() - } -} diff --git a/desktop/core/library/_cc.js b/desktop/core/library/_cc.js deleted file mode 100644 index d70571e..0000000 --- a/desktop/core/library/_cc.js +++ /dev/null @@ -1,32 +0,0 @@ -'use strict' - -import Operator from '../operator.js' - -export default function OperatorCC (orca, x, y) { - Operator.call(this, orca, x, y, '!', true) - - this.name = 'cc' - this.info = 'Sends MIDI control change' - this.ports.channel = { x: 1, y: 0, clamp: { min: 0, max: 15 } } - this.ports.knob = { x: 2, y: 0, clamp: { min: 0 } } - this.ports.value = { x: 3, y: 0, clamp: { min: 0 } } - - this.operation = function (force = false) { - if (!this.hasNeighbor('*') && force === false) { return } - if (this.listen(this.ports.channel) === '.') { return } - if (this.listen(this.ports.knob) === '.') { return } - - const channel = this.listen(this.ports.channel, true) - const knob = this.listen(this.ports.knob, true) - const rawValue = this.listen(this.ports.value, true) - const value = Math.ceil((127 * rawValue) / 35) - - terminal.io.cc.stack.push({ channel, knob, value, type: 'cc' }) - - this.draw = false - - if (force === true) { - terminal.io.cc.run() - } - } -} diff --git a/desktop/core/library/_comment.js b/desktop/core/library/_comment.js deleted file mode 100644 index 8dcf0ae..0000000 --- a/desktop/core/library/_comment.js +++ /dev/null @@ -1,19 +0,0 @@ -'use strict' - -import Operator from '../operator.js' - -export default function OperatorComment (orca, x, y, passive) { - Operator.call(this, orca, x, y, '#', true) - - this.name = 'comment' - this.info = 'Halts line' - this.draw = false - - this.operation = function () { - for (let x = this.x + 1; x <= orca.w; x++) { - orca.lock(x, this.y) - if (orca.glyphAt(x, this.y) === this.glyph) { break } - } - orca.lock(this.x, this.y) - } -} diff --git a/desktop/core/library/_midi.js b/desktop/core/library/_midi.js deleted file mode 100644 index 9fc614a..0000000 --- a/desktop/core/library/_midi.js +++ /dev/null @@ -1,37 +0,0 @@ -'use strict' - -import Operator from '../operator.js' - -export default function OperatorMidi (orca, x, y, passive) { - Operator.call(this, orca, x, y, ':', true) - - this.name = 'midi' - this.info = 'Sends MIDI note' - this.ports.channel = { x: 1, y: 0, clamp: { min: 0, max: 16 } } - this.ports.octave = { x: 2, y: 0, clamp: { min: 0, max: 8 } } - this.ports.note = { x: 3, y: 0 } - this.ports.velocity = { x: 4, y: 0, default: 'f', clamp: { min: 0, max: 16 } } - this.ports.length = { x: 5, y: 0, default: '1', clamp: { min: 0, max: 16 } } - - this.operation = function (force = false) { - if (!this.hasNeighbor('*') && force === false) { return } - if (this.listen(this.ports.channel) === '.') { return } - if (this.listen(this.ports.octave) === '.') { return } - if (this.listen(this.ports.note) === '.') { return } - if (!isNaN(this.listen(this.ports.note))) { return } - - const channel = this.listen(this.ports.channel, true) - const octave = this.listen(this.ports.octave, true) - const note = this.listen(this.ports.note) - const velocity = this.listen(this.ports.velocity, true) - const length = this.listen(this.ports.length, true) - - terminal.io.midi.push(channel, octave, note, velocity, length) - - if (force === true) { - terminal.io.midi.run() - } - - this.draw = false - } -} diff --git a/desktop/core/library/_mono.js b/desktop/core/library/_mono.js deleted file mode 100644 index db9d1fc..0000000 --- a/desktop/core/library/_mono.js +++ /dev/null @@ -1,37 +0,0 @@ -'use strict' - -import Operator from '../operator.js' - -export default function OperatorMono (orca, x, y, passive) { - Operator.call(this, orca, x, y, '%', true) - - this.name = 'mono' - this.info = 'Sends MIDI monophonic note' - this.ports.channel = { x: 1, y: 0, clamp: { min: 0, max: 16 } } - this.ports.octave = { x: 2, y: 0, clamp: { min: 0, max: 8 } } - this.ports.note = { x: 3, y: 0 } - this.ports.velocity = { x: 4, y: 0, default: 'f', clamp: { min: 0, max: 16 } } - this.ports.length = { x: 5, y: 0, default: '1', clamp: { min: 0, max: 16 } } - - this.operation = function (force = false) { - if (!this.hasNeighbor('*') && force === false) { return } - if (this.listen(this.ports.channel) === '.') { return } - if (this.listen(this.ports.octave) === '.') { return } - if (this.listen(this.ports.note) === '.') { return } - if (!isNaN(this.listen(this.ports.note))) { return } - - const channel = this.listen(this.ports.channel, true) - const octave = this.listen(this.ports.octave, true) - const note = this.listen(this.ports.note) - const velocity = this.listen(this.ports.velocity, true) - const length = this.listen(this.ports.length, true) - - terminal.io.mono.push(channel, octave, note, velocity, length) - - if (force === true) { - terminal.io.mono.run() - } - - this.draw = false - } -} diff --git a/desktop/core/library/_null.js b/desktop/core/library/_null.js deleted file mode 100644 index 30dd5c3..0000000 --- a/desktop/core/library/_null.js +++ /dev/null @@ -1,16 +0,0 @@ -'use strict' - -import Operator from '../operator.js' - -export default function OperatorNull (orca, x, y, passive) { - Operator.call(this, orca, x, y, '.', false) - - this.name = 'null' - this.info = 'empty' - - // Overwrite run, to disable draw. - - this.run = function (force = false) { - - } -} diff --git a/desktop/core/library/_osc.js b/desktop/core/library/_osc.js deleted file mode 100644 index 2b7af97..0000000 --- a/desktop/core/library/_osc.js +++ /dev/null @@ -1,36 +0,0 @@ -'use strict' - -import Operator from '../operator.js' - -export default function OperatorOsc (orca, x, y, passive) { - Operator.call(this, orca, x, y, '=', true) - - this.name = 'osc' - this.info = 'Sends OSC message' - - this.ports.path = { x: 1, y: 0 } - - this.operation = function (force = false) { - let msg = '' - for (let x = 2; x <= 36; x++) { - const g = orca.glyphAt(this.x + x, this.y) - orca.lock(this.x + x, this.y) - if (g === '.') { break } - msg += g - } - - if (!this.hasNeighbor('*') && force === false) { return } - if (msg === '') { return } - - const path = this.listen(this.ports.path) - - if (!path || path === '.') { return } - - this.draw = false - terminal.io.osc.push('/' + path, msg) - - if (force === true) { - terminal.io.osc.run() - } - } -} diff --git a/desktop/core/library/_pb.js b/desktop/core/library/_pb.js deleted file mode 100644 index 6b6c96b..0000000 --- a/desktop/core/library/_pb.js +++ /dev/null @@ -1,33 +0,0 @@ -'use strict' - -import Operator from '../operator.js' - -export default function OperatorPB (orca, x, y) { - Operator.call(this, orca, x, y, '?', true) - - this.name = 'cc' - this.info = 'Sends MIDI pitch bend' - this.ports.channel = { x: 1, y: 0, clamp: { min: 0, max: 15 } } - this.ports.lsb = { x: 2, y: 0, clamp: { min: 0 } } - this.ports.msb = { x: 3, y: 0, clamp: { min: 0 } } - - this.operation = function (force = false) { - if (!this.hasNeighbor('*') && force === false) { return } - if (this.listen(this.ports.channel) === '.') { return } - if (this.listen(this.ports.lsb) === '.') { return } - - const channel = this.listen(this.ports.channel, true) - const rawlsb = this.listen(this.ports.lsb, true) - const lsb = Math.ceil((127 * rawlsb) / 35) - const rawmsb = this.listen(this.ports.msb, true) - const msb = Math.ceil((127 * rawmsb) / 35) - - terminal.io.cc.stack.push({ channel, lsb, msb, type: 'pb' }) - - this.draw = false - - if (force === true) { - terminal.io.cc.run() - } - } -} diff --git a/desktop/core/library/_self.js b/desktop/core/library/_self.js deleted file mode 100644 index 67b144e..0000000 --- a/desktop/core/library/_self.js +++ /dev/null @@ -1,26 +0,0 @@ -'use strict' - -import Operator from '../operator.js' - -export default function OperatorSelf (orca, x, y, passive) { - Operator.call(this, orca, x, y, '*', true) - - this.name = 'self' - this.info = 'Send command to itself' - - this.run = function (force = false) { - let msg = '' - for (let x = 1; x <= 36; x++) { - const g = orca.glyphAt(this.x + x, this.y) - orca.lock(this.x + x, this.y) - if (g === '.') { break } - msg += g - } - - if (!this.hasNeighbor('*') && force === false) { return } - if (msg === '') { return } - - this.draw = false - terminal.commander.trigger(`${msg}`) - } -} diff --git a/desktop/core/library/_udp.js b/desktop/core/library/_udp.js deleted file mode 100644 index fd04d24..0000000 --- a/desktop/core/library/_udp.js +++ /dev/null @@ -1,30 +0,0 @@ -'use strict' - -import Operator from '../operator.js' - -export default function OperatorUdp (orca, x, y, passive) { - Operator.call(this, orca, x, y, ';', true) - - this.name = 'udp' - this.info = 'Sends UDP message' - - this.operation = function (force = false) { - let msg = '' - for (let x = 1; x <= 36; x++) { - const g = orca.glyphAt(this.x + x, this.y) - orca.lock(this.x + x, this.y) - if (g === '.') { break } - msg += g - } - - if (!this.hasNeighbor('*') && force === false) { return } - if (msg === '') { return } - - this.draw = false - terminal.io.udp.push(msg) - - if (force === true) { - terminal.io.udp.run() - } - } -} diff --git a/desktop/core/library/a.js b/desktop/core/library/a.js deleted file mode 100644 index c2c66e5..0000000 --- a/desktop/core/library/a.js +++ /dev/null @@ -1,20 +0,0 @@ -'use strict' - -import Operator from '../operator.js' - -export default function OperatorA (orca, x, y, passive) { - Operator.call(this, orca, x, y, 'a', passive) - - this.name = 'add' - this.info = 'Outputs sum of inputs' - - this.ports.a = { x: -1, y: 0 } - this.ports.b = { x: 1, y: 0 } - this.ports.output = { x: 0, y: 1, sensitive: true } - - this.operation = function (force = false) { - const a = this.listen(this.ports.a, true) - const b = this.listen(this.ports.b, true) - return orca.keyOf(a + b) - } -} diff --git a/desktop/core/library/b.js b/desktop/core/library/b.js deleted file mode 100644 index a3bf23a..0000000 --- a/desktop/core/library/b.js +++ /dev/null @@ -1,21 +0,0 @@ -'use strict' - -import Operator from '../operator.js' - -export default function OperatorB (orca, x, y, passive) { - Operator.call(this, orca, x, y, 'b', passive) - - this.name = 'bounce' - this.info = 'Outputs values between inputs' - - this.ports.rate = { x: -1, y: 0, clamp: { min: 1 } } - this.ports.mod = { x: 1, y: 0, default: '8' } - this.ports.output = { x: 0, y: 1, sensitive: true } - - this.operation = function (force = false) { - const rate = this.listen(this.ports.rate, true) - const mod = this.listen(this.ports.mod, true) - 1 - const key = Math.floor(orca.f / rate) % (mod * 2) - return orca.keyOf(key <= mod ? key : mod - (key - mod)) - } -} diff --git a/desktop/core/library/c.js b/desktop/core/library/c.js deleted file mode 100644 index 38dc20e..0000000 --- a/desktop/core/library/c.js +++ /dev/null @@ -1,21 +0,0 @@ -'use strict' - -import Operator from '../operator.js' - -export default function OperatorC (orca, x, y, passive) { - Operator.call(this, orca, x, y, 'c', passive) - - this.name = 'clock' - this.info = 'Outputs modulo of frame' - - this.ports.rate = { x: -1, y: 0, clamp: { min: 1 } } - this.ports.mod = { x: 1, y: 0, default: '8' } - this.ports.output = { x: 0, y: 1, sensitive: true } - - this.operation = function (force = false) { - const rate = this.listen(this.ports.rate, true) - const mod = this.listen(this.ports.mod, true) - const val = Math.floor(orca.f / rate) % mod - return orca.keyOf(val) - } -} diff --git a/desktop/core/library/d.js b/desktop/core/library/d.js deleted file mode 100644 index 90cad15..0000000 --- a/desktop/core/library/d.js +++ /dev/null @@ -1,21 +0,0 @@ -'use strict' - -import Operator from '../operator.js' - -export default function OperatorD (orca, x, y, passive) { - Operator.call(this, orca, x, y, 'd', passive) - - this.name = 'delay' - this.info = 'Bangs on modulo of frame' - - this.ports.rate = { x: -1, y: 0, clamp: { min: 1 } } - this.ports.mod = { x: 1, y: 0, default: '8' } - this.ports.output = { x: 0, y: 1, bang: true } - - this.operation = function (force = false) { - const rate = this.listen(this.ports.rate, true) - const mod = this.listen(this.ports.mod, true) - const res = orca.f % (mod * rate) - return res === 0 || mod === 1 - } -} diff --git a/desktop/core/library/e.js b/desktop/core/library/e.js deleted file mode 100644 index dab6b39..0000000 --- a/desktop/core/library/e.js +++ /dev/null @@ -1,16 +0,0 @@ -'use strict' - -import Operator from '../operator.js' - -export default function OperatorE (orca, x, y, passive) { - Operator.call(this, orca, x, y, 'e', passive) - - this.name = 'east' - this.info = 'Moves eastward, or bangs' - this.draw = false - - this.operation = function () { - this.move(1, 0) - this.passive = false - } -} diff --git a/desktop/core/library/f.js b/desktop/core/library/f.js deleted file mode 100644 index 9566562..0000000 --- a/desktop/core/library/f.js +++ /dev/null @@ -1,20 +0,0 @@ -'use strict' - -import Operator from '../operator.js' - -export default function OperatorF (orca, x, y, passive) { - Operator.call(this, orca, x, y, 'f', passive) - - this.name = 'if' - this.info = 'Bangs if inputs are equal' - - this.ports.a = { x: -1, y: 0 } - this.ports.b = { x: 1, y: 0 } - this.ports.output = { x: 0, y: 1, bang: true } - - this.operation = function (force = false) { - const a = this.listen(this.ports.a) - const b = this.listen(this.ports.b) - return a === b && a !== '.' - } -} diff --git a/desktop/core/library/g.js b/desktop/core/library/g.js deleted file mode 100644 index bc08aef..0000000 --- a/desktop/core/library/g.js +++ /dev/null @@ -1,28 +0,0 @@ -'use strict' - -import Operator from '../operator.js' - -export default function OperatorG (orca, x, y, passive) { - Operator.call(this, orca, x, y, 'g', passive) - - this.name = 'generator' - this.info = 'Writes operands with offset' - - this.ports.x = { x: -3, y: 0 } - this.ports.y = { x: -2, y: 0 } - this.ports.len = { x: -1, y: 0, clamp: { min: 1 } } - - this.operation = function (force = false) { - const len = this.listen(this.ports.len, true) - const x = this.listen(this.ports.x, true) - const y = this.listen(this.ports.y, true) + 1 - for (let offset = 0; offset < len; offset++) { - const inPort = { x: offset + 1, y: 0 } - const outPort = { x: x + offset, y: y, output: true } - this.addPort(`in${offset}`, inPort) - this.addPort(`out${offset}`, outPort) - const res = this.listen(inPort) - this.output(`${res}`, outPort) - } - } -} diff --git a/desktop/core/library/h.js b/desktop/core/library/h.js deleted file mode 100644 index 24b1184..0000000 --- a/desktop/core/library/h.js +++ /dev/null @@ -1,17 +0,0 @@ -'use strict' - -import Operator from '../operator.js' - -export default function OperatorH (orca, x, y, passive) { - Operator.call(this, orca, x, y, 'h', passive) - - this.name = 'halt' - this.info = 'Halts southward operand' - - this.ports.output = { x: 0, y: 1, reader: true } - - this.operation = function (force = false) { - orca.lock(this.x + this.ports.output.x, this.y + this.ports.output.y) - return this.listen(this.ports.output, true) - } -} diff --git a/desktop/core/library/i.js b/desktop/core/library/i.js deleted file mode 100644 index f896f25..0000000 --- a/desktop/core/library/i.js +++ /dev/null @@ -1,21 +0,0 @@ -'use strict' - -import Operator from '../operator.js' - -export default function OperatorI (orca, x, y, passive) { - Operator.call(this, orca, x, y, 'i', passive) - - this.name = 'increment' - this.info = 'Increments southward operand' - - this.ports.step = { x: -1, y: 0, default: '1' } - this.ports.mod = { x: 1, y: 0 } - this.ports.output = { x: 0, y: 1, sensitive: true, reader: true } - - this.operation = function (force = false) { - const step = this.listen(this.ports.step, true) - const mod = this.listen(this.ports.mod, true) - const val = this.listen(this.ports.output, true) - return orca.keyOf((val + step) % (mod > 0 ? mod : 36)) - } -} diff --git a/desktop/core/library/j.js b/desktop/core/library/j.js deleted file mode 100644 index 0c7e68d..0000000 --- a/desktop/core/library/j.js +++ /dev/null @@ -1,18 +0,0 @@ -'use strict' - -import Operator from '../operator.js' - -export default function OperatorJ (orca, x, y, passive) { - Operator.call(this, orca, x, y, 'j', passive) - - this.name = 'jumper' - this.info = 'Outputs northward operand' - - this.ports.val = { x: 0, y: -1 } - this.ports.output = { x: 0, y: 1 } - - this.operation = function (force = false) { - orca.lock(this.x, this.y + 1) - return this.listen(this.ports.val) - } -} diff --git a/desktop/core/library/k.js b/desktop/core/library/k.js deleted file mode 100644 index 0163bb5..0000000 --- a/desktop/core/library/k.js +++ /dev/null @@ -1,27 +0,0 @@ -'use strict' - -import Operator from '../operator.js' - -export default function OperatorK (orca, x, y, passive) { - Operator.call(this, orca, x, y, 'k', passive) - - this.name = 'konkat' - this.info = 'Reads multiple variables' - - this.ports.len = { x: -1, y: 0, clamp: { min: 1 } } - - this.operation = function (force = false) { - this.len = this.listen(this.ports.len, true) - for (let offset = 0; offset < this.len; offset++) { - const key = orca.glyphAt(this.x + offset + 1, this.y) - orca.lock(this.x + offset + 1, this.y) - if (key === '.') { continue } - const inPort = { x: offset + 1, y: 0 } - const outPort = { x: offset + 1, y: 1, output: true } - this.addPort(`in${offset}`, inPort) - this.addPort(`out${offset}`, outPort) - const res = orca.valueIn(key) - this.output(`${res}`, outPort) - } - } -} diff --git a/desktop/core/library/l.js b/desktop/core/library/l.js deleted file mode 100644 index 518c2ec..0000000 --- a/desktop/core/library/l.js +++ /dev/null @@ -1,30 +0,0 @@ -'use strict' - -import Operator from '../operator.js' - -export default function OperatorL (orca, x, y, passive) { - Operator.call(this, orca, x, y, 'l', passive) - - this.name = 'loop' - this.info = 'Moves eastward operands' - - this.ports.step = { x: -2, y: 0, default: '1' } - this.ports.len = { x: -1, y: 0 } - this.ports.val = { x: 1, y: 0 } - this.ports.output = { x: 0, y: 1 } - - this.operation = function (force = false) { - const len = this.listen(this.ports.len, true) - const step = this.listen(this.ports.step, true) - const index = orca.indexAt(this.x + 1, this.y) - const seg = orca.s.substr(index, len) - const res = seg.substr(len - step, step) + seg.substr(0, len - step) - for (let offset = 0; offset <= len; offset++) { - if (offset > 0) { - orca.lock(this.x + offset, this.y) - } - orca.write(this.x + offset + 1, this.y, res.charAt(offset)) - } - return this.listen(this.ports.val) - } -} diff --git a/desktop/core/library/m.js b/desktop/core/library/m.js deleted file mode 100644 index 5986708..0000000 --- a/desktop/core/library/m.js +++ /dev/null @@ -1,20 +0,0 @@ -'use strict' - -import Operator from '../operator.js' - -export default function OperatorM (orca, x, y, passive) { - Operator.call(this, orca, x, y, 'm', passive) - - this.name = 'multiply' - this.info = 'Outputs product of inputs' - - this.ports.a = { x: -1, y: 0 } - this.ports.b = { x: 1, y: 0 } - this.ports.output = { x: 0, y: 1, sensitive: true } - - this.operation = function (force = false) { - const a = this.listen(this.ports.a, true) - const b = this.listen(this.ports.b, true) - return orca.keyOf(a * b) - } -} diff --git a/desktop/core/library/n.js b/desktop/core/library/n.js deleted file mode 100644 index 1f1f290..0000000 --- a/desktop/core/library/n.js +++ /dev/null @@ -1,16 +0,0 @@ -'use strict' - -import Operator from '../operator.js' - -export default function OperatorN (orca, x, y, passive) { - Operator.call(this, orca, x, y, 'n', passive) - - this.name = 'north' - this.info = 'Moves Northward, or bangs' - this.draw = false - - this.operation = function () { - this.move(0, -1) - this.passive = false - } -} diff --git a/desktop/core/library/o.js b/desktop/core/library/o.js deleted file mode 100644 index 7a126ce..0000000 --- a/desktop/core/library/o.js +++ /dev/null @@ -1,21 +0,0 @@ -'use strict' - -import Operator from '../operator.js' - -export default function OperatorO (orca, x, y, passive) { - Operator.call(this, orca, x, y, 'o', passive) - - this.name = 'read' - this.info = 'Reads operand with offset' - - this.ports.x = { x: -2, y: 0 } - this.ports.y = { x: -1, y: 0 } - this.ports.output = { x: 0, y: 1 } - - this.operation = function (force = false) { - const x = this.listen(this.ports.x, true) - const y = this.listen(this.ports.y, true) - this.addPort('read', { x: x + 1, y: y }) - return this.listen(this.ports.read) - } -} diff --git a/desktop/core/library/p.js b/desktop/core/library/p.js deleted file mode 100644 index 2d42745..0000000 --- a/desktop/core/library/p.js +++ /dev/null @@ -1,24 +0,0 @@ -'use strict' - -import Operator from '../operator.js' - -export default function OperatorP (orca, x, y, passive) { - Operator.call(this, orca, x, y, 'p', passive) - - this.name = 'push' - this.info = 'Writes eastward operand' - - this.ports.key = { x: -2, y: 0 } - this.ports.len = { x: -1, y: 0, clamp: { min: 1 } } - this.ports.val = { x: 1, y: 0 } - - this.operation = function (force = false) { - const len = this.listen(this.ports.len, true) - const key = this.listen(this.ports.key, true) - for (let offset = 0; offset < len; offset++) { - orca.lock(this.x + offset, this.y + 1) - } - this.ports.output = { x: (key % len), y: 1 } - return this.listen(this.ports.val) - } -} diff --git a/desktop/core/library/q.js b/desktop/core/library/q.js deleted file mode 100644 index af12331..0000000 --- a/desktop/core/library/q.js +++ /dev/null @@ -1,28 +0,0 @@ -'use strict' - -import Operator from '../operator.js' - -export default function OperatorQ (orca, x, y, passive) { - Operator.call(this, orca, x, y, 'q', passive) - - this.name = 'query' - this.info = 'Reads operands with offset' - - this.ports.x = { x: -3, y: 0 } - this.ports.y = { x: -2, y: 0 } - this.ports.len = { x: -1, y: 0, clamp: { min: 1 } } - - this.operation = function (force = false) { - const len = this.listen(this.ports.len, true) - const x = this.listen(this.ports.x, true) - const y = this.listen(this.ports.y, true) - for (let offset = 0; offset < len; offset++) { - const inPort = { x: x + offset + 1, y: y } - const outPort = { x: offset - len + 1, y: 1, output: true } - this.addPort(`in${offset}`, inPort) - this.addPort(`out${offset}`, outPort) - const res = this.listen(inPort) - this.output(`${res}`, outPort) - } - } -} diff --git a/desktop/core/library/r.js b/desktop/core/library/r.js deleted file mode 100644 index 591717a..0000000 --- a/desktop/core/library/r.js +++ /dev/null @@ -1,21 +0,0 @@ -'use strict' - -import Operator from '../operator.js' - -export default function OperatorR (orca, x, y, passive) { - Operator.call(this, orca, x, y, 'r', passive) - - this.name = 'random' - this.info = 'Outputs random value' - - this.ports.min = { x: -1, y: 0 } - this.ports.max = { x: 1, y: 0 } - this.ports.output = { x: 0, y: 1, sensitive: true } - - this.operation = function (force = false) { - const min = this.listen(this.ports.min, true) - const max = this.listen(this.ports.max, true) - const val = parseInt((Math.random() * ((max > 0 ? max : 36) - min)) + min) - return orca.keyOf(val) - } -} diff --git a/desktop/core/library/s.js b/desktop/core/library/s.js deleted file mode 100644 index 0c13a28..0000000 --- a/desktop/core/library/s.js +++ /dev/null @@ -1,16 +0,0 @@ -'use strict' - -import Operator from '../operator.js' - -export default function OperatorS (orca, x, y, passive) { - Operator.call(this, orca, x, y, 's', passive) - - this.name = 'south' - this.info = 'Moves southward, or bangs' - this.draw = false - - this.operation = function () { - this.move(0, 1) - this.passive = false - } -} diff --git a/desktop/core/library/t.js b/desktop/core/library/t.js deleted file mode 100644 index 0e51cfe..0000000 --- a/desktop/core/library/t.js +++ /dev/null @@ -1,24 +0,0 @@ -'use strict' - -import Operator from '../operator.js' - -export default function OperatorT (orca, x, y, passive) { - Operator.call(this, orca, x, y, 't', passive) - - this.name = 'track' - this.info = 'Reads eastward operand' - - this.ports.key = { x: -2, y: 0 } - this.ports.len = { x: -1, y: 0, clamp: { min: 1 } } - this.ports.output = { x: 0, y: 1 } - - this.operation = function (force = false) { - const len = this.listen(this.ports.len, true) - const key = this.listen(this.ports.key, true) - for (let offset = 0; offset < len; offset++) { - orca.lock(this.x + offset + 1, this.y) - } - this.ports.val = { x: (key % len) + 1, y: 0 } - return this.listen(this.ports.val) - } -} diff --git a/desktop/core/library/u.js b/desktop/core/library/u.js deleted file mode 100644 index 4dc50e2..0000000 --- a/desktop/core/library/u.js +++ /dev/null @@ -1,21 +0,0 @@ -'use strict' - -import Operator from '../operator.js' - -export default function OperatorU (orca, x, y, passive) { - Operator.call(this, orca, x, y, 'u', passive) - - this.name = 'uclid' - this.info = 'Bangs on Euclidean rhythm' - - this.ports.step = { x: -1, y: 0, clamp: { min: 0 }, default: '1' } - this.ports.max = { x: 1, y: 0, clamp: { min: 1 }, default: '8' } - this.ports.output = { x: 0, y: 1, bang: true } - - this.operation = function (force = false) { - const step = this.listen(this.ports.step, true) - const max = this.listen(this.ports.max, true) - const bucket = (step * (orca.f + max - 1)) % max + step - return bucket >= max - } -} diff --git a/desktop/core/library/v.js b/desktop/core/library/v.js deleted file mode 100644 index 187a5cd..0000000 --- a/desktop/core/library/v.js +++ /dev/null @@ -1,26 +0,0 @@ -'use strict' - -import Operator from '../operator.js' - -export default function OperatorV (orca, x, y, passive) { - Operator.call(this, orca, x, y, 'v', passive) - - this.name = 'variable' - this.info = 'Reads and writes variable' - - this.ports.write = { x: -1, y: 0 } - this.ports.read = { x: 1, y: 0 } - - this.operation = function (force = false) { - const write = this.listen(this.ports.write) - const read = this.listen(this.ports.read) - if (write === '.' && read !== '.') { - this.addPort('output', { x: 0, y: 1 }) - } - if (write !== '.') { - orca.variables[write] = read - return - } - return orca.valueIn(read) - } -} diff --git a/desktop/core/library/w.js b/desktop/core/library/w.js deleted file mode 100644 index aae8615..0000000 --- a/desktop/core/library/w.js +++ /dev/null @@ -1,16 +0,0 @@ -'use strict' - -import Operator from '../operator.js' - -export default function OperatorW (orca, x, y, passive) { - Operator.call(this, orca, x, y, 'w', passive) - - this.name = 'west' - this.info = 'Moves westward, or bangs' - this.draw = false - - this.operation = function () { - this.move(-1, 0) - this.passive = false - } -} diff --git a/desktop/core/library/x.js b/desktop/core/library/x.js deleted file mode 100644 index 1230d8a..0000000 --- a/desktop/core/library/x.js +++ /dev/null @@ -1,21 +0,0 @@ -'use strict' - -import Operator from '../operator.js' - -export default function OperatorX (orca, x, y, passive) { - Operator.call(this, orca, x, y, 'x', passive) - - this.name = 'write' - this.info = 'Writes operand with offset' - - this.ports.x = { x: -2, y: 0 } - this.ports.y = { x: -1, y: 0 } - this.ports.val = { x: 1, y: 0 } - - this.operation = function (force = false) { - const x = this.listen(this.ports.x, true) - const y = this.listen(this.ports.y, true) + 1 - this.addPort('output', { x: x, y: y }) - return this.listen(this.ports.val) - } -} diff --git a/desktop/core/library/y.js b/desktop/core/library/y.js deleted file mode 100644 index a0ae7c9..0000000 --- a/desktop/core/library/y.js +++ /dev/null @@ -1,18 +0,0 @@ -'use strict' - -import Operator from '../operator.js' - -export default function OperatorY (orca, x, y, passive) { - Operator.call(this, orca, x, y, 'y', passive) - - this.name = 'jymper' - this.info = 'Outputs westward operand' - - this.ports.val = { x: -1, y: 0 } - this.ports.output = { x: 1, y: 0 } - - this.operation = function (force = false) { - orca.lock(this.x + 1, this.y) - return this.listen(this.ports.val) - } -} diff --git a/desktop/core/library/z.js b/desktop/core/library/z.js deleted file mode 100644 index b91cde4..0000000 --- a/desktop/core/library/z.js +++ /dev/null @@ -1,22 +0,0 @@ -'use strict' - -import Operator from '../operator.js' - -export default function OperatorZ (orca, x, y, passive) { - Operator.call(this, orca, x, y, 'z', passive) - - this.name = 'lerp' - this.info = 'Transitions operand to target' - - this.ports.rate = { x: -1, y: 0, default: '1' } - this.ports.target = { x: 1, y: 0 } - this.ports.output = { x: 0, y: 1, sensitive: true, reader: true } - - this.operation = function (force = false) { - const rate = this.listen(this.ports.rate, true) - const target = this.listen(this.ports.target, true) - const val = this.listen(this.ports.output, true) - const mod = val <= target - rate ? rate : val >= target + rate ? -rate : target - val - return orca.keyOf(val + mod) - } -} diff --git a/desktop/main.js b/desktop/main.js index b0017b6..ecedde7 100644 --- a/desktop/main.js +++ b/desktop/main.js @@ -1,32 +1,20 @@ -const { app, BrowserWindow, webFrame, Menu } = require('electron') -const path = require('path') +'use strict' -require('electron').protocol.registerSchemesAsPrivileged([ - { scheme: 'js', privileges: { standard: true, secure: true } } -]) +/* global createWindow */ -function protocolHandler (request, respond) { - try { - const pathname = request.url.replace(/^js:\/*/, '') - const filename = path.resolve(app.getAppPath(), pathname) - respond({ mimeType: 'text/javascript', data: require('fs').readFileSync(filename) }) - } catch (e) { - console.error(e, request) - } -} +const { app, BrowserWindow, Menu } = require('electron') +const path = require('path') let isShown = true app.win = null app.on('ready', () => { - require('electron').protocol.registerBufferProtocol('js', protocolHandler) - app.win = new BrowserWindow({ - width: 710, - height: 470, - minWidth: 310, - minHeight: 350, + width: 780, + height: 462, + minWidth: 380, + minHeight: 360, backgroundColor: '#000', icon: path.join(__dirname, { darwin: 'icon.icns', linux: 'icon.png', win32: 'icon.ico' }[process.platform] || 'icon.ico'), resizable: true, @@ -37,10 +25,9 @@ app.on('ready', () => { }) app.win.loadURL(`file://${__dirname}/sources/index.html`) - // app.inspect() + app.inspect() app.win.on('closed', () => { - win = null app.quit() }) @@ -69,19 +56,19 @@ app.inspect = function () { app.win.toggleDevTools() } -app.toggleMenubar = function () { - app.win.setMenuBarVisibility(!app.win.isMenuBarVisible()) -} - app.toggleFullscreen = function () { app.win.setFullScreen(!app.win.isFullScreen()) } +app.toggleMenubar = function () { + app.win.setMenuBarVisibility(!app.win.isMenuBarVisible()) +} + app.toggleVisible = function () { - if (process.platform === 'darwin') { - if (isShown && !app.win.isFullScreen()) { app.win.hide() } else { app.win.show() } - } else { + if (process.platform === 'win32') { if (!app.win.isMinimized()) { app.win.minimize() } else { app.win.restore() } + } else { + if (isShown && !app.win.isFullScreen()) { app.win.hide() } else { app.win.show() } } } diff --git a/desktop/sources/index.html b/desktop/sources/index.html index 2f4d665..d2d361c 100644 --- a/desktop/sources/index.html +++ b/desktop/sources/index.html @@ -1,26 +1,38 @@ -<!DOCTYPE html> -<html lang='en'> +<html> <head> <meta charset='utf-8'> <link rel="stylesheet" type="text/css" href="links/style.css"/> + <script type="text/javascript" src="scripts/lib/acels.js"></script> + <script type="text/javascript" src="scripts/lib/theme.js"></script> + <script type="text/javascript" src="scripts/lib/history.js"></script> + <script type="text/javascript" src="scripts/core/library.js"></script> + <script type="text/javascript" src="scripts/core/io.js"></script> + <script type="text/javascript" src="scripts/core/operator.js"></script> + <script type="text/javascript" src="scripts/core/orca.js"></script> + <script type="text/javascript" src="scripts/core/transpose.js"></script> + <script type="text/javascript" src="scripts/core/io/cc.js"></script> + <script type="text/javascript" src="scripts/core/io/midi.js"></script> + <script type="text/javascript" src="scripts/core/io/mono.js"></script> + <script type="text/javascript" src="scripts/core/io/osc.js"></script> + <script type="text/javascript" src="scripts/core/io/udp.js"></script> + <script type="text/javascript" src="scripts/clock.js"></script> + <script type="text/javascript" src="scripts/commander.js"></script> + <script type="text/javascript" src="scripts/cursor.js"></script> + <script type="text/javascript" src="scripts/source.js"></script> + <script type="text/javascript" src="scripts/terminal.js"></script> <title>Orca</title> </head> <body> - <script type="module"> + <script> 'use strict' - - console.clear() - - import Terminal from "js:./sources/scripts/terminal.js"; const terminal = new Terminal() - window.terminal = terminal // global availability for e.g. udp - terminal.install(document.body) window.addEventListener('load', () => { - terminal.start(); + terminal.start() + terminal.acels.inject('Orca') }) </script> </body> diff --git a/desktop/sources/scripts/clock.js b/desktop/sources/scripts/clock.js index 9baecd8..a1d1bc1 100644 --- a/desktop/sources/scripts/clock.js +++ b/desktop/sources/scripts/clock.js @@ -1,6 +1,10 @@ 'use strict' -export default function Clock (terminal) { +/* global Blob */ + +function Clock (terminal) { + const worker = 'onmessage = (e) => { setInterval(() => { postMessage(true) }, e.data)}' + this.isPaused = true this.timer = null this.isPuppet = false @@ -50,7 +54,7 @@ export default function Clock (terminal) { this.play = function (msg = false) { console.log('Clock', 'Play') - if (this.isPaused === false) { console.warn('Clock', 'Already playing'); return } + if (this.isPaused === false) { return } if (this.isPuppet === true) { console.warn('Clock', 'External Midi control'); return } this.isPaused = false if (msg === true) { terminal.io.midi.sendClockStart() } @@ -105,9 +109,12 @@ export default function Clock (terminal) { this.setTimer = function (bpm) { console.log('Clock', 'New Timer ' + bpm + 'bpm') this.clearTimer() - this.timer = new Worker(`${__dirname}/scripts/timer.js`) + this.timer = new Worker(window.URL.createObjectURL(new Blob([worker], { type: 'text/javascript' }))) this.timer.postMessage((60000 / bpm) / 4) - this.timer.onmessage = (event) => { terminal.io.midi.sendClock(); terminal.run() } + this.timer.onmessage = (event) => { + terminal.io.midi.sendClock() + terminal.run() + } } this.clearTimer = function () { diff --git a/desktop/sources/scripts/commander.js b/desktop/sources/scripts/commander.js index 4fd4372..f1ceb93 100644 --- a/desktop/sources/scripts/commander.js +++ b/desktop/sources/scripts/commander.js @@ -1,6 +1,6 @@ 'use strict' -export default function Commander (terminal) { +function Commander (terminal) { this.isActive = false this.query = '' this.history = [] @@ -72,13 +72,16 @@ export default function Commander (terminal) { // Begin - this.start = function (q = '') { + this.start = (q = '') => { + document.onkeydown = (event) => { this.onKeyDown(event) } + document.onkeyup = (event) => { this.onKeyUp(event) } + this.isActive = true this.query = q terminal.update() } - this.stop = function () { + this.stop = () => { this.isActive = false this.query = '' this.historyIndex = this.history.length @@ -90,8 +93,10 @@ export default function Commander (terminal) { this.preview() } - this.write = function (key) { - if (key.length !== 1) { return } + this.write = (key) => { + if (key === 'Backspace') { this.erase(); return } + if (key === 'Enter') { this.run(); return } + if (key === 'Escape') { this.stop(); return } this.query += key this.preview() } @@ -124,123 +129,16 @@ export default function Commander (terminal) { // Events - this.onKeyDown = function (event) { - // Reset - if ((event.metaKey || event.ctrlKey) && event.key === 'Backspace') { - terminal.reset() - event.preventDefault() - return - } - - if (event.keyCode === 191 && (event.metaKey || event.ctrlKey)) { terminal.cursor.comment(); event.preventDefault(); return } - - // Copy/Paste - if (event.keyCode === 67 && (event.metaKey || event.ctrlKey)) { terminal.cursor.copy(); event.preventDefault(); return } - if (event.keyCode === 88 && (event.metaKey || event.ctrlKey)) { terminal.cursor.cut(); event.preventDefault(); return } - if (event.keyCode === 86 && (event.metaKey || event.ctrlKey) && event.shiftKey) { terminal.cursor.paste(true); event.preventDefault(); return } - if (event.keyCode === 86 && (event.metaKey || event.ctrlKey)) { terminal.cursor.paste(false); event.preventDefault(); return } - if (event.keyCode === 65 && (event.metaKey || event.ctrlKey)) { terminal.cursor.selectAll(); event.preventDefault(); return } - - // Undo/Redo - if (event.keyCode === 90 && (event.metaKey || event.ctrlKey) && event.shiftKey) { terminal.history.redo(); event.preventDefault(); return } - if (event.keyCode === 90 && (event.metaKey || event.ctrlKey)) { terminal.history.undo(); event.preventDefault(); return } - - if (event.keyCode === 38) { this.onArrowUp(event.shiftKey, (event.metaKey || event.ctrlKey), event.altKey); return } - if (event.keyCode === 40) { this.onArrowDown(event.shiftKey, (event.metaKey || event.ctrlKey), event.altKey); return } - if (event.keyCode === 37) { this.onArrowLeft(event.shiftKey, (event.metaKey || event.ctrlKey), event.altKey); return } - if (event.keyCode === 39) { this.onArrowRight(event.shiftKey, (event.metaKey || event.ctrlKey), event.altKey); return } - - if (event.keyCode === 9) { terminal.toggleHardmode(); event.preventDefault(); return } - - if (event.metaKey) { return } - if (event.ctrlKey) { return } - - if (event.key === ' ' && terminal.cursor.mode === 0) { terminal.clock.togglePlay(event.shiftKey); event.preventDefault(); return } - if (event.key === ' ' && terminal.cursor.mode === 1) { terminal.cursor.move(1, 0); event.preventDefault(); return } - - if (event.key === 'Escape') { terminal.toggleGuide(false); terminal.commander.stop(); terminal.clear(); terminal.isPaused = false; terminal.cursor.reset(); return } - if (event.key === 'Backspace') { terminal[this.isActive === true ? 'commander' : 'cursor'].erase(); event.preventDefault(); return } - - if (event.key === ']') { terminal.modGrid(1, 0); event.preventDefault(); return } - if (event.key === '[') { terminal.modGrid(-1, 0); event.preventDefault(); return } - if (event.key === '}') { terminal.modGrid(0, 1); event.preventDefault(); return } - if (event.key === '{') { terminal.modGrid(0, -1); event.preventDefault(); return } - if (event.key === '>') { terminal.clock.modSpeed(1); event.preventDefault(); return } - if (event.key === '<') { terminal.clock.modSpeed(-1); event.preventDefault(); return } - - // Route key to Operator or Cursor - terminal[this.isActive === true ? 'commander' : 'cursor'].write(event.key) - } - - this.onKeyUp = function (event) { - terminal.update() - } - - this.onArrowUp = function (mod = false, skip = false, drag = false) { - // Navigate History - if (this.isActive === true) { - this.historyIndex -= this.historyIndex > 0 ? 1 : 0 - this.start(this.history[this.historyIndex]) - return - } - const leap = skip ? terminal.grid.h : 1 - terminal.toggleGuide(false) - if (drag) { - terminal.cursor.drag(0, leap) - } else if (mod) { - terminal.cursor.scale(0, leap) - } else { - terminal.cursor.move(0, leap) - } + this.onKeyDown = (e) => { + if (e.ctrlKey || e.metaKey || e.altKey) { return } + terminal[this.isActive === true ? 'commander' : 'cursor'].write(e.key) + e.stopPropagation() } - this.onArrowDown = function (mod = false, skip = false, drag = false) { - // Navigate History - if (this.isActive === true) { - this.historyIndex += this.historyIndex < this.history.length ? 1 : 0 - this.start(this.history[this.historyIndex]) - return - } - const leap = skip ? terminal.grid.h : 1 - terminal.toggleGuide(false) - if (drag) { - terminal.cursor.drag(0, -leap) - } else if (mod) { - terminal.cursor.scale(0, -leap) - } else { - terminal.cursor.move(0, -leap) - } + this.onKeyUp = (e) => { + // terminal.update() } - this.onArrowLeft = function (mod = false, skip = false, drag = false) { - const leap = skip ? terminal.grid.w : 1 - terminal.toggleGuide(false) - if (drag) { - terminal.cursor.drag(-leap, 0) - } else if (mod) { - terminal.cursor.scale(-leap, 0) - } else { - terminal.cursor.move(-leap, 0) - } - } - - this.onArrowRight = function (mod = false, skip = false, drag = false) { - const leap = skip ? terminal.grid.w : 1 - terminal.toggleGuide(false) - if (drag) { - terminal.cursor.drag(leap, 0) - } else if (mod) { - terminal.cursor.scale(leap, 0) - } else { - terminal.cursor.move(leap, 0) - } - } - - // Events - - document.onkeydown = (event) => { this.onKeyDown(event) } - document.onkeyup = (event) => { this.onKeyUp(event) } - // UI this.toString = function () { diff --git a/desktop/core/io.js b/desktop/sources/scripts/core/io.js index 96cacb1..6e3704a 100644 --- a/desktop/core/io.js +++ b/desktop/sources/scripts/core/io.js @@ -1,12 +1,6 @@ 'use strict' -import Midi from './io/midi.js' -import MidiCC from './io/cc.js' -import Mono from './io/mono.js' -import Udp from './io/udp.js' -import Osc from './io/osc.js' - -export default function IO (terminal) { +function IO (terminal) { this.ip = '127.0.0.1' this.midi = new Midi(terminal) diff --git a/desktop/core/io/cc.js b/desktop/sources/scripts/core/io/cc.js index f617ea7..630d3d9 100644 --- a/desktop/core/io/cc.js +++ b/desktop/sources/scripts/core/io/cc.js @@ -1,6 +1,6 @@ 'use strict' -export default function MidiCC (terminal) { +function MidiCC (terminal) { this.stack = [] this.offset = 64 diff --git a/desktop/core/io/midi.js b/desktop/sources/scripts/core/io/midi.js index 9ccf764..7062a3c 100644 --- a/desktop/core/io/midi.js +++ b/desktop/sources/scripts/core/io/midi.js @@ -1,8 +1,8 @@ 'use strict' -import transpose from '../transpose.js' +/* global transposeTable */ -export default function Midi (terminal) { +function Midi (terminal) { this.mode = 0 this.isClock = false @@ -15,7 +15,7 @@ export default function Midi (terminal) { this.start = function () { console.info('Midi Starting..') - this.setup() + this.refresh() } this.clear = function () { @@ -79,37 +79,6 @@ export default function Midi (terminal) { this.stack.push(item) } - this.update = () => { - terminal.controller.clearCat('default', 'Midi') - terminal.controller.add('default', 'Midi', 'Play/Pause Message', () => { this.toggleClock(true); this.update() }, 'shift+space') - terminal.controller.add('default', 'Midi', `MIDI Send Clock ${this.isClock === true ? ' — On' : ' — Off'}`, () => { this.toggleClock(); this.update() }, '') - terminal.controller.add('default', 'Midi', 'Refresh Device List', () => { this.setup(); this.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} Output ${this.outputIndex === parseInt(id) ? ' — Active' : ''}`, () => { this.selectOutput(id) }, '') - } - terminal.controller.add('default', 'Midi', `No Output ${this.outputIndex === -1 ? ' — Active' : ''}`, () => { this.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} Input ${this.inputIndex === parseInt(id) ? ' — Active' : ''}`, () => { this.selectInput(id) }, '') - } - terminal.controller.add('default', 'Midi', `No Input ${this.inputIndex === -1 ? ' — Active' : ''}`, () => { this.selectInput(-1) }, '') - } - - terminal.controller.commit() - } - this.allNotesOff = function () { if (!this.outputDevice()) { return } console.log('MIDI', 'All Notes Off') @@ -191,23 +160,21 @@ export default function Midi (terminal) { // Tools this.selectOutput = function (id) { - if (id === -1) { this.outputIndex = -1; console.log('MIDI', 'Select Output Device: None'); this.update(); return } + if (id === -1) { this.outputIndex = -1; console.log('MIDI', 'Select Output Device: None'); return } if (!this.outputs[id]) { return } this.outputIndex = parseInt(id) console.log('MIDI', `Select Output Device: ${this.outputDevice().name}`) - this.update() } this.selectInput = function (id) { if (this.inputDevice()) { this.inputDevice().onmidimessage = null } - if (id === -1) { this.inputIndex = -1; console.log('MIDI', 'Select Input Device: None'); this.update(); return } + if (id === -1) { this.inputIndex = -1; console.log('MIDI', 'Select Input Device: None'); return } if (!this.inputs[id]) { return } this.inputIndex = parseInt(id) this.inputDevice().onmidimessage = (msg) => { this.receive(msg) } console.log('MIDI', `Select Input Device: ${this.inputDevice().name}`) - this.update() } this.outputDevice = function () { @@ -218,11 +185,21 @@ export default function Midi (terminal) { return this.inputs[this.inputIndex] } + this.selectNextOutput = () => { + this.outputIndex = this.outputIndex < this.outputs.length ? this.outputIndex + 1 : 0 + terminal.update() + } + + this.selectNextInput = () => { + this.inputIndex = this.inputIndex < this.inputs.length ? this.inputIndex + 1 : 0 + terminal.update() + } + // Setup - this.setup = function () { + this.refresh = function () { if (!navigator.requestMIDIAccess) { return } - navigator.requestMIDIAccess({ sysex: false }).then(this.access, (err) => { + navigator.requestMIDIAccess().then(this.access, (err) => { console.warn('No Midi', err) }) } @@ -246,9 +223,9 @@ export default function Midi (terminal) { // UI this.transpose = function (n, o = 3) { - if (!transpose[n]) { return null } - const octave = clamp(parseInt(o) + parseInt(transpose[n].charAt(1)), 0, 8) - const note = transpose[n].charAt(0) + if (!transposeTable[n]) { return null } + const octave = clamp(parseInt(o) + parseInt(transposeTable[n].charAt(1)), 0, 8) + const note = transposeTable[n].charAt(0) const value = ['C', 'c', 'D', 'd', 'E', 'F', 'f', 'G', 'g', 'A', 'a', 'B'].indexOf(note) const id = clamp((octave * 12) + value + 24, 0, 127) return { id, value, note, octave } @@ -258,8 +235,8 @@ export default function Midi (terminal) { const note = ['C', 'c', 'D', 'd', 'E', 'F', 'f', 'G', 'g', 'A', 'a', 'B'][id % 12] const octave = Math.floor(id / 12) - 5 const name = `${note}${octave}` - const key = Object.values(transpose).indexOf(name) - return Object.keys(transpose)[key] + const key = Object.values(transposeTable).indexOf(name) + return Object.keys(transposeTable)[key] } this.toString = function () { diff --git a/desktop/core/io/mono.js b/desktop/sources/scripts/core/io/mono.js index 4386fac..903036b 100644 --- a/desktop/core/io/mono.js +++ b/desktop/sources/scripts/core/io/mono.js @@ -1,6 +1,6 @@ 'use strict' -export default function Mono (terminal) { +function Mono (terminal) { this.stack = {} this.start = function () { diff --git a/desktop/core/io/osc.js b/desktop/sources/scripts/core/io/osc.js index 4409158..346decf 100644 --- a/desktop/core/io/osc.js +++ b/desktop/sources/scripts/core/io/osc.js @@ -2,12 +2,13 @@ const osc = require('node-osc') -export default function Osc (terminal) { +function Osc (terminal) { this.stack = [] this.port = null this.options = { default: 49162, tidalCycles: 6010, sonicPi: 4559, superCollider: 57120, norns: 10111 } this.start = function () { + if (!osc) { console.warn('OSC', 'Could not start.'); return } console.info('OSC', 'Starting..') this.setup() this.select() @@ -45,16 +46,6 @@ export default function Osc (terminal) { console.info('OSC', `Selected port: ${port}`) this.port = parseInt(port) this.setup() - this.update() - } - - this.update = () => { - terminal.controller.clearCat('default', 'OSC') - for (const id in this.options) { - terminal.controller.add('default', 'OSC', `${id.charAt(0).toUpperCase() + id.substr(1)}(${this.options[id]}) ${this.port === this.options[id] ? ' — Active' : ''}`, () => { this.select(this.options[id]) }, '') - } - terminal.controller.add('default', 'OSC', 'Choose Custom Port', () => { terminal.commander.start('osc:') }, '') - terminal.controller.commit() } this.setup = function () { diff --git a/desktop/sources/scripts/core/io/udp.js b/desktop/sources/scripts/core/io/udp.js new file mode 100644 index 0000000..11fe0fd --- /dev/null +++ b/desktop/sources/scripts/core/io/udp.js @@ -0,0 +1,61 @@ +'use strict' + +const dgram = require('dgram') + +function Udp (terminal) { + this.stack = [] + this.port = null + this.options = { default: 49161, orca: 49160 } + this.client = dgram ? dgram.createSocket('udp4') : null + this.listener = dgram ? dgram.createSocket('udp4') : null + + this.start = function () { + if (!this.client || !this.listener) { console.warn('UDP', 'Could not start.'); return } + console.info('UDP', 'Starting..') + + this.listener.on('message', (msg, rinfo) => { + terminal.commander.trigger(`${msg}`, false) + }) + + this.listener.on('listening', () => { + const address = this.listener.address() + console.info('UDP', `Started client at ${address.address}:${address.port}`) + }) + + this.listener.on('error', (err) => { + console.warn('UDP', `Server error:\n ${err.stack}`) + this.listener.close() + }) + + this.listener.bind(49160) + + this.select() + } + + this.clear = function () { + this.stack = [] + } + + this.run = function () { + for (const id in this.stack) { + this.play(this.stack[id]) + } + } + + this.push = function (msg) { + this.stack.push(msg) + } + + this.play = function (data) { + this.client.send(Buffer.from(`${data}`), this.port, terminal.io.ip, (err) => { + if (err) { console.warn(err) } + }) + } + + this.select = function (port = this.options.default) { + if (parseInt(port) === this.port) { console.warn('UDP', 'Already selected'); return } + if (isNaN(port) || port < 1000) { console.warn('UDP', 'Unavailable port'); return } + console.info('UDP', `Selected port: ${port}`) + this.port = parseInt(port) + } +} diff --git a/desktop/sources/scripts/core/library.js b/desktop/sources/scripts/core/library.js new file mode 100644 index 0000000..1e6a272 --- /dev/null +++ b/desktop/sources/scripts/core/library.js @@ -0,0 +1,740 @@ +'use strict' + +/* global Operator */ + +const library = {} + +library.a = function OperatorA (orca, x, y, passive) { + Operator.call(this, orca, x, y, 'a', passive) + + this.name = 'add' + this.info = 'Outputs sum of inputs' + + this.ports.a = { x: -1, y: 0 } + this.ports.b = { x: 1, y: 0 } + this.ports.output = { x: 0, y: 1, sensitive: true } + + this.operation = function (force = false) { + const a = this.listen(this.ports.a, true) + const b = this.listen(this.ports.b, true) + return orca.keyOf(a + b) + } +} + +library.b = function OperatorB (orca, x, y, passive) { + Operator.call(this, orca, x, y, 'b', passive) + + this.name = 'bounce' + this.info = 'Outputs values between inputs' + + this.ports.rate = { x: -1, y: 0, clamp: { min: 1 } } + this.ports.mod = { x: 1, y: 0, default: '8' } + this.ports.output = { x: 0, y: 1, sensitive: true } + + this.operation = function (force = false) { + const rate = this.listen(this.ports.rate, true) + const mod = this.listen(this.ports.mod, true) - 1 + const key = Math.floor(orca.f / rate) % (mod * 2) + return orca.keyOf(key <= mod ? key : mod - (key - mod)) + } +} + +library.c = function OperatorC (orca, x, y, passive) { + Operator.call(this, orca, x, y, 'c', passive) + + this.name = 'clock' + this.info = 'Outputs modulo of frame' + + this.ports.rate = { x: -1, y: 0, clamp: { min: 1 } } + this.ports.mod = { x: 1, y: 0, default: '8' } + this.ports.output = { x: 0, y: 1, sensitive: true } + + this.operation = function (force = false) { + const rate = this.listen(this.ports.rate, true) + const mod = this.listen(this.ports.mod, true) + const val = Math.floor(orca.f / rate) % mod + return orca.keyOf(val) + } +} + +library.d = function OperatorD (orca, x, y, passive) { + Operator.call(this, orca, x, y, 'd', passive) + + this.name = 'delay' + this.info = 'Bangs on modulo of frame' + + this.ports.rate = { x: -1, y: 0, clamp: { min: 1 } } + this.ports.mod = { x: 1, y: 0, default: '8' } + this.ports.output = { x: 0, y: 1, bang: true } + + this.operation = function (force = false) { + const rate = this.listen(this.ports.rate, true) + const mod = this.listen(this.ports.mod, true) + const res = orca.f % (mod * rate) + return res === 0 || mod === 1 + } +} + +library.e = function OperatorE (orca, x, y, passive) { + Operator.call(this, orca, x, y, 'e', passive) + + this.name = 'east' + this.info = 'Moves eastward, or bangs' + this.draw = false + + this.operation = function () { + this.move(1, 0) + this.passive = false + } +} + +library.f = function OperatorF (orca, x, y, passive) { + Operator.call(this, orca, x, y, 'f', passive) + + this.name = 'if' + this.info = 'Bangs if inputs are equal' + + this.ports.a = { x: -1, y: 0 } + this.ports.b = { x: 1, y: 0 } + this.ports.output = { x: 0, y: 1, bang: true } + + this.operation = function (force = false) { + const a = this.listen(this.ports.a) + const b = this.listen(this.ports.b) + return a === b && a !== '.' + } +} + +library.g = function OperatorG (orca, x, y, passive) { + Operator.call(this, orca, x, y, 'g', passive) + + this.name = 'generator' + this.info = 'Writes operands with offset' + + this.ports.x = { x: -3, y: 0 } + this.ports.y = { x: -2, y: 0 } + this.ports.len = { x: -1, y: 0, clamp: { min: 1 } } + + this.operation = function (force = false) { + const len = this.listen(this.ports.len, true) + const x = this.listen(this.ports.x, true) + const y = this.listen(this.ports.y, true) + 1 + for (let offset = 0; offset < len; offset++) { + const inPort = { x: offset + 1, y: 0 } + const outPort = { x: x + offset, y: y, output: true } + this.addPort(`in${offset}`, inPort) + this.addPort(`out${offset}`, outPort) + const res = this.listen(inPort) + this.output(`${res}`, outPort) + } + } +} + +library.h = function OperatorH (orca, x, y, passive) { + Operator.call(this, orca, x, y, 'h', passive) + + this.name = 'halt' + this.info = 'Halts southward operand' + + this.ports.output = { x: 0, y: 1, reader: true } + + this.operation = function (force = false) { + orca.lock(this.x + this.ports.output.x, this.y + this.ports.output.y) + return this.listen(this.ports.output, true) + } +} + +library.i = function OperatorI (orca, x, y, passive) { + Operator.call(this, orca, x, y, 'i', passive) + + this.name = 'increment' + this.info = 'Increments southward operand' + + this.ports.step = { x: -1, y: 0, default: '1' } + this.ports.mod = { x: 1, y: 0 } + this.ports.output = { x: 0, y: 1, sensitive: true, reader: true } + + this.operation = function (force = false) { + const step = this.listen(this.ports.step, true) + const mod = this.listen(this.ports.mod, true) + const val = this.listen(this.ports.output, true) + return orca.keyOf((val + step) % (mod > 0 ? mod : 36)) + } +} + +library.j = function OperatorJ (orca, x, y, passive) { + Operator.call(this, orca, x, y, 'j', passive) + + this.name = 'jumper' + this.info = 'Outputs northward operand' + + this.ports.val = { x: 0, y: -1 } + this.ports.output = { x: 0, y: 1 } + + this.operation = function (force = false) { + orca.lock(this.x, this.y + 1) + return this.listen(this.ports.val) + } +} + +library.k = function OperatorK (orca, x, y, passive) { + Operator.call(this, orca, x, y, 'k', passive) + + this.name = 'konkat' + this.info = 'Reads multiple variables' + + this.ports.len = { x: -1, y: 0, clamp: { min: 1 } } + + this.operation = function (force = false) { + this.len = this.listen(this.ports.len, true) + for (let offset = 0; offset < this.len; offset++) { + const key = orca.glyphAt(this.x + offset + 1, this.y) + orca.lock(this.x + offset + 1, this.y) + if (key === '.') { continue } + const inPort = { x: offset + 1, y: 0 } + const outPort = { x: offset + 1, y: 1, output: true } + this.addPort(`in${offset}`, inPort) + this.addPort(`out${offset}`, outPort) + const res = orca.valueIn(key) + this.output(`${res}`, outPort) + } + } +} + +library.l = function OperatorL (orca, x, y, passive) { + Operator.call(this, orca, x, y, 'l', passive) + + this.name = 'loop' + this.info = 'Moves eastward operands' + + this.ports.step = { x: -2, y: 0, default: '1' } + this.ports.len = { x: -1, y: 0 } + this.ports.val = { x: 1, y: 0 } + this.ports.output = { x: 0, y: 1 } + + this.operation = function (force = false) { + const len = this.listen(this.ports.len, true) + const step = this.listen(this.ports.step, true) + const index = orca.indexAt(this.x + 1, this.y) + const seg = orca.s.substr(index, len) + const res = seg.substr(len - step, step) + seg.substr(0, len - step) + for (let offset = 0; offset <= len; offset++) { + if (offset > 0) { + orca.lock(this.x + offset, this.y) + } + orca.write(this.x + offset + 1, this.y, res.charAt(offset)) + } + return this.listen(this.ports.val) + } +} + +library.m = function OperatorM (orca, x, y, passive) { + Operator.call(this, orca, x, y, 'm', passive) + + this.name = 'multiply' + this.info = 'Outputs product of inputs' + + this.ports.a = { x: -1, y: 0 } + this.ports.b = { x: 1, y: 0 } + this.ports.output = { x: 0, y: 1, sensitive: true } + + this.operation = function (force = false) { + const a = this.listen(this.ports.a, true) + const b = this.listen(this.ports.b, true) + return orca.keyOf(a * b) + } +} + +library.n = function OperatorN (orca, x, y, passive) { + Operator.call(this, orca, x, y, 'n', passive) + + this.name = 'north' + this.info = 'Moves Northward, or bangs' + this.draw = false + + this.operation = function () { + this.move(0, -1) + this.passive = false + } +} + +library.o = function OperatorO (orca, x, y, passive) { + Operator.call(this, orca, x, y, 'o', passive) + + this.name = 'read' + this.info = 'Reads operand with offset' + + this.ports.x = { x: -2, y: 0 } + this.ports.y = { x: -1, y: 0 } + this.ports.output = { x: 0, y: 1 } + + this.operation = function (force = false) { + const x = this.listen(this.ports.x, true) + const y = this.listen(this.ports.y, true) + this.addPort('read', { x: x + 1, y: y }) + return this.listen(this.ports.read) + } +} + +library.p = function OperatorP (orca, x, y, passive) { + Operator.call(this, orca, x, y, 'p', passive) + + this.name = 'push' + this.info = 'Writes eastward operand' + + this.ports.key = { x: -2, y: 0 } + this.ports.len = { x: -1, y: 0, clamp: { min: 1 } } + this.ports.val = { x: 1, y: 0 } + + this.operation = function (force = false) { + const len = this.listen(this.ports.len, true) + const key = this.listen(this.ports.key, true) + for (let offset = 0; offset < len; offset++) { + orca.lock(this.x + offset, this.y + 1) + } + this.ports.output = { x: (key % len), y: 1 } + return this.listen(this.ports.val) + } +} + +library.q = function OperatorQ (orca, x, y, passive) { + Operator.call(this, orca, x, y, 'q', passive) + + this.name = 'query' + this.info = 'Reads operands with offset' + + this.ports.x = { x: -3, y: 0 } + this.ports.y = { x: -2, y: 0 } + this.ports.len = { x: -1, y: 0, clamp: { min: 1 } } + + this.operation = function (force = false) { + const len = this.listen(this.ports.len, true) + const x = this.listen(this.ports.x, true) + const y = this.listen(this.ports.y, true) + for (let offset = 0; offset < len; offset++) { + const inPort = { x: x + offset + 1, y: y } + const outPort = { x: offset - len + 1, y: 1, output: true } + this.addPort(`in${offset}`, inPort) + this.addPort(`out${offset}`, outPort) + const res = this.listen(inPort) + this.output(`${res}`, outPort) + } + } +} + +library.r = function OperatorR (orca, x, y, passive) { + Operator.call(this, orca, x, y, 'r', passive) + + this.name = 'random' + this.info = 'Outputs random value' + + this.ports.min = { x: -1, y: 0 } + this.ports.max = { x: 1, y: 0 } + this.ports.output = { x: 0, y: 1, sensitive: true } + + this.operation = function (force = false) { + const min = this.listen(this.ports.min, true) + const max = this.listen(this.ports.max, true) + const val = parseInt((Math.random() * ((max > 0 ? max : 36) - min)) + min) + return orca.keyOf(val) + } +} + +library.s = function OperatorS (orca, x, y, passive) { + Operator.call(this, orca, x, y, 's', passive) + + this.name = 'south' + this.info = 'Moves southward, or bangs' + this.draw = false + + this.operation = function () { + this.move(0, 1) + this.passive = false + } +} + +library.t = function OperatorT (orca, x, y, passive) { + Operator.call(this, orca, x, y, 't', passive) + + this.name = 'track' + this.info = 'Reads eastward operand' + + this.ports.key = { x: -2, y: 0 } + this.ports.len = { x: -1, y: 0, clamp: { min: 1 } } + this.ports.output = { x: 0, y: 1 } + + this.operation = function (force = false) { + const len = this.listen(this.ports.len, true) + const key = this.listen(this.ports.key, true) + for (let offset = 0; offset < len; offset++) { + orca.lock(this.x + offset + 1, this.y) + } + this.ports.val = { x: (key % len) + 1, y: 0 } + return this.listen(this.ports.val) + } +} + +library.u = function OperatorU (orca, x, y, passive) { + Operator.call(this, orca, x, y, 'u', passive) + + this.name = 'uclid' + this.info = 'Bangs on Euclidean rhythm' + + this.ports.step = { x: -1, y: 0, clamp: { min: 0 }, default: '1' } + this.ports.max = { x: 1, y: 0, clamp: { min: 1 }, default: '8' } + this.ports.output = { x: 0, y: 1, bang: true } + + this.operation = function (force = false) { + const step = this.listen(this.ports.step, true) + const max = this.listen(this.ports.max, true) + const bucket = (step * (orca.f + max - 1)) % max + step + return bucket >= max + } +} + +library.v = function OperatorV (orca, x, y, passive) { + Operator.call(this, orca, x, y, 'v', passive) + + this.name = 'variable' + this.info = 'Reads and writes variable' + + this.ports.write = { x: -1, y: 0 } + this.ports.read = { x: 1, y: 0 } + + this.operation = function (force = false) { + const write = this.listen(this.ports.write) + const read = this.listen(this.ports.read) + if (write === '.' && read !== '.') { + this.addPort('output', { x: 0, y: 1 }) + } + if (write !== '.') { + orca.variables[write] = read + return + } + return orca.valueIn(read) + } +} + +library.w = function OperatorW (orca, x, y, passive) { + Operator.call(this, orca, x, y, 'w', passive) + + this.name = 'west' + this.info = 'Moves westward, or bangs' + this.draw = false + + this.operation = function () { + this.move(-1, 0) + this.passive = false + } +} + +library.x = function OperatorX (orca, x, y, passive) { + Operator.call(this, orca, x, y, 'x', passive) + + this.name = 'write' + this.info = 'Writes operand with offset' + + this.ports.x = { x: -2, y: 0 } + this.ports.y = { x: -1, y: 0 } + this.ports.val = { x: 1, y: 0 } + + this.operation = function (force = false) { + const x = this.listen(this.ports.x, true) + const y = this.listen(this.ports.y, true) + 1 + this.addPort('output', { x: x, y: y }) + return this.listen(this.ports.val) + } +} + +library.y = function OperatorY (orca, x, y, passive) { + Operator.call(this, orca, x, y, 'y', passive) + + this.name = 'jymper' + this.info = 'Outputs westward operand' + + this.ports.val = { x: -1, y: 0 } + this.ports.output = { x: 1, y: 0 } + + this.operation = function (force = false) { + orca.lock(this.x + 1, this.y) + return this.listen(this.ports.val) + } +} + +library.z = function OperatorZ (orca, x, y, passive) { + Operator.call(this, orca, x, y, 'z', passive) + + this.name = 'lerp' + this.info = 'Transitions operand to target' + + this.ports.rate = { x: -1, y: 0, default: '1' } + this.ports.target = { x: 1, y: 0 } + this.ports.output = { x: 0, y: 1, sensitive: true, reader: true } + + this.operation = function (force = false) { + const rate = this.listen(this.ports.rate, true) + const target = this.listen(this.ports.target, true) + const val = this.listen(this.ports.output, true) + const mod = val <= target - rate ? rate : val >= target + rate ? -rate : target - val + return orca.keyOf(val + mod) + } +} + +// Specials + +library['*'] = function OperatorBang (orca, x, y, passive) { + Operator.call(this, orca, x, y, '*', true) + + this.name = 'bang' + this.info = 'Bangs neighboring operands' + this.draw = false + + this.run = function (force = false) { + this.draw = false + this.erase() + } +} + +library['#'] = function OperatorComment (orca, x, y, passive) { + Operator.call(this, orca, x, y, '#', true) + + this.name = 'comment' + this.info = 'Halts line' + this.draw = false + + this.operation = function () { + for (let x = this.x + 1; x <= orca.w; x++) { + orca.lock(x, this.y) + if (orca.glyphAt(x, this.y) === this.glyph) { break } + } + orca.lock(this.x, this.y) + } +} + +// IO + +library.$ = function OperatorSelf (orca, x, y, passive) { + Operator.call(this, orca, x, y, '*', true) + + this.name = 'self' + this.info = 'Send command to itself' + + this.run = function (force = false) { + let msg = '' + for (let x = 1; x <= 36; x++) { + const g = orca.glyphAt(this.x + x, this.y) + orca.lock(this.x + x, this.y) + if (g === '.') { break } + msg += g + } + + if (!this.hasNeighbor('*') && force === false) { return } + if (msg === '') { return } + + this.draw = false + terminal.commander.trigger(`${msg}`) + } +} + +library['!'] = function OperatorCC (orca, x, y) { + Operator.call(this, orca, x, y, '!', true) + + this.name = 'cc' + this.info = 'Sends MIDI control change' + this.ports.channel = { x: 1, y: 0, clamp: { min: 0, max: 15 } } + this.ports.knob = { x: 2, y: 0, clamp: { min: 0 } } + this.ports.value = { x: 3, y: 0, clamp: { min: 0 } } + + this.operation = function (force = false) { + if (!this.hasNeighbor('*') && force === false) { return } + if (this.listen(this.ports.channel) === '.') { return } + if (this.listen(this.ports.knob) === '.') { return } + + const channel = this.listen(this.ports.channel, true) + const knob = this.listen(this.ports.knob, true) + const rawValue = this.listen(this.ports.value, true) + const value = Math.ceil((127 * rawValue) / 35) + + terminal.io.cc.stack.push({ channel, knob, value, type: 'cc' }) + + this.draw = false + + if (force === true) { + terminal.io.cc.run() + } + } +} + +library[':'] = function OperatorMidi (orca, x, y, passive) { + Operator.call(this, orca, x, y, ':', true) + + this.name = 'midi' + this.info = 'Sends MIDI note' + this.ports.channel = { x: 1, y: 0, clamp: { min: 0, max: 16 } } + this.ports.octave = { x: 2, y: 0, clamp: { min: 0, max: 8 } } + this.ports.note = { x: 3, y: 0 } + this.ports.velocity = { x: 4, y: 0, default: 'f', clamp: { min: 0, max: 16 } } + this.ports.length = { x: 5, y: 0, default: '1', clamp: { min: 0, max: 16 } } + + this.operation = function (force = false) { + if (!this.hasNeighbor('*') && force === false) { return } + if (this.listen(this.ports.channel) === '.') { return } + if (this.listen(this.ports.octave) === '.') { return } + if (this.listen(this.ports.note) === '.') { return } + if (!isNaN(this.listen(this.ports.note))) { return } + + const channel = this.listen(this.ports.channel, true) + const octave = this.listen(this.ports.octave, true) + const note = this.listen(this.ports.note) + const velocity = this.listen(this.ports.velocity, true) + const length = this.listen(this.ports.length, true) + + terminal.io.midi.push(channel, octave, note, velocity, length) + + if (force === true) { + terminal.io.midi.run() + } + + this.draw = false + } +} + +library['%'] = function OperatorMono (orca, x, y, passive) { + Operator.call(this, orca, x, y, '%', true) + + this.name = 'mono' + this.info = 'Sends MIDI monophonic note' + this.ports.channel = { x: 1, y: 0, clamp: { min: 0, max: 16 } } + this.ports.octave = { x: 2, y: 0, clamp: { min: 0, max: 8 } } + this.ports.note = { x: 3, y: 0 } + this.ports.velocity = { x: 4, y: 0, default: 'f', clamp: { min: 0, max: 16 } } + this.ports.length = { x: 5, y: 0, default: '1', clamp: { min: 0, max: 16 } } + + this.operation = function (force = false) { + if (!this.hasNeighbor('*') && force === false) { return } + if (this.listen(this.ports.channel) === '.') { return } + if (this.listen(this.ports.octave) === '.') { return } + if (this.listen(this.ports.note) === '.') { return } + if (!isNaN(this.listen(this.ports.note))) { return } + + const channel = this.listen(this.ports.channel, true) + const octave = this.listen(this.ports.octave, true) + const note = this.listen(this.ports.note) + const velocity = this.listen(this.ports.velocity, true) + const length = this.listen(this.ports.length, true) + + terminal.io.mono.push(channel, octave, note, velocity, length) + + if (force === true) { + terminal.io.mono.run() + } + + this.draw = false + } +} + +library['='] = function OperatorOsc (orca, x, y, passive) { + Operator.call(this, orca, x, y, '=', true) + + this.name = 'osc' + this.info = 'Sends OSC message' + + this.ports.path = { x: 1, y: 0 } + + this.operation = function (force = false) { + let msg = '' + for (let x = 2; x <= 36; x++) { + const g = orca.glyphAt(this.x + x, this.y) + orca.lock(this.x + x, this.y) + if (g === '.') { break } + msg += g + } + + if (!this.hasNeighbor('*') && force === false) { return } + if (msg === '') { return } + + const path = this.listen(this.ports.path) + + if (!path || path === '.') { return } + + this.draw = false + terminal.io.osc.push('/' + path, msg) + + if (force === true) { + terminal.io.osc.run() + } + } +} + +library['?'] = function OperatorPB (orca, x, y) { + Operator.call(this, orca, x, y, '?', true) + + this.name = 'cc' + this.info = 'Sends MIDI pitch bend' + this.ports.channel = { x: 1, y: 0, clamp: { min: 0, max: 15 } } + this.ports.lsb = { x: 2, y: 0, clamp: { min: 0 } } + this.ports.msb = { x: 3, y: 0, clamp: { min: 0 } } + + this.operation = function (force = false) { + if (!this.hasNeighbor('*') && force === false) { return } + if (this.listen(this.ports.channel) === '.') { return } + if (this.listen(this.ports.lsb) === '.') { return } + + const channel = this.listen(this.ports.channel, true) + const rawlsb = this.listen(this.ports.lsb, true) + const lsb = Math.ceil((127 * rawlsb) / 35) + const rawmsb = this.listen(this.ports.msb, true) + const msb = Math.ceil((127 * rawmsb) / 35) + + terminal.io.cc.stack.push({ channel, lsb, msb, type: 'pb' }) + + this.draw = false + + if (force === true) { + terminal.io.cc.run() + } + } +} + +library[';'] = function OperatorUdp (orca, x, y, passive) { + Operator.call(this, orca, x, y, ';', true) + + this.name = 'udp' + this.info = 'Sends UDP message' + + this.operation = function (force = false) { + let msg = '' + for (let x = 1; x <= 36; x++) { + const g = orca.glyphAt(this.x + x, this.y) + orca.lock(this.x + x, this.y) + if (g === '.') { break } + msg += g + } + + if (!this.hasNeighbor('*') && force === false) { return } + if (msg === '') { return } + + this.draw = false + terminal.io.udp.push(msg) + + if (force === true) { + terminal.io.udp.run() + } + } +} + +// Add numbers + +for (let i = 0; i <= 9; i++) { + library[`${i}`] = function OperatorNull (orca, x, y, passive) { + Operator.call(this, orca, x, y, '.', false) + + this.name = 'null' + this.info = 'empty' + + // Overwrite run, to disable draw. + this.run = function (force = false) { + + } + } +} diff --git a/desktop/core/operator.js b/desktop/sources/scripts/core/operator.js index 58a6d5c..b4d3c6c 100644 --- a/desktop/core/operator.js +++ b/desktop/sources/scripts/core/operator.js @@ -1,6 +1,6 @@ 'use strict' -export default function Operator (orca, x, y, glyph = '.', passive = false) { +function Operator (orca, x, y, glyph = '.', passive = false) { this.name = 'unknown' this.x = x this.y = y diff --git a/desktop/core/orca.js b/desktop/sources/scripts/core/orca.js index ef55ab6..bb23ebc 100644 --- a/desktop/core/orca.js +++ b/desktop/sources/scripts/core/orca.js @@ -1,8 +1,6 @@ 'use strict' -import library from './library.js' - -export default function Orca () { +function Orca (library) { this.keys = Object.keys(library).slice(0, 36) this.w = 1 // Default Width diff --git a/desktop/core/transpose.js b/desktop/sources/scripts/core/transpose.js index 448fc38..6925240 100644 --- a/desktop/core/transpose.js +++ b/desktop/sources/scripts/core/transpose.js @@ -1,6 +1,6 @@ 'use strict' -export default { +const transposeTable = { A: 'A0', a: 'a0', B: 'B0', diff --git a/desktop/sources/scripts/cursor.js b/desktop/sources/scripts/cursor.js index ca3659e..cf3d0f4 100644 --- a/desktop/sources/scripts/cursor.js +++ b/desktop/sources/scripts/cursor.js @@ -1,8 +1,6 @@ 'use strict' -const { clipboard } = require('electron') - -export default function Cursor (terminal) { +function Cursor (terminal) { this.x = 0 this.y = 0 this.w = 0 @@ -15,12 +13,22 @@ export default function Cursor (terminal) { this.mode = 0 + this.start = () => { + document.onmousedown = (e) => { this.onMouseDown(e) } + document.onmouseup = (e) => { this.onMouseUp(e) } + document.onmousemove = (e) => { this.onMouseMove(e) } + document.oncopy = (e) => { this.onCopy(e) } + document.oncut = (e) => { this.onCut(e) } + document.onpaste = (e) => { this.onPaste(e) } + } + this.move = function (x, y) { if (isNaN(x) || isNaN(y)) { return } this.x = clamp(this.x + parseInt(x), 0, terminal.orca.w - 1) this.y = clamp(this.y - parseInt(y), 0, terminal.orca.h - 1) this.calculateBounds() + terminal.toggleGuide(false) terminal.update() } @@ -30,6 +38,7 @@ export default function Cursor (terminal) { this.y = clamp(parseInt(y), 0, terminal.orca.h - 1) this.calculateBounds() + terminal.toggleGuide(false) terminal.update() } @@ -63,9 +72,10 @@ export default function Cursor (terminal) { this.drag = function (x, y) { if (isNaN(x) || isNaN(y)) { return } this.mode = 0 - this.cut() + const block = this.getBlock() + this.erase() this.move(x, y) - this.paste() + this.writeBlock(block) } this.selectAll = function () { @@ -100,21 +110,15 @@ export default function Cursor (terminal) { } this.copy = function () { - const block = this.getBlock() - var rows = [] - for (var i = 0; i < block.length; i++) { - rows.push(block[i].join('')) - } - clipboard.writeText(rows.join('\n')) + document.execCommand('copy') } this.cut = function () { - this.copy() - this.erase() + document.execCommand('cut') } this.paste = function (overlap = false) { - this.writeBlock(clipboard.readText().split(/\r?\n/), overlap) + document.execCommand('paste') } this.read = function () { @@ -122,6 +126,7 @@ export default function Cursor (terminal) { } this.write = function (g) { + if (!terminal.orca.isAllowed(g)) { return } if (terminal.orca.write(this.x, this.y, g) && this.mode === 1) { this.move(1, 0) } @@ -246,6 +251,57 @@ export default function Cursor (terminal) { ) } + this.mouseFrom = null + + this.onMouseDown = (e) => { + const pos = this.tilePos(e.clientX, e.clientY) + this.select(pos.x, pos.y, 0, 0) + this.mouseFrom = pos + } + + this.onMouseUp = (e) => { + if (this.mouseFrom) { + const pos = this.tilePos(e.clientX, e.clientY) + this.select(this.mouseFrom.x, this.mouseFrom.y, pos.x - this.mouseFrom.x, pos.y - this.mouseFrom.y) + } + this.mouseFrom = null + } + + this.onMouseMove = (e) => { + if (!this.mouseFrom) { return } + const pos = this.tilePos(e.clientX, e.clientY) + this.select(this.mouseFrom.x, this.mouseFrom.y, pos.x - this.mouseFrom.x, pos.y - this.mouseFrom.y) + } + + this.onCopy = (e) => { + const block = this.getBlock() + var rows = [] + for (var i = 0; i < block.length; i++) { + rows.push(block[i].join('')) + } + const content = rows.join('\n') + const clipboard = e.clipboardData + e.clipboardData.setData('text/plain', content) + e.clipboardData.setData('text/source', content) + e.preventDefault() + } + + this.onCut = (e) => { + this.onCopy(e) + this.erase() + } + + this.onPaste = (e) => { + const data = e.clipboardData.getData('text/source') + this.writeBlock(data.split(/\r?\n/), false) + this.scaleTo(data.split('\n')[0].length, data.split('\n').length) + e.preventDefault() + } + + this.tilePos = (x, y, w = terminal.tile.w, h = terminal.tile.h) => { + return { x: parseInt((x - 30) / w), y: parseInt((y - 30) / h) } + } + function sense (s) { return s === s.toUpperCase() && s.toLowerCase() !== s.toUpperCase() } function clamp (v, min, max) { return v < min ? min : v > max ? max : v } } diff --git a/desktop/sources/scripts/lib/acels.js b/desktop/sources/scripts/lib/acels.js new file mode 100644 index 0000000..962d58e --- /dev/null +++ b/desktop/sources/scripts/lib/acels.js @@ -0,0 +1,123 @@ +'use strict' + +function Acels () { + this.all = {} + this.pipe = null + + this.install = (host = window) => { + host.addEventListener('keydown', this.onKeyDown, false) + host.addEventListener('keyup', this.onKeyUp, false) + } + + this.set = (cat, name, accelerator, downfn, upfn) => { + if (this.all[accelerator]) { console.warn('Acels', `Trying to overwrite ${this.all[accelerator].name}, with ${name}.`) } + this.all[accelerator] = { cat, name, downfn, upfn, accelerator } + } + + this.get = (accelerator) => { + return this.all[accelerator] + } + + this.sort = () => { + const h = {} + for (const item of Object.values(this.all)) { + if (!h[item.cat]) { h[item.cat] = [] } + h[item.cat].push(item) + } + return h + } + + this.convert = (event) => { + const accelerator = event.key === ' ' ? 'Space' : event.key.substr(0, 1).toUpperCase() + event.key.substr(1) + if ((event.ctrlKey || event.metaKey) && event.shiftKey) { + return `CmdOrCtrl+Shift+${accelerator}` + } + if (event.shiftKey) { + return `Shift+${accelerator}` + } + if (event.altKey) { + return `Alt+${accelerator}` + } + if (event.ctrlKey || event.metaKey) { + return `CmdOrCtrl+${accelerator}` + } + return accelerator + } + + this.pipe = (obj) => { + this.pipe = obj + } + + this.onKeyDown = (e) => { + const target = this.get(this.convert(e)) + if (!target || !target.downfn) { return this.pipe ? this.pipe.onKeyDown(e) : null } + target.downfn() + e.preventDefault() + } + + this.onKeyUp = (e) => { + const target = this.get(this.convert(e)) + if (!target || !target.upfn) { return this.pipe ? this.pipe.onKeyUp(e) : null } + target.upfn() + e.preventDefault() + } + + this.toMarkdown = () => { + const cats = this.sort() + let text = '' + for (const cat in cats) { + text += `\n### ${cat}\n\n` + for (const item of cats[cat]) { + text += `- \`${item.accelerator}\`: ${item.info}\n` + } + } + return text.trim() + } + + this.toString = () => { + const cats = this.sort() + let text = '' + for (const cat in cats) { + for (const item of cats[cat]) { + text += `${cat}: ${item.name} | ${item.accelerator}\n` + } + } + return text.trim() + } + + // Electron specifics + + this.inject = (name = 'Untitled') => { + const app = require('electron').remote.app + const injection = [] + + injection.push({ + label: name, + submenu: [ + { label: 'About', click: () => { require('electron').shell.openExternal('https://github.com/hundredrabbits/' + name) } }, + { label: 'Download Themes', click: () => { require('electron').shell.openExternal('https://github.com/hundredrabbits/Themes') } }, + { label: 'Fullscreen', accelerator: 'CmdOrCtrl+Enter', click: () => { app.toggleFullscreen() } }, + { label: 'Hide', accelerator: 'CmdOrCtrl+H', click: () => { app.toggleVisible() } }, + { label: 'Toggle Menubar', accelerator: 'Alt+H', click: () => { app.toggleMenubar() } }, + { label: 'Inspect', accelerator: 'CmdOrCtrl+.', click: () => { app.inspect() } }, + { label: 'Quit', accelerator: 'CmdOrCtrl+Q', click: () => { app.exit() } } + ] + }) + + const sorted = this.sort() + for (const cat of Object.keys(sorted)) { + const submenu = [] + for (const option of sorted[cat]) { + if (option.role) { + submenu.push({ role: option.role }) + } else if (option.type) { + submenu.push({ type: option.type }) + } else { + submenu.push({ label: option.name, accelerator: option.accelerator, click: option.downfn }) + } + } + injection.push({ label: cat, submenu: submenu }) + } + app.injectMenu(injection) + } +} diff --git a/desktop/sources/scripts/lib/controller.js b/desktop/sources/scripts/lib/controller.js deleted file mode 100644 index 6b81027..0000000 --- a/desktop/sources/scripts/lib/controller.js +++ /dev/null @@ -1,81 +0,0 @@ -'use strict' - -export default function Controller () { - this.menu = { default: {} } - this.mode = 'default' - this.app = require('electron').remote.app - - this.start = function () { - } - - this.add = function (mode, cat, label, fn, accelerator) { - if (!this.menu[mode]) { this.menu[mode] = {} } - if (!this.menu[mode][cat]) { this.menu[mode][cat] = {} } - this.menu[mode][cat][label] = { - fn: function (_menuItem, browserWindow) { - browserWindow.webContents.focus() - fn.apply(this, arguments) - }, - accelerator: accelerator - } - } - - this.addRole = function (mode, cat, label) { - if (!this.menu[mode]) { this.menu[mode] = {} } - if (!this.menu[mode][cat]) { this.menu[mode][cat] = {} } - 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] = {} } - } - - this.set = function (mode = 'default') { - this.mode = mode - this.commit() - } - - this.format = function () { - const f = [] - const m = this.menu[this.mode] - for (const cat in m) { - const submenu = [] - for (const name in m[cat]) { - 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 }) - } - } - f.push({ label: cat, submenu: submenu }) - } - return f - } - - this.commit = function () { - console.log('Controller', 'Changing..') - this.app.injectMenu(this.format()) - } - - this.accelerator = function (key, menu) { - const acc = { basic: null, ctrl: null } - for (const cat in menu) { - const options = menu[cat] - for (const id in options.submenu) { - const option = options.submenu[id]; if (option.role) { continue } - acc.basic = (option.accelerator.toLowerCase() === key.toLowerCase()) ? option.label.toUpperCase().replace('TOGGLE ', '').substr(0, 8).trim() : acc.basic - acc.ctrl = (option.accelerator.toLowerCase() === ('CmdOrCtrl+' + key).toLowerCase()) ? option.label.toUpperCase().replace('TOGGLE ', '').substr(0, 8).trim() : acc.ctrl - } - } - return acc - } -} diff --git a/desktop/sources/scripts/history.js b/desktop/sources/scripts/lib/history.js index 1d77a58..1bbf0ae 100644 --- a/desktop/sources/scripts/history.js +++ b/desktop/sources/scripts/lib/history.js @@ -1,6 +1,6 @@ 'use strict' -export default function History () { +function History () { this.index = 0 this.frames = [] this.host = null diff --git a/desktop/sources/scripts/lib/theme.js b/desktop/sources/scripts/lib/theme.js index a2777fe..94061ed 100644 --- a/desktop/sources/scripts/lib/theme.js +++ b/desktop/sources/scripts/lib/theme.js @@ -1,20 +1,25 @@ 'use strict' -export default function Theme (_default) { - const fs = require('fs') - const url = require('url') +/* global localStorage */ +/* global FileReader */ +/* global DOMParser */ - this.active = _default +function Theme () { + const themer = this + + this.default = { background: '#eee', f_high: '#000', f_med: '#999', f_low: '#ccc', f_inv: '#000', b_high: '#000', b_med: '#888', b_low: '#aaa', b_inv: '#ffb545' } + this.active = {} this.el = document.createElement('style') this.el.type = 'text/css' - this.install = function (host = document.body, callback) { + this.install = (host = document.body, callback) => { host.appendChild(this.el) this.callback = callback } - this.start = function () { + this.start = () => { + this.active = this.default console.log('Theme', 'Starting..') if (isJson(localStorage.theme)) { const storage = JSON.parse(localStorage.theme) @@ -24,12 +29,12 @@ export default function Theme (_default) { return } } - this.load(_default) + this.load(this.active) } - this.load = function (data) { + this.load = (data) => { const theme = parse(data) - if (!validate(theme)) { console.warn('Theme', 'Not a theme', theme); return } + if (!validate(theme)) { return } console.log('Theme', 'Loaded theme!') this.el.innerHTML = `:root { --background: ${theme.background}; --f_high: ${theme.f_high}; --f_med: ${theme.f_med}; --f_low: ${theme.f_low}; --f_inv: ${theme.f_inv}; --b_high: ${theme.b_high}; --b_med: ${theme.b_med}; --b_low: ${theme.b_low}; --b_inv: ${theme.b_inv}; }` localStorage.setItem('theme', JSON.stringify(theme)) @@ -39,18 +44,12 @@ export default function Theme (_default) { } } - this.reset = function () { - this.load(_default) - } - - this.setImage = function (path) { - document.body.style.backgroundImage = path && fs.existsSync(path) && document.body.style.backgroundImage !== `url(${url.pathToFileURL(path)})` ? `url(${url.pathToFileURL(path)})` : '' + this.reset = () => { + this.load(this.default) } - this.set = function (key, value) { - if (!this.active[key]) { console.warn('Theme', 'Unknown key ' + key); return } - if (!isColor(value)) { console.warn('Theme', 'Not a color ' + value); return } - this.active[key] = '#' + value + this.get = (key) => { + return this.active[key] } function parse (any) { @@ -60,7 +59,7 @@ export default function Theme (_default) { // Drag - this.drag = function (e) { + this.drag = (e) => { e.stopPropagation() e.preventDefault() e.dataTransfer.dropEffect = 'copy' @@ -71,10 +70,10 @@ export default function Theme (_default) { e.stopPropagation() const file = e.dataTransfer.files[0] if (!file || !file.name) { console.warn('Theme', 'Unnamed file.'); return } - if (file.name.indexOf('.thm') < 0 && file.name.indexOf('.svg') < 0) { console.warn('Theme', 'Skipped, not a theme'); return } + if (file.name.indexOf('.thm') < 0 && file.name.indexOf('.svg') < 0) { return } const reader = new FileReader() - reader.onload = (e) => { - this.load(e.target.result) + reader.onload = function (e) { + themer.load(e.target.result) } reader.readAsText(file) } @@ -82,11 +81,12 @@ export default function Theme (_default) { this.open = () => { const fs = require('fs') const { dialog, app } = require('electron').remote - const paths = dialog.showOpenDialogSync(app.win, { properties: ['openFile'], filters: [{ name: 'Themes', extensions: ['svg'] }] }) + const paths = dialog.showOpenDialog(app.win, { properties: ['openFile'], filters: [{ name: 'Themes', extensions: ['svg'] }] }) if (!paths) { console.log('Nothing to load'); return } - const data = fs.readFileSync(paths[0], 'utf8') - if (!data) { return } - this.load(data) + fs.readFile(paths[0], 'utf8', function (err, data) { + if (err) throw err + themer.load(data) + }) } window.addEventListener('dragover', this.drag) @@ -131,10 +131,6 @@ export default function Theme (_default) { try { JSON.parse(text); return true } catch (error) { return false } } - function isColor (str) { - return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test('#' + str) - } - function isHtml (text) { try { new DOMParser().parseFromString(text, 'text/xml'); return true } catch (error) { return false } } diff --git a/desktop/sources/scripts/source.js b/desktop/sources/scripts/source.js index 25a4095..61097b4 100644 --- a/desktop/sources/scripts/source.js +++ b/desktop/sources/scripts/source.js @@ -1,9 +1,11 @@ 'use strict' -export default function Source (terminal) { +function Source (terminal) { const fs = require('fs') const path = require('path') - const { dialog, app } = require('electron').remote + const electron = require('electron') + const dialog = electron ? electron.remote.dialog : null + const app = electron ? electron.remote.app : null this.path = null this.queue = [] @@ -29,11 +31,14 @@ export default function Source (terminal) { const paths = dialog.showOpenDialogSync(app.win, { properties: ['openFile'], filters: [{ name: 'Orca Machines', extensions: ['orca'] }] }) if (!paths) { console.log('Nothing to load'); return } this.read(paths[0]) + terminal.toggleGuide(false) } this.save = function (quitAfter = false) { console.log('Source', 'Saving file..') - if (this.path) { + if (!require('electron')) { + this.download('orca', 'orca', this.generate(), 'text/plain') + } else if (this.path) { this.write(this.path, this.generate(), quitAfter) } else { this.saveAs(quitAfter) @@ -49,6 +54,17 @@ export default function Source (terminal) { this.path = path } + this.download = (name, ext, content, type, settings = 'charset=utf-8') => { + const link = document.createElement('a') + link.setAttribute('download', `${name}-${timestamp()}.${ext}`) + if (type === 'image/png' || type === 'image/jpeg') { + link.setAttribute('href', content) + } else { + link.setAttribute('href', 'data:' + type + ';' + settings + ',' + encodeURIComponent(content)) + } + link.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true, view: window })) + } + this.revert = function () { if (!this.path) { return } console.log('Source', 'Revert a file..') @@ -81,8 +97,10 @@ export default function Source (terminal) { } } - this.read = function (loc = this.path) { + this.read = function (loc = this.path, content = '') { if (!loc) { return } + if (!fs && !content) { console.warn('Source', 'FileSystem unavailable'); return } + if (!fs && content) { this.load(content); return } if (!fs.existsSync(loc)) { console.warn('Source', 'File does not exist: ' + loc); return } console.log('Source', 'Reading ' + loc) this.path = loc @@ -230,4 +248,9 @@ export default function Source (terminal) { } return c } + + function timestamp (d = new Date(), e = new Date(d)) { + const ms = e - d.setHours(0, 0, 0, 0) + return (ms / 8640 / 10000).toFixed(6).substr(2, 6) + } } diff --git a/desktop/sources/scripts/terminal.js b/desktop/sources/scripts/terminal.js index 603cab2..3bb46ec 100644 --- a/desktop/sources/scripts/terminal.js +++ b/desktop/sources/scripts/terminal.js @@ -1,31 +1,23 @@ 'use strict' -import Orca from '../../core/orca.js' -import IO from '../../core/io.js' -import Cursor from './cursor.js' -import Source from './source.js' -import History from './history.js' -import Commander from './commander.js' -import Clock from './clock.js' -import Theme from './lib/theme.js' -import Controller from './lib/controller.js' -import library from '../../core/library.js' - -export default function Terminal () { - this.version = 145 +/* global library */ + +function Terminal () { + this.version = 146 this.library = library - this.orca = new Orca() + this.acels = new Acels() + this.orca = new Orca(this.library) this.io = new IO(this) this.cursor = new Cursor(this) this.source = new Source(this) this.commander = new Commander(this) this.clock = new Clock(this) this.history = new History() - this.controller = new Controller() // Themes - this.theme = new Theme({ background: '#000000', f_high: '#ffffff', f_med: '#777777', f_low: '#444444', f_inv: '#000000', b_high: '#eeeeee', b_med: '#72dec2', b_low: '#444444', b_inv: '#ffb545' }) + this.theme = new Theme() + this.theme.default = { background: '#000000', f_high: '#ffffff', f_med: '#777777', f_low: '#444444', f_inv: '#000000', b_high: '#eeeeee', b_med: '#72dec2', b_low: '#444444', b_inv: '#ffb545' } this.el = document.createElement('canvas') this.context = this.el.getContext('2d') @@ -44,82 +36,105 @@ export default function Terminal () { host.appendChild(this.el) this.theme.install(host) - this.controller.add('default', '*', 'About', () => { require('electron').shell.openExternal('https://github.com/hundredrabbits/Orca') }, 'CmdOrCtrl+,') - this.controller.add('default', '*', 'Fullscreen', () => { require('electron').remote.app.toggleFullscreen() }, 'CmdOrCtrl+Enter') - this.controller.add('default', '*', 'Hide', () => { require('electron').remote.app.toggleVisible() }, 'CmdOrCtrl+H') - this.controller.add('default', '*', 'Toggle Menubar', () => { require('electron').remote.app.toggleMenubar() }, 'Alt+H') - this.controller.add('default', '*', 'Inspect', () => { require('electron').remote.app.inspect() }, 'CmdOrCtrl+.') - this.controller.add('default', '*', 'Reset', () => { this.reset() }, 'CmdOrCtrl+Backspace') - this.controller.add('default', '*', 'Quit', () => { this.io.silence(); this.source.quit() }, 'CmdOrCtrl+Q') - - this.controller.add('default', 'File', 'New', () => { this.source.new() }, 'CmdOrCtrl+N') - this.controller.add('default', 'File', 'Save', () => { this.source.save() }, 'CmdOrCtrl+S') - this.controller.add('default', 'File', 'Save As', () => { this.source.saveAs() }, 'CmdOrCtrl+Shift+S') - this.controller.add('default', 'File', 'Open', () => { this.source.open() }, 'CmdOrCtrl+O') - this.controller.add('default', 'File', 'Resume', () => { this.source.resume() }) - this.controller.add('default', 'File', 'Revert', () => { this.source.revert() }, 'CmdOrCtrl+W') - - this.controller.add('default', 'Edit', 'Toggle Insert Mode', () => { this.cursor.toggleMode(1) }, 'CmdOrCtrl+I') - this.controller.add('default', 'Edit', 'Block Comment', () => { this.cursor.comment() }, 'CmdOrCtrl+/') - this.controller.add('default', 'Edit', 'Find', () => { this.commander.start('find:') }, 'CmdOrCtrl+P') - this.controller.add('default', 'Edit', 'Inject', () => { this.commander.start('inject:') }, 'CmdOrCtrl+J') - this.controller.add('default', 'Edit', 'Trigger Operator', () => { this.cursor.trigger() }, 'CmdOrCtrl+B') - this.controller.addSpacer('default', 'Edit', 'selection') - this.controller.add('default', 'Edit', 'Select All', () => { this.cursor.selectAll() }, 'CmdOrCtrl+A') - this.controller.add('default', 'Edit', 'Erase Selection', () => { this.cursor.erase() }, 'Backspace') - this.controller.add('default', 'Edit', 'Copy Selection', () => { this.cursor.copy() }, 'CmdOrCtrl+C') - this.controller.add('default', 'Edit', 'Cut Selection', () => { this.cursor.cut() }, 'CmdOrCtrl+X') - this.controller.add('default', 'Edit', 'Paste Selection', () => { this.cursor.paste(false) }, 'CmdOrCtrl+V') - this.controller.add('default', 'Edit', 'Paste Over', () => { this.cursor.paste(true) }, 'CmdOrCtrl+Shift+V') - this.controller.add('default', 'Edit', 'Undo', () => { this.history.undo() }, 'CmdOrCtrl+Z') - this.controller.add('default', 'Edit', 'Redo', () => { this.history.redo() }, 'CmdOrCtrl+Shift+Z') - - this.controller.add('default', 'Clock', 'Play/Pause', () => { this.clock.togglePlay(false) }, 'Space') - this.controller.add('default', 'Clock', 'Frame By Frame', () => { this.clock.touch() }, 'CmdOrCtrl+F') - this.controller.add('default', 'Clock', 'Reset Frame', () => { this.clock.resetFrame() }, 'CmdOrCtrl+R') - this.controller.add('default', 'Clock', 'Incr. Speed', () => { this.clock.modSpeed(1) }, '>') - this.controller.add('default', 'Clock', 'Decr. Speed', () => { this.clock.modSpeed(-1) }, '<') - this.controller.add('default', 'Clock', 'Incr. Speed(10x)', () => { this.clock.modSpeed(10, true) }, 'CmdOrCtrl+>') - this.controller.add('default', 'Clock', 'Decr. Speed(10x)', () => { this.clock.modSpeed(-10, true) }, 'CmdOrCtrl+<') - - this.controller.add('default', 'View', 'Zoom In', () => { this.modZoom(0.0625) }, 'CmdOrCtrl+=') - this.controller.add('default', 'View', 'Zoom Out', () => { this.modZoom(-0.0625) }, 'CmdOrCtrl+-') - this.controller.add('default', 'View', 'Zoom Reset', () => { this.modZoom(1, true) }, 'CmdOrCtrl+0') - this.controller.add('default', 'View', 'Toggle Retina', () => { this.toggleRetina() }, '`') - this.controller.add('default', 'View', 'Toggle Hardmode', () => { this.toggleHardmode() }, 'Tab') - this.controller.add('default', 'View', 'Toggle Guide', () => { this.toggleGuide() }, 'CmdOrCtrl+G') - this.controller.addSpacer('default', 'View', 'commander') - this.controller.add('default', 'View', 'Toggle Commander', () => { this.commander.start() }, 'CmdOrCtrl+K') - this.controller.add('default', 'View', 'Run Commander', () => { this.commander.run() }, 'Enter') - this.controller.addSpacer('default', 'View', 'sizes') - this.controller.add('default', 'View', 'Incr. Col', () => { this.modGrid(1, 0) }, ']') - this.controller.add('default', 'View', 'Decr. Col', () => { this.modGrid(-1, 0) }, '[') - this.controller.add('default', 'View', 'Incr. Row', () => { this.modGrid(0, 1) }, '}') - this.controller.add('default', 'View', 'Decr. Row', () => { this.modGrid(0, -1) }, '{') - - this.controller.add('default', 'Midi', 'Default') - this.controller.add('default', 'UDP', 'Default') - this.controller.add('default', 'OSC', 'Default') - - this.controller.add('default', 'Theme', 'Open Theme', () => { this.theme.open() }, 'CmdOrCtrl+Shift+O') - this.controller.add('default', 'Theme', 'Reset Theme', () => { this.theme.reset() }, 'CmdOrCtrl+Shift+Backspace') - this.controller.addSpacer('default', 'Theme', 'Download') - this.controller.add('default', 'Theme', 'Download Themes..', () => { require('electron').shell.openExternal('https://github.com/hundredrabbits/Themes') }) - - this.controller.commit() + this.acels.set('File', 'New', 'CmdOrCtrl+N', () => { this.source.new() }) + this.acels.set('File', 'Save', 'CmdOrCtrl+S', () => { this.source.save() }) + this.acels.set('File', 'Save', 'CmdOrCtrl+Shift+S', () => { this.source.saveAs() }) + this.acels.set('File', 'Open', 'CmdOrCtrl+O', () => { this.source.open() }) + this.acels.set('File', 'Revert', 'CmdOrCtrl+W', () => { this.source.revert() }) + + this.acels.set('Edit', 'Select All', 'CmdOrCtrl+A', () => { this.cursor.selectAll() }) + this.acels.set('Edit', 'Erase Selection', 'Backspace', () => { this.cursor.erase() }) + // this.acels.set('Edit', 'Copy Selection', 'CmdOrCtrl+C', () => { this.cursor.copy() }) + // this.acels.set('Edit', 'Cut Selection', 'CmdOrCtrl+X', () => { this.cursor.cut() }) + // this.acels.set('Edit', 'Paste Selection', 'CmdOrCtrl+V', () => { this.cursor.paste(false) }) + // this.acels.set('Edit', 'Paste Over', 'CmdOrCtrl+Shift+V', () => { this.cursor.paste(true) }) + this.acels.set('Edit', 'Undo', 'CmdOrCtrl+Z', () => { this.history.undo() }) + this.acels.set('Edit', 'Redo', 'CmdOrCtrl+Shift+Z', () => { this.history.redo() }) + + this.acels.set('Project', 'Find', 'CmdOrCtrl+J', () => { this.commander.start('find:') }) + this.acels.set('Project', 'Inject', 'CmdOrCtrl+B', () => { this.commander.start('inject:') }) + this.acels.set('Project', 'Toggle Commander', 'CmdOrCtrl+K', () => { this.commander.start() }) + this.acels.set('Project', 'Run Commander', 'Enter', () => { this.commander.run() }) + + this.acels.set('Cursor', 'Toggle Insert Mode', 'CmdOrCtrl+I', () => { this.cursor.toggleMode(1) }) + this.acels.set('Cursor', 'Toggle Block Comment', 'CmdOrCtrl+/', () => { this.cursor.comment() }) + this.acels.set('Cursor', 'Trigger Operator', 'CmdOrCtrl+P', () => { this.cursor.trigger() }) + this.acels.set('Cursor', 'Reset', 'Escape', () => { terminal.toggleGuide(false); terminal.commander.stop(); terminal.clear(); terminal.isPaused = false; terminal.cursor.reset() }) + + this.acels.set('Move', 'Move North', 'ArrowUp', () => { terminal.cursor.move(0, 1) }) + this.acels.set('Move', 'Move East', 'ArrowRight', () => { terminal.cursor.move(1, 0) }) + this.acels.set('Move', 'Move South', 'ArrowDown', () => { terminal.cursor.move(0, -1) }) + this.acels.set('Move', 'Move West', 'ArrowLeft', () => { terminal.cursor.move(-1, 0) }) + this.acels.set('Move', 'Scale North', 'Shift+ArrowUp', () => { terminal.cursor.scale(0, 1) }) + this.acels.set('Move', 'Scale East', 'Shift+ArrowRight', () => { terminal.cursor.scale(1, 0) }) + this.acels.set('Move', 'Scale South', 'Shift+ArrowDown', () => { terminal.cursor.scale(0, -1) }) + this.acels.set('Move', 'Scale West', 'Shift+ArrowLeft', () => { terminal.cursor.scale(-1, 0) }) + this.acels.set('Move', 'Drag North', 'Alt+ArrowUp', () => { terminal.cursor.drag(0, 1) }) + this.acels.set('Move', 'Drag East', 'Alt+ArrowRight', () => { terminal.cursor.drag(1, 0) }) + this.acels.set('Move', 'Drag South', 'Alt+ArrowDown', () => { terminal.cursor.drag(0, -1) }) + this.acels.set('Move', 'Drag West', 'Alt+ArrowLeft', () => { terminal.cursor.drag(-1, 0) }) + this.acels.set('Move', 'Move North(Leap)', 'CmdOrCtrl+ArrowUp', () => { terminal.cursor.move(0, this.grid.h) }) + this.acels.set('Move', 'Move East(Leap)', 'CmdOrCtrl+ArrowRight', () => { terminal.cursor.move(this.grid.w, 0) }) + this.acels.set('Move', 'Move South(Leap)', 'CmdOrCtrl+ArrowDown', () => { terminal.cursor.move(0, -this.grid.h) }) + this.acels.set('Move', 'Move West(Leap)', 'CmdOrCtrl+ArrowLeft', () => { terminal.cursor.move(-this.grid.w, 0) }) + this.acels.set('Move', 'Scale North(Leap)', 'CmdOrCtrl+Shift+ArrowUp', () => { terminal.cursor.scale(0, this.grid.h) }) + this.acels.set('Move', 'Scale East(Leap)', 'CmdOrCtrl+Shift+ArrowRight', () => { terminal.cursor.scale(this.grid.w, 0) }) + this.acels.set('Move', 'Scale South(Leap)', 'CmdOrCtrl+Shift+ArrowDown', () => { terminal.cursor.scale(0, -this.grid.h) }) + this.acels.set('Move', 'Scale West(Leap)', 'CmdOrCtrl+Shift+ArrowLeft', () => { terminal.cursor.scale(-this.grid.w, 0) }) + this.acels.set('Move', 'Drag North(Leap)', 'CmdOrCtrl+Alt+ArrowUp', () => { terminal.cursor.drag(0, this.grid.h) }) + this.acels.set('Move', 'Drag East(Leap)', 'CmdOrCtrl+Alt+ArrowRight', () => { terminal.cursor.drag(this.grid.w, 0) }) + this.acels.set('Move', 'Drag South(Leap)', 'CmdOrCtrl+Alt+ArrowDown', () => { terminal.cursor.drag(0, -this.grid.h) }) + this.acels.set('Move', 'Drag West(Leap)', 'CmdOrCtrl+Alt+ArrowLeft', () => { terminal.cursor.drag(-this.grid.w, 0) }) + + this.acels.set('Clock', 'Play/Pause', 'Space', () => { this.clock.togglePlay() }) + this.acels.set('Clock', 'Frame By Frame', 'CmdOrCtrl+F', () => { this.clock.touch() }) + this.acels.set('Clock', 'Reset Frame', 'CmdOrCtrl+Shift+R', () => { this.clock.resetFrame() }) + this.acels.set('Clock', 'Incr. Speed', 'Shift+>', () => { this.clock.modSpeed(1) }) + this.acels.set('Clock', 'Decr. Speed', 'Shift+<', () => { this.clock.modSpeed(-1) }) + this.acels.set('Clock', 'Incr. Speed(10x)', 'CmdOrCtrl+>', () => { this.clock.modSpeed(10, true) }) + this.acels.set('Clock', 'Decr. Speed(10x)', 'CmdOrCtrl+<', () => { this.clock.modSpeed(-10, true) }) + + this.acels.set('View', 'Toggle Retina', '`', () => { this.toggleRetina() }) + this.acels.set('View', 'Toggle Hardmode', 'Tab', () => { this.toggleHardmode() }) + this.acels.set('View', 'Toggle Guide', 'CmdOrCtrl+G', () => { this.toggleGuide() }) + this.acels.set('View', 'Incr. Col', ']', () => { this.modGrid(1, 0) }) + this.acels.set('View', 'Decr. Col', '[', () => { this.modGrid(-1, 0) }) + this.acels.set('View', 'Incr. Row', '}', () => { this.modGrid(0, 1) }) + this.acels.set('View', 'Decr. Row', '{', () => { this.modGrid(0, -1) }) + this.acels.set('View', 'Zoom In', 'CmdOrCtrl+=', () => { this.modZoom(0.0625) }) + this.acels.set('View', 'Zoom Out', 'CmdOrCtrl+-', () => { this.modZoom(-0.0625) }) + this.acels.set('View', 'Zoom Reset', 'CmdOrCtrl+0', () => { this.modZoom(1, true) }) + + this.acels.set('Midi', 'Play/Pause Midi', 'Shift+Space', () => { this.clock.togglePlay(true) }) + this.acels.set('Midi', 'Next Input Device', 'CmdOrCtrl+}', () => { this.io.midi.selectNextInput() }) + this.acels.set('Midi', 'Next Output Device', 'CmdOrCtrl+]', () => { this.io.midi.selectNextOutput() }) + this.acels.set('Midi', 'Refresh Devices', 'CmdOrCtrl+Shift+M', () => { this.io.midi.refresh() }) + + this.acels.set('Communication', 'Choose OSC Port', 'CmdOrCtrl+Shift+O', () => { this.commander.start('osc:') }) + this.acels.set('Communication', 'Choose UDP Port', 'CmdOrCtrl+Shift+U', () => { this.commander.start('udp:') }) + + this.acels.install(window) + this.acels.pipe(this.commander) } this.start = () => { + console.info('Terminal', 'Starting..') + console.info(`${this.acels}`) this.theme.start() this.io.start() this.source.start() this.history.bind(this.orca, 's') this.history.record(this.orca.s) this.clock.start() + this.cursor.start() this.update() this.el.className = 'ready' - this.toggleGuide(this.reqGuide() === true) + this.toggleGuide() + } + + this.whenOpen = (file) => { + } this.run = () => { @@ -306,26 +321,24 @@ export default function Terminal () { const col = this.grid.w const variables = Object.keys(this.orca.variables).join('') - if (this.commander.isActive === true) { - this.write(`${this.commander.query}${this.orca.f % 2 === 0 ? '_' : ''}`, col * 0, this.orca.h + 1, this.grid.w * 4) - } else { - this.write(`${this.cursor.x},${this.cursor.y}${this.cursor.mode === 1 ? '+' : ''}`, col * 0, this.orca.h + 1, this.grid.w, this.cursor.mode === 1 ? 1 : 2) - this.write(`${this.cursor.w}:${this.cursor.h}`, col * 1, this.orca.h + 1, this.grid.w) - this.write(`${this.cursor.inspect()}`, col * 2, this.orca.h + 1, this.grid.w) - this.write(`${this.orca.f}f${this.isPaused ? '*' : ''}`, col * 3, this.orca.h + 1, this.grid.w) - } + // Top Row(cursor) + + this.write(this.orca.f < 15 ? `ver${this.version}` : `${this.cursor.inspect()}`, col * 0, this.orca.h, this.grid.w) + this.write(`${this.cursor.x},${this.cursor.y}${this.cursor.mode === 1 ? '+' : ''}`, col * 1, this.orca.h, this.grid.w, this.cursor.mode === 1 ? 1 : 2) + this.write(`${this.cursor.w}:${this.cursor.h}`, col * 2, this.orca.h, this.grid.w) + this.write(`${this.orca.f}f${this.isPaused ? '*' : ''}`, col * 3, this.orca.h, this.grid.w) + this.write(`${this.io.inspect(this.grid.w)}`, col * 4, this.orca.h, this.grid.w) - this.write(`${this.orca.w}x${this.orca.h}`, col * 0, this.orca.h, this.grid.w) - this.write(`${this.grid.w}/${this.grid.h}${this.tile.w !== 10 ? ' ' + (this.tile.w / 10).toFixed(1) : ''}`, col * 1, this.orca.h, this.grid.w) - this.write(`${this.source}`, col * 2, this.orca.h, this.grid.w, this.source.queue.length > this.orca.f ? 3 : 2) - this.write(`${this.clock}`, col * 3, this.orca.h, this.grid.w, this.clock.isPuppet === true ? 3 : 2) + // Low Row(project) - if (this.orca.f < 15) { - this.write(`${this.io.midi}`, col * 4, this.orca.h, this.grid.w * 2) - this.write(`Version ${this.version}`, col * 4, this.orca.h + 1, this.grid.w * 2) + if (this.commander.isActive === true) { + this.write(`${this.commander.query}${this.orca.f % 2 === 0 ? '_' : ''}`, col * 0, this.orca.h + 1, this.grid.w * 4) } else { - this.write(`${this.io.inspect(this.grid.w)}`, col * 4, this.orca.h, this.grid.w) - this.write(`${display(variables, this.orca.f, this.grid.w)}`, col * 4, this.orca.h + 1, this.grid.w) + this.write(`${this.source}`, col * 0, this.orca.h + 1, this.grid.w, this.source.queue.length > this.orca.f ? 3 : 2) + this.write(`${this.orca.w}x${this.orca.h}`, col * 1, this.orca.h + 1, this.grid.w) + this.write(`${this.grid.w}/${this.grid.h}${this.tile.w !== 10 ? ' ' + (this.tile.w / 10).toFixed(1) : ''}`, col * 2, this.orca.h + 1, this.grid.w) + this.write(`${this.clock}`, col * 3, this.orca.h + 1, this.grid.w, this.clock.isPuppet === true ? 3 : 2) + this.write(`${this.io.midi}`, col * 4, this.orca.h + 1, this.grid.w * 4) } } @@ -369,6 +382,7 @@ export default function Terminal () { // Resize tools this.fit = () => { + if (!require('electron')) { return } const size = { w: (this.orca.w * this.tile.w) + 60, h: (this.orca.h * this.tile.h) + 60 + (2 * this.tile.h) } const win = require('electron').remote.getCurrentWindow() const winSize = win.getSize() @@ -457,7 +471,11 @@ export default function Terminal () { if (!path || path.indexOf('.orca') < 0) { console.log('Orca', 'Not a orca file'); return } - this.source.read(path) + const reader = new FileReader() + reader.onload = (event) => { + this.source.read(path, event.target.result) + } + reader.readAsText(file, 'UTF-8') }) window.onresize = (event) => { diff --git a/desktop/sources/scripts/timer.js b/desktop/sources/scripts/timer.js deleted file mode 100644 index 823094f..0000000 --- a/desktop/sources/scripts/timer.js +++ /dev/null @@ -1,6 +0,0 @@ -'use strict' - -onmessage = (event) => { - console.log('Timer', 'New Interval ' + event.data + 'ms') - setInterval(() => { postMessage(true) }, event.data) -} @@ -1,40 +1,49 @@ <html> <head> - <meta charset='utf-8'> - <!-- Basic --> - <meta name='author' content='Devine Lu Linvega'> - <meta name='description' content='Orca: Esoteric Programming Language'/> - <meta name='keywords' content='Orca, livecoding, programming language, lisp, udp, midi, ide' /> - <meta name='license' content='name=BY-NC-SA(4.0), url=https://creativecommons.org/licenses/by-nc-sa/4.0/'/> - <meta name='thumbnail' content='https://wiki.xxiivv.com/media/services/thumbnail.jpg' /> - <!-- Twitter --> - <meta name='twitter:card' content='summary'> - <meta name='twitter:site' content='@neauoire'> - <meta name='twitter:title' content='Orca'> - <meta name='twitter:description' content='An Esoteric Programming Language'> - <meta name='twitter:creator' content='@neauoire'> - <meta name='twitter:image' content='https://wiki.xxiivv.com/media/services/rss.jpg'> - <!-- Facebook --> - <meta property='og:title' content='Orca' /> - <meta property='og:type' content='article' /> - <meta property='og:url' content='http://wiki.xxiivv.com/' /> - <meta property='og:image' content='https://wiki.xxiivv.com/media/services/rss.jpg' /> - <meta property='og:description' content='An Esoteric Programming Language' /> - <meta property='og:site_name' content='XXIIVV' /> - <!-- Defaults --> + <meta charset='utf-8'> <link rel="stylesheet" type="text/css" href="desktop/sources/links/style.css"/> + + <script type="text/javascript"> + function require(name){ + console.warn('Failed to require '+name) + } + </script> + + <script type="text/javascript" src="desktop/sources/scripts/lib/acels.js"></script> + <script type="text/javascript" src="desktop/sources/scripts/lib/theme.js"></script> + <script type="text/javascript" src="desktop/sources/scripts/lib/history.js"></script> + + <script type="text/javascript" src="desktop/sources/scripts/core/library.js"></script> + <script type="text/javascript" src="desktop/sources/scripts/core/io.js"></script> + <script type="text/javascript" src="desktop/sources/scripts/core/operator.js"></script> + <script type="text/javascript" src="desktop/sources/scripts/core/orca.js"></script> + <script type="text/javascript" src="desktop/sources/scripts/core/transpose.js"></script> + + <script type="text/javascript" src="desktop/sources/scripts/core/io/cc.js"></script> + <script type="text/javascript" src="desktop/sources/scripts/core/io/midi.js"></script> + <script type="text/javascript" src="desktop/sources/scripts/core/io/mono.js"></script> + <script type="text/javascript" src="desktop/sources/scripts/core/io/osc.js"></script> + <script type="text/javascript" src="desktop/sources/scripts/core/io/udp.js"></script> + + <script type="text/javascript" src="desktop/sources/scripts/clock.js"></script> + <script type="text/javascript" src="desktop/sources/scripts/commander.js"></script> + <script type="text/javascript" src="desktop/sources/scripts/cursor.js"></script> + <script type="text/javascript" src="desktop/sources/scripts/source.js"></script> + <script type="text/javascript" src="desktop/sources/scripts/terminal.js"></script> + <title>Orca — Web</title> </head> <body> - <script type="module" src="browser/mock/require.js"></script> - <script type="module"> - console.clear() - import Terminal from "./desktop/sources/scripts/terminal.js"; + <script> + 'use strict' + const terminal = new Terminal() - window.__dirname = "desktop/sources"; - window.terminal = terminal + terminal.install(document.body) - terminal.start() + + window.addEventListener('load', () => { + terminal.start() + }) </script> </body> </html> |