├── .env ├── assets ├── icon.png └── favicon.ico ├── public ├── assets │ ├── logo.png │ ├── favicon.ico │ └── apple-touch-icon.png ├── const.js ├── rendererApi │ ├── path.js │ ├── dialog.js │ ├── store.js │ ├── wav.js │ ├── fs.js │ └── midi.js ├── events │ ├── events.js │ ├── mainProcessTriggers.js │ ├── mainProcessCallbacks.js │ ├── rendererProcessEvents.js │ └── mainProcessEvents.js ├── manifest.json ├── README.md ├── index.html ├── preload.js ├── electron.js └── mainApi │ └── menu.js ├── src ├── README.md ├── fonts │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.ttf │ ├── glyphicons-halflings-regular.woff │ └── glyphicons-halflings-regular.woff2 ├── util │ ├── buffer.js │ ├── fileDialog.js │ ├── storage.js │ ├── sampleStore.js │ └── kitFile.js ├── css │ ├── EditKit.css │ ├── EditKit.scss │ ├── Pad │ │ ├── Velocity.scss │ │ ├── Velocity.css │ │ ├── MuteGroup.css │ │ ├── MuteGroup.scss │ │ ├── Control.scss │ │ └── Control.css │ ├── Notice.css │ ├── Notice.scss │ ├── index.css │ ├── index.scss │ ├── SampleList.css │ ├── SampleList.scss │ ├── Pad.css │ ├── Pad.scss │ └── icons.css ├── state │ ├── store.js │ ├── sortModels.js │ ├── globalState.js │ ├── models.js │ └── reducers.js ├── menu │ ├── edit.js │ ├── midi.js │ └── deviceType.js ├── actions │ ├── notice.js │ ├── app.js │ ├── modal.js │ ├── drive.js │ ├── pad.js │ └── kit.js ├── index.js ├── component │ ├── Editor │ │ ├── Samplerack.js │ │ └── SamplepadPro.js │ ├── Pad │ │ ├── Row.js │ │ ├── MidiNoteSelect.js │ │ ├── PadName.js │ │ ├── KnobControl.js │ │ ├── SampleDropTarget.js │ │ ├── Velocity.js │ │ ├── SlideControl.js │ │ ├── MuteGroup.js │ │ ├── LayerB.js │ │ └── LayerA.js │ ├── Header.js │ ├── KitList.js │ ├── Notice.js │ ├── Sample.js │ ├── App.js │ ├── EditKit.js │ ├── SamplePlayer.js │ ├── Modal.js │ └── SampleList.js └── const.js ├── docs ├── SamplePad Kit Editor v1.png ├── SamplePad Kit Editor v2.png ├── SamplePad Kit Editor v6.png └── kit-format-notes.txt ├── craco.config.js ├── LICENSE ├── .gitignore ├── package.json └── README.md /.env: -------------------------------------------------------------------------------- 1 | NODE_PATH='src/' -------------------------------------------------------------------------------- /assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LesserChance/samplepad-editor/HEAD/assets/icon.png -------------------------------------------------------------------------------- /assets/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LesserChance/samplepad-editor/HEAD/assets/favicon.ico -------------------------------------------------------------------------------- /public/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LesserChance/samplepad-editor/HEAD/public/assets/logo.png -------------------------------------------------------------------------------- /src/README.md: -------------------------------------------------------------------------------- 1 | # Src Directory 2 | This directory holds all classes necessary for the renderer electron process. -------------------------------------------------------------------------------- /public/assets/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LesserChance/samplepad-editor/HEAD/public/assets/favicon.ico -------------------------------------------------------------------------------- /docs/SamplePad Kit Editor v1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LesserChance/samplepad-editor/HEAD/docs/SamplePad Kit Editor v1.png -------------------------------------------------------------------------------- /docs/SamplePad Kit Editor v2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LesserChance/samplepad-editor/HEAD/docs/SamplePad Kit Editor v2.png -------------------------------------------------------------------------------- /docs/SamplePad Kit Editor v6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LesserChance/samplepad-editor/HEAD/docs/SamplePad Kit Editor v6.png -------------------------------------------------------------------------------- /public/assets/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LesserChance/samplepad-editor/HEAD/public/assets/apple-touch-icon.png -------------------------------------------------------------------------------- /public/const.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | DeviceType: { 3 | SAMPLEPAD_PRO: 'samplepad_pro', 4 | SAMPLERACK: 'samplerack' 5 | } 6 | } -------------------------------------------------------------------------------- /craco.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | webpack: { 3 | configure: { 4 | target: 'electron-renderer' 5 | } 6 | } 7 | }; -------------------------------------------------------------------------------- /src/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LesserChance/samplepad-editor/HEAD/src/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /src/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LesserChance/samplepad-editor/HEAD/src/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /src/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LesserChance/samplepad-editor/HEAD/src/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /src/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LesserChance/samplepad-editor/HEAD/src/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /public/rendererApi/path.js: -------------------------------------------------------------------------------- 1 | /* Electron imports */ 2 | const path = require('path') 3 | 4 | module.exports = { 5 | parse: (fileName) => { 6 | return path.parse(fileName) 7 | } 8 | } -------------------------------------------------------------------------------- /src/util/buffer.js: -------------------------------------------------------------------------------- 1 | /* Electron imports */ 2 | const { fs } = window.api 3 | 4 | export const getBuffer = (filePath) => { 5 | return Buffer.from(fs.readFileBufferArray(filePath)); 6 | } -------------------------------------------------------------------------------- /public/rendererApi/dialog.js: -------------------------------------------------------------------------------- 1 | /* Electron imports */ 2 | const { remote } = require("electron") 3 | 4 | module.exports = { 5 | showOpenDialog: (options) => { 6 | return remote.dialog.showOpenDialog(options) 7 | } 8 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This work is licensed under the Creative Commons Attribution 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by/4.0/ or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA. -------------------------------------------------------------------------------- /src/css/EditKit.css: -------------------------------------------------------------------------------- 1 | .kit { 2 | margin: .8em 0 0 0; } 3 | 4 | .kitHeader { 5 | margin: 1em 0 .7em 0 !important; } 6 | 7 | .pad-table { 8 | max-height: 33.5em; 9 | overflow-y: scroll; 10 | padding-right: .2em; 11 | padding-bottom: 2em; } 12 | -------------------------------------------------------------------------------- /src/css/EditKit.scss: -------------------------------------------------------------------------------- 1 | .kit { 2 | margin: .8em 0 0 0; 3 | } 4 | .kitHeader { 5 | margin: 1em 0 .7em 0 !important; 6 | } 7 | .pad-table { 8 | max-height: 33.5em; 9 | overflow-y: scroll; 10 | padding-right: .2em; 11 | padding-bottom: 2em; 12 | } 13 | -------------------------------------------------------------------------------- /public/events/events.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | SELECT_MIDI_INPUT: 'SELECT_MIDI_INPUT', 3 | SELECT_MIDI_SCAN: 'SELECT_MIDI_SCAN', 4 | GENERATE_MIDI_MENU: 'GENERATE_MIDI_MENU', 5 | SELECT_DEVICE_TYPE: 'SELECT_DEVICE_TYPE', 6 | SET_DEVICE_TYPE: 'SET_DEVICE_TYPE', 7 | LOAD_SD_CARD: 'LOAD_SD_CARD' 8 | } -------------------------------------------------------------------------------- /public/rendererApi/store.js: -------------------------------------------------------------------------------- 1 | /* Electron imports */ 2 | const Store = require('electron-store') 3 | 4 | const store = new Store() 5 | 6 | module.exports = { 7 | get: (param) => { 8 | return store.get(param) 9 | }, 10 | save: (param, val) => { 11 | return store.set(param, val) 12 | } 13 | } -------------------------------------------------------------------------------- /src/css/Pad/Velocity.scss: -------------------------------------------------------------------------------- 1 | .velocityContainer { 2 | width: 5em; 3 | text-align: center; 4 | 5 | input { 6 | width: 1.8em; 7 | padding: .2em 0; 8 | height: 1.5em; 9 | } 10 | &.has-tooltip-bottom::before { 11 | width: 11em; 12 | white-space: normal !important; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/css/Pad/Velocity.css: -------------------------------------------------------------------------------- 1 | .velocityContainer { 2 | width: 5em; 3 | text-align: center; } 4 | .velocityContainer input { 5 | width: 1.8em; 6 | padding: .2em 0; 7 | height: 1.5em; } 8 | .velocityContainer.has-tooltip-bottom::before { 9 | width: 11em; 10 | white-space: normal !important; } 11 | -------------------------------------------------------------------------------- /src/state/store.js: -------------------------------------------------------------------------------- 1 | /* Global imports */ 2 | import { createStore, applyMiddleware } from 'redux' 3 | import thunk from 'redux-thunk'; 4 | 5 | /* App imports */ 6 | import reducers from 'state/reducers' 7 | 8 | /* Initalize React App */ 9 | const store = createStore(reducers, applyMiddleware(thunk)); 10 | 11 | export default store; -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # dependencies 2 | /node_modules 3 | 4 | # production 5 | /build 6 | /dist 7 | 8 | # misc 9 | package-lock.json 10 | yarn.lock 11 | .DS_Store 12 | .env.local 13 | .env.development.local 14 | .env.test.local 15 | .env.production.local 16 | .tern-project 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "SamplePad Kit Editorr", 3 | "name": "SamplePad Kit Editor", 4 | "icons": [ 5 | { 6 | "src": "assets/favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": ".", 12 | "display": "standalone", 13 | } 14 | -------------------------------------------------------------------------------- /src/css/Notice.css: -------------------------------------------------------------------------------- 1 | .Notice { 2 | position: absolute; 3 | width: 100%; 4 | top: 0; 5 | z-index: 10; 6 | -webkit-box-shadow: 15px 5px 15px 0px rgba(0, 0, 0, 0.3); 7 | -moz-box-shadow: 5px 5px 15px 0px rgba(0, 0, 0, 0.3); 8 | box-shadow: 5px 5px 15px 0px rgba(0, 0, 0, 0.3); } 9 | .Notice.hidden { 10 | transition: transform .5s; 11 | transform: translateY(-5em); } 12 | -------------------------------------------------------------------------------- /src/css/Notice.scss: -------------------------------------------------------------------------------- 1 | .Notice { 2 | position: absolute; 3 | width: 100%; 4 | top: 0; 5 | z-index:10; 6 | 7 | -webkit-box-shadow: 15px 5px 15px 0px rgba(0,0,0,0.3); 8 | -moz-box-shadow: 5px 5px 15px 0px rgba(0,0,0,0.3); 9 | box-shadow: 5px 5px 15px 0px rgba(0,0,0,0.3); 10 | 11 | &.hidden { 12 | transition: transform .5s; 13 | transform: translateY(-5em); 14 | } 15 | } -------------------------------------------------------------------------------- /src/css/index.css: -------------------------------------------------------------------------------- 1 | @import url(bulma.min.css); 2 | @import url(bulma-tooltip.min.css); 3 | @import url(icons.css); 4 | button.link { 5 | background: none; 6 | color: inherit; 7 | border: none; 8 | font: inherit; 9 | cursor: pointer; 10 | outline: inherit; } 11 | 12 | .splash p { 13 | margin: auto; 14 | max-width: 50%; 15 | padding-top: 2em; 16 | text-align: center; } 17 | -------------------------------------------------------------------------------- /src/css/index.scss: -------------------------------------------------------------------------------- 1 | // use buttons as links, but remove all button-like style 2 | button.link { 3 | background: none; 4 | color: inherit; 5 | border: none; 6 | font: inherit; 7 | cursor: pointer; 8 | outline: inherit; 9 | } 10 | 11 | .splash p { 12 | margin: auto; 13 | max-width: 50%; 14 | padding-top: 2em; 15 | text-align: center; 16 | } 17 | 18 | @import 'bulma.min.css'; 19 | @import 'bulma-tooltip.min.css'; 20 | @import 'icons.css'; 21 | -------------------------------------------------------------------------------- /src/menu/edit.js: -------------------------------------------------------------------------------- 1 | /* App imports */ 2 | import store from 'state/store' 3 | import { selectAndLoadDrive } from 'actions/drive' 4 | 5 | /* Electron imports */ 6 | const { mainProcessCallbacks } = window.api 7 | 8 | /** 9 | * Initialize the renderer process handlers for the menu 10 | */ 11 | export const initEditMenu = () => { 12 | mainProcessCallbacks.setLoadSDCardCallback(loadSDCard) 13 | } 14 | 15 | /** 16 | * "Load SD Card" has been selected from the menu 17 | */ 18 | export const loadSDCard = () => { 19 | store.dispatch(selectAndLoadDrive()); 20 | } -------------------------------------------------------------------------------- /src/actions/notice.js: -------------------------------------------------------------------------------- 1 | /* App imports */ 2 | import { Actions } from 'const'; 3 | import { NoticeModel } from 'state/models'; 4 | 5 | /** NOTICE ACTION CREATORS */ 6 | /** 7 | * Show a temporary notice across the header 8 | * @param {String} style - classname for thie notice (is-success, is-warning, is-danger, ...) 9 | * @param {String} text - the text to show in the notice 10 | */ 11 | export function showNotice(style, text) { 12 | return (dispatch, getState) => { 13 | dispatch({ type: Actions.SHOW_NOTICE, notice: NoticeModel(style, text)}); 14 | } 15 | } 16 | 17 | -------------------------------------------------------------------------------- /public/README.md: -------------------------------------------------------------------------------- 1 | # Public Directory 2 | This directory holds all classes necessary for the main electron process. 3 | 4 | **rendererApi** 5 | This directory holds all classes that expose all native node and electron APIs to the renderer process. It is expected that any access to electron apis would need to use remote. 6 | 7 | **mainApi** 8 | This directory holds all classes that expose all native electron APIs to the main process. It is expected that any access to electron apis can be used directly. 9 | 10 | **events** 11 | This directory holds all classes that expose channels for communication between the main and renderer processes -------------------------------------------------------------------------------- /public/events/mainProcessTriggers.js: -------------------------------------------------------------------------------- 1 | const Events = require("./events") 2 | 3 | /** 4 | * This class is responsible for the main process receiving events 5 | * from the renderer process 6 | * 7 | * context: renderer 8 | */ 9 | module.exports = { 10 | generateMidiMenu: (inputList, currentMidiInput) => { 11 | window.postMessage({ 12 | type: Events.GENERATE_MIDI_MENU, 13 | midiInputs: inputList, 14 | currentMidiInput: currentMidiInput 15 | }) 16 | }, 17 | 18 | setDeviceType: (deviceType) => { 19 | window.postMessage({ 20 | type: Events.SET_DEVICE_TYPE, 21 | deviceType: deviceType 22 | }) 23 | } 24 | } -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | SamplePad Kit Editor 11 | 12 | 13 | 14 |
15 | 16 | 17 | -------------------------------------------------------------------------------- /src/actions/app.js: -------------------------------------------------------------------------------- 1 | /* App imports */ 2 | import { Actions } from 'const'; 3 | import { loadKitDetails } from 'actions/kit'; 4 | 5 | /** APP ACTION CREATORS */ 6 | /** 7 | * set the dropdown's selected kit and set it as currently active 8 | * @param {String} kitId 9 | */ 10 | export function selectKit(kitId) { 11 | return (dispatch, getState) => { 12 | // if the kit isnt loaded, load it before activating it 13 | dispatch(loadKitDetails(kitId)); 14 | 15 | // set it as the selected and active kit 16 | dispatch({ type: Actions.SET_SELECTED_KIT_ID, kitId: kitId }); 17 | dispatch({ type: Actions.SET_ACTIVE_KIT_ID, kitId: kitId }); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | /* Global imports */ 2 | import React from 'react' 3 | import { render } from 'react-dom' 4 | import { Provider } from 'react-redux' 5 | 6 | /* App imports */ 7 | import store from 'state/store' 8 | import { initEditMenu } from 'menu/edit' 9 | import { initMidiMenu } from 'menu/midi' 10 | import { initDeviceTypeMenu } from 'menu/deviceType' 11 | 12 | /* Component imports */ 13 | import App from 'component/App' 14 | import 'css/index.css'; 15 | 16 | /* Initalize Electron App From Renderer Process */ 17 | initEditMenu(); 18 | initMidiMenu(); 19 | initDeviceTypeMenu(); 20 | 21 | render( 22 | 23 | 24 | , 25 | document.getElementById('root') 26 | ) -------------------------------------------------------------------------------- /src/css/Pad/MuteGroup.css: -------------------------------------------------------------------------------- 1 | .mgrpContainer { 2 | position: relative; } 3 | .mgrpContainer .mgrpIcon { 4 | border-radius: 2px; 5 | box-shadow: 0 2px 3px 0 rgba(0, 0, 0, 0.1), inset 0 0 0 1px rgba(0, 0, 0, 0.1); 6 | display: inline-block; 7 | height: 1.5em; 8 | width: 1.5em; 9 | text-align: center; } 10 | .mgrpContainer > div { 11 | z-index: 10; 12 | left: -5.3em !important; } 13 | .mgrpContainer > div > div { 14 | left: 6em !important; } 15 | .mgrpContainer .selectMgrp button { 16 | width: 100%; 17 | text-align: center; 18 | display: inline-block; 19 | margin-top: -.3em; 20 | padding-bottom: .3em; } 21 | .mgrpContainer .selectMgrp .mgrpIcon { 22 | cursor: pointer; 23 | margin: .1em; } 24 | -------------------------------------------------------------------------------- /src/css/Pad/MuteGroup.scss: -------------------------------------------------------------------------------- 1 | .mgrpContainer { 2 | position: relative; 3 | 4 | .mgrpIcon { 5 | border-radius: 2px; 6 | box-shadow: 0 2px 3px 0 rgba(0,0,0,.1),inset 0 0 0 1px rgba(0,0,0,.1); 7 | display: inline-block; 8 | height: 1.5em; 9 | width: 1.5em; 10 | text-align: center; 11 | } 12 | 13 | & > div { 14 | z-index: 10; 15 | left: -5.3em !important; 16 | 17 | & > div { 18 | left: 6em !important; 19 | } 20 | } 21 | 22 | .selectMgrp { 23 | button { 24 | width: 100%; 25 | text-align: center; 26 | display: inline-block; 27 | margin-top:-.3em; 28 | padding-bottom: .3em; 29 | } 30 | .mgrpIcon { 31 | cursor: pointer; 32 | margin: .1em; 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /src/component/Editor/Samplerack.js: -------------------------------------------------------------------------------- 1 | /* Global imports */ 2 | import React from 'react'; 3 | import { connect } from 'react-redux' 4 | 5 | /* Component imports */ 6 | import PadRowComponent from 'component/Pad/Row' 7 | 8 | const EditKit = (props) => { 9 | 10 | return ( 11 |
12 | { 13 | props.pads.map((padId) => { 14 | return ( 15 | 16 | ); 17 | }) 18 | } 19 |
20 | ); 21 | } 22 | 23 | const mapStateToProps = (state, ownProps) => { 24 | let kit = state.kits.models[ownProps.kitId]; 25 | 26 | return { 27 | pads: kit.pads 28 | } 29 | } 30 | 31 | const mapDispatchToProps = (dispatch, ownProps) => { 32 | return {} 33 | } 34 | 35 | export default connect(mapStateToProps, mapDispatchToProps)(EditKit) 36 | -------------------------------------------------------------------------------- /src/css/SampleList.css: -------------------------------------------------------------------------------- 1 | .SampleList { 2 | margin: .5em 0 0 .5em; } 3 | .SampleList .samples { 4 | width: 100%; 5 | overflow-y: scroll; 6 | max-height: 30em; } 7 | .SampleList .samples button.sample { 8 | text-align: left; } 9 | .SampleList .samples .sampleName { 10 | max-width: 10em; } 11 | .SampleList .samples .sampleContainer:hover { 12 | width: 100%; 13 | background: white; } 14 | .SampleList .samples .sampleContainer:hover .sample { 15 | width: 100%; 16 | background: white; 17 | border-radius: 2px; 18 | box-shadow: 0 2px 3px 0 rgba(0, 0, 0, 0.1), inset 0 0 0 1px rgba(0, 0, 0, 0.1); } 19 | .SampleList .samples .sampleContainer:hover .sample .sampleName { 20 | background: white; 21 | text-overflow: normal; 22 | white-space: normal; } 23 | -------------------------------------------------------------------------------- /src/css/SampleList.scss: -------------------------------------------------------------------------------- 1 | .SampleList { 2 | margin: .5em 0 0 .5em; 3 | 4 | .samples { 5 | width: 100%; 6 | overflow-y: scroll; 7 | max-height: 30em; 8 | 9 | button.sample { 10 | text-align: left; 11 | } 12 | 13 | .sampleName { 14 | // text-overflow: ellipsis; 15 | max-width: 10em; 16 | // overflow: hidden; 17 | // white-space: nowrap; 18 | } 19 | 20 | .sampleContainer:hover { 21 | width: 100%; 22 | background: white; 23 | 24 | .sample { 25 | width: 100%; 26 | background: white; 27 | border-radius: 2px; 28 | box-shadow: 0 2px 3px 0 rgba(0,0,0,.1),inset 0 0 0 1px rgba(0,0,0,.1); 29 | 30 | .sampleName { 31 | background: white; 32 | text-overflow: normal; 33 | white-space: normal; 34 | } 35 | } 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /src/component/Pad/Row.js: -------------------------------------------------------------------------------- 1 | /* Global imports */ 2 | import React from 'react'; 3 | 4 | /* Component imports */ 5 | import PadSampleDropTargetComponent from 'component/Pad/SampleDropTarget' 6 | import 'css/Pad.css' 7 | 8 | class PadRowComponent extends React.Component { 9 | /* 10 | * @constructor 11 | * @param {Object} props 12 | */ 13 | constructor(props) { 14 | super(props); 15 | 16 | this.state = { 17 | showLayerB: false 18 | }; 19 | 20 | this.toggleLayerB = this.toggleLayerB.bind(this); 21 | } 22 | 23 | toggleLayerB(filter) { 24 | this.setState({showLayerB: !this.state.showLayerB}) 25 | } 26 | 27 | render() { 28 | return ; 33 | } 34 | } 35 | 36 | export default PadRowComponent 37 | -------------------------------------------------------------------------------- /src/css/Pad/Control.scss: -------------------------------------------------------------------------------- 1 | .controlContainer { 2 | width: 1.5em; 3 | height: 1.5em; 4 | overflow: hidden; 5 | padding-left: .2em; 6 | cursor: pointer; 7 | 8 | .rc-slider-rail, .rc-slider-track, .rc-slider-step, .rc-slider-mark { 9 | display: none; 10 | } 11 | 12 | .overlapContainer { 13 | position: absolute; 14 | top: 0; 15 | 16 | .glyphicon.overlapValue { 17 | overflow: hidden; 18 | top: 2px; 19 | } 20 | 21 | .overlapHandle { 22 | width:1.5em; 23 | } 24 | } 25 | } 26 | 27 | .height-25 { 28 | .rc-slider, .rc-slider-rail, .rc-slider-mark { 29 | height: 25px !important; 30 | } 31 | } 32 | 33 | .height-50 { 34 | .rc-slider, .rc-slider-rail, .rc-slider-mark { 35 | height: 50px !important; 36 | } 37 | } 38 | 39 | .height-100 { 40 | .rc-slider, .rc-slider-rail, .rc-slider-mark { 41 | height: 100px !important; 42 | } 43 | } -------------------------------------------------------------------------------- /src/css/Pad/Control.css: -------------------------------------------------------------------------------- 1 | .controlContainer { 2 | width: 1.5em; 3 | height: 1.5em; 4 | overflow: hidden; 5 | padding-left: .2em; 6 | cursor: pointer; } 7 | .controlContainer .rc-slider-rail, .controlContainer .rc-slider-track, .controlContainer .rc-slider-step, .controlContainer .rc-slider-mark { 8 | display: none; } 9 | .controlContainer .overlapContainer { 10 | position: absolute; 11 | top: 0; } 12 | .controlContainer .overlapContainer .glyphicon.overlapValue { 13 | overflow: hidden; 14 | top: 2px; } 15 | .controlContainer .overlapContainer .overlapHandle { 16 | width: 1.5em; } 17 | 18 | .height-25 .rc-slider, .height-25 .rc-slider-rail, .height-25 .rc-slider-mark { 19 | height: 25px !important; } 20 | 21 | .height-50 .rc-slider, .height-50 .rc-slider-rail, .height-50 .rc-slider-mark { 22 | height: 50px !important; } 23 | 24 | .height-100 .rc-slider, .height-100 .rc-slider-rail, .height-100 .rc-slider-mark { 25 | height: 100px !important; } 26 | -------------------------------------------------------------------------------- /public/preload.js: -------------------------------------------------------------------------------- 1 | /* Electron imports */ 2 | const { contextBridge } = require("electron") 3 | const path = require('./rendererApi/path') 4 | const wav = require('./rendererApi/wav') 5 | const fs = require('./rendererApi/fs') 6 | const store = require('./rendererApi/store') 7 | const dialog = require('./rendererApi/dialog') 8 | const midi = require('./rendererApi/midi') 9 | 10 | const mainProcessCallbacks = require('./events/mainProcessCallbacks') 11 | const mainProcessTriggers = require('./events/mainProcessTriggers') 12 | const mainProcessEvents = require('./events/mainProcessEvents') 13 | 14 | // Initialize the apis that should be accessible from the renderer process 15 | contextBridge.exposeInMainWorld( 16 | "api", { 17 | path: path, 18 | wav: wav, 19 | fs: fs, 20 | store: store, 21 | dialog: dialog, 22 | midi: midi, 23 | mainProcessTriggers: mainProcessTriggers, 24 | mainProcessCallbacks: mainProcessCallbacks 25 | } 26 | ) 27 | 28 | // Initialize the renderer message handlers for communication with the main process 29 | mainProcessEvents.initIpcRendererSender(); -------------------------------------------------------------------------------- /public/rendererApi/wav.js: -------------------------------------------------------------------------------- 1 | /* Electron imports */ 2 | const { remote } = require("electron") 3 | const spawn = require('child_process').spawn 4 | 5 | let wavSpawn = {} 6 | 7 | module.exports = { 8 | playWavFile: (wavId, path) => { 9 | return new Promise((resolve, reject) => { 10 | switch (remote.process.platform) { 11 | case 'darwin': 12 | wavSpawn[wavId] = spawn('afplay', [path]) 13 | break 14 | case 'win32': 15 | wavSpawn[wavId] = spawn('powershell', [ 16 | '-c', 17 | '(New-Object System.Media.SoundPlayer "' + path + '").PlaySync()' 18 | ]) 19 | wavSpawn[wavId].stdin.end() 20 | break 21 | default: 22 | resolve() 23 | break 24 | } 25 | 26 | wavSpawn[wavId].on('close', (code) => { 27 | resolve() 28 | }) 29 | }) 30 | }, 31 | stopWavFile: (wavId) => { 32 | if (wavSpawn[wavId]) { 33 | wavSpawn[wavId].removeAllListeners('close') 34 | if (wavSpawn[wavId]) { 35 | wavSpawn[wavId].kill() 36 | } 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /src/component/Pad/MidiNoteSelect.js: -------------------------------------------------------------------------------- 1 | /* Global imports */ 2 | import React from 'react'; 3 | 4 | /* App imports */ 5 | import { MidiMap } from 'const' 6 | 7 | const MidiNoteSelect = (props) => { 8 | return ( 9 |
10 |
11 |
12 | 27 |
28 |