├── .gitignore ├── LICENSE.md ├── README.md ├── browser ├── index.html └── mock │ ├── electron.js │ ├── fs.js │ └── require.js ├── desktop ├── icon.icns ├── icon.ico ├── icon.png ├── icon.svg ├── main.js ├── package-lock.json ├── package.json └── sources │ ├── index.html │ ├── links │ ├── fonts.css │ ├── main.css │ ├── reset.css │ ├── style.css │ └── theme.css │ ├── media │ └── fonts │ │ ├── input_mono_medium.ttf │ │ └── input_mono_regular.ttf │ └── scripts │ ├── commander.js │ ├── interface.channel.js │ ├── interface.effect.js │ ├── interface.js │ ├── lib │ ├── controller.js │ └── theme.js │ ├── listener.js │ ├── mixer.js │ ├── pilot.js │ ├── recorder.js │ └── transpose.js └── resources ├── device.jpg └── preview.jpg /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | builds/ 3 | .DS_Store 4 | */.DS_Store 5 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Hundredrabbits 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Pilot 2 | 3 | [Pilot](http://wiki.xxiivv.com/Pilot) is a **UDP synthesizer** designed to be controlled externally. It was created as a companion application to the livecoding environment [ORCA](https://hundredrabbits.itch.io/orca). 4 | 5 | ## Install & Run 6 | 7 | You can download [builds](https://hundredrabbits.itch.io/pilot) for **OSX, Windows and Linux**, or if you wish to build it yourself, follow these steps: 8 | 9 | ``` 10 | git clone https://github.com/hundredrabbits/Pilot.git 11 | cd Pilot/desktop/ 12 | npm install 13 | npm start 14 | ``` 15 | 16 | 17 | 18 | ## Commands 19 | 20 | Pilot has 16 voices, and 8 effects. Commands can be entered directly with the input bar, or through UDP via the port `49161`. You can send multiple commands at once by using the `;` character. For example, `03C;13E` will play a `C3` and `E3` chord. 21 | 22 | ### Channel 23 | 24 | #### Play 25 | 26 | The Play commands allows you to play synth notes. 27 | 28 | | Command | Channel | Octave | Note | Velocity | Length | 29 | | :- | :-: | :-: | :-: | :-: | :-: | 30 | | `04C` | 0 | 4 | C | _64_ | _1/16_ | 31 | | `04Cf` | 0 | 4 | C | 127 | _1/16_ | 32 | | `04Cff` | 0 | 4 | C | 127 | 1bar | 33 | 34 | #### Settings 35 | 36 | The Settings commands allow you to change the sound of the synth. The settings command format is a **channel** value between `0-G`, a 3 characters long **name**, followed by four values between `0-G`. The possible waveforms are `si`, `2i`, `4i`, `8i`, `tr`, `2r`, `4r`, `8r`, `sq`, `2q`, `4q` `8q`, `sw`, `2w`, `4w` and `8w`. 37 | 38 | | Command | Channel | Name | Info | 39 | | :- | :- | :- | :- | 40 | | `0ENV056f` | 0 | Envelope | Set **Attack**:0.00, **Decay**:0.33, **Sustain**:0.40 and **Release**:1.00 | 41 | | `1OSCsisq` | 1 | Oscilloscope | Set **Osc1**:Sine, **Osc2**:Square | 42 | 43 | ### Global 44 | 45 | #### Effects 46 | 47 | The Effects are applied to all channels. The effect command format is a 3 characters long **name**, followed by one value between `0-G` for **wet** and **depth**. 48 | 49 | | Command | Channel | Operation | Info | 50 | | :- | :- | :- | :- | 51 | | `BITff` | All | Bitcrusher | .. | 52 | | `DISff` | All | Distortion | .. | 53 | | `WAHff` | All | AutoWah | .. | 54 | | `CHEff` | All | Chebyshev | .. | 55 | | `FEEff` | All | Feedback | .. | 56 | | `DELff` | All | Ping Pong Delay | .. | 57 | | `TREff` | All | Tremolo | .. | 58 | | `REVff` | All | Reverb | .. | 59 | | `PHAff` | All | Pashor | .. | 60 | | `VIBff` | All | Vibrato | .. | 61 | | `CHOff` | All | Chorus | .. | 62 | | `STEff` | All | StereoWidener | .. | 63 | | `EQUff` | All | EQ3 | .. | 64 | | `COMff` | All | Compressor | .. | 65 | | `VOLff` | All | Volume | .. | 66 | | `LIMff` | All | Limiter | .. | 67 | 68 | #### Masters 69 | 70 | `TODO` Add the ability to change the mastering effects like compressor and volume. Coming soon! 71 | 72 | #### Special 73 | 74 | - `bpm140`, sets the BPM to `140`. This command is designed to apply to effects like feedback. 75 | - `renv`, randomizes envelopes. 76 | - `rosc`, randomizes oscillators. 77 | - `refx`, randomizes effects. 78 | - `reset`, reset all. 79 | 80 | ## Record 81 | 82 | Press **cmd/ctrl+r** to record, and press it again to stop. 83 | 84 | ## Convert OGG to MP3 85 | 86 | Just use ffmpeg. 87 | 88 | ``` 89 | ~/Documents/ffmpeg -i last.{ogg,mp3} 90 | ``` 91 | 92 | 93 | 94 | ## Extras 95 | 96 | - This application supports the [Ecosystem Theme](https://github.com/hundredrabbits/Themes). 97 | - Support this project through [Patreon](https://www.patreon.com/hundredrabbits). 98 | - See the [License](LICENSE.md) file for license rights and limitations (MIT). 99 | - Pull Requests are welcome! 100 | -------------------------------------------------------------------------------- /browser/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Pilot — Web 9 | 10 | 11 | 12 | 13 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /browser/mock/electron.js: -------------------------------------------------------------------------------- 1 | export let remote = {}; 2 | -------------------------------------------------------------------------------- /browser/mock/fs.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hundredrabbits/Pilot/a77a4e059147d02fbbfb676e2417974a587dbaed/browser/mock/fs.js -------------------------------------------------------------------------------- /browser/mock/require.js: -------------------------------------------------------------------------------- 1 | import * as dgram from "https://unpkg.com/browser-dgram@latest/index.js"; 2 | import * as electron from "./electron.js"; 3 | import * as fs from "./fs.js"; 4 | 5 | window.require = function(what) { 6 | switch (what) { 7 | case "dgram": return dgram; break; 8 | case "electron": return electron; break; 9 | case "tone": return Tone; break; 10 | case "fs": return fs; break; 11 | 12 | default: console.log(what); break; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /desktop/icon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hundredrabbits/Pilot/a77a4e059147d02fbbfb676e2417974a587dbaed/desktop/icon.icns -------------------------------------------------------------------------------- /desktop/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hundredrabbits/Pilot/a77a4e059147d02fbbfb676e2417974a587dbaed/desktop/icon.ico -------------------------------------------------------------------------------- /desktop/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hundredrabbits/Pilot/a77a4e059147d02fbbfb676e2417974a587dbaed/desktop/icon.png -------------------------------------------------------------------------------- /desktop/icon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /desktop/main.js: -------------------------------------------------------------------------------- 1 | const { app, BrowserWindow, webFrame, Menu, dialog } = require('electron') 2 | const path = require('path') 3 | const url = require('url') 4 | const shell = require('electron').shell 5 | 6 | let isShown = true 7 | 8 | require('electron').protocol.registerSchemesAsPrivileged([ 9 | { scheme: 'js', privileges: { standard: true, secure: true } } 10 | ]) 11 | 12 | function protocolHandler (request, respond) { 13 | try { 14 | let pathname = request.url.replace(/^js:\/*/, '') 15 | let filename = path.resolve(app.getAppPath(), pathname) 16 | respond({ mimeType: 'text/javascript', data: require('fs').readFileSync(filename) }) 17 | } catch (e) { 18 | console.error(e, request) 19 | } 20 | } 21 | 22 | app.on('ready', () => { 23 | require('electron').protocol.registerBufferProtocol('js', protocolHandler) 24 | 25 | app.win = new BrowserWindow({ 26 | width: 445, 27 | height: 210, 28 | minWidth: 200, 29 | minHeight: 190, 30 | backgroundColor: '#000', 31 | icon: __dirname + '/' + { darwin: 'icon.icns', linux: 'icon.png', win32: 'icon.ico' }[process.platform] || 'icon.ico', 32 | resizable: true, 33 | frame: process.platform !== 'darwin', 34 | skipTaskbar: process.platform === 'darwin', 35 | autoHideMenuBar: process.platform === 'darwin', 36 | webPreferences: { zoomFactor: 1.0, nodeIntegration: true, backgroundThrottling: false } 37 | }) 38 | 39 | app.win.loadURL(`file://${__dirname}/sources/index.html`) 40 | // app.inspect() 41 | 42 | app.win.on('closed', () => { 43 | win = null 44 | app.quit() 45 | }) 46 | 47 | app.win.on('hide', function () { 48 | isShown = false 49 | }) 50 | 51 | app.win.on('show', function () { 52 | isShown = true 53 | }) 54 | 55 | app.on('window-all-closed', () => { 56 | app.quit() 57 | }) 58 | 59 | app.on('activate', () => { 60 | if (app.win === null) { 61 | createWindow() 62 | } else { 63 | app.win.show() 64 | } 65 | }) 66 | }) 67 | 68 | app.inspect = function () { 69 | app.win.toggleDevTools() 70 | } 71 | 72 | app.toggleFullscreen = function () { 73 | app.win.setFullScreen(!app.win.isFullScreen()) 74 | } 75 | 76 | app.toggleVisible = function () { 77 | if (process.platform === 'darwin') { 78 | if (isShown && !app.win.isFullScreen()) { app.win.hide() } else { app.win.show() } 79 | } else { 80 | if (!app.win.isMinimized()) { app.win.minimize() } else { app.win.restore() } 81 | } 82 | } 83 | 84 | app.injectMenu = function (menu) { 85 | try { 86 | Menu.setApplicationMenu(Menu.buildFromTemplate(menu)) 87 | } catch (err) { 88 | console.warn('Cannot inject menu.') 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /desktop/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Pilot", 3 | "version": "0.1.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@types/node": { 8 | "version": "10.14.6", 9 | "resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.6.tgz", 10 | "integrity": "sha512-Fvm24+u85lGmV4hT5G++aht2C5I4Z4dYlWZIh62FAfFO/TfzXtPpoLI6I7AuBWkIFqZCnhFOoTT7RjjaIL5Fjg==", 11 | "dev": true 12 | }, 13 | "ajv": { 14 | "version": "6.10.0", 15 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", 16 | "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", 17 | "dev": true, 18 | "requires": { 19 | "fast-deep-equal": "^2.0.1", 20 | "fast-json-stable-stringify": "^2.0.0", 21 | "json-schema-traverse": "^0.4.1", 22 | "uri-js": "^4.2.2" 23 | } 24 | }, 25 | "ansi-regex": { 26 | "version": "2.1.1", 27 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", 28 | "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", 29 | "dev": true 30 | }, 31 | "array-find-index": { 32 | "version": "1.0.2", 33 | "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", 34 | "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", 35 | "dev": true 36 | }, 37 | "asar": { 38 | "version": "1.0.0", 39 | "resolved": "https://registry.npmjs.org/asar/-/asar-1.0.0.tgz", 40 | "integrity": "sha512-MBiDU5cDr9UWuY2F0zq2fZlnyRq1aOPmJGMas22Qa14K1odpRXL3xkMHPN3uw2hAK5mD89Q+/KidOUtpi4V0Cg==", 41 | "dev": true, 42 | "requires": { 43 | "chromium-pickle-js": "^0.2.0", 44 | "commander": "^2.19.0", 45 | "cuint": "^0.2.2", 46 | "glob": "^7.1.3", 47 | "minimatch": "^3.0.4", 48 | "mkdirp": "^0.5.1", 49 | "pify": "^4.0.1", 50 | "tmp-promise": "^1.0.5" 51 | }, 52 | "dependencies": { 53 | "pify": { 54 | "version": "4.0.1", 55 | "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", 56 | "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", 57 | "dev": true 58 | } 59 | } 60 | }, 61 | "asn1": { 62 | "version": "0.2.4", 63 | "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", 64 | "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", 65 | "dev": true, 66 | "requires": { 67 | "safer-buffer": "~2.1.0" 68 | } 69 | }, 70 | "assert-plus": { 71 | "version": "1.0.0", 72 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 73 | "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", 74 | "dev": true 75 | }, 76 | "asynckit": { 77 | "version": "0.4.0", 78 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 79 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", 80 | "dev": true 81 | }, 82 | "author-regex": { 83 | "version": "1.0.0", 84 | "resolved": "https://registry.npmjs.org/author-regex/-/author-regex-1.0.0.tgz", 85 | "integrity": "sha1-0IiFvmubv5Q5/gh8dihyRfCoFFA=", 86 | "dev": true 87 | }, 88 | "aws-sign2": { 89 | "version": "0.7.0", 90 | "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", 91 | "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", 92 | "dev": true 93 | }, 94 | "aws4": { 95 | "version": "1.8.0", 96 | "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", 97 | "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", 98 | "dev": true 99 | }, 100 | "balanced-match": { 101 | "version": "1.0.0", 102 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 103 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 104 | "dev": true 105 | }, 106 | "base64-js": { 107 | "version": "1.3.0", 108 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", 109 | "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", 110 | "dev": true 111 | }, 112 | "bcrypt-pbkdf": { 113 | "version": "1.0.2", 114 | "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", 115 | "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", 116 | "dev": true, 117 | "requires": { 118 | "tweetnacl": "^0.14.3" 119 | } 120 | }, 121 | "bluebird": { 122 | "version": "3.5.4", 123 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.4.tgz", 124 | "integrity": "sha512-FG+nFEZChJrbQ9tIccIfZJBz3J7mLrAhxakAbnrJWn8d7aKOC+LWifa0G+p4ZqKp4y13T7juYvdhq9NzKdsrjw==", 125 | "dev": true 126 | }, 127 | "brace-expansion": { 128 | "version": "1.1.11", 129 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 130 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 131 | "dev": true, 132 | "requires": { 133 | "balanced-match": "^1.0.0", 134 | "concat-map": "0.0.1" 135 | } 136 | }, 137 | "buffer-alloc": { 138 | "version": "1.2.0", 139 | "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", 140 | "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", 141 | "dev": true, 142 | "requires": { 143 | "buffer-alloc-unsafe": "^1.1.0", 144 | "buffer-fill": "^1.0.0" 145 | } 146 | }, 147 | "buffer-alloc-unsafe": { 148 | "version": "1.1.0", 149 | "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", 150 | "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", 151 | "dev": true 152 | }, 153 | "buffer-fill": { 154 | "version": "1.0.0", 155 | "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", 156 | "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", 157 | "dev": true 158 | }, 159 | "buffer-from": { 160 | "version": "1.1.1", 161 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", 162 | "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", 163 | "dev": true 164 | }, 165 | "camelcase": { 166 | "version": "2.1.1", 167 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", 168 | "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", 169 | "dev": true 170 | }, 171 | "camelcase-keys": { 172 | "version": "2.1.0", 173 | "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", 174 | "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", 175 | "dev": true, 176 | "requires": { 177 | "camelcase": "^2.0.0", 178 | "map-obj": "^1.0.0" 179 | } 180 | }, 181 | "caseless": { 182 | "version": "0.12.0", 183 | "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", 184 | "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", 185 | "dev": true 186 | }, 187 | "chromium-pickle-js": { 188 | "version": "0.2.0", 189 | "resolved": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz", 190 | "integrity": "sha1-BKEGZywYsIWrd02YPfo+oTjyIgU=", 191 | "dev": true 192 | }, 193 | "code-point-at": { 194 | "version": "1.1.0", 195 | "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", 196 | "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", 197 | "dev": true 198 | }, 199 | "combined-stream": { 200 | "version": "1.0.7", 201 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", 202 | "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", 203 | "dev": true, 204 | "requires": { 205 | "delayed-stream": "~1.0.0" 206 | } 207 | }, 208 | "commander": { 209 | "version": "2.20.0", 210 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", 211 | "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", 212 | "dev": true 213 | }, 214 | "compare-version": { 215 | "version": "0.1.2", 216 | "resolved": "https://registry.npmjs.org/compare-version/-/compare-version-0.1.2.tgz", 217 | "integrity": "sha1-AWLsLZNR9d3VmpICy6k1NmpyUIA=", 218 | "dev": true 219 | }, 220 | "concat-map": { 221 | "version": "0.0.1", 222 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 223 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 224 | "dev": true 225 | }, 226 | "concat-stream": { 227 | "version": "1.6.2", 228 | "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", 229 | "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", 230 | "dev": true, 231 | "requires": { 232 | "buffer-from": "^1.0.0", 233 | "inherits": "^2.0.3", 234 | "readable-stream": "^2.2.2", 235 | "typedarray": "^0.0.6" 236 | }, 237 | "dependencies": { 238 | "isarray": { 239 | "version": "1.0.0", 240 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 241 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", 242 | "dev": true 243 | }, 244 | "readable-stream": { 245 | "version": "2.3.6", 246 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", 247 | "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", 248 | "dev": true, 249 | "requires": { 250 | "core-util-is": "~1.0.0", 251 | "inherits": "~2.0.3", 252 | "isarray": "~1.0.0", 253 | "process-nextick-args": "~2.0.0", 254 | "safe-buffer": "~5.1.1", 255 | "string_decoder": "~1.1.1", 256 | "util-deprecate": "~1.0.1" 257 | } 258 | }, 259 | "string_decoder": { 260 | "version": "1.1.1", 261 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 262 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 263 | "dev": true, 264 | "requires": { 265 | "safe-buffer": "~5.1.0" 266 | } 267 | } 268 | } 269 | }, 270 | "core-util-is": { 271 | "version": "1.0.2", 272 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 273 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", 274 | "dev": true 275 | }, 276 | "cuint": { 277 | "version": "0.2.2", 278 | "resolved": "https://registry.npmjs.org/cuint/-/cuint-0.2.2.tgz", 279 | "integrity": "sha1-QICG1AlVDCYxFVYZ6fp7ytw7mRs=", 280 | "dev": true 281 | }, 282 | "currently-unhandled": { 283 | "version": "0.4.1", 284 | "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", 285 | "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", 286 | "dev": true, 287 | "requires": { 288 | "array-find-index": "^1.0.1" 289 | } 290 | }, 291 | "dashdash": { 292 | "version": "1.14.1", 293 | "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", 294 | "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", 295 | "dev": true, 296 | "requires": { 297 | "assert-plus": "^1.0.0" 298 | } 299 | }, 300 | "debug": { 301 | "version": "3.2.6", 302 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", 303 | "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", 304 | "dev": true, 305 | "requires": { 306 | "ms": "^2.1.1" 307 | } 308 | }, 309 | "decamelize": { 310 | "version": "1.2.0", 311 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", 312 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", 313 | "dev": true 314 | }, 315 | "deep-extend": { 316 | "version": "0.6.0", 317 | "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", 318 | "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", 319 | "dev": true 320 | }, 321 | "delayed-stream": { 322 | "version": "1.0.0", 323 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 324 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", 325 | "dev": true 326 | }, 327 | "ecc-jsbn": { 328 | "version": "0.1.2", 329 | "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", 330 | "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", 331 | "dev": true, 332 | "requires": { 333 | "jsbn": "~0.1.0", 334 | "safer-buffer": "^2.1.0" 335 | } 336 | }, 337 | "electron": { 338 | "version": "5.0.1", 339 | "resolved": "https://registry.npmjs.org/electron/-/electron-5.0.1.tgz", 340 | "integrity": "sha512-8KksyhAPcpXVeO8ViVGxfZAuf8yEVBCtV0h/lMBD8VFbCQ9icej1K5csCFAGirbZbqOz5IdsBZX9Gpb9n4RCag==", 341 | "dev": true, 342 | "requires": { 343 | "@types/node": "^10.12.18", 344 | "electron-download": "^4.1.0", 345 | "extract-zip": "^1.0.3" 346 | } 347 | }, 348 | "electron-download": { 349 | "version": "4.1.1", 350 | "resolved": "https://registry.npmjs.org/electron-download/-/electron-download-4.1.1.tgz", 351 | "integrity": "sha512-FjEWG9Jb/ppK/2zToP+U5dds114fM1ZOJqMAR4aXXL5CvyPE9fiqBK/9YcwC9poIFQTEJk/EM/zyRwziziRZrg==", 352 | "dev": true, 353 | "requires": { 354 | "debug": "^3.0.0", 355 | "env-paths": "^1.0.0", 356 | "fs-extra": "^4.0.1", 357 | "minimist": "^1.2.0", 358 | "nugget": "^2.0.1", 359 | "path-exists": "^3.0.0", 360 | "rc": "^1.2.1", 361 | "semver": "^5.4.1", 362 | "sumchecker": "^2.0.2" 363 | } 364 | }, 365 | "electron-notarize": { 366 | "version": "0.0.5", 367 | "resolved": "https://registry.npmjs.org/electron-notarize/-/electron-notarize-0.0.5.tgz", 368 | "integrity": "sha512-YzrqZ6RDQ7Wt2RWlxzRoQUuxnTeXrfp7laH7XKcmQqrZ6GaAr50DMPvFMpqDKdrZSHSbcgZgB7ktIQbjvITmCQ==", 369 | "dev": true, 370 | "requires": { 371 | "debug": "^4.1.0", 372 | "fs-extra": "^7.0.0" 373 | }, 374 | "dependencies": { 375 | "debug": { 376 | "version": "4.1.1", 377 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", 378 | "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", 379 | "dev": true, 380 | "requires": { 381 | "ms": "^2.1.1" 382 | } 383 | }, 384 | "fs-extra": { 385 | "version": "7.0.1", 386 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", 387 | "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", 388 | "dev": true, 389 | "requires": { 390 | "graceful-fs": "^4.1.2", 391 | "jsonfile": "^4.0.0", 392 | "universalify": "^0.1.0" 393 | } 394 | } 395 | } 396 | }, 397 | "electron-osx-sign": { 398 | "version": "0.4.11", 399 | "resolved": "https://registry.npmjs.org/electron-osx-sign/-/electron-osx-sign-0.4.11.tgz", 400 | "integrity": "sha512-VVd40nrnVqymvFrY9ZkOYgHJOvexHHYTR3di/SN+mjJ0OWhR1I8BRVj3U+Yamw6hnkZZNKZp52rqL5EFAAPFkQ==", 401 | "dev": true, 402 | "requires": { 403 | "bluebird": "^3.5.0", 404 | "compare-version": "^0.1.2", 405 | "debug": "^2.6.8", 406 | "isbinaryfile": "^3.0.2", 407 | "minimist": "^1.2.0", 408 | "plist": "^3.0.1" 409 | }, 410 | "dependencies": { 411 | "debug": { 412 | "version": "2.6.9", 413 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 414 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 415 | "dev": true, 416 | "requires": { 417 | "ms": "2.0.0" 418 | } 419 | }, 420 | "ms": { 421 | "version": "2.0.0", 422 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 423 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", 424 | "dev": true 425 | } 426 | } 427 | }, 428 | "electron-packager": { 429 | "version": "13.1.1", 430 | "resolved": "https://registry.npmjs.org/electron-packager/-/electron-packager-13.1.1.tgz", 431 | "integrity": "sha512-3Drgcw8OEOP3Psw/PprloAFJSkSUSQgjUq3AmWffJGB3Kj5WXmZl6A3GOUs8aT7bP/8GWg4oYqSiCSnA5PQkdQ==", 432 | "dev": true, 433 | "requires": { 434 | "asar": "^1.0.0", 435 | "debug": "^4.0.1", 436 | "electron-download": "^4.1.1", 437 | "electron-notarize": "^0.0.5", 438 | "electron-osx-sign": "^0.4.11", 439 | "extract-zip": "^1.0.3", 440 | "fs-extra": "^7.0.0", 441 | "galactus": "^0.2.1", 442 | "get-package-info": "^1.0.0", 443 | "parse-author": "^2.0.0", 444 | "pify": "^4.0.0", 445 | "plist": "^3.0.0", 446 | "rcedit": "^1.0.0", 447 | "resolve": "^1.1.6", 448 | "sanitize-filename": "^1.6.0", 449 | "semver": "^5.3.0", 450 | "yargs-parser": "^13.0.0" 451 | }, 452 | "dependencies": { 453 | "debug": { 454 | "version": "4.1.1", 455 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", 456 | "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", 457 | "dev": true, 458 | "requires": { 459 | "ms": "^2.1.1" 460 | } 461 | }, 462 | "fs-extra": { 463 | "version": "7.0.1", 464 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", 465 | "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", 466 | "dev": true, 467 | "requires": { 468 | "graceful-fs": "^4.1.2", 469 | "jsonfile": "^4.0.0", 470 | "universalify": "^0.1.0" 471 | } 472 | }, 473 | "pify": { 474 | "version": "4.0.1", 475 | "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", 476 | "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", 477 | "dev": true 478 | } 479 | } 480 | }, 481 | "env-paths": { 482 | "version": "1.0.0", 483 | "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-1.0.0.tgz", 484 | "integrity": "sha1-QWgTO0K7BcOKNbGuQ5fIKYqzaeA=", 485 | "dev": true 486 | }, 487 | "error-ex": { 488 | "version": "1.3.2", 489 | "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", 490 | "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", 491 | "dev": true, 492 | "requires": { 493 | "is-arrayish": "^0.2.1" 494 | } 495 | }, 496 | "extend": { 497 | "version": "3.0.2", 498 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", 499 | "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", 500 | "dev": true 501 | }, 502 | "extract-zip": { 503 | "version": "1.6.7", 504 | "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.7.tgz", 505 | "integrity": "sha1-qEC0uK9kAyZMjbV/Txp0Mz74H+k=", 506 | "dev": true, 507 | "requires": { 508 | "concat-stream": "1.6.2", 509 | "debug": "2.6.9", 510 | "mkdirp": "0.5.1", 511 | "yauzl": "2.4.1" 512 | }, 513 | "dependencies": { 514 | "debug": { 515 | "version": "2.6.9", 516 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 517 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 518 | "dev": true, 519 | "requires": { 520 | "ms": "2.0.0" 521 | } 522 | }, 523 | "ms": { 524 | "version": "2.0.0", 525 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 526 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", 527 | "dev": true 528 | } 529 | } 530 | }, 531 | "extsprintf": { 532 | "version": "1.3.0", 533 | "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", 534 | "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", 535 | "dev": true 536 | }, 537 | "fast-deep-equal": { 538 | "version": "2.0.1", 539 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", 540 | "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", 541 | "dev": true 542 | }, 543 | "fast-json-stable-stringify": { 544 | "version": "2.0.0", 545 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", 546 | "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", 547 | "dev": true 548 | }, 549 | "fd-slicer": { 550 | "version": "1.0.1", 551 | "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", 552 | "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", 553 | "dev": true, 554 | "requires": { 555 | "pend": "~1.2.0" 556 | } 557 | }, 558 | "find-up": { 559 | "version": "1.1.2", 560 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", 561 | "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", 562 | "dev": true, 563 | "requires": { 564 | "path-exists": "^2.0.0", 565 | "pinkie-promise": "^2.0.0" 566 | }, 567 | "dependencies": { 568 | "path-exists": { 569 | "version": "2.1.0", 570 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", 571 | "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", 572 | "dev": true, 573 | "requires": { 574 | "pinkie-promise": "^2.0.0" 575 | } 576 | } 577 | } 578 | }, 579 | "flora-colossus": { 580 | "version": "1.0.0", 581 | "resolved": "https://registry.npmjs.org/flora-colossus/-/flora-colossus-1.0.0.tgz", 582 | "integrity": "sha1-VHKcNh7ezuAU3UQWeeGjfB13OkU=", 583 | "dev": true, 584 | "requires": { 585 | "debug": "^3.1.0", 586 | "fs-extra": "^4.0.0" 587 | } 588 | }, 589 | "forever-agent": { 590 | "version": "0.6.1", 591 | "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", 592 | "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", 593 | "dev": true 594 | }, 595 | "form-data": { 596 | "version": "2.3.3", 597 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", 598 | "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", 599 | "dev": true, 600 | "requires": { 601 | "asynckit": "^0.4.0", 602 | "combined-stream": "^1.0.6", 603 | "mime-types": "^2.1.12" 604 | } 605 | }, 606 | "fs-extra": { 607 | "version": "4.0.3", 608 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", 609 | "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", 610 | "dev": true, 611 | "requires": { 612 | "graceful-fs": "^4.1.2", 613 | "jsonfile": "^4.0.0", 614 | "universalify": "^0.1.0" 615 | } 616 | }, 617 | "fs.realpath": { 618 | "version": "1.0.0", 619 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 620 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 621 | "dev": true 622 | }, 623 | "galactus": { 624 | "version": "0.2.1", 625 | "resolved": "https://registry.npmjs.org/galactus/-/galactus-0.2.1.tgz", 626 | "integrity": "sha1-y+0tIKQMH1Z5o1kI4rlBVzPnjbk=", 627 | "dev": true, 628 | "requires": { 629 | "debug": "^3.1.0", 630 | "flora-colossus": "^1.0.0", 631 | "fs-extra": "^4.0.0" 632 | } 633 | }, 634 | "get-package-info": { 635 | "version": "1.0.0", 636 | "resolved": "https://registry.npmjs.org/get-package-info/-/get-package-info-1.0.0.tgz", 637 | "integrity": "sha1-ZDJ5ZWPigRPNlHTbvQAFKYWkmZw=", 638 | "dev": true, 639 | "requires": { 640 | "bluebird": "^3.1.1", 641 | "debug": "^2.2.0", 642 | "lodash.get": "^4.0.0", 643 | "read-pkg-up": "^2.0.0" 644 | }, 645 | "dependencies": { 646 | "debug": { 647 | "version": "2.6.9", 648 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 649 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 650 | "dev": true, 651 | "requires": { 652 | "ms": "2.0.0" 653 | } 654 | }, 655 | "find-up": { 656 | "version": "2.1.0", 657 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", 658 | "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", 659 | "dev": true, 660 | "requires": { 661 | "locate-path": "^2.0.0" 662 | } 663 | }, 664 | "load-json-file": { 665 | "version": "2.0.0", 666 | "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", 667 | "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", 668 | "dev": true, 669 | "requires": { 670 | "graceful-fs": "^4.1.2", 671 | "parse-json": "^2.2.0", 672 | "pify": "^2.0.0", 673 | "strip-bom": "^3.0.0" 674 | } 675 | }, 676 | "ms": { 677 | "version": "2.0.0", 678 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 679 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", 680 | "dev": true 681 | }, 682 | "path-type": { 683 | "version": "2.0.0", 684 | "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", 685 | "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", 686 | "dev": true, 687 | "requires": { 688 | "pify": "^2.0.0" 689 | } 690 | }, 691 | "read-pkg": { 692 | "version": "2.0.0", 693 | "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", 694 | "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", 695 | "dev": true, 696 | "requires": { 697 | "load-json-file": "^2.0.0", 698 | "normalize-package-data": "^2.3.2", 699 | "path-type": "^2.0.0" 700 | } 701 | }, 702 | "read-pkg-up": { 703 | "version": "2.0.0", 704 | "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", 705 | "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", 706 | "dev": true, 707 | "requires": { 708 | "find-up": "^2.0.0", 709 | "read-pkg": "^2.0.0" 710 | } 711 | }, 712 | "strip-bom": { 713 | "version": "3.0.0", 714 | "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", 715 | "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", 716 | "dev": true 717 | } 718 | } 719 | }, 720 | "get-stdin": { 721 | "version": "4.0.1", 722 | "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", 723 | "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", 724 | "dev": true 725 | }, 726 | "getpass": { 727 | "version": "0.1.7", 728 | "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", 729 | "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", 730 | "dev": true, 731 | "requires": { 732 | "assert-plus": "^1.0.0" 733 | } 734 | }, 735 | "glob": { 736 | "version": "7.1.3", 737 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", 738 | "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", 739 | "dev": true, 740 | "requires": { 741 | "fs.realpath": "^1.0.0", 742 | "inflight": "^1.0.4", 743 | "inherits": "2", 744 | "minimatch": "^3.0.4", 745 | "once": "^1.3.0", 746 | "path-is-absolute": "^1.0.0" 747 | } 748 | }, 749 | "graceful-fs": { 750 | "version": "4.1.15", 751 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", 752 | "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", 753 | "dev": true 754 | }, 755 | "har-schema": { 756 | "version": "2.0.0", 757 | "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", 758 | "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", 759 | "dev": true 760 | }, 761 | "har-validator": { 762 | "version": "5.1.3", 763 | "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", 764 | "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", 765 | "dev": true, 766 | "requires": { 767 | "ajv": "^6.5.5", 768 | "har-schema": "^2.0.0" 769 | } 770 | }, 771 | "hosted-git-info": { 772 | "version": "2.7.1", 773 | "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", 774 | "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", 775 | "dev": true 776 | }, 777 | "http-signature": { 778 | "version": "1.2.0", 779 | "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", 780 | "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", 781 | "dev": true, 782 | "requires": { 783 | "assert-plus": "^1.0.0", 784 | "jsprim": "^1.2.2", 785 | "sshpk": "^1.7.0" 786 | } 787 | }, 788 | "indent-string": { 789 | "version": "2.1.0", 790 | "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", 791 | "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", 792 | "dev": true, 793 | "requires": { 794 | "repeating": "^2.0.0" 795 | } 796 | }, 797 | "inflight": { 798 | "version": "1.0.6", 799 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 800 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 801 | "dev": true, 802 | "requires": { 803 | "once": "^1.3.0", 804 | "wrappy": "1" 805 | } 806 | }, 807 | "inherits": { 808 | "version": "2.0.3", 809 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 810 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", 811 | "dev": true 812 | }, 813 | "ini": { 814 | "version": "1.3.5", 815 | "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", 816 | "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", 817 | "dev": true 818 | }, 819 | "is-arrayish": { 820 | "version": "0.2.1", 821 | "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", 822 | "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", 823 | "dev": true 824 | }, 825 | "is-finite": { 826 | "version": "1.0.2", 827 | "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", 828 | "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", 829 | "dev": true, 830 | "requires": { 831 | "number-is-nan": "^1.0.0" 832 | } 833 | }, 834 | "is-fullwidth-code-point": { 835 | "version": "1.0.0", 836 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", 837 | "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", 838 | "dev": true, 839 | "requires": { 840 | "number-is-nan": "^1.0.0" 841 | } 842 | }, 843 | "is-typedarray": { 844 | "version": "1.0.0", 845 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 846 | "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", 847 | "dev": true 848 | }, 849 | "is-utf8": { 850 | "version": "0.2.1", 851 | "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", 852 | "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", 853 | "dev": true 854 | }, 855 | "isarray": { 856 | "version": "0.0.1", 857 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", 858 | "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", 859 | "dev": true 860 | }, 861 | "isbinaryfile": { 862 | "version": "3.0.3", 863 | "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz", 864 | "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==", 865 | "dev": true, 866 | "requires": { 867 | "buffer-alloc": "^1.2.0" 868 | } 869 | }, 870 | "isstream": { 871 | "version": "0.1.2", 872 | "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", 873 | "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", 874 | "dev": true 875 | }, 876 | "jsbn": { 877 | "version": "0.1.1", 878 | "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", 879 | "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", 880 | "dev": true 881 | }, 882 | "json-schema": { 883 | "version": "0.2.3", 884 | "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", 885 | "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", 886 | "dev": true 887 | }, 888 | "json-schema-traverse": { 889 | "version": "0.4.1", 890 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 891 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", 892 | "dev": true 893 | }, 894 | "json-stringify-safe": { 895 | "version": "5.0.1", 896 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", 897 | "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", 898 | "dev": true 899 | }, 900 | "jsonfile": { 901 | "version": "4.0.0", 902 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", 903 | "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", 904 | "dev": true, 905 | "requires": { 906 | "graceful-fs": "^4.1.6" 907 | } 908 | }, 909 | "jsprim": { 910 | "version": "1.4.1", 911 | "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", 912 | "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", 913 | "dev": true, 914 | "requires": { 915 | "assert-plus": "1.0.0", 916 | "extsprintf": "1.3.0", 917 | "json-schema": "0.2.3", 918 | "verror": "1.10.0" 919 | } 920 | }, 921 | "load-json-file": { 922 | "version": "1.1.0", 923 | "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", 924 | "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", 925 | "dev": true, 926 | "requires": { 927 | "graceful-fs": "^4.1.2", 928 | "parse-json": "^2.2.0", 929 | "pify": "^2.0.0", 930 | "pinkie-promise": "^2.0.0", 931 | "strip-bom": "^2.0.0" 932 | } 933 | }, 934 | "locate-path": { 935 | "version": "2.0.0", 936 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", 937 | "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", 938 | "dev": true, 939 | "requires": { 940 | "p-locate": "^2.0.0", 941 | "path-exists": "^3.0.0" 942 | } 943 | }, 944 | "lodash.get": { 945 | "version": "4.4.2", 946 | "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", 947 | "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", 948 | "dev": true 949 | }, 950 | "loud-rejection": { 951 | "version": "1.6.0", 952 | "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", 953 | "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", 954 | "dev": true, 955 | "requires": { 956 | "currently-unhandled": "^0.4.1", 957 | "signal-exit": "^3.0.0" 958 | } 959 | }, 960 | "map-obj": { 961 | "version": "1.0.1", 962 | "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", 963 | "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", 964 | "dev": true 965 | }, 966 | "meow": { 967 | "version": "3.7.0", 968 | "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", 969 | "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", 970 | "dev": true, 971 | "requires": { 972 | "camelcase-keys": "^2.0.0", 973 | "decamelize": "^1.1.2", 974 | "loud-rejection": "^1.0.0", 975 | "map-obj": "^1.0.1", 976 | "minimist": "^1.1.3", 977 | "normalize-package-data": "^2.3.4", 978 | "object-assign": "^4.0.1", 979 | "read-pkg-up": "^1.0.1", 980 | "redent": "^1.0.0", 981 | "trim-newlines": "^1.0.0" 982 | } 983 | }, 984 | "mime-db": { 985 | "version": "1.40.0", 986 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", 987 | "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==", 988 | "dev": true 989 | }, 990 | "mime-types": { 991 | "version": "2.1.24", 992 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", 993 | "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", 994 | "dev": true, 995 | "requires": { 996 | "mime-db": "1.40.0" 997 | } 998 | }, 999 | "minimatch": { 1000 | "version": "3.0.4", 1001 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 1002 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 1003 | "dev": true, 1004 | "requires": { 1005 | "brace-expansion": "^1.1.7" 1006 | } 1007 | }, 1008 | "minimist": { 1009 | "version": "1.2.0", 1010 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", 1011 | "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", 1012 | "dev": true 1013 | }, 1014 | "mkdirp": { 1015 | "version": "0.5.1", 1016 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", 1017 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", 1018 | "dev": true, 1019 | "requires": { 1020 | "minimist": "0.0.8" 1021 | }, 1022 | "dependencies": { 1023 | "minimist": { 1024 | "version": "0.0.8", 1025 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", 1026 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", 1027 | "dev": true 1028 | } 1029 | } 1030 | }, 1031 | "ms": { 1032 | "version": "2.1.1", 1033 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", 1034 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", 1035 | "dev": true 1036 | }, 1037 | "normalize-package-data": { 1038 | "version": "2.5.0", 1039 | "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", 1040 | "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", 1041 | "dev": true, 1042 | "requires": { 1043 | "hosted-git-info": "^2.1.4", 1044 | "resolve": "^1.10.0", 1045 | "semver": "2 || 3 || 4 || 5", 1046 | "validate-npm-package-license": "^3.0.1" 1047 | } 1048 | }, 1049 | "nugget": { 1050 | "version": "2.0.1", 1051 | "resolved": "https://registry.npmjs.org/nugget/-/nugget-2.0.1.tgz", 1052 | "integrity": "sha1-IBCVpIfhrTYIGzQy+jytpPjQcbA=", 1053 | "dev": true, 1054 | "requires": { 1055 | "debug": "^2.1.3", 1056 | "minimist": "^1.1.0", 1057 | "pretty-bytes": "^1.0.2", 1058 | "progress-stream": "^1.1.0", 1059 | "request": "^2.45.0", 1060 | "single-line-log": "^1.1.2", 1061 | "throttleit": "0.0.2" 1062 | }, 1063 | "dependencies": { 1064 | "debug": { 1065 | "version": "2.6.9", 1066 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 1067 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 1068 | "dev": true, 1069 | "requires": { 1070 | "ms": "2.0.0" 1071 | } 1072 | }, 1073 | "ms": { 1074 | "version": "2.0.0", 1075 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1076 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", 1077 | "dev": true 1078 | } 1079 | } 1080 | }, 1081 | "number-is-nan": { 1082 | "version": "1.0.1", 1083 | "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", 1084 | "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", 1085 | "dev": true 1086 | }, 1087 | "oauth-sign": { 1088 | "version": "0.9.0", 1089 | "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", 1090 | "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", 1091 | "dev": true 1092 | }, 1093 | "object-assign": { 1094 | "version": "4.1.1", 1095 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 1096 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", 1097 | "dev": true 1098 | }, 1099 | "object-keys": { 1100 | "version": "0.4.0", 1101 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", 1102 | "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", 1103 | "dev": true 1104 | }, 1105 | "once": { 1106 | "version": "1.4.0", 1107 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1108 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 1109 | "dev": true, 1110 | "requires": { 1111 | "wrappy": "1" 1112 | } 1113 | }, 1114 | "os-tmpdir": { 1115 | "version": "1.0.2", 1116 | "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", 1117 | "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", 1118 | "dev": true 1119 | }, 1120 | "p-limit": { 1121 | "version": "1.3.0", 1122 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", 1123 | "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", 1124 | "dev": true, 1125 | "requires": { 1126 | "p-try": "^1.0.0" 1127 | } 1128 | }, 1129 | "p-locate": { 1130 | "version": "2.0.0", 1131 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", 1132 | "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", 1133 | "dev": true, 1134 | "requires": { 1135 | "p-limit": "^1.1.0" 1136 | } 1137 | }, 1138 | "p-try": { 1139 | "version": "1.0.0", 1140 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", 1141 | "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", 1142 | "dev": true 1143 | }, 1144 | "parse-author": { 1145 | "version": "2.0.0", 1146 | "resolved": "https://registry.npmjs.org/parse-author/-/parse-author-2.0.0.tgz", 1147 | "integrity": "sha1-00YL8d3Q367tQtp1QkLmX7aEqB8=", 1148 | "dev": true, 1149 | "requires": { 1150 | "author-regex": "^1.0.0" 1151 | } 1152 | }, 1153 | "parse-json": { 1154 | "version": "2.2.0", 1155 | "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", 1156 | "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", 1157 | "dev": true, 1158 | "requires": { 1159 | "error-ex": "^1.2.0" 1160 | } 1161 | }, 1162 | "path-exists": { 1163 | "version": "3.0.0", 1164 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", 1165 | "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", 1166 | "dev": true 1167 | }, 1168 | "path-is-absolute": { 1169 | "version": "1.0.1", 1170 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1171 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 1172 | "dev": true 1173 | }, 1174 | "path-parse": { 1175 | "version": "1.0.6", 1176 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", 1177 | "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", 1178 | "dev": true 1179 | }, 1180 | "path-type": { 1181 | "version": "1.1.0", 1182 | "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", 1183 | "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", 1184 | "dev": true, 1185 | "requires": { 1186 | "graceful-fs": "^4.1.2", 1187 | "pify": "^2.0.0", 1188 | "pinkie-promise": "^2.0.0" 1189 | } 1190 | }, 1191 | "pend": { 1192 | "version": "1.2.0", 1193 | "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", 1194 | "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", 1195 | "dev": true 1196 | }, 1197 | "performance-now": { 1198 | "version": "2.1.0", 1199 | "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", 1200 | "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", 1201 | "dev": true 1202 | }, 1203 | "pify": { 1204 | "version": "2.3.0", 1205 | "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", 1206 | "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", 1207 | "dev": true 1208 | }, 1209 | "pinkie": { 1210 | "version": "2.0.4", 1211 | "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", 1212 | "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", 1213 | "dev": true 1214 | }, 1215 | "pinkie-promise": { 1216 | "version": "2.0.1", 1217 | "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", 1218 | "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", 1219 | "dev": true, 1220 | "requires": { 1221 | "pinkie": "^2.0.0" 1222 | } 1223 | }, 1224 | "plist": { 1225 | "version": "3.0.1", 1226 | "resolved": "https://registry.npmjs.org/plist/-/plist-3.0.1.tgz", 1227 | "integrity": "sha512-GpgvHHocGRyQm74b6FWEZZVRroHKE1I0/BTjAmySaohK+cUn+hZpbqXkc3KWgW3gQYkqcQej35FohcT0FRlkRQ==", 1228 | "dev": true, 1229 | "requires": { 1230 | "base64-js": "^1.2.3", 1231 | "xmlbuilder": "^9.0.7", 1232 | "xmldom": "0.1.x" 1233 | } 1234 | }, 1235 | "pretty-bytes": { 1236 | "version": "1.0.4", 1237 | "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz", 1238 | "integrity": "sha1-CiLoIQYJrTVUL4yNXSFZr/B1HIQ=", 1239 | "dev": true, 1240 | "requires": { 1241 | "get-stdin": "^4.0.1", 1242 | "meow": "^3.1.0" 1243 | } 1244 | }, 1245 | "process-nextick-args": { 1246 | "version": "2.0.0", 1247 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", 1248 | "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", 1249 | "dev": true 1250 | }, 1251 | "progress-stream": { 1252 | "version": "1.2.0", 1253 | "resolved": "https://registry.npmjs.org/progress-stream/-/progress-stream-1.2.0.tgz", 1254 | "integrity": "sha1-LNPP6jO6OonJwSHsM0er6asSX3c=", 1255 | "dev": true, 1256 | "requires": { 1257 | "speedometer": "~0.1.2", 1258 | "through2": "~0.2.3" 1259 | } 1260 | }, 1261 | "psl": { 1262 | "version": "1.1.31", 1263 | "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", 1264 | "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==", 1265 | "dev": true 1266 | }, 1267 | "punycode": { 1268 | "version": "2.1.1", 1269 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", 1270 | "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", 1271 | "dev": true 1272 | }, 1273 | "qs": { 1274 | "version": "6.5.2", 1275 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", 1276 | "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", 1277 | "dev": true 1278 | }, 1279 | "rc": { 1280 | "version": "1.2.8", 1281 | "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", 1282 | "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", 1283 | "dev": true, 1284 | "requires": { 1285 | "deep-extend": "^0.6.0", 1286 | "ini": "~1.3.0", 1287 | "minimist": "^1.2.0", 1288 | "strip-json-comments": "~2.0.1" 1289 | } 1290 | }, 1291 | "rcedit": { 1292 | "version": "1.1.2", 1293 | "resolved": "https://registry.npmjs.org/rcedit/-/rcedit-1.1.2.tgz", 1294 | "integrity": "sha512-z2ypB4gbINhI6wVe0JJMmdpmOpmNc4g90sE6/6JSuch5kYnjfz9CxvVPqqhShgR6GIkmtW3W2UlfiXhWljA0Fw==", 1295 | "dev": true 1296 | }, 1297 | "read-pkg": { 1298 | "version": "1.1.0", 1299 | "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", 1300 | "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", 1301 | "dev": true, 1302 | "requires": { 1303 | "load-json-file": "^1.0.0", 1304 | "normalize-package-data": "^2.3.2", 1305 | "path-type": "^1.0.0" 1306 | } 1307 | }, 1308 | "read-pkg-up": { 1309 | "version": "1.0.1", 1310 | "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", 1311 | "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", 1312 | "dev": true, 1313 | "requires": { 1314 | "find-up": "^1.0.0", 1315 | "read-pkg": "^1.0.0" 1316 | } 1317 | }, 1318 | "readable-stream": { 1319 | "version": "1.1.14", 1320 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", 1321 | "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", 1322 | "dev": true, 1323 | "requires": { 1324 | "core-util-is": "~1.0.0", 1325 | "inherits": "~2.0.1", 1326 | "isarray": "0.0.1", 1327 | "string_decoder": "~0.10.x" 1328 | } 1329 | }, 1330 | "redent": { 1331 | "version": "1.0.0", 1332 | "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", 1333 | "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", 1334 | "dev": true, 1335 | "requires": { 1336 | "indent-string": "^2.1.0", 1337 | "strip-indent": "^1.0.1" 1338 | } 1339 | }, 1340 | "repeating": { 1341 | "version": "2.0.1", 1342 | "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", 1343 | "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", 1344 | "dev": true, 1345 | "requires": { 1346 | "is-finite": "^1.0.0" 1347 | } 1348 | }, 1349 | "request": { 1350 | "version": "2.88.0", 1351 | "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", 1352 | "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", 1353 | "dev": true, 1354 | "requires": { 1355 | "aws-sign2": "~0.7.0", 1356 | "aws4": "^1.8.0", 1357 | "caseless": "~0.12.0", 1358 | "combined-stream": "~1.0.6", 1359 | "extend": "~3.0.2", 1360 | "forever-agent": "~0.6.1", 1361 | "form-data": "~2.3.2", 1362 | "har-validator": "~5.1.0", 1363 | "http-signature": "~1.2.0", 1364 | "is-typedarray": "~1.0.0", 1365 | "isstream": "~0.1.2", 1366 | "json-stringify-safe": "~5.0.1", 1367 | "mime-types": "~2.1.19", 1368 | "oauth-sign": "~0.9.0", 1369 | "performance-now": "^2.1.0", 1370 | "qs": "~6.5.2", 1371 | "safe-buffer": "^5.1.2", 1372 | "tough-cookie": "~2.4.3", 1373 | "tunnel-agent": "^0.6.0", 1374 | "uuid": "^3.3.2" 1375 | } 1376 | }, 1377 | "resolve": { 1378 | "version": "1.10.1", 1379 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.1.tgz", 1380 | "integrity": "sha512-KuIe4mf++td/eFb6wkaPbMDnP6kObCaEtIDuHOUED6MNUo4K670KZUHuuvYPZDxNF0WVLw49n06M2m2dXphEzA==", 1381 | "dev": true, 1382 | "requires": { 1383 | "path-parse": "^1.0.6" 1384 | } 1385 | }, 1386 | "safe-buffer": { 1387 | "version": "5.1.2", 1388 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 1389 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", 1390 | "dev": true 1391 | }, 1392 | "safer-buffer": { 1393 | "version": "2.1.2", 1394 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1395 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", 1396 | "dev": true 1397 | }, 1398 | "sanitize-filename": { 1399 | "version": "1.6.1", 1400 | "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.1.tgz", 1401 | "integrity": "sha1-YS2hyWRz+gLczaktzVtKsWSmdyo=", 1402 | "dev": true, 1403 | "requires": { 1404 | "truncate-utf8-bytes": "^1.0.0" 1405 | } 1406 | }, 1407 | "semver": { 1408 | "version": "5.7.0", 1409 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", 1410 | "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", 1411 | "dev": true 1412 | }, 1413 | "signal-exit": { 1414 | "version": "3.0.2", 1415 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", 1416 | "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", 1417 | "dev": true 1418 | }, 1419 | "single-line-log": { 1420 | "version": "1.1.2", 1421 | "resolved": "https://registry.npmjs.org/single-line-log/-/single-line-log-1.1.2.tgz", 1422 | "integrity": "sha1-wvg/Jzo+GhbtsJlWYdoO1e8DM2Q=", 1423 | "dev": true, 1424 | "requires": { 1425 | "string-width": "^1.0.1" 1426 | } 1427 | }, 1428 | "spdx-correct": { 1429 | "version": "3.1.0", 1430 | "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", 1431 | "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", 1432 | "dev": true, 1433 | "requires": { 1434 | "spdx-expression-parse": "^3.0.0", 1435 | "spdx-license-ids": "^3.0.0" 1436 | } 1437 | }, 1438 | "spdx-exceptions": { 1439 | "version": "2.2.0", 1440 | "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", 1441 | "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", 1442 | "dev": true 1443 | }, 1444 | "spdx-expression-parse": { 1445 | "version": "3.0.0", 1446 | "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", 1447 | "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", 1448 | "dev": true, 1449 | "requires": { 1450 | "spdx-exceptions": "^2.1.0", 1451 | "spdx-license-ids": "^3.0.0" 1452 | } 1453 | }, 1454 | "spdx-license-ids": { 1455 | "version": "3.0.4", 1456 | "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.4.tgz", 1457 | "integrity": "sha512-7j8LYJLeY/Yb6ACbQ7F76qy5jHkp0U6jgBfJsk97bwWlVUnUWsAgpyaCvo17h0/RQGnQ036tVDomiwoI4pDkQA==", 1458 | "dev": true 1459 | }, 1460 | "speedometer": { 1461 | "version": "0.1.4", 1462 | "resolved": "https://registry.npmjs.org/speedometer/-/speedometer-0.1.4.tgz", 1463 | "integrity": "sha1-mHbb0qFp0xFUAtSObqYynIgWpQ0=", 1464 | "dev": true 1465 | }, 1466 | "sshpk": { 1467 | "version": "1.16.1", 1468 | "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", 1469 | "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", 1470 | "dev": true, 1471 | "requires": { 1472 | "asn1": "~0.2.3", 1473 | "assert-plus": "^1.0.0", 1474 | "bcrypt-pbkdf": "^1.0.0", 1475 | "dashdash": "^1.12.0", 1476 | "ecc-jsbn": "~0.1.1", 1477 | "getpass": "^0.1.1", 1478 | "jsbn": "~0.1.0", 1479 | "safer-buffer": "^2.0.2", 1480 | "tweetnacl": "~0.14.0" 1481 | } 1482 | }, 1483 | "string-width": { 1484 | "version": "1.0.2", 1485 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", 1486 | "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", 1487 | "dev": true, 1488 | "requires": { 1489 | "code-point-at": "^1.0.0", 1490 | "is-fullwidth-code-point": "^1.0.0", 1491 | "strip-ansi": "^3.0.0" 1492 | } 1493 | }, 1494 | "string_decoder": { 1495 | "version": "0.10.31", 1496 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", 1497 | "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", 1498 | "dev": true 1499 | }, 1500 | "strip-ansi": { 1501 | "version": "3.0.1", 1502 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", 1503 | "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", 1504 | "dev": true, 1505 | "requires": { 1506 | "ansi-regex": "^2.0.0" 1507 | } 1508 | }, 1509 | "strip-bom": { 1510 | "version": "2.0.0", 1511 | "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", 1512 | "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", 1513 | "dev": true, 1514 | "requires": { 1515 | "is-utf8": "^0.2.0" 1516 | } 1517 | }, 1518 | "strip-indent": { 1519 | "version": "1.0.1", 1520 | "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", 1521 | "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", 1522 | "dev": true, 1523 | "requires": { 1524 | "get-stdin": "^4.0.1" 1525 | } 1526 | }, 1527 | "strip-json-comments": { 1528 | "version": "2.0.1", 1529 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", 1530 | "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", 1531 | "dev": true 1532 | }, 1533 | "sumchecker": { 1534 | "version": "2.0.2", 1535 | "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-2.0.2.tgz", 1536 | "integrity": "sha1-D0LBDl0F2l1C7qPlbDOZo31sWz4=", 1537 | "dev": true, 1538 | "requires": { 1539 | "debug": "^2.2.0" 1540 | }, 1541 | "dependencies": { 1542 | "debug": { 1543 | "version": "2.6.9", 1544 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 1545 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 1546 | "dev": true, 1547 | "requires": { 1548 | "ms": "2.0.0" 1549 | } 1550 | }, 1551 | "ms": { 1552 | "version": "2.0.0", 1553 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1554 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", 1555 | "dev": true 1556 | } 1557 | } 1558 | }, 1559 | "throttleit": { 1560 | "version": "0.0.2", 1561 | "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-0.0.2.tgz", 1562 | "integrity": "sha1-z+34jmDADdlpe2H90qg0OptoDq8=", 1563 | "dev": true 1564 | }, 1565 | "through2": { 1566 | "version": "0.2.3", 1567 | "resolved": "https://registry.npmjs.org/through2/-/through2-0.2.3.tgz", 1568 | "integrity": "sha1-6zKE2k6jEbbMis42U3SKUqvyWj8=", 1569 | "dev": true, 1570 | "requires": { 1571 | "readable-stream": "~1.1.9", 1572 | "xtend": "~2.1.1" 1573 | } 1574 | }, 1575 | "tmp": { 1576 | "version": "0.0.33", 1577 | "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", 1578 | "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", 1579 | "dev": true, 1580 | "requires": { 1581 | "os-tmpdir": "~1.0.2" 1582 | } 1583 | }, 1584 | "tmp-promise": { 1585 | "version": "1.0.5", 1586 | "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-1.0.5.tgz", 1587 | "integrity": "sha512-hOabTz9Tp49wCozFwuJe5ISrOqkECm6kzw66XTP23DuzNU7QS/KiZq5LC9Y7QSy8f1rPSLy4bKaViP0OwGI1cA==", 1588 | "dev": true, 1589 | "requires": { 1590 | "bluebird": "^3.5.0", 1591 | "tmp": "0.0.33" 1592 | } 1593 | }, 1594 | "tone": { 1595 | "version": "13.4.9", 1596 | "resolved": "https://registry.npmjs.org/tone/-/tone-13.4.9.tgz", 1597 | "integrity": "sha512-jU3MJOzt9wcGbo57TIzgAQe13EgwvdC7N6N/cA6ZkGYHH8gop+L6a87NRP3LIBCcJxVps6I6i/39ZUJI2aCWUA==" 1598 | }, 1599 | "tough-cookie": { 1600 | "version": "2.4.3", 1601 | "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", 1602 | "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", 1603 | "dev": true, 1604 | "requires": { 1605 | "psl": "^1.1.24", 1606 | "punycode": "^1.4.1" 1607 | }, 1608 | "dependencies": { 1609 | "punycode": { 1610 | "version": "1.4.1", 1611 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", 1612 | "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", 1613 | "dev": true 1614 | } 1615 | } 1616 | }, 1617 | "trim-newlines": { 1618 | "version": "1.0.0", 1619 | "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", 1620 | "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", 1621 | "dev": true 1622 | }, 1623 | "truncate-utf8-bytes": { 1624 | "version": "1.0.2", 1625 | "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", 1626 | "integrity": "sha1-QFkjkJWS1W94pYGENLC3hInKXys=", 1627 | "dev": true, 1628 | "requires": { 1629 | "utf8-byte-length": "^1.0.1" 1630 | } 1631 | }, 1632 | "tunnel-agent": { 1633 | "version": "0.6.0", 1634 | "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", 1635 | "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", 1636 | "dev": true, 1637 | "requires": { 1638 | "safe-buffer": "^5.0.1" 1639 | } 1640 | }, 1641 | "tweetnacl": { 1642 | "version": "0.14.5", 1643 | "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", 1644 | "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", 1645 | "dev": true 1646 | }, 1647 | "typedarray": { 1648 | "version": "0.0.6", 1649 | "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", 1650 | "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", 1651 | "dev": true 1652 | }, 1653 | "universalify": { 1654 | "version": "0.1.2", 1655 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", 1656 | "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", 1657 | "dev": true 1658 | }, 1659 | "uri-js": { 1660 | "version": "4.2.2", 1661 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", 1662 | "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", 1663 | "dev": true, 1664 | "requires": { 1665 | "punycode": "^2.1.0" 1666 | } 1667 | }, 1668 | "utf8-byte-length": { 1669 | "version": "1.0.4", 1670 | "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz", 1671 | "integrity": "sha1-9F8VDExm7uloGGUFq5P8u4rWv2E=", 1672 | "dev": true 1673 | }, 1674 | "util-deprecate": { 1675 | "version": "1.0.2", 1676 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 1677 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", 1678 | "dev": true 1679 | }, 1680 | "uuid": { 1681 | "version": "3.3.2", 1682 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", 1683 | "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", 1684 | "dev": true 1685 | }, 1686 | "validate-npm-package-license": { 1687 | "version": "3.0.4", 1688 | "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", 1689 | "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", 1690 | "dev": true, 1691 | "requires": { 1692 | "spdx-correct": "^3.0.0", 1693 | "spdx-expression-parse": "^3.0.0" 1694 | } 1695 | }, 1696 | "verror": { 1697 | "version": "1.10.0", 1698 | "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", 1699 | "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", 1700 | "dev": true, 1701 | "requires": { 1702 | "assert-plus": "^1.0.0", 1703 | "core-util-is": "1.0.2", 1704 | "extsprintf": "^1.2.0" 1705 | } 1706 | }, 1707 | "wrappy": { 1708 | "version": "1.0.2", 1709 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1710 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 1711 | "dev": true 1712 | }, 1713 | "xmlbuilder": { 1714 | "version": "9.0.7", 1715 | "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", 1716 | "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=", 1717 | "dev": true 1718 | }, 1719 | "xmldom": { 1720 | "version": "0.1.27", 1721 | "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.27.tgz", 1722 | "integrity": "sha1-1QH5ezvbQDr4757MIFcxh6rawOk=", 1723 | "dev": true 1724 | }, 1725 | "xtend": { 1726 | "version": "2.1.2", 1727 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", 1728 | "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", 1729 | "dev": true, 1730 | "requires": { 1731 | "object-keys": "~0.4.0" 1732 | } 1733 | }, 1734 | "yargs-parser": { 1735 | "version": "13.0.0", 1736 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.0.0.tgz", 1737 | "integrity": "sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw==", 1738 | "dev": true, 1739 | "requires": { 1740 | "camelcase": "^5.0.0", 1741 | "decamelize": "^1.2.0" 1742 | }, 1743 | "dependencies": { 1744 | "camelcase": { 1745 | "version": "5.3.1", 1746 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", 1747 | "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", 1748 | "dev": true 1749 | } 1750 | } 1751 | }, 1752 | "yauzl": { 1753 | "version": "2.4.1", 1754 | "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz", 1755 | "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=", 1756 | "dev": true, 1757 | "requires": { 1758 | "fd-slicer": "~1.0.1" 1759 | } 1760 | } 1761 | } 1762 | } 1763 | -------------------------------------------------------------------------------- /desktop/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Pilot", 3 | "version": "0.1.0", 4 | "main": "main.js", 5 | "scripts": { 6 | "start": "electron .", 7 | "time": "node time.js", 8 | "docs": "node ../docs.js", 9 | "fix": "standard --fix", 10 | "clean": "rm -r ~/Desktop/Pilot-darwin-x64/ ; rm -r ~/Desktop/Pilot-linux-x64/ ; rm -r ~/Desktop/Pilot-win32-x64/ ; echo 'cleaned build location'", 11 | "build_osx": "electron-packager . Pilot --platform=darwin --arch=x64 --out ~/Desktop/ --overwrite --icon=icon.icns ; echo 'Built for OSX'", 12 | "build_linux": "electron-packager . Pilot --platform=linux --arch=x64 --out ~/Desktop/ --overwrite --icon=icon.ico ; echo 'Built for LINUX'", 13 | "build_win": "electron-packager . Pilot --platform=win32 --arch=x64 --out ~/Desktop/ --overwrite --icon=icon.ico ; echo 'Built for WIN'", 14 | "build": "npm run clean ; npm run build_osx ; npm run build_linux ; npm run build_win", 15 | "push_osx": "~/butler push ~/Desktop/Pilot-darwin-x64/ hundredrabbits/pilot:osx-64", 16 | "push_linux": "~/butler push ~/Desktop/Pilot-linux-x64/ hundredrabbits/pilot:linux-64", 17 | "push_win": "~/butler push ~/Desktop/Pilot-win32-x64/ hundredrabbits/pilot:windows-64", 18 | "push_status": "~/butler status hundredrabbits/pilot", 19 | "push": "npm run build ; npm run push_osx ; npm run push_linux ; npm run push_win ; npm run clean ; npm run push_status" 20 | }, 21 | "devDependencies": { 22 | "electron": "^5.0.1", 23 | "electron-packager": "^13.1.1" 24 | }, 25 | "dependencies": { 26 | "tone": "^13.4.9" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /desktop/sources/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Pilot 9 | 10 | 11 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /desktop/sources/links/fonts.css: -------------------------------------------------------------------------------- 1 | /* Input */ 2 | 3 | @font-face { 4 | font-family: 'input_mono_regular'; 5 | src: url('../media/fonts/input_mono_regular.ttf') format('truetype'); 6 | font-weight: normal; 7 | font-style: normal; 8 | } 9 | 10 | @font-face { 11 | font-family: 'input_mono_medium'; 12 | src: url('../media/fonts/input_mono_medium.ttf') format('truetype'); 13 | font-weight: normal; 14 | font-style: normal; 15 | } -------------------------------------------------------------------------------- /desktop/sources/links/main.css: -------------------------------------------------------------------------------- 1 | body { background:black; padding: 30px; font-family: 'input_mono_regular'; font-size: 11px; line-height: 15px; -webkit-app-region: drag; transition: background-color 500ms; overflow: hidden;} 2 | 3 | /* Mixer */ 4 | 5 | #mixer { line-height: 15px; color:#666; position: relative; text-transform: uppercase; min-width: 420px} 6 | #mixer > div { position: absolute; width: 95px} 7 | #mixer > div.channel { position: absolute; } 8 | #mixer > div.effect { width:65px; } 9 | #mixer > div .cid { font-family: 'input_mono_medium'; font-weight: normal; } 10 | #mixer > div canvas { position: absolute; right: -10px;top: 0.5px;} 11 | #mixer span { padding: 0px 2.55px; } 12 | 13 | #mixer #ch0 { top:calc(0 * 15px); left:0px; } 14 | #mixer #ch1 { top:calc(1 * 15px); left:0px; } 15 | #mixer #ch2 { top:calc(2 * 15px); left:0px; } 16 | #mixer #ch3 { top:calc(3 * 15px); left:0px; } 17 | #mixer #ch4 { top:calc(4 * 15px); left:0px; } 18 | #mixer #ch5 { top:calc(5 * 15px); left:0px; } 19 | #mixer #ch6 { top:calc(6 * 15px); left:0px; } 20 | #mixer #ch7 { top:calc(7 * 15px); left:0px; } 21 | 22 | #mixer #ch8 { top:calc(0 * 15px); left:calc(1 * 110px); } 23 | #mixer #ch9 { top:calc(1 * 15px); left:calc(1 * 110px); } 24 | #mixer #cha { top:calc(2 * 15px); left:calc(1 * 110px); } 25 | #mixer #chb { top:calc(3 * 15px); left:calc(1 * 110px); } 26 | #mixer #chc { top:calc(4 * 15px); left:calc(1 * 110px); } 27 | #mixer #chd { top:calc(5 * 15px); left:calc(1 * 110px); } 28 | #mixer #che { top:calc(6 * 15px); left:calc(1 * 110px); } 29 | #mixer #chf { top:calc(7 * 15px); left:calc(1 * 110px); } 30 | 31 | #mixer #chbit { top:calc(0 * 15px); left:calc(2 * 110px); } 32 | #mixer #chdis { top:calc(1 * 15px); left:calc(2 * 110px); } 33 | #mixer #chwah { top:calc(2 * 15px); left:calc(2 * 110px); } 34 | #mixer #chche { top:calc(3 * 15px); left:calc(2 * 110px); } 35 | #mixer #chfee { top:calc(4 * 15px); left:calc(2 * 110px); } 36 | #mixer #chdel { top:calc(5 * 15px); left:calc(2 * 110px); } 37 | #mixer #chtre { top:calc(6 * 15px); left:calc(2 * 110px); } 38 | #mixer #chrev { top:calc(7 * 15px); left:calc(2 * 110px); } 39 | 40 | #mixer #chpha { top:calc(0 * 15px); left:calc(2 * 150px); } 41 | #mixer #chvib { top:calc(1 * 15px); left:calc(2 * 150px); } 42 | #mixer #chcho { top:calc(2 * 15px); left:calc(2 * 150px); } 43 | #mixer #chste { top:calc(3 * 15px); left:calc(2 * 150px); } 44 | #mixer #chequ { top:calc(4 * 15px); left:calc(2 * 150px); } 45 | #mixer #chcom { top:calc(5 * 15px); left:calc(2 * 150px); } 46 | #mixer #chvol { top:calc(6 * 15px); left:calc(2 * 150px); } 47 | #mixer #chlim { top:calc(7 * 15px); left:calc(2 * 150px); } 48 | 49 | /* Commander */ 50 | 51 | #commander input { padding: 0px 5px 0px 2.5px; width: calc(100vw - 70px); background: transparent; } 52 | 53 | /* Recorder */ 54 | 55 | #pilot.recording #recorder { animation: blink 500ms linear infinite; } 56 | #recorder { position: absolute; top: calc(11 * 15px); color: #333; left: 30px; font-family: 'input_mono_medium'; font-weight: normal;} 57 | 58 | #commander { top: calc(11 * 15px); left: 55px; position: absolute; line-height: 11px; } 59 | 60 | @media (max-width: 420px) { 61 | #pilot #mixer { columns:1 !important; min-width: 0px } 62 | #pilot #mixer > div { max-width: 100%} 63 | 64 | #mixer #ch0 { top:calc(0 * 15px); left:0px; } 65 | #mixer #ch1 { top:calc(1 * 15px); left:0px; } 66 | #mixer #ch2 { top:calc(2 * 15px); left:0px; } 67 | #mixer #ch3 { top:calc(3 * 15px); left:0px; } 68 | #mixer #ch4 { top:calc(4 * 15px); left:0px; } 69 | #mixer #ch5 { top:calc(5 * 15px); left:0px; } 70 | #mixer #ch6 { top:calc(6 * 15px); left:0px; } 71 | #mixer #ch7 { top:calc(7 * 15px); left:0px; } 72 | #mixer #ch8 { top:calc(8 * 15px); left:0px; } 73 | #mixer #ch9 { top:calc(9 * 15px); left:0px; } 74 | #mixer #cha { top:calc(10 * 15px); left:0px; } 75 | #mixer #chb { top:calc(11 * 15px); left:0px; } 76 | #mixer #chc { top:calc(12 * 15px); left:0px; } 77 | #mixer #chd { top:calc(13 * 15px); left:0px; } 78 | #mixer #che { top:calc(14 * 15px); left:0px; } 79 | #mixer #chf { top:calc(15 * 15px); left:0px; } 80 | 81 | #mixer #chbit { top:calc(0 * 15px); left:calc(1 * 110px) } 82 | #mixer #chdis { top:calc(1 * 15px); left:calc(1 * 110px) } 83 | #mixer #chwah { top:calc(2 * 15px); left:calc(1 * 110px) } 84 | #mixer #chche { top:calc(3 * 15px); left:calc(1 * 110px) } 85 | #mixer #chfee { top:calc(4 * 15px); left:calc(1 * 110px) } 86 | #mixer #chdel { top:calc(5 * 15px); left:calc(1 * 110px) } 87 | #mixer #chtre { top:calc(6 * 15px); left:calc(1 * 110px) } 88 | #mixer #chrev { top:calc(7 * 15px); left:calc(1 * 110px) } 89 | #mixer #chpha { top:calc(8 * 15px); left:calc(1 * 110px) } 90 | #mixer #chvib { top:calc(9 * 15px); left:calc(1 * 110px) } 91 | #mixer #chcho { top:calc(10 * 15px); left:calc(1 * 110px) } 92 | #mixer #chste { top:calc(11 * 15px); left:calc(1 * 110px) } 93 | #mixer #chequ { top:calc(12 * 15px); left:calc(1 * 110px) } 94 | #mixer #chcom { top:calc(13 * 15px); left:calc(1 * 110px) } 95 | #mixer #chvol { top:calc(14 * 15px); left:calc(1 * 110px) } 96 | #mixer #chlim { top:calc(15 * 15px); left:calc(1 * 110px) } 97 | 98 | #commander {top:calc(17 * 16px); } 99 | #recorder {top:calc(17 * 16px); } 100 | } -------------------------------------------------------------------------------- /desktop/sources/links/reset.css: -------------------------------------------------------------------------------- 1 | * { margin:0;padding:0;border:0;outline:0;text-decoration:none;font-weight:inherit;font-style:inherit;color:inherit;font-size:100%;font-family:inherit;vertical-align:baseline;list-style:none;border-collapse:collapse;border-spacing:0; -webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;} -------------------------------------------------------------------------------- /desktop/sources/links/style.css: -------------------------------------------------------------------------------- 1 | @import url(reset.css); 2 | @import url(fonts.css); 3 | @import url(main.css); 4 | @import url(theme.css); 5 | -------------------------------------------------------------------------------- /desktop/sources/links/theme.css: -------------------------------------------------------------------------------- 1 | body { background:var(--background) !important; color:var(--f_high) !important; } 2 | 3 | #mixer > div span { color:var(--f_high) !important; } 4 | #mixer > div span.cid { color:var(--f_low) !important; } 5 | #mixer > div .oct { background-color: var(--background) !important; -webkit-transition: background-color 250ms linear; } 6 | #mixer > div .env { background-color: var(--background) !important; -webkit-transition: background-color 250ms linear; } 7 | #mixer > div .osc { background-color: var(--background) !important; -webkit-transition: background-color 250ms linear; } 8 | #mixer > div .val { background-color: var(--background) !important; -webkit-transition: background-color 250ms linear; } 9 | 10 | #mixer > div .oct.active { background-color: var(--b_med) !important; -webkit-transition: background-color 1ms linear; color:var(--background) !important; } 11 | #mixer > div .env.active { background-color: var(--b_inv) !important; -webkit-transition: background-color 1ms linear; color:var(--background) !important; } 12 | #mixer > div .osc.active { background-color: var(--b_inv) !important; -webkit-transition: background-color 1ms linear; color:var(--background) !important; } 13 | #mixer > div .val.active { background-color: var(--b_inv) !important; -webkit-transition: background-color 1ms linear; color:var(--background) !important; } 14 | 15 | #commander input { color:var(--f_high) !important; } 16 | 17 | #pilot.recording #recorder { color:var(--b_inv) !important; } 18 | 19 | @keyframes blink { 20 | 0% { color: var(--b_inv) !important; } 21 | 100% { color: black; } 22 | } 23 | 24 | @-webkit-keyframes blink { 25 | 0% { color: var(--b_inv) !important; } 26 | 100% { color: black; } 27 | } -------------------------------------------------------------------------------- /desktop/sources/media/fonts/input_mono_medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hundredrabbits/Pilot/a77a4e059147d02fbbfb676e2417974a587dbaed/desktop/sources/media/fonts/input_mono_medium.ttf -------------------------------------------------------------------------------- /desktop/sources/media/fonts/input_mono_regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hundredrabbits/Pilot/a77a4e059147d02fbbfb676e2417974a587dbaed/desktop/sources/media/fonts/input_mono_regular.ttf -------------------------------------------------------------------------------- /desktop/sources/scripts/commander.js: -------------------------------------------------------------------------------- 1 | export default function Commander (pilot) { 2 | this.el = document.createElement('div') 3 | this.el.id = 'commander' 4 | 5 | this.input = document.createElement('input') 6 | 7 | // History of commands entered. 8 | this.history = [] 9 | 10 | // Index of history command to show in input. 11 | this.historyIndex = 0 12 | 13 | // Holds whether the user is browsing the history or not. 14 | this.isBrowsingHistory = false 15 | 16 | this.install = function (host) { 17 | this.el.appendChild(this.input) 18 | host.appendChild(this.el) 19 | } 20 | 21 | this.start = function () { 22 | this.input.focus() 23 | } 24 | 25 | this.input.oninput = (e) => { 26 | 27 | } 28 | 29 | this.input.onkeydown = (e) => { 30 | switch (e.keyCode) { 31 | case 40: // Down 32 | e.preventDefault() 33 | if (!this.isBrowsingHistory) { 34 | return 35 | } 36 | 37 | if (this.history.length) { 38 | if (this.historyIndex === this.history.length - 1) { 39 | this.isBrowsingHistory = false 40 | this.input.value = '' 41 | return 42 | } 43 | 44 | this.historyIndex += 1 45 | this.input.value = this.history[this.historyIndex] 46 | } 47 | break 48 | case 38: // Up 49 | e.preventDefault() 50 | if (!this.isBrowsingHistory) { 51 | this.historyIndex = this.history.length 52 | } 53 | 54 | this.isBrowsingHistory = true 55 | if (this.history.length && this.historyIndex > 0) { 56 | this.historyIndex -= 1 57 | this.input.value = this.history[this.historyIndex] 58 | } 59 | 60 | break 61 | } 62 | } 63 | 64 | this.input.onkeypress = (e) => { 65 | if (e.keyCode !== 13) { return } 66 | e.preventDefault() 67 | this.isBrowsingHistory = false 68 | this.history.push(this.input.value) 69 | pilot.mixer.run(this.input.value) 70 | this.input.value = '' 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /desktop/sources/scripts/interface.channel.js: -------------------------------------------------------------------------------- 1 | import Interface from './interface.js' 2 | import transposeTable from './transpose.js' 3 | 'use strict' 4 | 5 | const Tone = require('tone') 6 | 7 | const OCTAVE = ['C', 'c', 'D', 'd', 'E', 'F', 'f', 'G', 'g', 'A', 'a', 'B'] 8 | const MAJOR = ['C', 'D', 'E', 'F', 'G', 'A', 'B'] 9 | const MINOR = ['c', 'd', 'F', 'f', 'g', 'a', 'C'] 10 | const WAVCODES = ['si', 'tr', 'sq', 'sw', '2i', '2r', '2q', '2w', '4i', '4r', '4q', '4w', '8i', '8r', '8q', '8w'] 11 | const WAVNAMES = ['sine', 'triangle', 'square', 'sawtooth', 'sine2', 'triangle2', 'square2', 'sawtooth2', 'sine4', 'triangle4', 'square4', 'sawtooth4', 'sine8', 'triangle8', 'square8', 'sawtooth8'] 12 | 13 | export default function ChannelInterface (pilot, id, node) { 14 | Interface.call(this, pilot, id, node, true) 15 | 16 | this.node = node 17 | 18 | this.el = document.createElement('div') 19 | this.el.id = `ch${id.toString(16)}` 20 | this.el.className = 'channel' 21 | this.cid_el = document.createElement('span') 22 | this.cid_el.className = `cid` 23 | this.env_el = document.createElement('span') 24 | this.env_el.className = `env` 25 | this.osc_el = document.createElement('span') 26 | this.osc_el.className = `osc` 27 | 28 | this.cid_el.innerHTML = `${str36(id)}` 29 | 30 | this.el.appendChild(this.cid_el) 31 | this.el.appendChild(this.env_el) 32 | this.el.appendChild(this.osc_el) 33 | this.el.appendChild(this.canvas) 34 | 35 | // Run 36 | 37 | this.run = function (msg) { 38 | const channel = `${msg}`.substr(0, 1) 39 | if (int36(channel) === id) { 40 | this.operate(`${msg}`.substr(1)) 41 | } 42 | } 43 | 44 | this.operate = function (msg) { 45 | const data = parse(`${msg}`) 46 | if (!data) { console.warn(`Unknown data`); return } 47 | if (data.isEnv) { 48 | this.setEnv(data) 49 | } else if (data.isOsc) { 50 | this.setOsc(data) 51 | } else if (data.isNote) { 52 | this.playNote(data) 53 | } else if (data.isRen) { 54 | this.randEnv() 55 | } else if (data.isRos) { 56 | this.randOsc() 57 | } 58 | } 59 | 60 | this.playNote = function (data) { 61 | if (isNaN(data.octave)) { return } 62 | if (OCTAVE.indexOf(data.note) < 0) { console.warn(`Unknown Note`); return } 63 | if (this.lastNote && performance.now() - this.lastNote < 100) { return } 64 | const name = `${data.note}${data.sharp}${data.octave}` 65 | const length = clamp(data.length, 0.1, 0.9) 66 | this.node.triggerAttackRelease(name, length, '+0', data.velocity) 67 | this.lastNote = performance.now() 68 | } 69 | 70 | this.setEnv = function (data) { 71 | if (this.lastEnv && performance.now() - this.lastEnv < 100) { return } 72 | if (!this.node.envelope) { return } 73 | if (id > 11) { return } 74 | if (!isNaN(data.attack)) { this.node.envelope.attack = clamp(data.attack, 0.01, 1.0) } 75 | if (!isNaN(data.decay)) { this.node.envelope.decay = clamp(data.decay, 0.01, 1.0) } 76 | if (!isNaN(data.sustain)) { this.node.envelope.sustain = clamp(data.sustain, 0.01, 1.0) } 77 | if (!isNaN(data.release)) { this.node.envelope.release = clamp(data.release, 0.01, 1.0) } 78 | this.lastEnv = performance.now() 79 | this.updateEnv(data) 80 | } 81 | 82 | this.setOsc = function (data) { 83 | if (this.lastOsc && performance.now() - this.lastOsc < 100) { return } 84 | if (data.wav && this.node.oscillator) { 85 | this.node.oscillator._oscillator.set('type', data.wav) 86 | } 87 | if (data.mod && this.node.modulation) { 88 | this.node.modulation._oscillator.set('type', data.mod) 89 | } 90 | this.lastOsc = performance.now() 91 | this.updateOsc(data) 92 | } 93 | 94 | // Updates 95 | 96 | this.updateAll = function (data, force = false) { 97 | this.updateEnv(data, force) 98 | this.updateOsc(data, force) 99 | } 100 | 101 | this.updateEnv = function (data, force = false) { 102 | if (pilot.animate !== true) { return } 103 | if (force !== true && (!data || !data.isEnv)) { return } 104 | if (!this.node.envelope) { return } 105 | setContent(this.env_el, `${to16(this.node.envelope.attack)}${to16(this.node.envelope.decay)}${to16(this.node.envelope.sustain)}${to16(this.node.envelope.release)}`) 106 | } 107 | 108 | this.updateOsc = function (data, force = false) { 109 | if (pilot.animate !== true) { return } 110 | if (force !== true && (!data || !data.isOsc)) { return } 111 | setContent(this.osc_el, `${this.node.oscillator ? wavCode(this.node.oscillator._oscillator.type) : '--'}${this.node.modulation ? wavCode(this.node.modulation._oscillator.type) : '--'}`) 112 | } 113 | 114 | this.randEnv = function () { 115 | const a = to16(Math.random() * 0.25) 116 | const s = to16(Math.random() * 0.5) 117 | const d = to16(Math.random() * 0.75) 118 | const r = to16(Math.random() * 1) 119 | this.operate(`env${a}${s}${d}${r}`) 120 | } 121 | 122 | this.randOsc = function () { 123 | const a = WAVCODES[parseInt(Math.random() * WAVCODES.length)] 124 | const b = WAVCODES[parseInt(Math.random() * WAVCODES.length)] 125 | this.operate(`osc${a}${b}`) 126 | } 127 | 128 | // Parsers 129 | 130 | function parse (msg) { 131 | const cmd = msg.substr(0, 3).toLowerCase() 132 | const val = msg.substr(3) 133 | if (cmd === 'osc') { 134 | return parseOsc(val) 135 | } else if (cmd === 'env') { 136 | return parseEnv(val) 137 | } else if (cmd === 'ren') { 138 | return { isRen: true } 139 | } else if (cmd === 'ros') { 140 | return { isRos: true } 141 | } 142 | return parseNote(msg) 143 | } 144 | 145 | function parseNote (msg) { 146 | if (msg.length < 2) { console.warn(`Misformatted note`); return } 147 | const octave = clamp(parseInt(msg.substr(0, 1)), 0, 8) 148 | const note = msg.substr(1, 1) 149 | const velocity = msg.length >= 3 ? from16(msg.substr(2, 1)) : 0.66 150 | const length = msg.length === 4 ? from16(msg.substr(3, 1)) : 0.1 151 | const transposed = transpose(note, octave) 152 | console.log(transposed) 153 | return { isNote: true, octave: transposed.octave, note: transposed.note, sharp: isUpperCase(transposed.note) === false ? '#' : '', string: `${octave}${note}`, length: length, velocity: velocity } 154 | } 155 | 156 | function parseEnv (msg) { 157 | if (msg.length < 1) { console.warn(`Misformatted env`); return } 158 | const attack = int36(msg.substr(0, 1)) / 15 159 | const decay = msg.length > 1 ? int36(msg.substr(1, 1)) / 15 : null 160 | const sustain = msg.length > 2 ? int36(msg.substr(2, 1)) / 15 : null 161 | const release = msg.length > 3 ? int36(msg.substr(3, 1)) / 15 : null 162 | return { isEnv: true, attack: attack, decay: decay, sustain: sustain, release: release, string: 'env' } 163 | } 164 | 165 | function parseOsc (msg) { 166 | if (msg.length < 2) { console.warn(`Misformatted osc`); return } 167 | return { isOsc: true, wav: (msg.length > 1 ? wavName(msg.substr(0, 2)) : null), mod: (msg.length > 3 ? wavName(msg.substr(2, 2)) : null), string: 'osc' } 168 | } 169 | 170 | // Tools 171 | 172 | function transpose (n, o = 3) { 173 | if (!transposeTable[n]) { console.log('Unknown transpose: ', n); return null } 174 | const octave = clamp(parseInt(o) + parseInt(transposeTable[n].charAt(1)), 0, 8) 175 | const note = transposeTable[n].charAt(0) 176 | const value = ['C', 'c', 'D', 'd', 'E', 'F', 'f', 'G', 'g', 'A', 'a', 'B'].indexOf(note) 177 | const id = clamp((octave * 12) + value + 24, 0, 127) 178 | return { id, value, note, octave } 179 | } 180 | 181 | // Wave Codes 182 | 183 | function wavCode (n) { 184 | const name = n.toLowerCase() 185 | const index = WAVNAMES.indexOf(name) 186 | return index > -1 ? WAVCODES[index] : '??' 187 | } 188 | 189 | function wavName (c) { 190 | const code = c.toLowerCase() 191 | const index = WAVCODES.indexOf(code) 192 | return index > -1 ? WAVNAMES[index] : 'sine' 193 | } 194 | 195 | // Helpers 196 | function letterValue (c) { return c.toLowerCase().charCodeAt(0) - 97 } 197 | function isUpperCase (s) { return `${s}`.toUpperCase() === `${s}` } 198 | function from16 (str) { return (int36(str) / 15) } 199 | function to16 (float) { return str36(Math.floor(float * 15)) } 200 | function str36 (int) { return ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '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'][parseInt(int)] } 201 | function int36 (str) { return ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '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'].indexOf(`${str.toLowerCase()}`) } 202 | function clamp (v, min, max) { return v < min ? min : v > max ? max : v } 203 | 204 | // Dom Tools 205 | function setClass (el, cl) { if (el.className !== cl) { el.className = cl } } 206 | function setContent (el, ct) { if (el.innerHTML !== ct) { el.innerHTML = ct } } 207 | } 208 | -------------------------------------------------------------------------------- /desktop/sources/scripts/interface.effect.js: -------------------------------------------------------------------------------- 1 | import Interface from './interface.js' 2 | const Tone = require('tone') 3 | 4 | export default function EffectInterface (pilot, id, node) { 5 | Interface.call(this, pilot, id, node, true) 6 | 7 | this.node = node 8 | if (this.node.wet) { 9 | this.node.wet.value = 0 10 | } 11 | 12 | this.el = document.createElement('div') 13 | this.el.id = `ch${id}` 14 | this.el.className = 'effect' 15 | this.cid_el = document.createElement('span') 16 | this.cid_el.className = `cid` 17 | this.val_el = document.createElement('span') 18 | this.val_el.className = `val` 19 | 20 | this.cid_el.innerHTML = `${id}` 21 | 22 | this.el.appendChild(this.cid_el) 23 | this.el.appendChild(this.val_el) 24 | 25 | // Run 26 | 27 | this.run = function (msg) { 28 | if (!msg || msg.substr(0, 3).toLowerCase() !== id) { return } 29 | 30 | if (msg.substr(0, 3).toLowerCase() === id) { 31 | this.operate(`${msg}`.substr(3)) 32 | } 33 | } 34 | 35 | this.operate = function (msg) { 36 | const data = parse(`${msg}`) 37 | if (!data) { console.warn(`Unknown data`); return } 38 | this.setEffect(data) 39 | } 40 | 41 | this.setEffect = function (data) { 42 | if (this.lastEffect && performance.now() - this.lastEffect < 100) { return } 43 | 44 | if (this.node.wet) { 45 | this.node.wet.value = data.wet 46 | } 47 | 48 | if (!isNaN(data.value)) { 49 | if (data.code === 'rev') { 50 | this.node.roomSize.value = data.value 51 | } else if (data.code === 'dis') { 52 | this.node.distortion = data.value 53 | } else if (data.code === 'bit') { 54 | this.node.bits = clamp(parseInt(data.value * 8), 1, 8) 55 | } else if (data.code === 'cho') { 56 | this.node.depth = data.value 57 | } else if (data.code === 'fee') { 58 | this.node.delayTime.value = data.value 59 | } else if (data.code === 'tre') { 60 | this.node.depth.value = data.value 61 | } else if (data.code === 'vib') { 62 | this.node.depth.value = data.value 63 | } else if (data.code === 'aut') { 64 | this.node.depth.value = data.value 65 | } else if (data.code === 'pha') { 66 | this.node.octaves = clamp(parseInt(data.value * 3), 0, 8) 67 | } else if (data.code === 'wah') { 68 | this.node.octaves = clamp(parseInt(data.value * 6), 0, 8) 69 | } else if (data.code === 'che') { 70 | this.node.order = clamp(parseInt(data.value * 100), 0, 8) 71 | } else { 72 | console.warn('Unknown value', this.node) 73 | } 74 | } 75 | this.lastEffect = performance.now() 76 | this.updateEffect(data, true) 77 | } 78 | 79 | this.rand = function () { 80 | this.operate(`${to16(Math.random() * 0.5)}${to16(Math.random() * 1)}`) 81 | } 82 | 83 | // Updates 84 | 85 | this.updateAll = function (data, force = false) { 86 | this.updateEffect(data, force) 87 | } 88 | 89 | this.updateEffect = function (data, force = false) { 90 | if (pilot.animate !== true) { return } 91 | if (force !== true && (!data || !data.isEffect)) { return } 92 | 93 | let value = 0 94 | if (id === 'rev') { 95 | value = this.node.roomSize.value 96 | } else if (id === 'dis') { 97 | value = this.node.distortion 98 | } else if (id === 'cho') { 99 | value = this.node.depth 100 | } else if (id === 'bit') { 101 | value = this.node.bits / 8 102 | } else if (id === 'fee') { 103 | value = this.node.delayTime.value 104 | } else if (id === 'tre') { 105 | value = this.node.depth.value 106 | } else if (id === 'vib') { 107 | value = this.node.depth.value 108 | } else if (id === 'aut') { 109 | value = this.node.depth.value 110 | } else if (id === 'pha') { 111 | value = this.node.octaves / 3 112 | } else if (id === 'wah') { 113 | value = this.node.octaves / 6 114 | } else if (id === 'che') { 115 | value = this.node.order / 100 116 | } 117 | 118 | if (this.node.wet) { 119 | setContent(this.val_el, `${to16(this.node.wet.value)}${to16(value)}`) 120 | } 121 | } 122 | 123 | // Parsers 124 | 125 | function parse (msg) { 126 | if (msg.length !== 2 && msg.length !== 1) { console.warn(`Misformatted effect`, msg); return } 127 | const wet = int36(msg.substr(0, 1)) / 15 128 | const value = int36(msg.substr(1, 1)) / 15 129 | return { isEffect: true, code: id, wet: wet, value: value } 130 | } 131 | 132 | // Helpers 133 | function from16 (str) { return (int36(str) / 15) } 134 | function to16 (float) { return str36(Math.floor(float * 15)) } 135 | function str36 (int) { return ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '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'][parseInt(int)] } 136 | function int36 (str) { return ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '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'].indexOf(`${str}`) } 137 | function clamp (v, min, max) { return v < min ? min : v > max ? max : v } 138 | 139 | // Dom Tools 140 | function setContent (el, ct) { if (el.innerHTML !== ct) { el.innerHTML = ct } } 141 | } 142 | -------------------------------------------------------------------------------- /desktop/sources/scripts/interface.js: -------------------------------------------------------------------------------- 1 | const Tone = require('tone') 2 | 3 | export default function Interface (pilot, id, node) { 4 | this.node = node 5 | this.meter = new Tone.Meter(0.95) 6 | this.waveform = new Tone.Waveform(256) 7 | 8 | this.el = document.createElement('div') 9 | this.el.id = `ch${id}` 10 | this.canvas = document.createElement('canvas') 11 | 12 | const self = this 13 | 14 | const waveform = this.waveform 15 | const meter = this.meter 16 | const canvasWidth = 13 * 4 17 | const canvasHeight = 13 * 2 18 | const context = this.canvas.getContext('2d') 19 | 20 | let lastUpdate = null 21 | 22 | this.install = function (host) { 23 | this.canvas.width = canvasWidth 24 | this.canvas.height = canvasHeight 25 | this.canvas.style.width = (canvasWidth / 2) + 'px' 26 | this.canvas.style.height = (canvasHeight / 2) + 'px' 27 | 28 | context.lineJoin = 'round' 29 | context.lineWidth = 2 30 | context.strokeStyle = pilot.theme.active.f_high 31 | 32 | this.node.connect(this.meter) 33 | this.node.fan(this.waveform) 34 | this.el.appendChild(this.canvas) 35 | host.appendChild(this.el) 36 | } 37 | 38 | this.start = function () { 39 | this.updateAll({}, true) 40 | loop() 41 | } 42 | 43 | this.connect = function (node) { 44 | this.node.connect(node) 45 | } 46 | 47 | function draw (level) { 48 | if (pilot.animate !== true) { return } 49 | if (lastUpdate && performance.now() - lastUpdate < 30) { return } 50 | 51 | context.clearRect(0, 0, canvasWidth, canvasHeight) 52 | 53 | drawActivity() 54 | drawWaveform() 55 | 56 | lastUpdate = performance.now() 57 | } 58 | 59 | function drawWaveform () { 60 | const values = waveform.getValue() 61 | const level = meter.getLevel() 62 | const gain = Tone.dbToGain(level) 63 | 64 | context.beginPath() 65 | context.moveTo(0, parseInt(((values[0] + 1) / 2) * canvasHeight)) 66 | 67 | if (gain > 0.01) { 68 | for (let i = 1, len = values.length; i < len; i++) { 69 | if (i % 17 !== 0) { continue } 70 | const x = parseInt(canvasWidth * (i / len)) 71 | const y = parseInt(((values[i] + 1) / 2) * canvasHeight) 72 | context.lineTo(clamp(x, 2, canvasWidth - 2), clamp(y, 2, canvasHeight - 2)) 73 | } 74 | } 75 | 76 | context.lineTo(canvasWidth, parseInt(((values[0] + 1) / 2) * canvasHeight)) 77 | 78 | context.stroke() 79 | context.closePath() 80 | } 81 | 82 | function drawActivity () { 83 | if (!self) { return } 84 | if (!self.lastNote) { return } 85 | 86 | const elapsed = performance.now() - self.lastNote 87 | const max = 500 88 | 89 | context.beginPath() 90 | context.arc(2, 4, 2, 0, 2 * Math.PI, false) 91 | context.fillStyle = `rgba(255,255,255,${(1 - (elapsed / max))})` 92 | context.fill() 93 | context.closePath() 94 | } 95 | 96 | function loop () { 97 | requestAnimationFrame(loop) 98 | draw() 99 | } 100 | 101 | function clamp (v, min, max) { return v < min ? min : v > max ? max : v } 102 | } 103 | -------------------------------------------------------------------------------- /desktop/sources/scripts/lib/controller.js: -------------------------------------------------------------------------------- 1 | export default function Controller () { 2 | const fs = require('fs') 3 | const { dialog, app } = require('electron').remote 4 | 5 | this.menu = { default: {} } 6 | this.mode = 'default' 7 | 8 | this.app = require('electron').remote.app 9 | 10 | this.start = function () { 11 | } 12 | 13 | this.add = function (mode, cat, label, fn, accelerator) { 14 | if (!this.menu[mode]) { this.menu[mode] = {} } 15 | if (!this.menu[mode][cat]) { this.menu[mode][cat] = {} } 16 | this.menu[mode][cat][label] = { fn: fn, accelerator: accelerator } 17 | } 18 | 19 | this.addRole = function (mode, cat, label) { 20 | if (!this.menu[mode]) { this.menu[mode] = {} } 21 | if (!this.menu[mode][cat]) { this.menu[mode][cat] = {} } 22 | this.menu[mode][cat][label] = { role: label } 23 | } 24 | 25 | this.format = function () { 26 | const f = [] 27 | const m = this.menu[this.mode] 28 | for (const cat in m) { 29 | const submenu = [] 30 | for (const name in m[cat]) { 31 | const option = m[cat][name] 32 | if (option.role) { 33 | submenu.push({ role: option.role }) 34 | } else { 35 | submenu.push({ label: name, accelerator: option.accelerator, click: option.fn }) 36 | } 37 | } 38 | f.push({ label: cat, submenu: submenu }) 39 | } 40 | return f 41 | } 42 | 43 | this.commit = function () { 44 | this.app.injectMenu(this.format()) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /desktop/sources/scripts/lib/theme.js: -------------------------------------------------------------------------------- 1 | export default function Theme (_default) { 2 | const themer = this 3 | 4 | this.active = _default 5 | 6 | this.el = document.createElement('style') 7 | this.el.type = 'text/css' 8 | 9 | this.install = function (host = document.body, callback) { 10 | console.log('Theme', 'Installing..') 11 | host.appendChild(this.el) 12 | this.callback = callback 13 | } 14 | 15 | this.start = function () { 16 | console.log('Theme', 'Starting..') 17 | if (isJson(localStorage.theme)) { 18 | const storage = JSON.parse(localStorage.theme) 19 | if (validate(storage)) { 20 | console.log('Theme', 'Found theme in localStorage!') 21 | this.load(storage) 22 | return 23 | } 24 | } 25 | this.load(_default) 26 | } 27 | 28 | this.load = function (data) { 29 | const theme = parse(data) 30 | if (!validate(theme)) { console.warn('Theme', 'Not a theme', theme); return } 31 | console.log('Theme', `Loading theme with background ${theme.background}.`) 32 | 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}; }` 33 | localStorage.setItem('theme', JSON.stringify(theme)) 34 | this.active = theme 35 | if (this.callback) { 36 | this.callback() 37 | } 38 | } 39 | 40 | this.reset = function () { 41 | this.load(_default) 42 | } 43 | 44 | function parse (any) { 45 | if (any && any.background) { return any } else if (any && any.data) { return any.data } else if (any && isJson(any)) { return JSON.parse(any) } else if (any && isHtml(any)) { return extract(any) } 46 | return null 47 | } 48 | 49 | // Drag 50 | 51 | this.drag = function (e) { 52 | e.stopPropagation() 53 | e.preventDefault() 54 | e.dataTransfer.dropEffect = 'copy' 55 | } 56 | 57 | this.drop = function (e) { 58 | e.preventDefault() 59 | e.stopPropagation() 60 | const file = e.dataTransfer.files[0] 61 | if (!file || !file.name) { console.warn('Theme', 'Unnamed file.'); return } 62 | if (file.name.indexOf('.thm') < 0 && file.name.indexOf('.svg') < 0) { console.warn('Theme', 'Skipped, not a theme'); return } 63 | const reader = new FileReader() 64 | reader.onload = function (e) { 65 | themer.load(e.target.result) 66 | } 67 | reader.readAsText(file) 68 | } 69 | 70 | this.open = function () { 71 | const fs = require('fs') 72 | const { dialog, app } = require('electron').remote 73 | let paths = dialog.showOpenDialog(app.win, { properties: ['openFile'], filters: [{ name: 'Themes', extensions: ['svg'] }] }) 74 | if (!paths) { console.log('Nothing to load') } 75 | fs.readFile(paths[0], 'utf8', function (err, data) { 76 | if (err) throw err 77 | themer.load(data) 78 | }) 79 | } 80 | 81 | window.addEventListener('dragover', this.drag) 82 | window.addEventListener('drop', this.drop) 83 | 84 | // Helpers 85 | 86 | function validate (json) { 87 | if (!json) { return false } 88 | if (!json.background) { return false } 89 | if (!json.f_high) { return false } 90 | if (!json.f_med) { return false } 91 | if (!json.f_low) { return false } 92 | if (!json.f_inv) { return false } 93 | if (!json.b_high) { return false } 94 | if (!json.b_med) { return false } 95 | if (!json.b_low) { return false } 96 | if (!json.b_inv) { return false } 97 | return true 98 | } 99 | 100 | function extract (text) { 101 | const svg = new DOMParser().parseFromString(text, 'text/xml') 102 | try { 103 | return { 104 | 'background': svg.getElementById('background').getAttribute('fill'), 105 | 'f_high': svg.getElementById('f_high').getAttribute('fill'), 106 | 'f_med': svg.getElementById('f_med').getAttribute('fill'), 107 | 'f_low': svg.getElementById('f_low').getAttribute('fill'), 108 | 'f_inv': svg.getElementById('f_inv').getAttribute('fill'), 109 | 'b_high': svg.getElementById('b_high').getAttribute('fill'), 110 | 'b_med': svg.getElementById('b_med').getAttribute('fill'), 111 | 'b_low': svg.getElementById('b_low').getAttribute('fill'), 112 | 'b_inv': svg.getElementById('b_inv').getAttribute('fill') 113 | } 114 | } catch (err) { 115 | console.warn('Theme', 'Incomplete SVG Theme', err) 116 | } 117 | } 118 | 119 | function isJson (text) { 120 | try { JSON.parse(text); return true } catch (error) { return false } 121 | } 122 | 123 | function isHtml (text) { 124 | try { new DOMParser().parseFromString(text, 'text/xml'); return true } catch (error) { return false } 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /desktop/sources/scripts/listener.js: -------------------------------------------------------------------------------- 1 | const dgram = require('dgram') 2 | 3 | export default function Listener (pilot) { 4 | this.server = dgram.createSocket('udp4') 5 | 6 | this.server.on('message', (msg, rinfo) => { 7 | pilot.mixer.run(`${msg}`) 8 | }) 9 | 10 | this.server.on('listening', () => { 11 | const address = this.server.address() 12 | console.log(`Server listening for UDP:\n ${address.address}:${address.port}`) 13 | }) 14 | 15 | this.server.on('error', (err) => { 16 | console.log(`Server error:\n ${err.stack}`) 17 | server.close() 18 | }) 19 | 20 | this.server.bind(49161) // TODO - make this configurable 21 | } 22 | -------------------------------------------------------------------------------- /desktop/sources/scripts/mixer.js: -------------------------------------------------------------------------------- 1 | import ChannelInterface from './interface.channel.js' 2 | import EffectInterface from './interface.effect.js' 3 | 4 | const Tone = require('tone') 5 | 6 | export default function Mixer (pilot) { 7 | this.el = document.createElement('div') 8 | this.el.id = 'mixer' 9 | 10 | this.channels = [] 11 | this.effects = {} 12 | 13 | this.install = function (host) { 14 | console.log('Mixer', 'Installing..') 15 | 16 | Tone.start() 17 | Tone.Transport.start() 18 | 19 | // AM 20 | this.channels[0] = new ChannelInterface(pilot, 0, new Tone.AMSynth({ 'harmonicity': 1.25, 'oscillator': { 'type': 'sine8' }, 'modulation': { 'type': 'sine' } })) 21 | this.channels[1] = new ChannelInterface(pilot, 1, new Tone.AMSynth({ 'harmonicity': 1.5, 'oscillator': { 'type': 'triangle8' }, 'modulation': { 'type': 'sawtooth' } })) 22 | this.channels[2] = new ChannelInterface(pilot, 2, new Tone.AMSynth({ 'harmonicity': 1.75, 'oscillator': { 'type': 'sawtooth8' }, 'modulation': { 'type': 'triangle' } })) 23 | this.channels[3] = new ChannelInterface(pilot, 3, new Tone.AMSynth({ 'harmonicity': 2, 'oscillator': { 'type': 'square8' }, 'modulation': { 'type': 'square' } })) 24 | // AM 25 | this.channels[4] = new ChannelInterface(pilot, 4, new Tone.AMSynth({ 'harmonicity': 1.25, 'oscillator': { 'type': 'sine4' }, 'modulation': { 'type': 'square8' } })) 26 | this.channels[5] = new ChannelInterface(pilot, 5, new Tone.AMSynth({ 'harmonicity': 1.5, 'oscillator': { 'type': 'triangle4' }, 'modulation': { 'type': 'sawtooth8' } })) 27 | this.channels[6] = new ChannelInterface(pilot, 6, new Tone.FMSynth({ 'harmonicity': 1.75, 'modulationIndex': 10, 'oscillator': { 'type': 'sawtooth4' }, 'modulation': { 'type': 'triangle8' } })) 28 | this.channels[7] = new ChannelInterface(pilot, 7, new Tone.FMSynth({ 'harmonicity': 2, 'modulationIndex': 20, 'oscillator': { 'type': 'square4' }, 'modulation': { 'type': 'sine8' } })) 29 | // FM 30 | this.channels[8] = new ChannelInterface(pilot, 8, new Tone.FMSynth({ 'harmonicity': 0.5, 'modulationIndex': 30, 'oscillator': { 'type': 'sine' }, 'modulation': { 'type': 'sawtooth4' } })) 31 | this.channels[9] = new ChannelInterface(pilot, 9, new Tone.FMSynth({ 'harmonicity': 2.5, 'modulationIndex': 40, 'oscillator': { 'type': 'sine' }, 'modulation': { 'type': 'triangle8' } })) 32 | this.channels[10] = new ChannelInterface(pilot, 10, new Tone.MonoSynth({ 'volume': -20, oscillator: { 'type': 'sawtooth4' } })) 33 | this.channels[11] = new ChannelInterface(pilot, 11, new Tone.MonoSynth({ 'volume': -20, oscillator: { 'type': 'sine4' } })) 34 | // Membrane 35 | this.channels[12] = new ChannelInterface(pilot, 12, new Tone.MembraneSynth({ 'octaves': 5, 'oscillator': { 'type': 'sine' } })) 36 | this.channels[13] = new ChannelInterface(pilot, 13, new Tone.MembraneSynth({ 'octaves': 10, 'oscillator': { 'type': 'sawtooth' } })) 37 | this.channels[14] = new ChannelInterface(pilot, 14, new Tone.MembraneSynth({ 'octaves': 15, 'oscillator': { 'type': 'triangle' } })) 38 | this.channels[15] = new ChannelInterface(pilot, 15, new Tone.MembraneSynth({ 'octaves': 20, 'oscillator': { 'type': 'square' } })) 39 | 40 | // I 41 | this.effects.bitcrusher = new EffectInterface(pilot, 'bit', new Tone.BitCrusher(4)) 42 | this.effects.distortion = new EffectInterface(pilot, 'dis', new Tone.Distortion(0.05)) 43 | this.effects.autowah = new EffectInterface(pilot, 'wah', new Tone.AutoWah(100, 6, 0)) 44 | this.effects.chebyshev = new EffectInterface(pilot, 'che', new Tone.Chebyshev(50)) 45 | // II 46 | this.effects.feedback = new EffectInterface(pilot, 'fee', new Tone.FeedbackDelay(0)) 47 | this.effects.delay = new EffectInterface(pilot, 'del', new Tone.PingPongDelay('4n', 0.2)) 48 | this.effects.tremolo = new EffectInterface(pilot, 'tre', new Tone.Tremolo()) 49 | this.effects.reverb = new EffectInterface(pilot, 'rev', new Tone.JCReverb(0)) 50 | // III 51 | this.effects.phaser = new EffectInterface(pilot, 'pha', new Tone.Phaser(0.5, 3, 350)) 52 | this.effects.vibrato = new EffectInterface(pilot, 'vib', new Tone.Vibrato()) 53 | this.effects.chorus = new EffectInterface(pilot, 'cho', new Tone.Chorus(4, 2.5, 0.5)) 54 | this.effects.widener = new EffectInterface(pilot, 'ste', new Tone.StereoWidener(0.5, 3, 350)) 55 | // Mastering 56 | this.effects.equalizer = new EffectInterface(pilot, 'equ', new Tone.EQ3(5, 0, 5)) 57 | this.effects.compressor = new EffectInterface(pilot, 'com', new Tone.Compressor(-6, 4)) 58 | this.effects.volume = new EffectInterface(pilot, 'vol', new Tone.Volume(6)) 59 | this.effects.limiter = new EffectInterface(pilot, 'lim', new Tone.Limiter(-2)) 60 | 61 | // Connect 62 | for (const id in this.channels) { 63 | this.channels[id].connect(this.effects.bitcrusher.node) 64 | } 65 | 66 | this.effects.bitcrusher.connect(this.effects.distortion.node) 67 | this.effects.distortion.connect(this.effects.autowah.node) 68 | this.effects.autowah.connect(this.effects.chebyshev.node) 69 | this.effects.chebyshev.connect(this.effects.feedback.node) 70 | 71 | this.effects.feedback.connect(this.effects.delay.node) 72 | this.effects.delay.connect(this.effects.tremolo.node) 73 | this.effects.tremolo.connect(this.effects.reverb.node) 74 | this.effects.reverb.connect(this.effects.phaser.node) 75 | 76 | this.effects.phaser.connect(this.effects.vibrato.node) 77 | this.effects.vibrato.connect(this.effects.chorus.node) 78 | this.effects.chorus.connect(this.effects.widener.node) 79 | this.effects.widener.connect(this.effects.equalizer.node) 80 | 81 | this.effects.equalizer.connect(this.effects.compressor.node) 82 | this.effects.compressor.connect(this.effects.volume.node) 83 | this.effects.volume.connect(this.effects.limiter.node) 84 | 85 | // Add all instruments to dom 86 | for (const id in this.channels) { 87 | this.channels[id].install(this.el) 88 | } 89 | 90 | // Add all effects to dom 91 | for (const id in this.effects) { 92 | this.effects[id].install(this.el) 93 | } 94 | 95 | host.appendChild(this.el) 96 | } 97 | 98 | this.start = function () { 99 | console.log('Synthetiser', 'Starting..') 100 | for (const id in this.channels) { 101 | this.channels[id].start() 102 | } 103 | for (const id in this.effects) { 104 | this.effects[id].start() 105 | } 106 | 107 | // Set to Presets 108 | this.reset() 109 | 110 | this.setSpeed(120) 111 | setTimeout(() => { this.effects.limiter.node.toMaster() }, 2000) 112 | this.run() 113 | } 114 | 115 | this.run = function (msg) { 116 | // Multi 117 | if (`${msg}`.indexOf(';') > -1) { 118 | const parts = `${msg}`.split(';') 119 | for (const id in parts) { 120 | this.run(parts[id]) 121 | } 122 | return 123 | } 124 | // Single 125 | for (const id in this.channels) { 126 | this.channels[id].run(msg) 127 | } 128 | for (const id in this.effects) { 129 | this.effects[id].run(msg) 130 | } 131 | // Special 132 | if (msg && `${msg}`.substr(0, 3).toLowerCase() === 'bpm') { 133 | this.setSpeed(msg.substr(3)) 134 | } 135 | // Special 136 | if (msg && `${msg}`.substr(0, 4).toLowerCase() === 'renv') { 137 | for (const id in this.channels) { 138 | this.channels[id].randEnv() 139 | } 140 | } 141 | if (msg && `${msg}`.substr(0, 4).toLowerCase() === 'rosc') { 142 | for (const id in this.channels) { 143 | this.channels[id].randOsc() 144 | } 145 | } 146 | if (msg && `${msg}`.substr(0, 4).toLowerCase() === 'refx') { 147 | for (const id in this.effects) { 148 | this.effects[id].rand(msg) 149 | } 150 | } 151 | if (msg && `${msg}`.substr(0, 5).toLowerCase() === 'reset') { 152 | this.reset() 153 | } 154 | } 155 | 156 | this.setSpeed = function (bpm) { 157 | if (parseInt(bpm) < 30) { return } 158 | Tone.Transport.bpm.rampTo(parseInt(bpm), 4) 159 | console.log(`Changed BPM to ${bpm}.`) 160 | pilot.recorder.el.innerHTML = `${bpm}` 161 | } 162 | 163 | this.reset = function () { 164 | // Return to Env Presets 165 | for (const id in this.channels) { 166 | this.channels[id].setEnv({ isEnv: true, 167 | attack: 0.001, 168 | decay: clamp(((8 - (id % 8)) / 8), 0.01, 0.9), 169 | sustain: clamp(((id % 4) / 4), 0.01, 0.9), 170 | release: clamp(((id % 6) / 6), 0.01, 0.9) 171 | }) 172 | } 173 | // Return to Osc Presets 174 | this.run('0OSC8ISI;1OSC8RSW;2OSC8WTR;3OSC8QSQ;4OSC4I8Q;5OSC4R8W;6OSCTR8R;7OSCTR8I;8OSCTR4W;9OSCTR8R;AOSC4W--;BOSC4I--;COSCSI--;DOSCSW--;EOSCTR--;FOSCSQ--') 175 | // Return to Effects Presets 176 | this.run('BIT07;DIS00;WAH0F;CHE07;FEE00;TRE07;REV00;PHA0F;VIB01;CHO07') 177 | } 178 | 179 | function clamp (v, min, max) { return v < min ? min : v > max ? max : v } 180 | } 181 | -------------------------------------------------------------------------------- /desktop/sources/scripts/pilot.js: -------------------------------------------------------------------------------- 1 | import Listener from './listener.js' 2 | import Mixer from './mixer.js' 3 | import Recorder from './recorder.js' 4 | import Commander from './commander.js' 5 | import Theme from './lib/theme.js' 6 | 7 | const { webFrame } = require('electron') 8 | 9 | export default function Pilot () { 10 | this.listener = null 11 | this.mixer = null 12 | this.recorder = null 13 | this.commander = null 14 | this.theme = new Theme({ background: '#000000', f_high: '#ffffff', f_med: '#777777', f_low: '#444444', f_inv: '#000000', b_high: '#eeeeee', b_med: '#333', b_low: '#444444', b_inv: '#fff' }) 15 | 16 | this.el = document.createElement('div') 17 | this.el.id = 'pilot' 18 | 19 | this.animate = true 20 | 21 | this.install = function (host) { 22 | console.info('Pilot is installing..') 23 | 24 | this.mixer = new Mixer(this) 25 | this.listener = new Listener(this) 26 | this.recorder = new Recorder(this) 27 | this.commander = new Commander(this) 28 | 29 | host.appendChild(this.el) 30 | 31 | this.theme.install() 32 | this.mixer.install(this.el) 33 | this.recorder.install(this.el) 34 | this.commander.install(this.el) 35 | } 36 | 37 | this.start = function () { 38 | console.info('Pilot is starting..') 39 | this.mixer.start() 40 | this.commander.start() 41 | this.theme.start() 42 | 43 | const zoomFactor = Number(localStorage.getItem('zoomFactor')) 44 | webFrame.setZoomFactor(zoomFactor) 45 | } 46 | 47 | this.toggleAnimations = function (mod, set = false) { 48 | this.animate = this.animate !== true 49 | } 50 | 51 | this.modZoom = function (mod = 0, set = false) { 52 | const currentZoomFactor = webFrame.getZoomFactor() 53 | const newZoomFactor = set ? mod : currentZoomFactor + mod 54 | webFrame.setZoomFactor(newZoomFactor) 55 | localStorage.setItem('zoomFactor', newZoomFactor) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /desktop/sources/scripts/recorder.js: -------------------------------------------------------------------------------- 1 | const { dialog, app } = require('electron').remote 2 | const Tone = require('tone') 3 | const fs = require('fs') 4 | 5 | export default function Recorder (pilot) { 6 | this.el = document.createElement('div') 7 | this.el.id = 'recorder' 8 | this.el.className = 'blink' 9 | this.el.textContent = '•' 10 | this.isRecording = false 11 | 12 | let chunks = [] 13 | 14 | this.install = function (host) { 15 | console.log('Recorder', 'Installing..') 16 | 17 | pilot.mixer.hook = Tone.context.createMediaStreamDestination() 18 | pilot.mixer.recorder = new MediaRecorder(pilot.mixer.hook.stream) 19 | pilot.mixer.effects.limiter.connect(pilot.mixer.hook) 20 | 21 | pilot.mixer.recorder.onstop = evt => { 22 | const blob = new Blob(chunks, { type: 'audio/opus; codecs=opus' }) 23 | pilot.recorder.save(blob) 24 | } 25 | 26 | pilot.mixer.recorder.ondataavailable = evt => { 27 | chunks.push(evt.data) 28 | } 29 | 30 | host.appendChild(this.el) 31 | } 32 | 33 | this.start = function () { 34 | console.log('Recorder', 'Starting..') 35 | this.isRecording = true 36 | chunks = [] 37 | pilot.mixer.recorder.start() 38 | pilot.el.className = 'recording' 39 | } 40 | 41 | this.stop = function () { 42 | if (!this.isRecording) { return } 43 | 44 | console.log('Recorder', 'Stopping..') 45 | this.isRecording = false 46 | pilot.mixer.recorder.stop() 47 | pilot.el.className = '' 48 | } 49 | 50 | this.toggle = function () { 51 | if (this.isRecording !== true) { 52 | this.start() 53 | } else { 54 | this.stop() 55 | } 56 | } 57 | 58 | this.save = function (blob) { 59 | dialog.showSaveDialog({ filters: [{ name: 'Audio File', extensions: ['opus'] }] }, (path) => { 60 | if (path === undefined) { return } 61 | pilot.recorder.write(path, blob) 62 | }) 63 | } 64 | 65 | this.write = function (path, blob) { 66 | const reader = new FileReader() 67 | reader.onload = function () { 68 | const buffer = new Buffer.from(reader.result) 69 | fs.writeFile(path, buffer, {}, (err, res) => { 70 | if (err) { console.error(err); return } 71 | console.log('Recorder', 'Export complete.') 72 | }) 73 | } 74 | reader.readAsArrayBuffer(blob) 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /desktop/sources/scripts/transpose.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | export default { 4 | 'A': 'A0', 5 | 'a': 'a0', 6 | 'B': 'B0', 7 | 'C': 'C0', 8 | 'c': 'c0', 9 | 'D': 'D0', 10 | 'd': 'd0', 11 | 'E': 'E0', 12 | 'F': 'F0', 13 | 'f': 'f0', 14 | 'G': 'G0', 15 | 'g': 'g0', 16 | 'H': 'A0', 17 | 'h': 'a0', 18 | 'I': 'B0', 19 | 'J': 'C1', 20 | 'j': 'c1', 21 | 'K': 'D1', 22 | 'k': 'd1', 23 | 'L': 'E1', 24 | 'M': 'F1', 25 | 'm': 'f1', 26 | 'N': 'G1', 27 | 'n': 'g1', 28 | 'O': 'A1', 29 | 'o': 'a1', 30 | 'P': 'B1', 31 | 'Q': 'C2', 32 | 'q': 'c2', 33 | 'R': 'D2', 34 | 'r': 'd2', 35 | 'S': 'E2', 36 | 'T': 'F2', 37 | 't': 'f2', 38 | 'U': 'G2', 39 | 'u': 'g2', 40 | 'V': 'A2', 41 | 'v': 'a2', 42 | 'W': 'B2', 43 | 'X': 'C3', 44 | 'x': 'c3', 45 | 'Y': 'D3', 46 | 'y': 'd3', 47 | 'Z': 'E3', 48 | // Catch e 49 | 'e': 'F0', 50 | 'l': 'F1', 51 | 's': 'F2', 52 | 'z': 'F3', 53 | // Catch b 54 | 'b': 'C1', 55 | 'i': 'C1', 56 | 'p': 'C2', 57 | 'w': 'C3' 58 | } 59 | -------------------------------------------------------------------------------- /resources/device.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hundredrabbits/Pilot/a77a4e059147d02fbbfb676e2417974a587dbaed/resources/device.jpg -------------------------------------------------------------------------------- /resources/preview.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hundredrabbits/Pilot/a77a4e059147d02fbbfb676e2417974a587dbaed/resources/preview.jpg --------------------------------------------------------------------------------