Skip to content

Instantly share code, notes, and snippets.

@LDK
Created November 2, 2018 04:19
Show Gist options
  • Save LDK/62d5ca528dc43357a0ada646571669b3 to your computer and use it in GitHub Desktop.
Save LDK/62d5ca528dc43357a0ada646571669b3 to your computer and use it in GitHub Desktop.
pg interface
<div id="errors" style="
background: #c00;
color: #fff;
display: none;
margin: -20px -20px 20px;
padding: 20px;
white-space: pre-wrap;
"></div>
<div id="root"></div>
<script>
window.addEventListener('mousedown', function(e) {
document.body.classList.add('mouse-navigation');
document.body.classList.remove('kbd-navigation');
});
window.addEventListener('keydown', function(e) {
if (e.keyCode === 9) {
document.body.classList.add('kbd-navigation');
document.body.classList.remove('mouse-navigation');
}
});
window.addEventListener('click', function(e) {
if (e.target.tagName === 'A' && e.target.getAttribute('href') === '#') {
e.preventDefault();
}
});
window.onerror = function(message, source, line, col, error) {
var text = error ? error.stack || error : message + ' (at ' + source + ':' + line + ':' + col + ')';
errors.textContent += text + '\n';
errors.style.display = '';
};
console.error = (function(old) {
return function error() {
errors.textContent += Array.prototype.slice.call(arguments).join(' ') + '\n';
errors.style.display = '';
old.apply(this, arguments);
}
})(console.error);
</script>
function Cell(props) {
return (
<button className="cell" onClick={props.onClick}>
{props.indicator}
</button>
);
}
function stepFormat(step){
var bar = (Math.floor((step-1) / 16)) + 1;
var beat = (Math.floor((step-1) / 4) % 4) + 1;
var tick = (1 + (step-1) * 8) % 32;
return {bar: bar, beat: beat, tick: tick};
// return bar + "." + beat + "." + tick;
}
class Channel extends React.Component {
constructor(props) {
super(props);
this.state = {
trackName: props.trackName || 'New Channel',
steps: Array(32).fill(null),
volume: 0,
pan: 0,
transpose: 0,
attack: 0,
peak: 0,
decay: 0,
sustain: 0,
release: 0
};
}
handleClick(i) {
const steps = this.state.steps.slice();
steps[i] = !steps[i];
this.setState({steps: steps});
}
renderCell(i) {
var indicator = '';
var loc = stepFormat(i);
if (this.state.steps[i]) { indicator = 'X'; }
return <Cell bar={loc.bar} beat={loc.beat} tick={loc.tick} value={this.state.steps[i]} indicator={indicator} onClick={() => this.handleClick(i)} />;
}
render() {
return (
<div>
<span>{this.state.trackName}</span>
<div className="pattern-row">
{this.renderCell(1)}
{this.renderCell(2)}
{this.renderCell(3)}
{this.renderCell(4)}
{this.renderCell(5)}
{this.renderCell(6)}
{this.renderCell(7)}
{this.renderCell(8)}
{this.renderCell(9)}
{this.renderCell(10)}
{this.renderCell(11)}
{this.renderCell(12)}
{this.renderCell(13)}
{this.renderCell(14)}
{this.renderCell(15)}
{this.renderCell(16)}
{this.renderCell(17)}
{this.renderCell(18)}
{this.renderCell(19)}
{this.renderCell(20)}
{this.renderCell(21)}
{this.renderCell(22)}
{this.renderCell(23)}
{this.renderCell(24)}
{this.renderCell(25)}
{this.renderCell(26)}
{this.renderCell(27)}
{this.renderCell(28)}
{this.renderCell(29)}
{this.renderCell(30)}
{this.renderCell(31)}
{this.renderCell(32)}
</div>
</div>
);
}
}
class Pattern extends React.Component {
constructor(props) {
super(props);
this.state = {
bpm: 126,
swing: .75,
bars: 2,
title: 'pyGroove Demo Beat',
tracks: {
"Kick":
{
"wav": "808-Kick2.wav",
"pan": 0,
"amp": {
"volume": "1.2",
"attack": 333,
"decay": 60000,
"peak": 0,
"sustain": 0,
"release": 212
},
"filter": {
"filterType": "lpf",
"cutoff": 492
}
},
},
selectedTrack: 'Kick'
};
this.updateBPM = this.updateBPM.bind(this);
}
updateBPM(event){
this.setState({bpm: event.target.value});
}
renderChannel(trackName) {
return <Channel trackName={trackName} />;
}
render() {
const selectedStatus = 'Selected Instrument: Kick';
return (
<div>
<form onSubmit={this.handleSubmit}>
<div className="status">
BPM: <input type="text" value={this.state.bpm} onChange={this.updateBPM} />
</div>
{this.renderChannel('Kick')}
{this.renderChannel('Closed Hat')}
{this.renderChannel('Open Hat')}
{this.renderChannel('Snare')}
</form>
</div>
);
}
}
class Note extends React.Component {
constructor(props) {
super(props);
this.state = {
offset: 0,
transpose: 0,
pan: 0,
volume: 0,
bar: props.bar || null,
beat: props.beat || null,
tick: props.tick || null
};
}
}
class Song extends React.Component {
render() {
return (
<div className="song">
<div className="song-pattern">
<Pattern />
</div>
<div className="song-info">
<div>{/* status */}</div>
<ol>{/* TODO */}</ol>
</div>
</div>
);
}
}
class BPMInput extends React.Component {
constructor(props) {
super(props);
this.state = {value: ''};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({value: event.target.value});
}
handleSubmit(event) {
alert('A name was submitted: ' + this.state.value);
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input type="text" value={this.state.value} onChange={this.handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
}
// ========================================
ReactDOM.render(
<Song />,
document.getElementById('root')
);
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
body {
font: 14px "Century Gothic", Futura, sans-serif;
margin: 20px;
}
ol, ul {
padding-left: 30px;
}
.pattern-row:after {
clear: both;
content: "";
display: table;
}
.status {
margin-bottom: 10px;
}
.cell {
background-color: #eee;
border: 1px solid #999;
float: left;
font-size: 24px;
font-weight: bold;
line-height: 34px;
height: 32px;
margin-right: -1px;
margin-top: -1px;
padding: 0;
text-align: center;
width: 24px;
}
.cell:focus {
outline: none;
}
.cell:nth-child(1),
.cell:nth-child(5),
.cell:nth-child(9),
.cell:nth-child(13),
.cell:nth-child(17),
.cell:nth-child(21),
.cell:nth-child(25),
.cell:nth-child(29)
{
background-color: #ddbaba;
}
.kbd-navigation .cell:focus {
background: #ddd;
}
.song {
display: flex;
flex-direction: row;
}
.song-info {
margin-left: 20px;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment