mirror of https://github.com/dcoredump/dexed.git
parent
3dd5e5a224
commit
3d5ec67038
@ -1,379 +0,0 @@ |
|||||||
/**
|
|
||||||
* |
|
||||||
* Copyright (c) 2014, 2015 Pascal Gauthier. |
|
||||||
* |
|
||||||
* This program is free software; you can redistribute it and/or modify |
|
||||||
* it under the terms of the GNU General Public License as published by |
|
||||||
* the Free Software Foundation; either version 3 of the License, or |
|
||||||
* (at your option) any later version. |
|
||||||
* |
|
||||||
* This program is distributed in the hope that it will be useful, |
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
* GNU General Public License for more details. |
|
||||||
* |
|
||||||
* You should have received a copy of the GNU General Public License |
|
||||||
* along with this program; if not, write to the Free Software Foundation, |
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
||||||
* |
|
||||||
*/ |
|
||||||
|
|
||||||
#include "AlgoDisplay.h" |
|
||||||
#include "DXLookNFeel.h" |
|
||||||
#include "Dexed.h" |
|
||||||
|
|
||||||
AlgoDisplay::AlgoDisplay() { |
|
||||||
static char tmpAlgo = 0; |
|
||||||
algo = &tmpAlgo; |
|
||||||
} |
|
||||||
|
|
||||||
inline void displayOp(Graphics &g, char id, int x, int y, char link, char fb) { |
|
||||||
const int LINE_SZ = 3; |
|
||||||
String t(id); |
|
||||||
|
|
||||||
x *= 25; |
|
||||||
x += 3; |
|
||||||
y *= 21; |
|
||||||
y += 5; |
|
||||||
|
|
||||||
g.setColour(Colours::white); |
|
||||||
g.drawText(t, x, y, 16, 12, Justification::centred, true); |
|
||||||
|
|
||||||
g.setColour(DXLookNFeel::fillColour); |
|
||||||
switch(link) { |
|
||||||
case 0 : // LINE DOWN
|
|
||||||
g.drawLine(x+8, y+12, x+8, y+21, LINE_SZ); |
|
||||||
break; |
|
||||||
case 1: // ARROW TO RIGHT
|
|
||||||
g.drawLine(x+8, y+12, x+8, y+18, LINE_SZ); |
|
||||||
g.drawLine(x+7, y+18, x+34, y+18, LINE_SZ); |
|
||||||
break; |
|
||||||
case 2: // ARROW TO RIGHT JOIN
|
|
||||||
g.drawLine(x+8, y+12, x+8, y+19, LINE_SZ); |
|
||||||
break; |
|
||||||
case 3: // ARROW TO RIGHT AND DOWN
|
|
||||||
g.drawLine(x+8, y+12, x+8, y+21, LINE_SZ); |
|
||||||
g.drawLine(x+7, y+18, x+34, y+18, LINE_SZ); |
|
||||||
g.drawLine(x+34, y+17, x+34, y+21, LINE_SZ); |
|
||||||
break; |
|
||||||
case 4: // ARROW TO RIGHT+LEFT AND DOWN
|
|
||||||
g.drawLine(x+8, y+12, x+8, y+21, LINE_SZ); |
|
||||||
g.drawLine(x+7, y+18, x+34, y+18, LINE_SZ); |
|
||||||
g.drawLine(x+34, y+17, x+34, y+21, LINE_SZ); |
|
||||||
g.drawLine(x-17, y+18, x+8, y+18, LINE_SZ); |
|
||||||
g.drawLine(x-17, y+17, x-17, y+21, LINE_SZ); |
|
||||||
break; |
|
||||||
case 6: |
|
||||||
g.drawLine(x+8, y+12, x+8, y+18, LINE_SZ); |
|
||||||
g.drawLine(x+7, y+18, x+58, y+18, LINE_SZ); |
|
||||||
break; |
|
||||||
case 7: // ARROW TO LEFT
|
|
||||||
g.drawLine(x+8, y+12, x+8, y+19, LINE_SZ); |
|
||||||
g.drawLine(x-17, y+18, x+9, y+18, LINE_SZ); |
|
||||||
break; |
|
||||||
} |
|
||||||
|
|
||||||
switch(fb) { |
|
||||||
case 0: |
|
||||||
break; |
|
||||||
case 1: |
|
||||||
g.drawLine(x+7, y, x+8, y-5, LINE_SZ); |
|
||||||
g.drawLine(x+8, y-4, x+21, y-4, LINE_SZ); |
|
||||||
g.drawLine(x+20, y-4, x+20, y+15, LINE_SZ); |
|
||||||
g.drawLine(x+19, y+15, x+20, y+16, LINE_SZ); |
|
||||||
g.drawLine(x+8, y+15, x+20, y+15, LINE_SZ); |
|
||||||
break; |
|
||||||
case 2: // ALGO 4
|
|
||||||
g.drawLine(x+7, y, x+8, y-5, LINE_SZ); |
|
||||||
g.drawLine(x+8, y-4, x+20, y-4, LINE_SZ); |
|
||||||
g.drawLine(x+19, y-4, x+19, y+59, LINE_SZ); |
|
||||||
g.drawLine(x+8, y+58, x+19, y+58, LINE_SZ); |
|
||||||
break; |
|
||||||
case 3: // ALGO 6
|
|
||||||
g.drawLine(x+7, y, x+8, y-5, LINE_SZ); |
|
||||||
g.drawLine(x+8, y-4, x+20, y-4, LINE_SZ); |
|
||||||
g.drawLine(x+19, y-4, x+19, y+37, LINE_SZ); |
|
||||||
g.drawLine(x+8, y+36, x+19, y+36, LINE_SZ); |
|
||||||
break; |
|
||||||
case 4: |
|
||||||
g.drawLine(x+7, y, x+8, y-5, LINE_SZ); |
|
||||||
g.drawLine(x+8, y-4, x-4, y-4, LINE_SZ); |
|
||||||
g.drawLine(x-3, y-4, x-3, y+15, LINE_SZ); |
|
||||||
g.drawLine(x-3, y+15, x+8, y+15, LINE_SZ); |
|
||||||
g.drawLine(x+8, y+15, x+8, y+12, LINE_SZ); |
|
||||||
break; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
void AlgoDisplay::paint(Graphics &g) { |
|
||||||
|
|
||||||
g.setColour(DXLookNFeel::fillColour); |
|
||||||
g.fillRect(1, 3, 20, 15); |
|
||||||
String n = String(*algo +1); |
|
||||||
|
|
||||||
g.setColour(Colours::white); |
|
||||||
g.drawText(n, 1, 3, 20, 15, Justification::centred, true); |
|
||||||
|
|
||||||
switch(*algo) { |
|
||||||
case 0: |
|
||||||
displayOp(g, 6, 3, 0, 0, 1); |
|
||||||
displayOp(g, 5, 3, 1, 0, 0); |
|
||||||
displayOp(g, 4, 3, 2, 0, 0); |
|
||||||
displayOp(g, 3, 3, 3, 2, 0); |
|
||||||
displayOp(g, 2, 2, 2, 0, 0); |
|
||||||
displayOp(g, 1, 2, 3, 1, 0); |
|
||||||
break; |
|
||||||
case 1: |
|
||||||
displayOp(g, 6, 3, 0, 0, 0); |
|
||||||
displayOp(g, 5, 3, 1, 0, 0); |
|
||||||
displayOp(g, 4, 3, 2, 0, 0); |
|
||||||
displayOp(g, 3, 3, 3, 2, 0); |
|
||||||
displayOp(g, 2, 2, 2, 0, 1); |
|
||||||
displayOp(g, 1, 2, 3, 1, 0); |
|
||||||
break; |
|
||||||
case 2: |
|
||||||
displayOp(g, 6, 3, 1, 0, 1); |
|
||||||
displayOp(g, 5, 3, 2, 0, 0); |
|
||||||
displayOp(g, 4, 3, 3, 2, 0); |
|
||||||
displayOp(g, 3, 2, 1, 0, 0); |
|
||||||
displayOp(g, 2, 2, 2, 0, 0); |
|
||||||
displayOp(g, 1, 2, 3, 1, 0); |
|
||||||
break; |
|
||||||
case 3: //
|
|
||||||
displayOp(g, 6, 3, 1, 0, 2); |
|
||||||
displayOp(g, 5, 3, 2, 0, 0); |
|
||||||
displayOp(g, 4, 3, 3, 2, 0); |
|
||||||
displayOp(g, 3, 2, 1, 0, 0); |
|
||||||
displayOp(g, 2, 2, 2, 0, 0); |
|
||||||
displayOp(g, 1, 2, 3, 1, 0); |
|
||||||
break; |
|
||||||
case 4: |
|
||||||
displayOp(g, 6, 4, 2, 0, 1); |
|
||||||
displayOp(g, 5, 4, 3, 2, 0); |
|
||||||
displayOp(g, 4, 3, 2, 0, 0); |
|
||||||
displayOp(g, 3, 3, 3, 1, 0); |
|
||||||
displayOp(g, 2, 2, 2, 0, 0); |
|
||||||
displayOp(g, 1, 2, 3, 1, 0); |
|
||||||
break; |
|
||||||
case 5: //
|
|
||||||
displayOp(g, 6, 4, 2, 0, 3); |
|
||||||
displayOp(g, 5, 4, 3, 2, 0); |
|
||||||
displayOp(g, 4, 3, 2, 0, 0); |
|
||||||
displayOp(g, 3, 3, 3, 1, 0); |
|
||||||
displayOp(g, 2, 2, 2, 0, 0); |
|
||||||
displayOp(g, 1, 2, 3, 1, 0); |
|
||||||
break; |
|
||||||
case 6: |
|
||||||
displayOp(g, 6, 4, 1, 0, 1); |
|
||||||
displayOp(g, 5, 4, 2, 7, 0); |
|
||||||
displayOp(g, 4, 3, 2, 0, 0); |
|
||||||
displayOp(g, 3, 3, 3, 2, 0); |
|
||||||
displayOp(g, 2, 2, 2, 0, 0); |
|
||||||
displayOp(g, 1, 2, 3, 1, 0); |
|
||||||
break; |
|
||||||
case 7: |
|
||||||
displayOp(g, 6, 4, 1, 0, 0); |
|
||||||
displayOp(g, 5, 4, 2, 7, 0); |
|
||||||
displayOp(g, 4, 3, 2, 0, 4); |
|
||||||
displayOp(g, 3, 3, 3, 2, 0); |
|
||||||
displayOp(g, 2, 2, 2, 0, 0); |
|
||||||
displayOp(g, 1, 2, 3, 1, 0); |
|
||||||
break; |
|
||||||
case 8: |
|
||||||
displayOp(g, 6, 4, 1, 0, 0); |
|
||||||
displayOp(g, 5, 4, 2, 7, 0); |
|
||||||
displayOp(g, 4, 3, 2, 0, 0); |
|
||||||
displayOp(g, 3, 3, 3, 2, 0); |
|
||||||
displayOp(g, 2, 2, 2, 0, 1); |
|
||||||
displayOp(g, 1, 2, 3, 1, 0); |
|
||||||
break; |
|
||||||
case 9: |
|
||||||
displayOp(g, 6, 2, 2, 0, 0); |
|
||||||
displayOp(g, 5, 1, 2, 1, 0); |
|
||||||
displayOp(g, 4, 2, 3, 1, 0); |
|
||||||
displayOp(g, 3, 3, 1, 0, 1); |
|
||||||
displayOp(g, 2, 3, 2, 0, 0); |
|
||||||
displayOp(g, 1, 3, 3, 2, 0); |
|
||||||
break; |
|
||||||
case 10: |
|
||||||
displayOp(g, 6, 2, 2, 0, 1); |
|
||||||
displayOp(g, 5, 1, 2, 1, 0); |
|
||||||
displayOp(g, 4, 2, 3, 1, 0); |
|
||||||
displayOp(g, 3, 3, 1, 0, 0); |
|
||||||
displayOp(g, 2, 3, 2, 0, 0); |
|
||||||
displayOp(g, 1, 3, 3, 2, 0); |
|
||||||
break; |
|
||||||
case 11: |
|
||||||
displayOp(g, 6, 3, 2, 7, 0); |
|
||||||
displayOp(g, 5, 2, 2, 0, 0); |
|
||||||
displayOp(g, 4, 1, 2, 1, 0); |
|
||||||
displayOp(g, 3, 2, 3, 6, 0); |
|
||||||
displayOp(g, 2, 4, 2, 0, 1); |
|
||||||
displayOp(g, 1, 4, 3, 2, 0); |
|
||||||
break; |
|
||||||
case 12: |
|
||||||
displayOp(g, 6, 3, 2, 7, 1); |
|
||||||
displayOp(g, 5, 2, 2, 0, 0); |
|
||||||
displayOp(g, 4, 1, 2, 1, 0); |
|
||||||
displayOp(g, 3, 2, 3, 6, 0); |
|
||||||
displayOp(g, 2, 4, 2, 0, 0); |
|
||||||
displayOp(g, 1, 4, 3, 2, 0); |
|
||||||
break; |
|
||||||
case 13: |
|
||||||
displayOp(g, 6, 3, 1, 0, 1); |
|
||||||
displayOp(g, 5, 2, 1, 1, 0); |
|
||||||
displayOp(g, 4, 3, 2, 0, 0); |
|
||||||
displayOp(g, 3, 3, 3, 2, 0); |
|
||||||
displayOp(g, 2, 2, 2, 0, 0); |
|
||||||
displayOp(g, 1, 2, 3, 1, 0); |
|
||||||
break; |
|
||||||
case 14: |
|
||||||
displayOp(g, 6, 3, 1, 0, 0); |
|
||||||
displayOp(g, 5, 2, 1, 1, 0); |
|
||||||
displayOp(g, 4, 3, 2, 0, 0); |
|
||||||
displayOp(g, 3, 3, 3, 2, 0); |
|
||||||
displayOp(g, 2, 2, 2, 0, 4); |
|
||||||
displayOp(g, 1, 2, 3, 1, 0); |
|
||||||
break; |
|
||||||
case 15: |
|
||||||
displayOp(g, 6, 4, 1, 0, 1); |
|
||||||
displayOp(g, 5, 4, 2, 7, 0); |
|
||||||
displayOp(g, 4, 3, 1, 0, 0); |
|
||||||
displayOp(g, 3, 3, 2, 0, 0); |
|
||||||
displayOp(g, 2, 2, 2, 1, 0); |
|
||||||
displayOp(g, 1, 3, 3, 0, 0); |
|
||||||
break; |
|
||||||
case 16: |
|
||||||
displayOp(g, 6, 4, 1, 0, 0); |
|
||||||
displayOp(g, 5, 4, 2, 7, 0); |
|
||||||
displayOp(g, 4, 3, 1, 0, 0); |
|
||||||
displayOp(g, 3, 3, 2, 0, 0); |
|
||||||
displayOp(g, 2, 2, 2, 1, 4); |
|
||||||
displayOp(g, 1, 3, 3, 0, 0); |
|
||||||
break; |
|
||||||
case 17: |
|
||||||
displayOp(g, 6, 4, 0, 0, 0); |
|
||||||
displayOp(g, 5, 4, 1, 0, 0); |
|
||||||
displayOp(g, 4, 4, 2, 7, 0); |
|
||||||
displayOp(g, 3, 3, 2, 0, 4); |
|
||||||
displayOp(g, 2, 2, 2, 1, 0); |
|
||||||
displayOp(g, 1, 3, 3, 0, 0); |
|
||||||
break; |
|
||||||
case 18: |
|
||||||
displayOp(g, 6, 3, 2, 3, 1); |
|
||||||
displayOp(g, 5, 4, 3, 2, 0); |
|
||||||
displayOp(g, 4, 3, 3, 1, 0); |
|
||||||
displayOp(g, 3, 2, 1, 0, 0); |
|
||||||
displayOp(g, 2, 2, 2, 0, 0); |
|
||||||
displayOp(g, 1, 2, 3, 1, 0); |
|
||||||
break; |
|
||||||
case 19: |
|
||||||
displayOp(g, 6, 4, 2, 0, 0); |
|
||||||
displayOp(g, 5, 3, 2, 1, 0); |
|
||||||
displayOp(g, 4, 4, 3, 2, 0); |
|
||||||
displayOp(g, 3, 1, 2, 3, 1); |
|
||||||
displayOp(g, 2, 2, 3, 6, 0); |
|
||||||
displayOp(g, 1, 1, 3, 1, 0); |
|
||||||
break; |
|
||||||
case 20: |
|
||||||
displayOp(g, 6, 3, 2, 3, 0); |
|
||||||
displayOp(g, 5, 4, 3, 2, 0); |
|
||||||
displayOp(g, 4, 3, 3, 1, 0); |
|
||||||
displayOp(g, 3, 1, 2, 3, 1); |
|
||||||
displayOp(g, 2, 2, 3, 1, 0); |
|
||||||
displayOp(g, 1, 1, 3, 1, 0); |
|
||||||
break; |
|
||||||
case 21: |
|
||||||
displayOp(g, 6, 3, 2, 4, 1); |
|
||||||
displayOp(g, 5, 4, 3, 2, 0); |
|
||||||
displayOp(g, 4, 3, 3, 1, 0); |
|
||||||
displayOp(g, 3, 2, 3, 1, 0); |
|
||||||
displayOp(g, 2, 1, 2, 0, 0); |
|
||||||
displayOp(g, 1, 1, 3, 1, 0); |
|
||||||
break; |
|
||||||
case 22: // CC
|
|
||||||
displayOp(g, 6, 3, 2, 3, 1); |
|
||||||
displayOp(g, 5, 4, 3, 2, 0); |
|
||||||
displayOp(g, 4, 3, 3, 1, 0); |
|
||||||
displayOp(g, 3, 2, 2, 0, 0); |
|
||||||
displayOp(g, 2, 2, 3, 1, 0); |
|
||||||
displayOp(g, 1, 1, 3, 1, 0); |
|
||||||
break; |
|
||||||
case 23: // CC
|
|
||||||
displayOp(g, 6, 3, 2, 4, 1); |
|
||||||
displayOp(g, 5, 4, 3, 2, 0); |
|
||||||
displayOp(g, 4, 3, 3, 1, 0); |
|
||||||
displayOp(g, 3, 2, 3, 1, 0); |
|
||||||
displayOp(g, 2, 1, 3, 1, 0); |
|
||||||
displayOp(g, 1, 0, 3, 1, 0); |
|
||||||
break; |
|
||||||
case 24: // CC
|
|
||||||
displayOp(g, 6, 3, 2, 3, 1); |
|
||||||
displayOp(g, 5, 4, 3, 2, 0); |
|
||||||
displayOp(g, 4, 3, 3, 1, 0); |
|
||||||
displayOp(g, 3, 2, 3, 1, 0); |
|
||||||
displayOp(g, 2, 1, 3, 1, 0); |
|
||||||
displayOp(g, 1, 0, 3, 1, 0); |
|
||||||
break; |
|
||||||
case 25: |
|
||||||
displayOp(g, 6, 4, 2, 0, 1); |
|
||||||
displayOp(g, 5, 3, 2, 1, 0); |
|
||||||
displayOp(g, 4, 4, 3, 2, 0); |
|
||||||
displayOp(g, 3, 2, 2, 0, 0); |
|
||||||
displayOp(g, 2, 2, 3, 6, 0); |
|
||||||
displayOp(g, 1, 1, 3, 1, 0); |
|
||||||
break; |
|
||||||
case 26: |
|
||||||
displayOp(g, 6, 4, 2, 0, 0); |
|
||||||
displayOp(g, 5, 3, 2, 1, 0); |
|
||||||
displayOp(g, 4, 4, 3, 2, 0); |
|
||||||
displayOp(g, 3, 2, 2, 0, 1); |
|
||||||
displayOp(g, 2, 2, 3, 6, 0); |
|
||||||
displayOp(g, 1, 1, 3, 1, 0); |
|
||||||
break; |
|
||||||
case 27: |
|
||||||
displayOp(g, 6, 4, 3, 2, 0); |
|
||||||
displayOp(g, 5, 3, 1, 0, 1); |
|
||||||
displayOp(g, 4, 3, 2, 0, 0); |
|
||||||
displayOp(g, 3, 3, 3, 1, 0); |
|
||||||
displayOp(g, 2, 2, 2, 0, 0); |
|
||||||
displayOp(g, 1, 2, 3, 1, 0); |
|
||||||
break; |
|
||||||
case 28: |
|
||||||
displayOp(g, 6, 4, 2, 0, 1); |
|
||||||
displayOp(g, 5, 4, 3, 2, 0); |
|
||||||
displayOp(g, 4, 3, 2, 0, 0); |
|
||||||
displayOp(g, 3, 3, 3, 1, 0); |
|
||||||
displayOp(g, 2, 2, 3, 1, 0); |
|
||||||
displayOp(g, 1, 1, 3, 1, 0); |
|
||||||
break; |
|
||||||
case 29: |
|
||||||
displayOp(g, 6, 4, 3, 2, 0); |
|
||||||
displayOp(g, 5, 3, 1, 0, 1); |
|
||||||
displayOp(g, 4, 3, 2, 0, 0); |
|
||||||
displayOp(g, 3, 3, 3, 1, 0); |
|
||||||
displayOp(g, 2, 2, 3, 1, 0); |
|
||||||
displayOp(g, 1, 1, 3, 1, 0); |
|
||||||
break; |
|
||||||
case 30: |
|
||||||
displayOp(g, 6, 4, 2, 0, 1); |
|
||||||
displayOp(g, 5, 4, 3, 2, 0); |
|
||||||
displayOp(g, 4, 3, 3, 1, 0); |
|
||||||
displayOp(g, 3, 2, 3, 1, 0); |
|
||||||
displayOp(g, 2, 1, 3, 1, 0); |
|
||||||
displayOp(g, 1, 0, 3, 1, 0);
|
|
||||||
break; |
|
||||||
case 31: |
|
||||||
displayOp(g, 6, 5, 3, 2, 1); |
|
||||||
displayOp(g, 5, 4, 3, 1, 0); |
|
||||||
displayOp(g, 4, 3, 3, 1, 0); |
|
||||||
displayOp(g, 3, 2, 3, 1, 0); |
|
||||||
displayOp(g, 2, 1, 3, 1, 0); |
|
||||||
displayOp(g, 1, 0, 3, 1, 0);
|
|
||||||
break; |
|
||||||
default: |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
@ -1,33 +0,0 @@ |
|||||||
/**
|
|
||||||
* |
|
||||||
* Copyright (c) 2014 Pascal Gauthier. |
|
||||||
* |
|
||||||
* This program is free software; you can redistribute it and/or modify |
|
||||||
* it under the terms of the GNU General Public License as published by |
|
||||||
* the Free Software Foundation; either version 3 of the License, or |
|
||||||
* (at your option) any later version. |
|
||||||
* |
|
||||||
* This program is distributed in the hope that it will be useful, |
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
* GNU General Public License for more details. |
|
||||||
* |
|
||||||
* You should have received a copy of the GNU General Public License |
|
||||||
* along with this program; if not, write to the Free Software Foundation, |
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
||||||
* |
|
||||||
*/ |
|
||||||
|
|
||||||
#ifndef ALGODISPLAY_H_INCLUDED |
|
||||||
#define ALGODISPLAY_H_INCLUDED |
|
||||||
|
|
||||||
#include "../JuceLibraryCode/JuceHeader.h" |
|
||||||
|
|
||||||
class AlgoDisplay : public Component { |
|
||||||
public: |
|
||||||
AlgoDisplay(); |
|
||||||
char *algo; |
|
||||||
void paint(Graphics &g); |
|
||||||
}; |
|
||||||
|
|
||||||
#endif // ALGODISPLAY_H_INCLUDED
|
|
@ -1,359 +0,0 @@ |
|||||||
/**
|
|
||||||
* |
|
||||||
* Copyright (c) 2015 Pascal Gauthier. |
|
||||||
* |
|
||||||
* This program is free software; you can redistribute it and/or modify |
|
||||||
* it under the terms of the GNU General Public License as published by |
|
||||||
* the Free Software Foundation; either version 3 of the License, or |
|
||||||
* (at your option) any later version. |
|
||||||
* |
|
||||||
* This program is distributed in the hope that it will be useful, |
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
* GNU General Public License for more details. |
|
||||||
* |
|
||||||
* You should have received a copy of the GNU General Public License |
|
||||||
* along with this program; if not, write to the Free Software Foundation, |
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
||||||
* |
|
||||||
*/ |
|
||||||
|
|
||||||
#include "PluginProcessor.h" |
|
||||||
#include "PluginEditor.h" |
|
||||||
#include "CartManager.h" |
|
||||||
#include "DXLookNFeel.h" |
|
||||||
#include "PluginData.h" |
|
||||||
|
|
||||||
#include <fstream> |
|
||||||
using namespace ::std; |
|
||||||
|
|
||||||
class SyxFileFilter : public FileFilter { |
|
||||||
public: |
|
||||||
SyxFileFilter() : FileFilter(".syx") {} |
|
||||||
bool isFileSuitable(const File &file) const { |
|
||||||
return file.getFileExtension().toLowerCase() == ".syx" && file.getSize() >= 4104; |
|
||||||
} |
|
||||||
bool isDirectorySuitable(const File &file) const { |
|
||||||
return true; |
|
||||||
}; |
|
||||||
}; |
|
||||||
|
|
||||||
class FileTreeDrop : public FileTreeComponent { |
|
||||||
public : |
|
||||||
FileTreeDrop(DirectoryContentsList &listToShow) : FileTreeComponent(listToShow) {} |
|
||||||
|
|
||||||
bool isInterestedInFileDrag (const StringArray &files) override { |
|
||||||
bool found = false; |
|
||||||
|
|
||||||
for(int i=0; i<files.size(); i++) { |
|
||||||
String filename = files[i].toLowerCase(); |
|
||||||
found |= filename.endsWith(".syx"); |
|
||||||
} |
|
||||||
return found; |
|
||||||
} |
|
||||||
|
|
||||||
void filesDropped(const StringArray &files, int x, int y) override { |
|
||||||
File targetDir = getSelectedFile(); |
|
||||||
|
|
||||||
if ( ! targetDir.exists() ) |
|
||||||
targetDir = DexedAudioProcessor::dexedCartDir; |
|
||||||
|
|
||||||
if ( ! targetDir.isDirectory() ) |
|
||||||
targetDir = targetDir.getParentDirectory(); |
|
||||||
|
|
||||||
for(int i=0; i<files.size(); i++) { |
|
||||||
if ( files[i].toLowerCase().endsWith(".syx") ) { |
|
||||||
File src(files[i]); |
|
||||||
File target = targetDir.getChildFile(src.getFileName()); |
|
||||||
src.copyFileTo(target); |
|
||||||
} |
|
||||||
} |
|
||||||
fileList.refresh(); |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
CartManager::CartManager(DexedAudioProcessorEditor *editor) : Component("CartManager") { |
|
||||||
mainWindow = editor; |
|
||||||
cartDir = DexedAudioProcessor::dexedCartDir;
|
|
||||||
|
|
||||||
addAndMakeVisible(activeCart = new ProgramListBox("activepgm", 8)); |
|
||||||
activeCart->setBounds(28, 441, 800, 96); |
|
||||||
activeCart->addListener(this); |
|
||||||
|
|
||||||
addAndMakeVisible(browserCart = new ProgramListBox("browserpgm", 2)); |
|
||||||
browserCart->setBounds(635, 18, 200, 384); |
|
||||||
browserCart->addListener(this); |
|
||||||
|
|
||||||
// -------------------------
|
|
||||||
syxFileFilter = new SyxFileFilter(); |
|
||||||
timeSliceThread = new TimeSliceThread("Cartridge Directory Scanner"); |
|
||||||
timeSliceThread->startThread(); |
|
||||||
cartBrowserList = new DirectoryContentsList(syxFileFilter, *timeSliceThread); |
|
||||||
cartBrowserList->setDirectory(cartDir, true, true); |
|
||||||
cartBrowser = new FileTreeDrop(*cartBrowserList); |
|
||||||
cartBrowser->addKeyListener(this); |
|
||||||
addAndMakeVisible(cartBrowser); |
|
||||||
|
|
||||||
cartBrowser->setBounds(23, 18, 590, 384); |
|
||||||
cartBrowser->setDragAndDropDescription("Sysex Browser"); |
|
||||||
cartBrowser->addListener(this); |
|
||||||
|
|
||||||
addAndMakeVisible(closeButton = new TextButton("CLOSE")); |
|
||||||
closeButton->setBounds(4, 545, 50, 30); |
|
||||||
closeButton->addListener(this); |
|
||||||
|
|
||||||
addAndMakeVisible(loadButton = new TextButton("LOAD")); |
|
||||||
loadButton->setBounds(52, 545, 50, 30); |
|
||||||
loadButton->addListener(this); |
|
||||||
|
|
||||||
addAndMakeVisible(saveButton = new TextButton("SAVE")); |
|
||||||
saveButton->setBounds(100, 545, 50, 30); |
|
||||||
saveButton->addListener(this); |
|
||||||
|
|
||||||
addAndMakeVisible(fileMgrButton = new TextButton("SHOW DIR")); |
|
||||||
fileMgrButton->setBounds(148, 545, 70, 30); |
|
||||||
fileMgrButton->addListener(this); |
|
||||||
/*
|
|
||||||
* |
|
||||||
* I've removed this since it only works on the DX7 II. TBC. |
|
||||||
* |
|
||||||
|
|
||||||
addAndMakeVisible(getDXPgmButton = new TextButton("GET DX7 PGM")); |
|
||||||
getDXPgmButton->setBounds(656, 545, 100, 30); |
|
||||||
getDXPgmButton->addListener(this); |
|
||||||
|
|
||||||
addAndMakeVisible(getDXCartButton = new TextButton("GET DX7 CART")); |
|
||||||
getDXCartButton->setBounds(755, 545, 100, 30); |
|
||||||
getDXCartButton->addListener(this); |
|
||||||
*/ |
|
||||||
} |
|
||||||
|
|
||||||
CartManager::~CartManager() { |
|
||||||
timeSliceThread->stopThread(500); |
|
||||||
delete cartBrowser; |
|
||||||
delete cartBrowserList; |
|
||||||
delete timeSliceThread; |
|
||||||
} |
|
||||||
|
|
||||||
void CartManager::paint(Graphics &g) { |
|
||||||
g.fillAll(DXLookNFeel::lightBackground); |
|
||||||
g.setColour(DXLookNFeel::roundBackground); |
|
||||||
g.fillRoundedRectangle(8, 418, 843, 126, 15); |
|
||||||
g.setColour(Colours::whitesmoke); |
|
||||||
g.drawText("currently loaded cartridge", 38, 410, 150, 40, Justification::left); |
|
||||||
} |
|
||||||
|
|
||||||
void CartManager::programSelected(ProgramListBox *source, int pos) { |
|
||||||
if ( source == activeCart ) { |
|
||||||
browserCart->setSelected(-1); |
|
||||||
mainWindow->processor->setCurrentProgram(pos); |
|
||||||
mainWindow->processor->updateHostDisplay(); |
|
||||||
} else { |
|
||||||
uint8_t unpackPgm[161]; |
|
||||||
source->getCurrentCart().unpackProgram(unpackPgm, pos); |
|
||||||
activeCart->setSelected(-1); |
|
||||||
browserCart->setSelected(pos); |
|
||||||
repaint(); |
|
||||||
mainWindow->processor->updateProgramFromSysex((uint8_t *) unpackPgm); |
|
||||||
mainWindow->processor->updateHostDisplay(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void CartManager::buttonClicked(juce::Button *buttonThatWasClicked) { |
|
||||||
if ( buttonThatWasClicked == closeButton ) { |
|
||||||
mainWindow->startTimer(100); |
|
||||||
setVisible(false); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
if ( buttonThatWasClicked == loadButton ) { |
|
||||||
FileChooser fc ("Import original DX sysex...", File::nonexistent, "*.syx;*.SYX;*.*", 1); |
|
||||||
|
|
||||||
if ( fc.browseForFileToOpen()) |
|
||||||
mainWindow->loadCart(fc.getResult()); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
if ( buttonThatWasClicked == saveButton ) { |
|
||||||
mainWindow->saveCart(); |
|
||||||
} |
|
||||||
|
|
||||||
if ( buttonThatWasClicked == fileMgrButton ) { |
|
||||||
cartDir.revealToUser(); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
// THIS IS NOT USED
|
|
||||||
if ( buttonThatWasClicked == getDXPgmButton ) { |
|
||||||
if ( mainWindow->processor->sysexComm.isInputActive() && mainWindow->processor->sysexComm.isOutputActive() ) { |
|
||||||
unsigned char msg[] = { 0xF0, 0x43, 0x20, 0x09, 0xF7 }; |
|
||||||
mainWindow->processor->sysexComm.send(MidiMessage(msg, 5)); |
|
||||||
} else { |
|
||||||
showSysexConfigMsg(); |
|
||||||
} |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
if ( buttonThatWasClicked == getDXCartButton ) { |
|
||||||
if ( mainWindow->processor->sysexComm.isInputActive() && mainWindow->processor->sysexComm.isOutputActive() ) { |
|
||||||
unsigned char msg[] = { 0xF0, 0x43, 0x20, 0x00, 0xF7 }; |
|
||||||
mainWindow->processor->sysexComm.send(MidiMessage(msg, 5)); |
|
||||||
} else { |
|
||||||
showSysexConfigMsg(); |
|
||||||
} |
|
||||||
return; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void CartManager::fileDoubleClicked(const File& file) { |
|
||||||
if ( file.isDirectory() ) |
|
||||||
return; |
|
||||||
mainWindow->loadCart(file); |
|
||||||
activeCart->setCartridge(mainWindow->processor->currentCart); |
|
||||||
} |
|
||||||
|
|
||||||
void CartManager::fileClicked(const File& file, const MouseEvent& e) { |
|
||||||
if ( e.mods.isRightButtonDown() ) { |
|
||||||
PopupMenu menu; |
|
||||||
|
|
||||||
menu.addItem(1000, "Open location"); |
|
||||||
if ( ! file.isDirectory() ) { |
|
||||||
menu.addItem(1010, "Send sysex cartridge to DX7"); |
|
||||||
} |
|
||||||
menu.addSeparator(); |
|
||||||
menu.addItem(1020, "Refresh"); |
|
||||||
|
|
||||||
switch(menu.show()) { |
|
||||||
case 1000: |
|
||||||
file.revealToUser(); |
|
||||||
break; |
|
||||||
case 1010 : |
|
||||||
mainWindow->processor->sendSysexCartridge(file); |
|
||||||
break; |
|
||||||
case 1020: |
|
||||||
cartBrowserList->refresh(); |
|
||||||
break; |
|
||||||
} |
|
||||||
return; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void CartManager::setActiveProgram(int idx, String activeName) { |
|
||||||
if ( activeCart->programNames[idx] == activeName ) { |
|
||||||
activeCart->setSelected(idx); |
|
||||||
browserCart->setSelected(-1); |
|
||||||
} |
|
||||||
activeCart->repaint(); |
|
||||||
} |
|
||||||
|
|
||||||
void CartManager::resetActiveSysex() { |
|
||||||
activeCart->setCartridge(mainWindow->processor->currentCart); |
|
||||||
} |
|
||||||
|
|
||||||
void CartManager::selectionChanged() { |
|
||||||
File file = cartBrowser->getSelectedFile(); |
|
||||||
|
|
||||||
if ( ! file.exists() ) |
|
||||||
return; |
|
||||||
|
|
||||||
if ( file.isDirectory() ) |
|
||||||
return; |
|
||||||
|
|
||||||
Cartridge browserSysex; |
|
||||||
int rc = browserSysex.load(file); |
|
||||||
if ( rc < 0 ) { |
|
||||||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, "Error", "Unable to open file"); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
if ( rc != 0 ) { |
|
||||||
browserCart->readOnly = true; |
|
||||||
} else { |
|
||||||
browserCart->readOnly = false; |
|
||||||
} |
|
||||||
browserCart->setSelected(-1); |
|
||||||
browserCart->setCartridge(browserSysex); |
|
||||||
} |
|
||||||
|
|
||||||
void CartManager::programRightClicked(ProgramListBox *source, int pos) { |
|
||||||
PopupMenu menu; |
|
||||||
|
|
||||||
menu.addItem(1000, "Send program '" + source->programNames[pos] + "' to DX7"); |
|
||||||
|
|
||||||
if ( source == activeCart ) |
|
||||||
menu.addItem(1010, "Send current sysex cartridge to DX7"); |
|
||||||
|
|
||||||
switch(menu.show()) { |
|
||||||
case 1000: |
|
||||||
uint8_t unpackPgm[161]; |
|
||||||
|
|
||||||
if ( source == activeCart ) { |
|
||||||
mainWindow->processor->currentCart.unpackProgram(unpackPgm, pos); |
|
||||||
} else { |
|
||||||
source->getCurrentCart().unpackProgram(unpackPgm, pos); |
|
||||||
} |
|
||||||
|
|
||||||
if ( mainWindow->processor->sysexComm.isOutputActive() ) { |
|
||||||
uint8_t msg[163]; |
|
||||||
exportSysexPgm(msg, unpackPgm); |
|
||||||
mainWindow->processor->sysexComm.send(MidiMessage(msg, 163)); |
|
||||||
} |
|
||||||
break; |
|
||||||
|
|
||||||
case 1010: |
|
||||||
mainWindow->processor->sendCurrentSysexCartridge(); |
|
||||||
break; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
void CartManager::programDragged(ProgramListBox *destListBox, int dest, char *packedPgm) { |
|
||||||
if ( destListBox == activeCart ) { |
|
||||||
char *sysex = mainWindow->processor->currentCart.getRawVoice(); |
|
||||||
memcpy(sysex+(dest*128), packedPgm, 128); |
|
||||||
mainWindow->updateUI(); |
|
||||||
} else { |
|
||||||
File file = cartBrowser->getSelectedFile(); |
|
||||||
|
|
||||||
if ( ! file.exists() ) |
|
||||||
return; |
|
||||||
|
|
||||||
if ( file.isDirectory() ) |
|
||||||
return; |
|
||||||
if ( file.getSize() != 4104 ) |
|
||||||
return; |
|
||||||
|
|
||||||
Cartridge cart; |
|
||||||
cart.load(file); |
|
||||||
memcpy(cart.getRawVoice()+(dest*128), packedPgm, 128); |
|
||||||
cart.saveVoice(file); |
|
||||||
browserCart->setCartridge(cart); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void CartManager::initialFocus() { |
|
||||||
cartBrowser->grabKeyboardFocus(); |
|
||||||
} |
|
||||||
|
|
||||||
bool CartManager::keyPressed(const KeyPress& key, Component* originatingComponent) { |
|
||||||
if ( key.getKeyCode() == 13 ) { |
|
||||||
File file = cartBrowser->getSelectedFile(); |
|
||||||
if ( file.isDirectory() ) |
|
||||||
return true; |
|
||||||
mainWindow->loadCart(file); |
|
||||||
activeCart->setCartridge(mainWindow->processor->currentCart); |
|
||||||
return true; |
|
||||||
} |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
void CartManager::showSysexConfigMsg() { |
|
||||||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, "Warning", "The DX7 midi interface is not configured correctly.\n\n" |
|
||||||
"These buttons are used to 'ask' the DX7 to send the current program/cartridge.\n\n"
|
|
||||||
"In order to use this correctly, you need to connect your midi in and midi out of your DX7 to a midi interface and configure this midi interface with the [PARM] dialog. THIS ONLY WORKS ON A DX7-II"); |
|
||||||
} |
|
||||||
|
|
||||||
// unused stuff from FileBrowserListener
|
|
||||||
void CartManager::browserRootChanged (const File& newRoot) {} |
|
||||||
|
|
||||||
|
|
@ -1,77 +0,0 @@ |
|||||||
/**
|
|
||||||
* |
|
||||||
* Copyright (c) 2015 Pascal Gauthier. |
|
||||||
* |
|
||||||
* This program is free software; you can redistribute it and/or modify |
|
||||||
* it under the terms of the GNU General Public License as published by |
|
||||||
* the Free Software Foundation; either version 3 of the License, or |
|
||||||
* (at your option) any later version. |
|
||||||
* |
|
||||||
* This program is distributed in the hope that it will be useful, |
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
* GNU General Public License for more details. |
|
||||||
* |
|
||||||
* You should have received a copy of the GNU General Public License |
|
||||||
* along with this program; if not, write to the Free Software Foundation, |
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
||||||
* |
|
||||||
*/ |
|
||||||
|
|
||||||
#ifndef CARTMANAGER_H_INCLUDED |
|
||||||
#define CARTMANAGER_H_INCLUDED |
|
||||||
|
|
||||||
#include "../JuceLibraryCode/JuceHeader.h" |
|
||||||
#include "PluginData.h" |
|
||||||
#include "ProgramListBox.h" |
|
||||||
#include "PluginData.h" |
|
||||||
|
|
||||||
class CartManager : public Component, public ButtonListener, public DragAndDropContainer, public FileBrowserListener |
|
||||||
, public ProgramListBoxListener, public KeyListener { |
|
||||||
ScopedPointer<TextButton> newButton; |
|
||||||
ScopedPointer<TextButton> loadButton; |
|
||||||
ScopedPointer<TextButton> saveButton; |
|
||||||
ScopedPointer<TextButton> closeButton; |
|
||||||
ScopedPointer<TextButton> fileMgrButton; |
|
||||||
ScopedPointer<TextButton> getDXPgmButton; |
|
||||||
ScopedPointer<TextButton> getDXCartButton; |
|
||||||
|
|
||||||
ScopedPointer<ProgramListBox> activeCart; |
|
||||||
ScopedPointer<ProgramListBox> browserCart; |
|
||||||
|
|
||||||
ScopedPointer<FileFilter> syxFileFilter; |
|
||||||
|
|
||||||
FileTreeComponent *cartBrowser; |
|
||||||
TimeSliceThread *timeSliceThread; |
|
||||||
DirectoryContentsList *cartBrowserList; |
|
||||||
|
|
||||||
File cartDir; |
|
||||||
|
|
||||||
DexedAudioProcessorEditor *mainWindow; |
|
||||||
|
|
||||||
void showSysexConfigMsg(); |
|
||||||
|
|
||||||
public: |
|
||||||
CartManager(DexedAudioProcessorEditor *editor); |
|
||||||
virtual ~CartManager(); |
|
||||||
void paint(Graphics& g) override; |
|
||||||
void buttonClicked (Button* buttonThatWasClicked) override; |
|
||||||
|
|
||||||
void selectionChanged() override; |
|
||||||
void fileClicked (const File& file, const MouseEvent& e) override; |
|
||||||
void fileDoubleClicked (const File& file) override; |
|
||||||
void browserRootChanged (const File& newRoot) override; |
|
||||||
|
|
||||||
void setActiveProgram(int idx, String activeName); |
|
||||||
void resetActiveSysex(); |
|
||||||
|
|
||||||
virtual void programSelected(ProgramListBox *source, int pos) override; |
|
||||||
virtual void programRightClicked(ProgramListBox *source, int pos) override; |
|
||||||
virtual void programDragged(ProgramListBox *destListBox, int dest, char *packedPgm) override; |
|
||||||
virtual bool keyPressed(const KeyPress& key, Component* originatingComponent) override; |
|
||||||
|
|
||||||
void initialFocus(); |
|
||||||
}; |
|
||||||
|
|
||||||
|
|
||||||
#endif // CARTMANAGER_H_INCLUDED
|
|
@ -1,442 +0,0 @@ |
|||||||
/**
|
|
||||||
* |
|
||||||
* Copyright (c) 2014 Pascal Gauthier. |
|
||||||
* |
|
||||||
* DX7 Envelope Tables from legasynth-0.4.1 / DX7 Patch Editor |
|
||||||
* Copyright (C) 2002 Juan Linietsky <coding@reduz.com.ar> |
|
||||||
* Copyright (C) 2006 Mark-André Hopf <mhopf@mark13.org> |
|
||||||
* |
|
||||||
* This program is free software; you can redistribute it and/or modify |
|
||||||
* it under the terms of the GNU General Public License as published by |
|
||||||
* the Free Software Foundation; either version 3 of the License, or |
|
||||||
* (at your option) any later version. |
|
||||||
* |
|
||||||
* This program is distributed in the hope that it will be useful, |
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
* GNU General Public License for more details. |
|
||||||
* |
|
||||||
* You should have received a copy of the GNU General Public License |
|
||||||
* along with this program; if not, write to the Free Software Foundation, |
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
||||||
* |
|
||||||
*/ |
|
||||||
|
|
||||||
#include "Dexed.h" |
|
||||||
#include "DXComponents.h" |
|
||||||
#include "DXLookNFeel.h" |
|
||||||
#include "PluginProcessor.h" |
|
||||||
#include "msfa/pitchenv.h" |
|
||||||
|
|
||||||
static char TMP_LEVEL_PTR[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; |
|
||||||
|
|
||||||
static float EG_rate_rise_duration[128] = { |
|
||||||
38.00000 ,34.96000 ,31.92000 ,28.88000 ,25.84000 , |
|
||||||
22.80000 ,20.64000 ,18.48000 ,16.32000 ,14.16000 , |
|
||||||
12.00000 ,11.10000 ,10.20000 ,9.30000 ,8.40000 , |
|
||||||
7.50000 ,6.96000 ,6.42000 ,5.88000 ,5.34000 , |
|
||||||
4.80000 ,4.38000 ,3.96000 ,3.54000 ,3.12000 , |
|
||||||
2.70000 ,2.52000 ,2.34000 ,2.16000 ,1.98000 , |
|
||||||
1.80000 ,1.70000 ,1.60000 ,1.50000 ,1.40000 , |
|
||||||
1.30000 ,1.22962 ,1.15925 ,1.08887 ,1.01850 , |
|
||||||
0.94813 ,0.87775 ,0.80737 ,0.73700 ,0.69633 , |
|
||||||
0.65567 ,0.61500 ,0.57833 ,0.54167 ,0.50500 , |
|
||||||
0.47300 ,0.44100 ,0.40900 ,0.37967 ,0.35033 , |
|
||||||
0.32100 ,0.28083 ,0.24067 ,0.20050 ,0.16033 , |
|
||||||
0.12017 ,0.08000 ,0.07583 ,0.07167 ,0.06750 , |
|
||||||
0.06333 ,0.05917 ,0.05500 ,0.04350 ,0.03200 , |
|
||||||
0.02933 ,0.02667 ,0.02400 ,0.02200 ,0.02000 , |
|
||||||
0.01800 ,0.01667 ,0.01533 ,0.01400 ,0.01300 , |
|
||||||
0.01200 ,0.01100 ,0.01000 ,0.00900 ,0.00800 , |
|
||||||
0.00800 ,0.00800 ,0.00800 ,0.00767 ,0.00733 , |
|
||||||
0.00700 ,0.00633 ,0.00567 ,0.00500 ,0.00433 , |
|
||||||
0.00367 ,0.00300 ,0.00300 ,0.00300 ,0.00300 , |
|
||||||
0.00300 ,0.00300 ,0.00300 ,0.00300 ,0.00300 , |
|
||||||
0.00300 ,0.00300 ,0.00300 ,0.00300 ,0.00300 , |
|
||||||
0.00300 ,0.00300 ,0.00300 ,0.00300 ,0.00300 , |
|
||||||
0.00300 ,0.00300 ,0.00300 ,0.00300 ,0.00300 , |
|
||||||
0.00300 ,0.00300 ,0.00300 ,0.00300 ,0.00300 , |
|
||||||
0.00300 ,0.00300 ,0.00300 |
|
||||||
}; |
|
||||||
|
|
||||||
static float EG_rate_decay_duration[128] = { |
|
||||||
318.00000 ,283.75000 ,249.50000 ,215.25000 ,181.00000 , |
|
||||||
167.80000 ,154.60001 ,141.39999 ,128.20000 ,115.00000 , |
|
||||||
104.60000 ,94.20000 ,83.80000 ,73.40000 ,63.00000 , |
|
||||||
58.34000 ,53.68000 ,49.02000 ,44.36000 ,39.70000 , |
|
||||||
35.76000 ,31.82000 ,27.88000 ,23.94000 ,20.00000 , |
|
||||||
18.24000 ,16.48000 ,14.72000 ,12.96000 ,11.20000 , |
|
||||||
10.36000 ,9.52000 ,8.68000 ,7.84000 ,7.00000 , |
|
||||||
6.83250 ,6.66500 ,6.49750 ,6.33000 ,6.16250 , |
|
||||||
5.99500 ,5.82750 ,5.66000 ,5.10000 ,4.54000 , |
|
||||||
3.98000 ,3.64833 ,3.31667 ,2.98500 ,2.65333 , |
|
||||||
2.32167 ,1.99000 ,1.77333 ,1.55667 ,1.34000 , |
|
||||||
1.22333 ,1.10667 ,0.99000 ,0.89667 ,0.80333 , |
|
||||||
0.71000 ,0.65000 ,0.59000 ,0.53000 ,0.47000 , |
|
||||||
0.41000 ,0.32333 ,0.23667 ,0.15000 ,0.12700 , |
|
||||||
0.10400 ,0.08100 ,0.07667 ,0.07233 ,0.06800 , |
|
||||||
0.06100 ,0.05400 ,0.04700 ,0.04367 ,0.04033 , |
|
||||||
0.03700 ,0.03300 ,0.02900 ,0.02500 ,0.02333 , |
|
||||||
0.02167 ,0.02000 ,0.01767 ,0.01533 ,0.01300 , |
|
||||||
0.01133 ,0.00967 ,0.00800 ,0.00800 ,0.00800 , |
|
||||||
0.00800 ,0.00800 ,0.00800 ,0.00800 ,0.00800 , |
|
||||||
0.00800 ,0.00800 ,0.00800 ,0.00800 ,0.00800 , |
|
||||||
0.00800 ,0.00800 ,0.00800 ,0.00800 ,0.00800 , |
|
||||||
0.00800 ,0.00800 ,0.00800 ,0.00800 ,0.00800 , |
|
||||||
0.00800 ,0.00800 ,0.00800 ,0.00800 ,0.00800 , |
|
||||||
0.00800 ,0.00800 ,0.00800 ,0.00800 ,0.00800 , |
|
||||||
0.00800 ,0.00800 ,0.00800 |
|
||||||
}; |
|
||||||
|
|
||||||
static float EG_rate_decay_percent[128] = { |
|
||||||
0.00001 ,0.00001 ,0.00001 ,0.00001 ,0.00001 , |
|
||||||
0.00001 ,0.00001 ,0.00001 ,0.00001 ,0.00001 , |
|
||||||
0.00001 ,0.00001 ,0.00001 ,0.00001 ,0.00001 , |
|
||||||
0.00001 ,0.00001 ,0.00001 ,0.00001 ,0.00001 , |
|
||||||
0.00001 ,0.00001 ,0.00001 ,0.00001 ,0.00001 , |
|
||||||
0.00001 ,0.00001 ,0.00001 ,0.00001 ,0.00001 , |
|
||||||
0.00001 ,0.00001 ,0.00501 ,0.01001 ,0.01500 , |
|
||||||
0.02000 ,0.02800 ,0.03600 ,0.04400 ,0.05200 , |
|
||||||
0.06000 ,0.06800 ,0.07600 ,0.08400 ,0.09200 , |
|
||||||
0.10000 ,0.10800 ,0.11600 ,0.12400 ,0.13200 , |
|
||||||
0.14000 ,0.15000 ,0.16000 ,0.17000 ,0.18000 , |
|
||||||
0.19000 ,0.20000 ,0.21000 ,0.22000 ,0.23000 , |
|
||||||
0.24000 ,0.25100 ,0.26200 ,0.27300 ,0.28400 , |
|
||||||
0.29500 ,0.30600 ,0.31700 ,0.32800 ,0.33900 , |
|
||||||
0.35000 ,0.36500 ,0.38000 ,0.39500 ,0.41000 , |
|
||||||
0.42500 ,0.44000 ,0.45500 ,0.47000 ,0.48500 , |
|
||||||
0.50000 ,0.52000 ,0.54000 ,0.56000 ,0.58000 , |
|
||||||
0.60000 ,0.62000 ,0.64000 ,0.66000 ,0.68000 , |
|
||||||
0.70000 ,0.73200 ,0.76400 ,0.79600 ,0.82800 , |
|
||||||
0.86000 ,0.89500 ,0.93000 ,0.96500 ,1.00000 , |
|
||||||
1.00000 ,1.00000 ,1.00000 ,1.00000 ,1.00000 , |
|
||||||
1.00000 ,1.00000 ,1.00000 ,1.00000 ,1.00000 , |
|
||||||
1.00000 ,1.00000 ,1.00000 ,1.00000 ,1.00000 , |
|
||||||
1.00000 ,1.00000 ,1.00000 ,1.00000 ,1.00000 , |
|
||||||
1.00000 ,1.00000 ,1.00000 ,1.00000 ,1.00000 , |
|
||||||
1.00000 ,1.00000 ,1.00000 |
|
||||||
|
|
||||||
}; |
|
||||||
|
|
||||||
static float EG_rate_rise_percent[128] = { |
|
||||||
0.00001 ,0.00001 ,0.00001 ,0.00001 ,0.00001 , |
|
||||||
0.00001 ,0.00001 ,0.00001 ,0.00001 ,0.00001 , |
|
||||||
0.00001 ,0.00001 ,0.00001 ,0.00001 ,0.00001 , |
|
||||||
0.00001 ,0.00001 ,0.00001 ,0.00001 ,0.00001 , |
|
||||||
0.00001 ,0.00001 ,0.00001 ,0.00001 ,0.00001 , |
|
||||||
0.00001 ,0.00001 ,0.00001 ,0.00001 ,0.00001 , |
|
||||||
0.00001 ,0.00001 ,0.00501 ,0.01001 ,0.01500 , |
|
||||||
0.02000 ,0.02800 ,0.03600 ,0.04400 ,0.05200 , |
|
||||||
0.06000 ,0.06800 ,0.07600 ,0.08400 ,0.09200 , |
|
||||||
0.10000 ,0.10800 ,0.11600 ,0.12400 ,0.13200 , |
|
||||||
0.14000 ,0.15000 ,0.16000 ,0.17000 ,0.18000 , |
|
||||||
0.19000 ,0.20000 ,0.21000 ,0.22000 ,0.23000 , |
|
||||||
0.24000 ,0.25100 ,0.26200 ,0.27300 ,0.28400 , |
|
||||||
0.29500 ,0.30600 ,0.31700 ,0.32800 ,0.33900 , |
|
||||||
0.35000 ,0.36500 ,0.38000 ,0.39500 ,0.41000 , |
|
||||||
0.42500 ,0.44000 ,0.45500 ,0.47000 ,0.48500 , |
|
||||||
0.50000 ,0.52000 ,0.54000 ,0.56000 ,0.58000 , |
|
||||||
0.60000 ,0.62000 ,0.64000 ,0.66000 ,0.68000 , |
|
||||||
0.70000 ,0.73200 ,0.76400 ,0.79600 ,0.82800 , |
|
||||||
0.86000 ,0.89500 ,0.93000 ,0.96500 ,1.00000 , |
|
||||||
1.00000 ,1.00000 ,1.00000 ,1.00000 ,1.00000 , |
|
||||||
1.00000 ,1.00000 ,1.00000 ,1.00000 ,1.00000 , |
|
||||||
1.00000 ,1.00000 ,1.00000 ,1.00000 ,1.00000 , |
|
||||||
1.00000 ,1.00000 ,1.00000 ,1.00000 ,1.00000 , |
|
||||||
1.00000 ,1.00000 ,1.00000 ,1.00000 ,1.00000 , |
|
||||||
1.00000 ,1.00000 ,1.00000 |
|
||||||
}; |
|
||||||
|
|
||||||
static double getDuration(int p_rate, int p_level_l, int p_level_r) { |
|
||||||
float *duration_table=(p_level_r>p_level_l) ? EG_rate_rise_duration : EG_rate_decay_duration; |
|
||||||
double duration=duration_table[p_rate]; |
|
||||||
|
|
||||||
float* percent_table =(p_level_r>p_level_l) ? EG_rate_rise_percent : EG_rate_decay_percent; |
|
||||||
duration *= fabs(percent_table[p_level_r]-percent_table[p_level_l]); |
|
||||||
return duration; |
|
||||||
} |
|
||||||
|
|
||||||
EnvDisplay::EnvDisplay() { |
|
||||||
pvalues = (uint8_t *) &TMP_LEVEL_PTR; |
|
||||||
} |
|
||||||
|
|
||||||
void EnvDisplay::paint(Graphics &g) { |
|
||||||
int h = getHeight(); |
|
||||||
uint8_t *rates = pvalues; |
|
||||||
uint8_t *levels = pvalues + 4; |
|
||||||
|
|
||||||
double d[4]; |
|
||||||
double keyoff = 0.0; |
|
||||||
double release = 0.0; |
|
||||||
d[0] = getDuration(rates[0], levels[3], levels[0]); |
|
||||||
d[1] = getDuration(rates[1], levels[0], levels[1]); |
|
||||||
d[2] = getDuration(rates[2], levels[1], levels[2]); |
|
||||||
|
|
||||||
double ko = 0.0; |
|
||||||
for(int j=0; j<3; ++j) |
|
||||||
ko += d[j]; |
|
||||||
if (ko>keyoff) |
|
||||||
keyoff=ko; |
|
||||||
|
|
||||||
d[3] = getDuration(rates[3], levels[2], levels[3]); |
|
||||||
if ( d[3]>release ) { |
|
||||||
release = d[3]; |
|
||||||
} |
|
||||||
keyoff += 10.0; |
|
||||||
double w = getWidth() / (keyoff + release); |
|
||||||
|
|
||||||
g.setColour(Colour(0xF0000000)); |
|
||||||
g.fillRoundedRectangle (keyoff*w, 0.0f, (float) getWidth(), (float) getHeight(), 1.0f); |
|
||||||
g.setColour(Colours::white); |
|
||||||
|
|
||||||
int x, y; |
|
||||||
|
|
||||||
Path p; |
|
||||||
p.startNewSubPath(0, 32); |
|
||||||
|
|
||||||
// 0
|
|
||||||
x = 0; |
|
||||||
y = h - h / 99.0 * levels[3]; |
|
||||||
p.lineTo(x, y); |
|
||||||
if ( vPos == 0 || vPos == 1 ) { |
|
||||||
g.fillEllipse(x-2, y-2, 4, 4); |
|
||||||
} |
|
||||||
|
|
||||||
// 1
|
|
||||||
x = d[0]*w; |
|
||||||
y = h - h / 99.0 * levels[0]; |
|
||||||
p.lineTo( x, y ); |
|
||||||
if ( vPos == 1 || vPos == 2 ) { |
|
||||||
g.fillEllipse(x-2, y-2, 4, 4); |
|
||||||
} |
|
||||||
|
|
||||||
// 2
|
|
||||||
x = (d[0]+d[1])*w; |
|
||||||
y = h - h / 99.0 * levels[1]; |
|
||||||
p.lineTo( x, y ); |
|
||||||
if ( vPos == 2 || vPos == 3 ) { |
|
||||||
g.fillEllipse(x-2, y-2, 4, 4); |
|
||||||
} |
|
||||||
|
|
||||||
// 3
|
|
||||||
x = (d[0]+d[1]+d[2])*w; |
|
||||||
y = h - h / 99.0 * levels[2]; |
|
||||||
p.lineTo( x, y ); |
|
||||||
if ( vPos == 3 || vPos == 4) { |
|
||||||
g.fillEllipse(x-2, y-2, 4, 4); |
|
||||||
} |
|
||||||
|
|
||||||
// 4
|
|
||||||
x = keyoff*w; |
|
||||||
y = h - h / 99.0 * levels[2]; |
|
||||||
p.lineTo( x, y ); |
|
||||||
if ( vPos == 4 ) { |
|
||||||
g.fillEllipse(x-2, y-2, 4, 4); |
|
||||||
} |
|
||||||
|
|
||||||
// 5
|
|
||||||
p.lineTo( (d[0]+d[1]+d[2]+keyoff+d[3])*w, h - h / 99.0 * levels[3] ); |
|
||||||
|
|
||||||
p.lineTo(96,32); |
|
||||||
p.lineTo(0, 32); |
|
||||||
|
|
||||||
g.setColour(DXLookNFeel::fillColour); |
|
||||||
g.fillPath(p); |
|
||||||
|
|
||||||
g.setColour(Colour(0xFFFFFFFF)); |
|
||||||
String len; |
|
||||||
len << ((int) vPos); |
|
||||||
g.drawText(len, 5, 1, 72, 14, Justification::left, true); |
|
||||||
} |
|
||||||
|
|
||||||
PitchEnvDisplay::PitchEnvDisplay() { |
|
||||||
pvalues = (uint8_t *) &TMP_LEVEL_PTR; |
|
||||||
vPos = 0; |
|
||||||
} |
|
||||||
|
|
||||||
void PitchEnvDisplay::paint(Graphics &g) { |
|
||||||
g.setColour(Colours::white); |
|
||||||
|
|
||||||
uint8_t *levels = pvalues + 4; |
|
||||||
uint8_t *rates = pvalues; |
|
||||||
|
|
||||||
float dist[4]; |
|
||||||
float total = 0; |
|
||||||
|
|
||||||
int old = pitchenv_tab[levels[3]] + 128; |
|
||||||
|
|
||||||
// find the scale
|
|
||||||
for(int i=0;i<4;i++) { |
|
||||||
int nw = pitchenv_tab[levels[i]] + 128; |
|
||||||
dist[i] = ((float)abs(nw - old)) / pitchenv_rate[rates[i]]; |
|
||||||
total += dist[i]; |
|
||||||
old = nw; |
|
||||||
} |
|
||||||
|
|
||||||
if ( total < 0.00001 ) { |
|
||||||
dist[0] = dist[1] = dist[2] = dist[3] = 1; |
|
||||||
total = 4; |
|
||||||
} |
|
||||||
|
|
||||||
float ratio = 96 / total; |
|
||||||
|
|
||||||
Path p; |
|
||||||
p.startNewSubPath(0, 32); |
|
||||||
|
|
||||||
int x = 0; |
|
||||||
int y = 25 - (pitchenv_tab[levels[3]] + 128) / 10; |
|
||||||
p.lineTo(0,y); |
|
||||||
|
|
||||||
int dx = x; |
|
||||||
int dy = y; |
|
||||||
|
|
||||||
int i; |
|
||||||
for(i=0;i<4;i++) { |
|
||||||
if ( vPos == i ) { |
|
||||||
dx = x; |
|
||||||
dy = y; |
|
||||||
} |
|
||||||
|
|
||||||
x = dist[i] * ratio + x; |
|
||||||
y = 25 - (pitchenv_tab[levels[i]] + 128) / 10; |
|
||||||
p.lineTo(x, y); |
|
||||||
} |
|
||||||
|
|
||||||
if ( vPos == i ) { |
|
||||||
dx = x; |
|
||||||
dy = y; |
|
||||||
} |
|
||||||
|
|
||||||
p.lineTo(96,32); |
|
||||||
p.lineTo(0, 32); |
|
||||||
g.setColour(DXLookNFeel::fillColour); |
|
||||||
g.fillPath(p); |
|
||||||
|
|
||||||
g.setColour(Colours::white); |
|
||||||
g.fillEllipse(dx-2, dy-2, 4, 4); |
|
||||||
} |
|
||||||
|
|
||||||
void VuMeter::paint(Graphics &g) { |
|
||||||
Image myStrip = ImageCache::getFromMemory(BinaryData::Meter_140x8_png, BinaryData::Meter_140x8_pngSize); |
|
||||||
|
|
||||||
g.drawImage(myStrip, 0, 0, 140, 8, 0, 0, 140, 8); |
|
||||||
|
|
||||||
if ( v <= 0 ) |
|
||||||
return; |
|
||||||
|
|
||||||
const int totalBlocks = 46; |
|
||||||
int numBlocks = roundToInt(totalBlocks * v); |
|
||||||
|
|
||||||
if ( numBlocks > 46 ) |
|
||||||
numBlocks = totalBlocks; |
|
||||||
int brkpoint = numBlocks * 3 + 2; |
|
||||||
|
|
||||||
g.drawImage(myStrip, 0, 0, brkpoint, 8, 0, 8, brkpoint, 8); |
|
||||||
} |
|
||||||
|
|
||||||
LcdDisplay::LcdDisplay() { |
|
||||||
paramMsg = "DEXED " DEXED_VERSION; |
|
||||||
} |
|
||||||
|
|
||||||
void LcdDisplay::setSystemMsg(String msg) { |
|
||||||
paramMsg = msg; |
|
||||||
} |
|
||||||
|
|
||||||
void LcdDisplay::paint(Graphics &g) { |
|
||||||
g.setColour (Colours::white);
|
|
||||||
g.drawText (paramMsg, |
|
||||||
0, 0, 140, 14, |
|
||||||
Justification::centred, true); |
|
||||||
} |
|
||||||
|
|
||||||
void ComboBoxImage::paint(Graphics &g) { |
|
||||||
int idx = getSelectedItemIndex(); |
|
||||||
if ( itemPos[0] != -1 ) { |
|
||||||
if ( idx < 4 ) |
|
||||||
idx = itemPos[idx]; |
|
||||||
} |
|
||||||
|
|
||||||
g.drawImage(items, 0, 0, items.getWidth(), itemHeight, 0, idx * itemHeight, items.getWidth(), itemHeight); |
|
||||||
} |
|
||||||
|
|
||||||
ComboBoxImage::ComboBoxImage() { |
|
||||||
itemPos[0] = -1; |
|
||||||
} |
|
||||||
|
|
||||||
static void comboBoxPopupMenuFinishedCallback (int result, ComboBoxImage* combo) { |
|
||||||
if (combo != nullptr) { |
|
||||||
combo->hidePopup(); |
|
||||||
|
|
||||||
if (result != 0) |
|
||||||
combo->setSelectedId (result); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void ComboBoxImage::showPopup() { |
|
||||||
popup.showMenuAsync (PopupMenu::Options().withTargetComponent (this) |
|
||||||
.withItemThatMustBeVisible(getSelectedId()) |
|
||||||
.withMinimumWidth(getWidth()) |
|
||||||
.withMaximumNumColumns(1) |
|
||||||
.withStandardItemHeight(itemHeight), |
|
||||||
ModalCallbackFunction::forComponent(comboBoxPopupMenuFinishedCallback, this)); |
|
||||||
} |
|
||||||
|
|
||||||
void ComboBoxImage::setImage(Image image) { |
|
||||||
items = image; |
|
||||||
|
|
||||||
int numItems = getNumItems(); |
|
||||||
itemHeight = image.getHeight() / numItems; |
|
||||||
|
|
||||||
for(int i=0;i<numItems;i++) { |
|
||||||
Image tmp = image.getClippedImage(Rectangle<int>(0,itemHeight*i, image.getWidth(), itemHeight)); |
|
||||||
popup.addItem(i+1, getItemText(i), true, false, tmp); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void ComboBoxImage::setImage(Image image, int pos[]) { |
|
||||||
items = image; |
|
||||||
|
|
||||||
int numItems = getNumItems(); |
|
||||||
itemHeight = 26; |
|
||||||
|
|
||||||
for(int i=0;i<numItems;i++) { |
|
||||||
Image tmp = image.getClippedImage(Rectangle<int>(0,itemHeight*pos[i], image.getWidth(), itemHeight)); |
|
||||||
popup.addItem(i+1, getItemText(i), true, false, tmp); |
|
||||||
} |
|
||||||
|
|
||||||
for(int i=0;i<4;i++) |
|
||||||
itemPos[i] = pos[i]; |
|
||||||
} |
|
||||||
|
|
||||||
void ProgramSelector::mouseDown(const MouseEvent &event) { |
|
||||||
if ( event.x < getWidth() - 8) { |
|
||||||
ComboBox::mouseDown(event); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
int cur = getSelectedItemIndex(); |
|
||||||
if ( event.y < getHeight() / 2 ) { |
|
||||||
if ( cur == 0 ) |
|
||||||
cur = 31; |
|
||||||
else |
|
||||||
cur--; |
|
||||||
} else { |
|
||||||
if ( cur == 31 ) |
|
||||||
cur = 0; |
|
||||||
else |
|
||||||
cur++; |
|
||||||
} |
|
||||||
setSelectedItemIndex(cur); |
|
||||||
} |
|
||||||
|
|
||||||
void ProgramSelector::paint(Graphics &g) { |
|
||||||
int x = getWidth(); |
|
||||||
int y = getHeight(); |
|
||||||
|
|
||||||
Path path; |
|
||||||
path.addTriangle(x-8, y/2-1, x-4, 2, x, y/2-1); |
|
||||||
path.addTriangle(x-8, y/2+1, x-4, y-2, x, y/2+1); |
|
||||||
|
|
||||||
g.setColour(Colours::white); |
|
||||||
g.fillPath(path); |
|
||||||
} |
|
@ -1,78 +0,0 @@ |
|||||||
/**
|
|
||||||
* |
|
||||||
* Copyright (c) 2014 Pascal Gauthier. |
|
||||||
* |
|
||||||
* This program is free software; you can redistribute it and/or modify |
|
||||||
* it under the terms of the GNU General Public License as published by |
|
||||||
* the Free Software Foundation; either version 3 of the License, or |
|
||||||
* (at your option) any later version. |
|
||||||
* |
|
||||||
* This program is distributed in the hope that it will be useful, |
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
* GNU General Public License for more details. |
|
||||||
* |
|
||||||
* You should have received a copy of the GNU General Public License |
|
||||||
* along with this program; if not, write to the Free Software Foundation, |
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
||||||
* |
|
||||||
*/ |
|
||||||
|
|
||||||
#ifndef DXCOMPONENTS_H_INCLUDED |
|
||||||
#define DXCOMPONENTS_H_INCLUDED |
|
||||||
|
|
||||||
#include "../JuceLibraryCode/JuceHeader.h" |
|
||||||
#include <stdint.h> |
|
||||||
|
|
||||||
class EnvDisplay : public Component { |
|
||||||
public: |
|
||||||
EnvDisplay(); |
|
||||||
uint8_t *pvalues; |
|
||||||
char vPos;
|
|
||||||
void paint(Graphics &g); |
|
||||||
}; |
|
||||||
|
|
||||||
class PitchEnvDisplay : public Component { |
|
||||||
char rvalues[8]; |
|
||||||
public: |
|
||||||
PitchEnvDisplay(); |
|
||||||
uint8_t *pvalues; |
|
||||||
char vPos; |
|
||||||
void paint(Graphics &g); |
|
||||||
}; |
|
||||||
|
|
||||||
class VuMeter: public Component { |
|
||||||
void paint(Graphics &g); |
|
||||||
public :
|
|
||||||
float v; |
|
||||||
}; |
|
||||||
|
|
||||||
class LcdDisplay : public Component { |
|
||||||
public: |
|
||||||
LcdDisplay(); |
|
||||||
void setSystemMsg(String msg); |
|
||||||
String paramMsg; |
|
||||||
void paint(Graphics &g);
|
|
||||||
}; |
|
||||||
|
|
||||||
class ComboBoxImage : public ComboBox { |
|
||||||
Image items; |
|
||||||
int itemHeight; |
|
||||||
PopupMenu popup; |
|
||||||
int itemPos[4]; |
|
||||||
public: |
|
||||||
ComboBoxImage(); |
|
||||||
|
|
||||||
virtual void paint(Graphics &g) override; |
|
||||||
virtual void showPopup() override; |
|
||||||
void setImage(Image image); |
|
||||||
void setImage(Image image, int pos[]); |
|
||||||
}; |
|
||||||
|
|
||||||
class ProgramSelector : public ComboBox { |
|
||||||
public: |
|
||||||
void mouseDown(const MouseEvent &event) override;
|
|
||||||
virtual void paint(Graphics &g) override; |
|
||||||
}; |
|
||||||
|
|
||||||
#endif // DXCOMPONENTS_H_INCLUDED
|
|
@ -1,255 +0,0 @@ |
|||||||
/**
|
|
||||||
* |
|
||||||
* Copyright (c) 2013-2016 Pascal Gauthier. |
|
||||||
* |
|
||||||
* This program is free software; you can redistribute it and/or modify |
|
||||||
* it under the terms of the GNU General Public License as published by |
|
||||||
* the Free Software Foundation; either version 3 of the License, or |
|
||||||
* (at your option) any later version. |
|
||||||
* |
|
||||||
* This program is distributed in the hope that it will be useful, |
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
* GNU General Public License for more details. |
|
||||||
* |
|
||||||
* You should have received a copy of the GNU General Public License |
|
||||||
* along with this program; if not, write to the Free Software Foundation, |
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
|
||||||
* |
|
||||||
*/ |
|
||||||
|
|
||||||
#include "DXLookNFeel.h" |
|
||||||
#include "DXComponents.h" |
|
||||||
#include "Dexed.h" |
|
||||||
#include "PluginProcessor.h" |
|
||||||
|
|
||||||
#define REG_COLOUR(id, value) setColour(id, value); colourMap.set(#id, id) |
|
||||||
|
|
||||||
Image findImage(String path) { |
|
||||||
Image img; |
|
||||||
if ( path.length() <= 3 )
|
|
||||||
return img; |
|
||||||
File imgFile(path); |
|
||||||
img = ImageCache::getFromFile(imgFile); |
|
||||||
return img; |
|
||||||
} |
|
||||||
|
|
||||||
DXLookNFeel::DXLookNFeel() { |
|
||||||
Colour ctrlBackground; |
|
||||||
|
|
||||||
DexedAudioProcessor::dexedAppDir.setAsCurrentWorkingDirectory(); |
|
||||||
ctrlBackground = Colour(20,18,18); |
|
||||||
|
|
||||||
REG_COLOUR(TextButton::buttonColourId,Colour(0xFF0FC00F)); |
|
||||||
REG_COLOUR(TextButton::textColourOnId, Colours::white); |
|
||||||
REG_COLOUR(TextButton::textColourOffId, Colours::white); |
|
||||||
REG_COLOUR(Slider::rotarySliderOutlineColourId,Colour(0xFF0FC00F)); |
|
||||||
REG_COLOUR(Slider::rotarySliderFillColourId,Colour(0xFFFFFFFF)); |
|
||||||
REG_COLOUR(AlertWindow::backgroundColourId,lightBackground); |
|
||||||
REG_COLOUR(AlertWindow::textColourId, Colours::white); |
|
||||||
REG_COLOUR(TextEditor::backgroundColourId,ctrlBackground); |
|
||||||
REG_COLOUR(TextEditor::textColourId, Colours::white); |
|
||||||
REG_COLOUR(TextEditor::highlightColourId, fillColour); |
|
||||||
REG_COLOUR(TextEditor::outlineColourId, Colours::transparentBlack); |
|
||||||
REG_COLOUR(ComboBox::backgroundColourId, ctrlBackground); |
|
||||||
REG_COLOUR(ComboBox::textColourId, Colours::white); |
|
||||||
REG_COLOUR(ComboBox::buttonColourId, Colours::white); |
|
||||||
REG_COLOUR(PopupMenu::backgroundColourId, background); |
|
||||||
REG_COLOUR(PopupMenu::textColourId, Colours::white); |
|
||||||
REG_COLOUR(PopupMenu::highlightedTextColourId, Colours::white); |
|
||||||
REG_COLOUR(PopupMenu::highlightedBackgroundColourId, fillColour); |
|
||||||
REG_COLOUR(TreeView::backgroundColourId, background); |
|
||||||
REG_COLOUR(DirectoryContentsDisplayComponent::highlightColourId, fillColour); |
|
||||||
REG_COLOUR(DirectoryContentsDisplayComponent::textColourId, Colours::white); |
|
||||||
|
|
||||||
imageKnob = ImageCache::getFromMemory(BinaryData::Knob_34x34_png, BinaryData::Knob_34x34_pngSize); |
|
||||||
imageSwitch = ImageCache::getFromMemory(BinaryData::Switch_48x26_png, BinaryData::Switch_48x26_pngSize); |
|
||||||
imageSwitchOperator = ImageCache::getFromMemory(BinaryData::Switch_32x32_png, BinaryData::Switch_32x32_pngSize); |
|
||||||
imageButton = ImageCache::getFromMemory(BinaryData::ButtonUnlabeled_50x30_png, BinaryData::ButtonUnlabeled_50x30_pngSize); |
|
||||||
imageSlider = ImageCache::getFromMemory(BinaryData::Slider_26x26_png, BinaryData::Slider_26x26_pngSize); |
|
||||||
imageScaling = ImageCache::getFromMemory(BinaryData::Scaling_36_26_png, BinaryData::Scaling_36_26_pngSize);; |
|
||||||
imageLight = ImageCache::getFromMemory(BinaryData::Light_14x14_png, BinaryData::Light_14x14_pngSize); |
|
||||||
imageLFO = ImageCache::getFromMemory(BinaryData::LFO_36_26_png, BinaryData::LFO_36_26_pngSize); |
|
||||||
imageOperator = ImageCache::getFromMemory(BinaryData::OperatorEditor_287x218_png, BinaryData::OperatorEditor_287x218_pngSize); |
|
||||||
imageGlobal = ImageCache::getFromMemory (BinaryData::GlobalEditor_864x144_png, BinaryData::GlobalEditor_864x144_pngSize); |
|
||||||
|
|
||||||
defaultFont = Typeface::createSystemTypefaceFor(BinaryData::NotoSansRegular_ttf, BinaryData::NotoSansRegular_ttfSize); |
|
||||||
defaultFontBold = Typeface::createSystemTypefaceFor(BinaryData::NotoSansBold_ttf, BinaryData::NotoSansBold_ttfSize); |
|
||||||
|
|
||||||
File dexedTheme = DexedAudioProcessor::dexedAppDir.getChildFile("DexedTheme.xml"); |
|
||||||
|
|
||||||
if ( ! dexedTheme.existsAsFile() ) |
|
||||||
return; |
|
||||||
|
|
||||||
XmlElement *root = XmlDocument::parse(dexedTheme); |
|
||||||
if ( root == NULL ) |
|
||||||
return; |
|
||||||
|
|
||||||
forEachXmlChildElementWithTagName(*root, colour, "colour") { |
|
||||||
String name = colour->getStringAttribute("id", ""); |
|
||||||
if ( name == "" ) |
|
||||||
continue; |
|
||||||
String value = colour->getStringAttribute("value", ""); |
|
||||||
if ( value == "" ) |
|
||||||
continue; |
|
||||||
if ( value.length() < 8 )
|
|
||||||
continue; |
|
||||||
int conv = strtol(value.toRawUTF8(), NULL, 16); |
|
||||||
if ( colourMap.contains(name) ) { |
|
||||||
setColour(colourMap[name], Colour(conv)); |
|
||||||
} else { |
|
||||||
if ( name == "Dexed::backgroundId" ) { |
|
||||||
background = Colour(conv); |
|
||||||
continue; |
|
||||||
} |
|
||||||
if ( name == "Dexed::fillColourId" ) { |
|
||||||
fillColour = Colour(conv); |
|
||||||
continue; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
forEachXmlChildElementWithTagName(*root, image, "image") { |
|
||||||
String name = image->getStringAttribute("id", ""); |
|
||||||
String path = image->getStringAttribute("path", ""); |
|
||||||
if ( name == "Knob_34x34.png" ) { |
|
||||||
imageKnob = findImage(path); |
|
||||||
continue; |
|
||||||
} |
|
||||||
if ( name == "Switch_48x26.png" ) { |
|
||||||
imageSwitch = findImage(path); |
|
||||||
continue; |
|
||||||
} |
|
||||||
if ( name == "Switch_32x64.png" ) { |
|
||||||
imageSwitchOperator = findImage(path); |
|
||||||
continue; |
|
||||||
} |
|
||||||
if ( name == "ButtonUnlabeled_50x30.png" ) { |
|
||||||
imageButton = findImage(path); |
|
||||||
continue; |
|
||||||
} |
|
||||||
if ( name == "Slider_26x26.png" ) { |
|
||||||
imageSlider = findImage(path); |
|
||||||
continue; |
|
||||||
} |
|
||||||
if ( name == "Scaling_36_26.png" ) { |
|
||||||
imageScaling = findImage(path); |
|
||||||
continue; |
|
||||||
} |
|
||||||
if ( name == "Light_14x14.png" ) { |
|
||||||
imageLight = findImage(path); |
|
||||||
continue; |
|
||||||
} |
|
||||||
if ( name == "LFO_36_26.png" ) { |
|
||||||
imageLFO = findImage(path); |
|
||||||
continue; |
|
||||||
} |
|
||||||
if ( name == "OperatorEditor_287x218.png" ) { |
|
||||||
imageOperator = findImage(path); |
|
||||||
continue; |
|
||||||
} |
|
||||||
if ( name == "GlobalEditor_864x144.png" ) { |
|
||||||
imageGlobal = findImage(path); |
|
||||||
continue; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
delete root; |
|
||||||
} |
|
||||||
|
|
||||||
Typeface::Ptr DXLookNFeel::getTypefaceForFont(const Font &) { |
|
||||||
return defaultFont; |
|
||||||
} |
|
||||||
|
|
||||||
void DXLookNFeel::drawRotarySlider( Graphics &g, int x, int y, int width, int height, float sliderPosProportional, |
|
||||||
float rotaryStartAngle, float rotaryEndAngle, Slider &slider ) { |
|
||||||
if ( imageKnob.isNull() ) { |
|
||||||
LookAndFeel_V3::drawRotarySlider(g, x, y, width, height, sliderPosProportional, rotaryStartAngle, rotaryEndAngle, slider); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
const double fractRotation = (slider.getValue() - slider.getMinimum()) / (slider.getMaximum() - slider.getMinimum()); //value between 0 and 1 for current amount of rotation
|
|
||||||
const int nFrames = imageKnob.getHeight()/imageKnob.getWidth(); // number of frames for vertical film strip
|
|
||||||
const int frameIdx = (int)ceil(fractRotation * ((double)nFrames-1.0) ); // current index from 0 --> nFrames-1
|
|
||||||
|
|
||||||
const float radius = jmin (width / 2.0f, height / 2.0f) ; |
|
||||||
const float centreX = x + width * 0.5f; |
|
||||||
const float centreY = y + height * 0.5f; |
|
||||||
const float rx = centreX - radius - 1.0f; |
|
||||||
const float ry = centreY - radius - 1.0f; |
|
||||||
|
|
||||||
g.drawImage(imageKnob, (int)rx, (int)ry, 2*(int)radius, 2*(int)radius, 0, frameIdx*imageKnob.getWidth(), imageKnob.getWidth(), imageKnob.getWidth()); |
|
||||||
}; |
|
||||||
|
|
||||||
void DXLookNFeel::drawToggleButton(Graphics& g, ToggleButton& button, bool isMouseOverButton, bool isButtonDown) { |
|
||||||
if ( imageSwitch.isNull() ) { |
|
||||||
LookAndFeel_V3::drawToggleButton(g, button, isMouseOverButton, isButtonDown); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
g.drawImage(imageSwitch, 0, 0, 48, 26, 0, button.getToggleState() ? 0 : 26, 48, 26); |
|
||||||
} |
|
||||||
|
|
||||||
void DXLookNFeel::drawButtonBackground(Graphics &g, Button &button, const Colour& backgroundColour, bool isMouseOverButton, bool isButtonDown) { |
|
||||||
if ( imageButton.isNull() ) { |
|
||||||
LookAndFeel_V3::drawButtonBackground(g, button, backgroundColour, isMouseOverButton, isButtonDown); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
int w = button.getWidth(); |
|
||||||
|
|
||||||
// dx, dy, dw, dl, sx, sy, sw, sl
|
|
||||||
g.drawImage(imageButton, 0, 0, 3, 30, 0, isButtonDown ? 30 : 0, 3, 30); |
|
||||||
g.drawImage(imageButton, 3, 0, w-6, 30, 3, isButtonDown ? 30 : 0, 44, 30); |
|
||||||
g.drawImage(imageButton, w-3, 0, 3, 30, 47, isButtonDown ? 30 : 0, 47, 30); |
|
||||||
} |
|
||||||
|
|
||||||
void DXLookNFeel::drawLinearSliderBackground (Graphics&, int x, int y, int width, int height, |
|
||||||
float sliderPos, float minSliderPos, float maxSliderPos, |
|
||||||
const Slider::SliderStyle st, Slider& s) { |
|
||||||
// NOP
|
|
||||||
} |
|
||||||
|
|
||||||
void DXLookNFeel::drawLinearSliderThumb (Graphics& g, int x, int y, int width, int height, |
|
||||||
float sliderPos, float minSliderPos, float maxSliderPos, |
|
||||||
const Slider::SliderStyle st, Slider& s) { |
|
||||||
if ( imageSlider.isNull() ) { |
|
||||||
LookAndFeel_V3::drawLinearSliderThumb(g, x, y, width, height, sliderPos, minSliderPos, maxSliderPos, st, s); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
int p = sliderPos - minSliderPos; |
|
||||||
p -= 6; |
|
||||||
g.drawImage(imageSlider, p, 0, 26, 26, 0, 0, 26, 26); |
|
||||||
} |
|
||||||
|
|
||||||
Font DXLookNFeel::getTextButtonFont(TextButton& button, int buttonHeight) { |
|
||||||
return Font(defaultFontBold); |
|
||||||
} |
|
||||||
|
|
||||||
void DXLookNFeel::positionComboBoxText(ComboBox& box, Label& label) { |
|
||||||
ComboBox *src = &box; |
|
||||||
|
|
||||||
// I'm not proud of this one, but really... it must be another way to do this....
|
|
||||||
ComboBoxImage* img = dynamic_cast<ComboBoxImage*>(src); |
|
||||||
if( img != 0 ) { |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
LookAndFeel_V3::positionComboBoxText(box, label); |
|
||||||
} |
|
||||||
|
|
||||||
CriticalSection DXLookNFeel::lock; |
|
||||||
DXLookNFeel * DXLookNFeel::ins = NULL; |
|
||||||
Colour DXLookNFeel::fillColour = Colour(77,159,151); |
|
||||||
Colour DXLookNFeel::lightBackground = Colour(78,72,63); |
|
||||||
Colour DXLookNFeel::background = Colour(60,50,47); |
|
||||||
Colour DXLookNFeel::roundBackground = Colour(58,52,48); |
|
||||||
|
|
||||||
DXLookNFeel *DXLookNFeel::getLookAndFeel() { |
|
||||||
const ScopedLock locker(lock); |
|
||||||
if ( ins != NULL ) |
|
||||||
return ins; |
|
||||||
ins = new DXLookNFeel(); |
|
||||||
return ins; |
|
||||||
} |
|
@ -1,63 +0,0 @@ |
|||||||
/**
|
|
||||||
* |
|
||||||
* Copyright (c) 2013-2016 Pascal Gauthier. |
|
||||||
* |
|
||||||
* This program is free software; you can redistribute it and/or modify |
|
||||||
* it under the terms of the GNU General Public License as published by |
|
||||||
* the Free Software Foundation; either version 3 of the License, or |
|
||||||
* (at your option) any later version. |
|
||||||
* |
|
||||||
* This program is distributed in the hope that it will be useful, |
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
* GNU General Public License for more details. |
|
||||||
* |
|
||||||
* You should have received a copy of the GNU General Public License |
|
||||||
* along with this program; if not, write to the Free Software Foundation, |
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
||||||
* |
|
||||||
*/ |
|
||||||
|
|
||||||
#ifndef DXLOOKNFEEL_H_INCLUDED |
|
||||||
#define DXLOOKNFEEL_H_INCLUDED |
|
||||||
|
|
||||||
#include "../JuceLibraryCode/JuceHeader.h" |
|
||||||
|
|
||||||
class DXLookNFeel : public LookAndFeel_V3 { |
|
||||||
static CriticalSection lock; |
|
||||||
static DXLookNFeel *ins; |
|
||||||
DXLookNFeel(); |
|
||||||
|
|
||||||
HashMap<String, int> colourMap; |
|
||||||
|
|
||||||
public: |
|
||||||
Typeface::Ptr defaultFont; |
|
||||||
Typeface::Ptr defaultFontBold; |
|
||||||
|
|
||||||
Image imageKnob, imageSwitch, imageButton, imageSlider, imageScaling, imageLight, imageLFO; |
|
||||||
Image imageSwitchOperator; |
|
||||||
Image imageOperator, imageGlobal; |
|
||||||
|
|
||||||
/* overriden methods */ |
|
||||||
virtual void drawRotarySlider(Graphics &g, int x, int y, int width, int height, float sliderPosProportional, float rotaryStartAngle, float rotaryEndAngle, Slider &slider ) override; |
|
||||||
virtual void drawToggleButton(Graphics& g, ToggleButton& button, bool isMouseOverButton, bool isButtonDown) override; |
|
||||||
virtual void drawLinearSliderBackground (Graphics&, int x, int y, int width, int height, |
|
||||||
float sliderPos, float minSliderPos, float maxSliderPos, |
|
||||||
const Slider::SliderStyle, Slider&) override; |
|
||||||
virtual void drawLinearSliderThumb (Graphics&, int x, int y, int width, int height, |
|
||||||
float sliderPos, float minSliderPos, float maxSliderPos, |
|
||||||
const Slider::SliderStyle, Slider&) override; |
|
||||||
virtual void drawButtonBackground (Graphics&, Button&, const Colour& backgroundColour, |
|
||||||
bool isMouseOverButton, bool isButtonDown) override; |
|
||||||
virtual Font getTextButtonFont(TextButton&, int buttonHeight) override; |
|
||||||
virtual Typeface::Ptr getTypefaceForFont(const Font &) override; |
|
||||||
virtual void positionComboBoxText (ComboBox& box, Label& label) override; |
|
||||||
|
|
||||||
static DXLookNFeel *getLookAndFeel(); |
|
||||||
static Colour fillColour; |
|
||||||
static Colour lightBackground; |
|
||||||
static Colour background; |
|
||||||
static Colour roundBackground; |
|
||||||
}; |
|
||||||
|
|
||||||
#endif // DXLOOKNFEEL_H_INCLUDED
|
|
@ -1,788 +0,0 @@ |
|||||||
/*
|
|
||||||
============================================================================== |
|
||||||
|
|
||||||
This is an automatically generated GUI class created by the Introjucer! |
|
||||||
|
|
||||||
Be careful when adding custom code to these files, as only the code within |
|
||||||
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded |
|
||||||
and re-saved. |
|
||||||
|
|
||||||
Created with Introjucer version: 3.2.0 |
|
||||||
|
|
||||||
------------------------------------------------------------------------------ |
|
||||||
|
|
||||||
The Introjucer is part of the JUCE library - "Jules' Utility Class Extensions" |
|
||||||
Copyright (c) 2015 - ROLI Ltd. |
|
||||||
|
|
||||||
============================================================================== |
|
||||||
*/ |
|
||||||
|
|
||||||
//[Headers] You can add your own extra header files here...
|
|
||||||
#include "PluginEditor.h" |
|
||||||
#include "DXLookNFeel.h" |
|
||||||
//[/Headers]
|
|
||||||
|
|
||||||
#include "GlobalEditor.h" |
|
||||||
|
|
||||||
|
|
||||||
//[MiscUserDefs] You can add your own user definitions and misc code here...
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ugly but usefull midi monitor to know if you are really sending/receiving something from the DX7 |
|
||||||
* If the midi is not configured this component wont show up |
|
||||||
*/ |
|
||||||
class MidiMonitor : public Component { |
|
||||||
SysexComm *midi; |
|
||||||
Image light; |
|
||||||
|
|
||||||
public: |
|
||||||
MidiMonitor(SysexComm *sysexComm) { |
|
||||||
midi = sysexComm; |
|
||||||
light = DXLookNFeel::getLookAndFeel()->imageLight; |
|
||||||
} |
|
||||||
|
|
||||||
void paint(Graphics &g) { |
|
||||||
if ( ! (midi->isInputActive() || midi->isOutputActive() ) ) |
|
||||||
return; |
|
||||||
g.setColour(Colours::white); |
|
||||||
|
|
||||||
if ( midi->isInputActive() ) { |
|
||||||
g.drawSingleLineText("DX7 IN", 17,14); |
|
||||||
g.drawImage(light, 0, 3, 14, 14, 0, midi->inActivity ? 14 : 0, 14, 14); |
|
||||||
midi->inActivity = false; |
|
||||||
} |
|
||||||
|
|
||||||
if ( midi->isOutputActive() ) { |
|
||||||
g.drawSingleLineText("DX7 OUT", 17, 28); |
|
||||||
g.drawImage(light, 0, 17, 14, 14, 0, midi->outActivity ? 14 : 0, 14, 14); |
|
||||||
midi->outActivity = false; |
|
||||||
} |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
class AboutBox : public DialogWindow { |
|
||||||
public: |
|
||||||
Image about_png; |
|
||||||
|
|
||||||
AboutBox(Component *parent) : DialogWindow("About", Colour(0xFF000000), true) { |
|
||||||
setUsingNativeTitleBar(false); |
|
||||||
setAlwaysOnTop(true); |
|
||||||
about_png = ImageCache::getFromMemory(BinaryData::about_png, BinaryData::about_pngSize); |
|
||||||
setSize(about_png.getWidth(), about_png.getHeight()); |
|
||||||
centreAroundComponent (parent, getWidth(), getHeight()); |
|
||||||
} |
|
||||||
|
|
||||||
void closeButtonPressed() { |
|
||||||
setVisible (false); |
|
||||||
} |
|
||||||
|
|
||||||
void paint(Graphics &g) { |
|
||||||
g.drawImage (about_png, 0, 0, about_png.getWidth(), about_png.getHeight(), |
|
||||||
0, 0, about_png.getWidth(), about_png.getHeight()); |
|
||||||
g.setColour(Colour(0xFF000000)); |
|
||||||
String ver("Version " DEXED_VERSION " ; build date " __DATE__ ); |
|
||||||
g.drawSingleLineText(ver, 18, 130); |
|
||||||
} |
|
||||||
}; |
|
||||||
//[/MiscUserDefs]
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
GlobalEditor::GlobalEditor () |
|
||||||
{ |
|
||||||
//[Constructor_pre] You can add your own custom stuff here..
|
|
||||||
//[/Constructor_pre]
|
|
||||||
|
|
||||||
addAndMakeVisible (lfoSpeed = new Slider ("lfoSpeed")); |
|
||||||
lfoSpeed->setRange (0, 99, 1); |
|
||||||
lfoSpeed->setSliderStyle (Slider::RotaryVerticalDrag); |
|
||||||
lfoSpeed->setTextBoxStyle (Slider::NoTextBox, false, 80, 20); |
|
||||||
lfoSpeed->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (lfoAmDepth = new Slider ("lfoAmDepth")); |
|
||||||
lfoAmDepth->setRange (0, 99, 1); |
|
||||||
lfoAmDepth->setSliderStyle (Slider::RotaryVerticalDrag); |
|
||||||
lfoAmDepth->setTextBoxStyle (Slider::NoTextBox, false, 80, 20); |
|
||||||
lfoAmDepth->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (lfoPitchDepth = new Slider ("lfoPitchDepth")); |
|
||||||
lfoPitchDepth->setRange (0, 99, 1); |
|
||||||
lfoPitchDepth->setSliderStyle (Slider::RotaryVerticalDrag); |
|
||||||
lfoPitchDepth->setTextBoxStyle (Slider::NoTextBox, false, 80, 20); |
|
||||||
lfoPitchDepth->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (lfoDelay = new Slider ("lfoDelay")); |
|
||||||
lfoDelay->setRange (0, 99, 1); |
|
||||||
lfoDelay->setSliderStyle (Slider::RotaryVerticalDrag); |
|
||||||
lfoDelay->setTextBoxStyle (Slider::NoTextBox, false, 80, 20); |
|
||||||
lfoDelay->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (cutoff = new Slider ("cutoff")); |
|
||||||
cutoff->setRange (0, 1, 0); |
|
||||||
cutoff->setSliderStyle (Slider::RotaryVerticalDrag); |
|
||||||
cutoff->setTextBoxStyle (Slider::NoTextBox, true, 80, 20); |
|
||||||
cutoff->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (reso = new Slider ("reso")); |
|
||||||
reso->setRange (0, 1, 0); |
|
||||||
reso->setSliderStyle (Slider::RotaryVerticalDrag); |
|
||||||
reso->setTextBoxStyle (Slider::NoTextBox, true, 80, 20); |
|
||||||
reso->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (pitchRate2 = new Slider ("pitchRate2")); |
|
||||||
pitchRate2->setRange (0, 99, 1); |
|
||||||
pitchRate2->setSliderStyle (Slider::RotaryVerticalDrag); |
|
||||||
pitchRate2->setTextBoxStyle (Slider::NoTextBox, false, 80, 20); |
|
||||||
pitchRate2->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (pitchRate3 = new Slider ("pitchRate3")); |
|
||||||
pitchRate3->setRange (0, 99, 1); |
|
||||||
pitchRate3->setSliderStyle (Slider::RotaryVerticalDrag); |
|
||||||
pitchRate3->setTextBoxStyle (Slider::NoTextBox, false, 80, 20); |
|
||||||
pitchRate3->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (pitchRate4 = new Slider ("pitchRate4")); |
|
||||||
pitchRate4->setRange (0, 99, 1); |
|
||||||
pitchRate4->setSliderStyle (Slider::RotaryVerticalDrag); |
|
||||||
pitchRate4->setTextBoxStyle (Slider::NoTextBox, false, 80, 20); |
|
||||||
pitchRate4->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (pitchRate1 = new Slider ("pitchRate1")); |
|
||||||
pitchRate1->setRange (0, 99, 1); |
|
||||||
pitchRate1->setSliderStyle (Slider::RotaryVerticalDrag); |
|
||||||
pitchRate1->setTextBoxStyle (Slider::NoTextBox, false, 80, 20); |
|
||||||
pitchRate1->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (pitchLevel2 = new Slider ("pitchLevel2")); |
|
||||||
pitchLevel2->setRange (0, 99, 1); |
|
||||||
pitchLevel2->setSliderStyle (Slider::RotaryVerticalDrag); |
|
||||||
pitchLevel2->setTextBoxStyle (Slider::NoTextBox, false, 80, 20); |
|
||||||
pitchLevel2->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (pitchLevel3 = new Slider ("pitchLevel3")); |
|
||||||
pitchLevel3->setRange (0, 99, 1); |
|
||||||
pitchLevel3->setSliderStyle (Slider::RotaryVerticalDrag); |
|
||||||
pitchLevel3->setTextBoxStyle (Slider::NoTextBox, false, 80, 20); |
|
||||||
pitchLevel3->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (pitchLevel4 = new Slider ("pitchLevel4")); |
|
||||||
pitchLevel4->setRange (0, 99, 1); |
|
||||||
pitchLevel4->setSliderStyle (Slider::RotaryVerticalDrag); |
|
||||||
pitchLevel4->setTextBoxStyle (Slider::NoTextBox, false, 80, 20); |
|
||||||
pitchLevel4->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (pitchLevel1 = new Slider ("pitchLevel1")); |
|
||||||
pitchLevel1->setRange (0, 99, 1); |
|
||||||
pitchLevel1->setSliderStyle (Slider::RotaryVerticalDrag); |
|
||||||
pitchLevel1->setTextBoxStyle (Slider::NoTextBox, false, 80, 20); |
|
||||||
pitchLevel1->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (transpose = new Slider ("transpose")); |
|
||||||
transpose->setRange (0, 48, 1); |
|
||||||
transpose->setSliderStyle (Slider::RotaryVerticalDrag); |
|
||||||
transpose->setTextBoxStyle (Slider::NoTextBox, true, 80, 20); |
|
||||||
transpose->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (oscSync = new ToggleButton ("oscSync")); |
|
||||||
oscSync->setButtonText (String::empty); |
|
||||||
oscSync->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (pitchModSens = new Slider ("pitchModSens")); |
|
||||||
pitchModSens->setRange (0, 7, 1); |
|
||||||
pitchModSens->setSliderStyle (Slider::RotaryVerticalDrag); |
|
||||||
pitchModSens->setTextBoxStyle (Slider::NoTextBox, false, 80, 20); |
|
||||||
pitchModSens->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (lfoSync = new ToggleButton ("lfoSync")); |
|
||||||
lfoSync->setButtonText (String::empty); |
|
||||||
lfoSync->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (pitchEnvDisplay = new PitchEnvDisplay()); |
|
||||||
pitchEnvDisplay->setName ("pitchEnvDisplay"); |
|
||||||
|
|
||||||
addAndMakeVisible (algoDisplay = new AlgoDisplay()); |
|
||||||
algoDisplay->setName ("algoDisplay"); |
|
||||||
|
|
||||||
addAndMakeVisible (feedback = new Slider ("feedback")); |
|
||||||
feedback->setRange (0, 7, 1); |
|
||||||
feedback->setSliderStyle (Slider::RotaryVerticalDrag); |
|
||||||
feedback->setTextBoxStyle (Slider::NoTextBox, false, 80, 20); |
|
||||||
feedback->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (algo = new Slider ("algo")); |
|
||||||
algo->setRange (1, 32, 1); |
|
||||||
algo->setSliderStyle (Slider::RotaryVerticalDrag); |
|
||||||
algo->setTextBoxStyle (Slider::NoTextBox, true, 80, 20); |
|
||||||
algo->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (lcdDisplay = new LcdDisplay()); |
|
||||||
lcdDisplay->setName ("lcdDisplay"); |
|
||||||
|
|
||||||
addAndMakeVisible (output = new Slider ("output")); |
|
||||||
output->setRange (0, 1, 0); |
|
||||||
output->setSliderStyle (Slider::RotaryVerticalDrag); |
|
||||||
output->setTextBoxStyle (Slider::NoTextBox, true, 80, 20); |
|
||||||
output->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (vuOutput = new VuMeter()); |
|
||||||
vuOutput->setName ("vuOutput"); |
|
||||||
|
|
||||||
addAndMakeVisible (initButton = new TextButton ("initButton")); |
|
||||||
initButton->setButtonText (TRANS("INIT")); |
|
||||||
initButton->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (parmButton = new TextButton ("parmButton")); |
|
||||||
parmButton->setButtonText (TRANS("PARM")); |
|
||||||
parmButton->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (cartButton = new TextButton ("cartButton")); |
|
||||||
cartButton->setButtonText (TRANS("CART")); |
|
||||||
cartButton->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (storeButton = new TextButton ("storeButton")); |
|
||||||
storeButton->setButtonText (TRANS("STORE")); |
|
||||||
storeButton->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (monoMode = new ToggleButton ("monoMode")); |
|
||||||
monoMode->setButtonText (String::empty); |
|
||||||
monoMode->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (lfoType = new ComboBoxImage()); |
|
||||||
lfoType->setName ("lfoType"); |
|
||||||
|
|
||||||
addAndMakeVisible (programSelector = new ProgramSelector()); |
|
||||||
programSelector->setName ("programSelector"); |
|
||||||
|
|
||||||
addAndMakeVisible (aboutButton = new ImageButton ("aboutButton")); |
|
||||||
aboutButton->setButtonText (String::empty); |
|
||||||
aboutButton->addListener (this); |
|
||||||
|
|
||||||
aboutButton->setImages (false, true, false, |
|
||||||
Image(), 1.000f, Colour (0x00000000), |
|
||||||
Image(), 1.000f, Colour (0x00000000), |
|
||||||
Image(), 1.000f, Colour (0x00000000)); |
|
||||||
addAndMakeVisible (tune = new Slider ("tune")); |
|
||||||
tune->setRange (0, 1, 0); |
|
||||||
tune->setSliderStyle (Slider::RotaryVerticalDrag); |
|
||||||
tune->setTextBoxStyle (Slider::NoTextBox, true, 80, 20); |
|
||||||
tune->addListener (this); |
|
||||||
|
|
||||||
|
|
||||||
//[UserPreSize]
|
|
||||||
//[/UserPreSize]
|
|
||||||
|
|
||||||
setSize (864, 144); |
|
||||||
|
|
||||||
|
|
||||||
//[Constructor] You can add your own custom stuff here..
|
|
||||||
lfoType->addItem("TRIANGLE", 1); |
|
||||||
lfoType->addItem("SAW DOWN", 2); |
|
||||||
lfoType->addItem("SAW UP", 3); |
|
||||||
lfoType->addItem("SQUARE", 4); |
|
||||||
lfoType->addItem("SINE", 5); |
|
||||||
lfoType->addItem("S&HOLD", 6); |
|
||||||
lfoType->setImage(DXLookNFeel::getLookAndFeel()->imageLFO); |
|
||||||
|
|
||||||
programs = programSelector; |
|
||||||
|
|
||||||
background = DXLookNFeel::getLookAndFeel()->imageGlobal; |
|
||||||
imageLight = DXLookNFeel::getLookAndFeel()->imageLight; |
|
||||||
//[/Constructor]
|
|
||||||
} |
|
||||||
|
|
||||||
GlobalEditor::~GlobalEditor() |
|
||||||
{ |
|
||||||
//[Destructor_pre]. You can add your own custom destruction code here..
|
|
||||||
//[/Destructor_pre]
|
|
||||||
|
|
||||||
lfoSpeed = nullptr; |
|
||||||
lfoAmDepth = nullptr; |
|
||||||
lfoPitchDepth = nullptr; |
|
||||||
lfoDelay = nullptr; |
|
||||||
cutoff = nullptr; |
|
||||||
reso = nullptr; |
|
||||||
pitchRate2 = nullptr; |
|
||||||
pitchRate3 = nullptr; |
|
||||||
pitchRate4 = nullptr; |
|
||||||
pitchRate1 = nullptr; |
|
||||||
pitchLevel2 = nullptr; |
|
||||||
pitchLevel3 = nullptr; |
|
||||||
pitchLevel4 = nullptr; |
|
||||||
pitchLevel1 = nullptr; |
|
||||||
transpose = nullptr; |
|
||||||
oscSync = nullptr; |
|
||||||
pitchModSens = nullptr; |
|
||||||
lfoSync = nullptr; |
|
||||||
pitchEnvDisplay = nullptr; |
|
||||||
algoDisplay = nullptr; |
|
||||||
feedback = nullptr; |
|
||||||
algo = nullptr; |
|
||||||
lcdDisplay = nullptr; |
|
||||||
output = nullptr; |
|
||||||
vuOutput = nullptr; |
|
||||||
initButton = nullptr; |
|
||||||
parmButton = nullptr; |
|
||||||
cartButton = nullptr; |
|
||||||
storeButton = nullptr; |
|
||||||
monoMode = nullptr; |
|
||||||
lfoType = nullptr; |
|
||||||
programSelector = nullptr; |
|
||||||
aboutButton = nullptr; |
|
||||||
tune = nullptr; |
|
||||||
|
|
||||||
|
|
||||||
//[Destructor]. You can add your own custom destruction code here..
|
|
||||||
//[/Destructor]
|
|
||||||
} |
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
void GlobalEditor::paint (Graphics& g) |
|
||||||
{ |
|
||||||
//[UserPrePaint] Add your own custom painting code here..
|
|
||||||
g.drawImage(background, 0, 0, 864, 144, 0, 0, 864, 144); |
|
||||||
//[/UserPrePaint]
|
|
||||||
|
|
||||||
//[UserPaint] Add your own custom painting code here..
|
|
||||||
g.drawImage(imageLight, 300, 70, 14, 14, 0, monoMode->getToggleState() ? 14 : 0, 14, 14); |
|
||||||
g.drawImage(imageLight, 619, 102, 14, 14, 0, lfoSync->getToggleState() ? 14 : 0, 14, 14); |
|
||||||
g.drawImage(imageLight, 705, 102, 14, 14, 0, oscSync->getToggleState() ? 14 : 0, 14, 14); |
|
||||||
//[/UserPaint]
|
|
||||||
} |
|
||||||
|
|
||||||
void GlobalEditor::resized() |
|
||||||
{ |
|
||||||
//[UserPreResize] Add your own custom resize code here..
|
|
||||||
//[/UserPreResize]
|
|
||||||
|
|
||||||
lfoSpeed->setBounds (564, 50, 34, 34); |
|
||||||
lfoAmDepth->setBounds (686, 50, 34, 34); |
|
||||||
lfoPitchDepth->setBounds (646, 50, 34, 34); |
|
||||||
lfoDelay->setBounds (603, 50, 34, 34); |
|
||||||
cutoff->setBounds (234, 9, 34, 34); |
|
||||||
reso->setBounds (278, 9, 34, 34); |
|
||||||
pitchRate2->setBounds (767, 96, 34, 34); |
|
||||||
pitchRate3->setBounds (795, 96, 35, 34); |
|
||||||
pitchRate4->setBounds (823, 96, 34, 34); |
|
||||||
pitchRate1->setBounds (739, 96, 34, 34); |
|
||||||
pitchLevel2->setBounds (767, 57, 34, 34); |
|
||||||
pitchLevel3->setBounds (795, 56, 34, 34); |
|
||||||
pitchLevel4->setBounds (823, 56, 34, 34); |
|
||||||
pitchLevel1->setBounds (739, 57, 34, 34); |
|
||||||
transpose->setBounds (202, 60, 34, 34); |
|
||||||
oscSync->setBounds (650, 96, 48, 26); |
|
||||||
pitchModSens->setBounds (666, 5, 34, 34); |
|
||||||
lfoSync->setBounds (565, 96, 48, 26); |
|
||||||
pitchEnvDisplay->setBounds (751, 10, 93, 30); |
|
||||||
algoDisplay->setBounds (335, 30, 152, 91); |
|
||||||
feedback->setBounds (501, 81, 34, 34); |
|
||||||
algo->setBounds (501, 22, 34, 34); |
|
||||||
lcdDisplay->setBounds (6, 87, 140, 13); |
|
||||||
output->setBounds (157, 60, 34, 34); |
|
||||||
vuOutput->setBounds (6, 103, 140, 8); |
|
||||||
initButton->setBounds (100, 111, 50, 30); |
|
||||||
parmButton->setBounds (52, 111, 50, 30); |
|
||||||
cartButton->setBounds (3, 111, 50, 30); |
|
||||||
storeButton->setBounds (270, 109, 50, 30); |
|
||||||
monoMode->setBounds (249, 65, 48, 26); |
|
||||||
lfoType->setBounds (583, 8, 36, 26); |
|
||||||
programSelector->setBounds (153, 115, 112, 18); |
|
||||||
aboutButton->setBounds (8, 11, 135, 46); |
|
||||||
tune->setBounds (190, 9, 34, 34); |
|
||||||
//[UserResized] Add your own custom resize handling here..
|
|
||||||
//[/UserResized]
|
|
||||||
} |
|
||||||
|
|
||||||
void GlobalEditor::sliderValueChanged (Slider* sliderThatWasMoved) |
|
||||||
{ |
|
||||||
//[UsersliderValueChanged_Pre]
|
|
||||||
//[/UsersliderValueChanged_Pre]
|
|
||||||
|
|
||||||
if (sliderThatWasMoved == lfoSpeed) |
|
||||||
{ |
|
||||||
//[UserSliderCode_lfoSpeed] -- add your slider handling code here..
|
|
||||||
//[/UserSliderCode_lfoSpeed]
|
|
||||||
} |
|
||||||
else if (sliderThatWasMoved == lfoAmDepth) |
|
||||||
{ |
|
||||||
//[UserSliderCode_lfoAmDepth] -- add your slider handling code here..
|
|
||||||
//[/UserSliderCode_lfoAmDepth]
|
|
||||||
} |
|
||||||
else if (sliderThatWasMoved == lfoPitchDepth) |
|
||||||
{ |
|
||||||
//[UserSliderCode_lfoPitchDepth] -- add your slider handling code here..
|
|
||||||
//[/UserSliderCode_lfoPitchDepth]
|
|
||||||
} |
|
||||||
else if (sliderThatWasMoved == lfoDelay) |
|
||||||
{ |
|
||||||
//[UserSliderCode_lfoDelay] -- add your slider handling code here..
|
|
||||||
//[/UserSliderCode_lfoDelay]
|
|
||||||
} |
|
||||||
else if (sliderThatWasMoved == cutoff) |
|
||||||
{ |
|
||||||
//[UserSliderCode_cutoff] -- add your slider handling code here..
|
|
||||||
//[/UserSliderCode_cutoff]
|
|
||||||
} |
|
||||||
else if (sliderThatWasMoved == reso) |
|
||||||
{ |
|
||||||
//[UserSliderCode_reso] -- add your slider handling code here..
|
|
||||||
//[/UserSliderCode_reso]
|
|
||||||
} |
|
||||||
else if (sliderThatWasMoved == pitchRate2) |
|
||||||
{ |
|
||||||
//[UserSliderCode_pitchRate2] -- add your slider handling code here..
|
|
||||||
pitchEnvDisplay->repaint(); |
|
||||||
//[/UserSliderCode_pitchRate2]
|
|
||||||
} |
|
||||||
else if (sliderThatWasMoved == pitchRate3) |
|
||||||
{ |
|
||||||
//[UserSliderCode_pitchRate3] -- add your slider handling code here..
|
|
||||||
pitchEnvDisplay->repaint(); |
|
||||||
//[/UserSliderCode_pitchRate3]
|
|
||||||
} |
|
||||||
else if (sliderThatWasMoved == pitchRate4) |
|
||||||
{ |
|
||||||
//[UserSliderCode_pitchRate4] -- add your slider handling code here..
|
|
||||||
pitchEnvDisplay->repaint(); |
|
||||||
//[/UserSliderCode_pitchRate4]
|
|
||||||
} |
|
||||||
else if (sliderThatWasMoved == pitchRate1) |
|
||||||
{ |
|
||||||
//[UserSliderCode_pitchRate1] -- add your slider handling code here..
|
|
||||||
pitchEnvDisplay->repaint(); |
|
||||||
//[/UserSliderCode_pitchRate1]
|
|
||||||
} |
|
||||||
else if (sliderThatWasMoved == pitchLevel2) |
|
||||||
{ |
|
||||||
//[UserSliderCode_pitchLevel2] -- add your slider handling code here..
|
|
||||||
pitchEnvDisplay->repaint(); |
|
||||||
//[/UserSliderCode_pitchLevel2]
|
|
||||||
} |
|
||||||
else if (sliderThatWasMoved == pitchLevel3) |
|
||||||
{ |
|
||||||
//[UserSliderCode_pitchLevel3] -- add your slider handling code here..
|
|
||||||
pitchEnvDisplay->repaint(); |
|
||||||
//[/UserSliderCode_pitchLevel3]
|
|
||||||
} |
|
||||||
else if (sliderThatWasMoved == pitchLevel4) |
|
||||||
{ |
|
||||||
//[UserSliderCode_pitchLevel4] -- add your slider handling code here..
|
|
||||||
pitchEnvDisplay->repaint(); |
|
||||||
//[/UserSliderCode_pitchLevel4]
|
|
||||||
} |
|
||||||
else if (sliderThatWasMoved == pitchLevel1) |
|
||||||
{ |
|
||||||
//[UserSliderCode_pitchLevel1] -- add your slider handling code here..
|
|
||||||
pitchEnvDisplay->repaint(); |
|
||||||
//[/UserSliderCode_pitchLevel1]
|
|
||||||
} |
|
||||||
else if (sliderThatWasMoved == transpose) |
|
||||||
{ |
|
||||||
//[UserSliderCode_transpose] -- add your slider handling code here..
|
|
||||||
//[/UserSliderCode_transpose]
|
|
||||||
} |
|
||||||
else if (sliderThatWasMoved == pitchModSens) |
|
||||||
{ |
|
||||||
//[UserSliderCode_pitchModSens] -- add your slider handling code here..
|
|
||||||
//[/UserSliderCode_pitchModSens]
|
|
||||||
} |
|
||||||
else if (sliderThatWasMoved == feedback) |
|
||||||
{ |
|
||||||
//[UserSliderCode_feedback] -- add your slider handling code here..
|
|
||||||
//[/UserSliderCode_feedback]
|
|
||||||
} |
|
||||||
else if (sliderThatWasMoved == algo) |
|
||||||
{ |
|
||||||
//[UserSliderCode_algo] -- add your slider handling code here..
|
|
||||||
//[/UserSliderCode_algo]
|
|
||||||
} |
|
||||||
else if (sliderThatWasMoved == output) |
|
||||||
{ |
|
||||||
//[UserSliderCode_output] -- add your slider handling code here..
|
|
||||||
//[/UserSliderCode_output]
|
|
||||||
} |
|
||||||
else if (sliderThatWasMoved == tune) |
|
||||||
{ |
|
||||||
//[UserSliderCode_tune] -- add your slider handling code here..
|
|
||||||
//[/UserSliderCode_tune]
|
|
||||||
} |
|
||||||
|
|
||||||
//[UsersliderValueChanged_Post]
|
|
||||||
//[/UsersliderValueChanged_Post]
|
|
||||||
} |
|
||||||
|
|
||||||
void GlobalEditor::buttonClicked (Button* buttonThatWasClicked) |
|
||||||
{ |
|
||||||
//[UserbuttonClicked_Pre]
|
|
||||||
//[/UserbuttonClicked_Pre]
|
|
||||||
|
|
||||||
if (buttonThatWasClicked == oscSync) |
|
||||||
{ |
|
||||||
//[UserButtonCode_oscSync] -- add your button handler code here..
|
|
||||||
repaint(); |
|
||||||
//[/UserButtonCode_oscSync]
|
|
||||||
} |
|
||||||
else if (buttonThatWasClicked == lfoSync) |
|
||||||
{ |
|
||||||
//[UserButtonCode_lfoSync] -- add your button handler code here..
|
|
||||||
repaint(); |
|
||||||
//[/UserButtonCode_lfoSync]
|
|
||||||
} |
|
||||||
else if (buttonThatWasClicked == initButton) |
|
||||||
{ |
|
||||||
//[UserButtonCode_initButton] -- add your button handler code here..
|
|
||||||
editor->initProgram(); |
|
||||||
//[/UserButtonCode_initButton]
|
|
||||||
} |
|
||||||
else if (buttonThatWasClicked == parmButton) |
|
||||||
{ |
|
||||||
//[UserButtonCode_parmButton] -- add your button handler code here..
|
|
||||||
editor->parmShow(); |
|
||||||
//[/UserButtonCode_parmButton]
|
|
||||||
} |
|
||||||
else if (buttonThatWasClicked == cartButton) |
|
||||||
{ |
|
||||||
//[UserButtonCode_cartButton] -- add your button handler code here..
|
|
||||||
editor->cartShow(); |
|
||||||
//[/UserButtonCode_cartButton]
|
|
||||||
} |
|
||||||
else if (buttonThatWasClicked == storeButton) |
|
||||||
{ |
|
||||||
//[UserButtonCode_storeButton] -- add your button handler code here..
|
|
||||||
editor->storeProgram(); |
|
||||||
//[/UserButtonCode_storeButton]
|
|
||||||
} |
|
||||||
else if (buttonThatWasClicked == monoMode) |
|
||||||
{ |
|
||||||
//[UserButtonCode_monoMode] -- add your button handler code here..
|
|
||||||
editor->processor->setMonoMode(monoMode->getToggleState()); |
|
||||||
repaint(); |
|
||||||
//[/UserButtonCode_monoMode]
|
|
||||||
} |
|
||||||
else if (buttonThatWasClicked == aboutButton) |
|
||||||
{ |
|
||||||
//[UserButtonCode_aboutButton] -- add your button handler code here..
|
|
||||||
AboutBox about(this->getParentComponent()); |
|
||||||
about.runModalLoop(); |
|
||||||
//[/UserButtonCode_aboutButton]
|
|
||||||
} |
|
||||||
|
|
||||||
//[UserbuttonClicked_Post]
|
|
||||||
//[/UserbuttonClicked_Post]
|
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//[MiscUserCode] You can add your own definitions of your custom methods or any other code here...
|
|
||||||
|
|
||||||
void GlobalEditor::bind(DexedAudioProcessorEditor *edit) { |
|
||||||
processor = edit->processor; |
|
||||||
processor->algo->bind(algo); |
|
||||||
processor->lfoRate->bind(lfoSpeed); |
|
||||||
processor->lfoDelay->bind(lfoDelay); |
|
||||||
processor->lfoWaveform->bind(lfoType); |
|
||||||
processor->lfoAmpDepth->bind(lfoAmDepth); |
|
||||||
processor->lfoPitchDepth->bind(lfoPitchDepth); |
|
||||||
processor->lfoSync->bind(lfoSync); |
|
||||||
processor->oscSync->bind(oscSync); |
|
||||||
processor->transpose->bind(transpose); |
|
||||||
processor->feedback->bind(feedback); |
|
||||||
processor->pitchModSens->bind(pitchModSens); |
|
||||||
processor->pitchEgLevel[0]->bind(pitchLevel1); |
|
||||||
processor->pitchEgLevel[1]->bind(pitchLevel2); |
|
||||||
processor->pitchEgLevel[2]->bind(pitchLevel3); |
|
||||||
processor->pitchEgLevel[3]->bind(pitchLevel4); |
|
||||||
processor->pitchEgRate[0]->bind(pitchRate1); |
|
||||||
processor->pitchEgRate[1]->bind(pitchRate2); |
|
||||||
processor->pitchEgRate[2]->bind(pitchRate3); |
|
||||||
processor->pitchEgRate[3]->bind(pitchRate4); |
|
||||||
processor->fxCutoff->bind(cutoff); |
|
||||||
processor->fxReso->bind(reso); |
|
||||||
processor->output->bind(output); |
|
||||||
processor->tune->bind(tune); |
|
||||||
algoDisplay->algo = (char *) &(processor->data[134]); |
|
||||||
pitchEnvDisplay->pvalues = &(processor->data[126]); |
|
||||||
|
|
||||||
editor = edit; |
|
||||||
|
|
||||||
midiMonitor = new MidiMonitor(&(processor->sysexComm)); |
|
||||||
//addAndMakeVisible(midiMonitor);
|
|
||||||
//midiMonitor->setBounds(155, 21, 80, 45);
|
|
||||||
|
|
||||||
repaint(); |
|
||||||
} |
|
||||||
|
|
||||||
void GlobalEditor::setSystemMessage(String msg) { |
|
||||||
lcdDisplay->setSystemMsg(msg); |
|
||||||
} |
|
||||||
|
|
||||||
void GlobalEditor::setParamMessage(String msg) { |
|
||||||
lcdDisplay->paramMsg = msg; |
|
||||||
} |
|
||||||
|
|
||||||
void GlobalEditor::updateDisplay() { |
|
||||||
repaint(); |
|
||||||
} |
|
||||||
|
|
||||||
void GlobalEditor::updatePitchPos(int pos) { |
|
||||||
pitchEnvDisplay->vPos = pos; |
|
||||||
pitchEnvDisplay->repaint(); |
|
||||||
} |
|
||||||
|
|
||||||
void GlobalEditor::updateVu(float f) { |
|
||||||
vuOutput->v = f; |
|
||||||
vuOutput->repaint(); |
|
||||||
midiMonitor->repaint(); |
|
||||||
} |
|
||||||
|
|
||||||
void GlobalEditor::setMonoState(bool state) { |
|
||||||
monoMode->setToggleState(state ? Button::buttonDown : Button::buttonNormal, dontSendNotification); |
|
||||||
} |
|
||||||
//[/MiscUserCode]
|
|
||||||
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
#if 0 |
|
||||||
/* -- Introjucer information section --
|
|
||||||
|
|
||||||
This is where the Introjucer stores the metadata that describe this GUI layout, so |
|
||||||
make changes in here at your peril! |
|
||||||
|
|
||||||
BEGIN_JUCER_METADATA |
|
||||||
|
|
||||||
<JUCER_COMPONENT documentType="Component" className="GlobalEditor" componentName="" |
|
||||||
parentClasses="public Component" constructorParams="" variableInitialisers="" |
|
||||||
snapPixels="8" snapActive="0" snapShown="1" overlayOpacity="0.330" |
|
||||||
fixedSize="1" initialWidth="864" initialHeight="144"> |
|
||||||
<BACKGROUND backgroundColour="ffffff"/> |
|
||||||
<SLIDER name="lfoSpeed" id="b10eaf327ab3bff5" memberName="lfoSpeed" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="564 50 34 34" min="0" max="99" int="1" |
|
||||||
style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="1" |
|
||||||
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> |
|
||||||
<SLIDER name="lfoAmDepth" id="3e95a6206fa4a891" memberName="lfoAmDepth" |
|
||||||
virtualName="" explicitFocusOrder="0" pos="686 50 34 34" min="0" |
|
||||||
max="99" int="1" style="RotaryVerticalDrag" textBoxPos="NoTextBox" |
|
||||||
textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> |
|
||||||
<SLIDER name="lfoPitchDepth" id="6ead769ca786c813" memberName="lfoPitchDepth" |
|
||||||
virtualName="" explicitFocusOrder="0" pos="646 50 34 34" min="0" |
|
||||||
max="99" int="1" style="RotaryVerticalDrag" textBoxPos="NoTextBox" |
|
||||||
textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> |
|
||||||
<SLIDER name="lfoDelay" id="1fce68dc81619ef5" memberName="lfoDelay" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="603 50 34 34" min="0" max="99" int="1" |
|
||||||
style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="1" |
|
||||||
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> |
|
||||||
<SLIDER name="cutoff" id="40531f16bb0bd225" memberName="cutoff" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="234 9 34 34" min="0" max="1" int="0" |
|
||||||
style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="0" |
|
||||||
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> |
|
||||||
<SLIDER name="reso" id="c8c13464e81a8d83" memberName="reso" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="278 9 34 34" min="0" max="1" int="0" |
|
||||||
style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="0" |
|
||||||
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> |
|
||||||
<SLIDER name="pitchRate2" id="73f386b3c91d3de4" memberName="pitchRate2" |
|
||||||
virtualName="" explicitFocusOrder="0" pos="767 96 34 34" min="0" |
|
||||||
max="99" int="1" style="RotaryVerticalDrag" textBoxPos="NoTextBox" |
|
||||||
textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> |
|
||||||
<SLIDER name="pitchRate3" id="187c25b24413fccf" memberName="pitchRate3" |
|
||||||
virtualName="" explicitFocusOrder="0" pos="795 96 35 34" min="0" |
|
||||||
max="99" int="1" style="RotaryVerticalDrag" textBoxPos="NoTextBox" |
|
||||||
textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> |
|
||||||
<SLIDER name="pitchRate4" id="1aeb2a8fbbcbeaab" memberName="pitchRate4" |
|
||||||
virtualName="" explicitFocusOrder="0" pos="823 96 34 34" min="0" |
|
||||||
max="99" int="1" style="RotaryVerticalDrag" textBoxPos="NoTextBox" |
|
||||||
textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> |
|
||||||
<SLIDER name="pitchRate1" id="419d613b3fb9604e" memberName="pitchRate1" |
|
||||||
virtualName="" explicitFocusOrder="0" pos="739 96 34 34" min="0" |
|
||||||
max="99" int="1" style="RotaryVerticalDrag" textBoxPos="NoTextBox" |
|
||||||
textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> |
|
||||||
<SLIDER name="pitchLevel2" id="3a355ad2221887d9" memberName="pitchLevel2" |
|
||||||
virtualName="" explicitFocusOrder="0" pos="767 57 34 34" min="0" |
|
||||||
max="99" int="1" style="RotaryVerticalDrag" textBoxPos="NoTextBox" |
|
||||||
textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> |
|
||||||
<SLIDER name="pitchLevel3" id="5c5d782e8a7f3ad7" memberName="pitchLevel3" |
|
||||||
virtualName="" explicitFocusOrder="0" pos="795 56 34 34" min="0" |
|
||||||
max="99" int="1" style="RotaryVerticalDrag" textBoxPos="NoTextBox" |
|
||||||
textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> |
|
||||||
<SLIDER name="pitchLevel4" id="eb900b141fbad8ff" memberName="pitchLevel4" |
|
||||||
virtualName="" explicitFocusOrder="0" pos="823 56 34 34" min="0" |
|
||||||
max="99" int="1" style="RotaryVerticalDrag" textBoxPos="NoTextBox" |
|
||||||
textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> |
|
||||||
<SLIDER name="pitchLevel1" id="344cbe26ec9fa128" memberName="pitchLevel1" |
|
||||||
virtualName="" explicitFocusOrder="0" pos="739 57 34 34" min="0" |
|
||||||
max="99" int="1" style="RotaryVerticalDrag" textBoxPos="NoTextBox" |
|
||||||
textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> |
|
||||||
<SLIDER name="transpose" id="7d1266b1c1534947" memberName="transpose" |
|
||||||
virtualName="" explicitFocusOrder="0" pos="202 60 34 34" min="0" |
|
||||||
max="48" int="1" style="RotaryVerticalDrag" textBoxPos="NoTextBox" |
|
||||||
textBoxEditable="0" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> |
|
||||||
<TOGGLEBUTTON name="oscSync" id="8f3fe641537cd00" memberName="oscSync" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="650 96 48 26" buttonText="" connectedEdges="0" |
|
||||||
needsCallback="1" radioGroupId="0" state="0"/> |
|
||||||
<SLIDER name="pitchModSens" id="904f73df85a9f886" memberName="pitchModSens" |
|
||||||
virtualName="" explicitFocusOrder="0" pos="666 5 34 34" min="0" |
|
||||||
max="7" int="1" style="RotaryVerticalDrag" textBoxPos="NoTextBox" |
|
||||||
textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> |
|
||||||
<TOGGLEBUTTON name="lfoSync" id="ff92bb0a5a4f7187" memberName="lfoSync" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="565 96 48 26" buttonText="" connectedEdges="0" |
|
||||||
needsCallback="1" radioGroupId="0" state="0"/> |
|
||||||
<GENERICCOMPONENT name="pitchEnvDisplay" id="9ddaae8ef924a038" memberName="pitchEnvDisplay" |
|
||||||
virtualName="" explicitFocusOrder="0" pos="751 10 93 30" class="PitchEnvDisplay" |
|
||||||
params=""/> |
|
||||||
<GENERICCOMPONENT name="algoDisplay" id="b26fb9e3b5f0bc37" memberName="algoDisplay" |
|
||||||
virtualName="" explicitFocusOrder="0" pos="335 30 152 91" class="AlgoDisplay" |
|
||||||
params=""/> |
|
||||||
<SLIDER name="feedback" id="4fac1940c29ab8c" memberName="feedback" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="501 81 34 34" min="0" max="7" int="1" |
|
||||||
style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="1" |
|
||||||
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> |
|
||||||
<SLIDER name="algo" id="8a226ddf9bbff752" memberName="algo" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="501 22 34 34" min="1" max="32" int="1" |
|
||||||
style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="0" |
|
||||||
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> |
|
||||||
<GENERICCOMPONENT name="lcdDisplay" id="30c7bb8f114cbbe3" memberName="lcdDisplay" |
|
||||||
virtualName="" explicitFocusOrder="0" pos="6 87 140 13" class="LcdDisplay" |
|
||||||
params=""/> |
|
||||||
<SLIDER name="output" id="7697fdd54fd1593e" memberName="output" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="157 60 34 34" min="0" max="1" int="0" |
|
||||||
style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="0" |
|
||||||
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> |
|
||||||
<GENERICCOMPONENT name="vuOutput" id="dac75af912267f51" memberName="vuOutput" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="6 103 140 8" class="VuMeter" params=""/> |
|
||||||
<TEXTBUTTON name="initButton" id="92b278163c42e21d" memberName="initButton" |
|
||||||
virtualName="" explicitFocusOrder="0" pos="100 111 50 30" buttonText="INIT" |
|
||||||
connectedEdges="0" needsCallback="1" radioGroupId="0"/> |
|
||||||
<TEXTBUTTON name="parmButton" id="d5cd6260b34be817" memberName="parmButton" |
|
||||||
virtualName="" explicitFocusOrder="0" pos="52 111 50 30" buttonText="PARM" |
|
||||||
connectedEdges="0" needsCallback="1" radioGroupId="0"/> |
|
||||||
<TEXTBUTTON name="cartButton" id="465a101c3a0e744" memberName="cartButton" |
|
||||||
virtualName="" explicitFocusOrder="0" pos="3 111 50 30" buttonText="CART" |
|
||||||
connectedEdges="0" needsCallback="1" radioGroupId="0"/> |
|
||||||
<TEXTBUTTON name="storeButton" id="a94bec26832eb58b" memberName="storeButton" |
|
||||||
virtualName="" explicitFocusOrder="0" pos="270 109 50 30" buttonText="STORE" |
|
||||||
connectedEdges="0" needsCallback="1" radioGroupId="0"/> |
|
||||||
<TOGGLEBUTTON name="monoMode" id="e683d8cbe286367b" memberName="monoMode" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="249 65 48 26" buttonText="" connectedEdges="0" |
|
||||||
needsCallback="1" radioGroupId="0" state="0"/> |
|
||||||
<GENERICCOMPONENT name="lfoType" id="62f61dda9f76c8f" memberName="lfoType" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="583 8 36 26" class="ComboBoxImage" |
|
||||||
params=""/> |
|
||||||
<GENERICCOMPONENT name="programSelector" id="990bbcccae72dbe6" memberName="programSelector" |
|
||||||
virtualName="" explicitFocusOrder="0" pos="153 115 112 18" class="ProgramSelector" |
|
||||||
params=""/> |
|
||||||
<IMAGEBUTTON name="aboutButton" id="d195a60b29440aa1" memberName="aboutButton" |
|
||||||
virtualName="" explicitFocusOrder="0" pos="8 11 135 46" buttonText="" |
|
||||||
connectedEdges="0" needsCallback="1" radioGroupId="0" keepProportions="0" |
|
||||||
resourceNormal="" opacityNormal="1" colourNormal="0" resourceOver="" |
|
||||||
opacityOver="1" colourOver="0" resourceDown="" opacityDown="1" |
|
||||||
colourDown="0"/> |
|
||||||
<SLIDER name="tune" id="d22c34aa3363a28a" memberName="tune" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="190 9 34 34" min="0" max="1" int="0" |
|
||||||
style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="0" |
|
||||||
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> |
|
||||||
</JUCER_COMPONENT> |
|
||||||
|
|
||||||
END_JUCER_METADATA |
|
||||||
*/ |
|
||||||
#endif |
|
||||||
|
|
||||||
|
|
||||||
//[EndFile] You can add extra defines here...
|
|
||||||
//[/EndFile]
|
|
@ -1,126 +0,0 @@ |
|||||||
/*
|
|
||||||
============================================================================== |
|
||||||
|
|
||||||
This is an automatically generated GUI class created by the Introjucer! |
|
||||||
|
|
||||||
Be careful when adding custom code to these files, as only the code within |
|
||||||
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded |
|
||||||
and re-saved. |
|
||||||
|
|
||||||
Created with Introjucer version: 3.2.0 |
|
||||||
|
|
||||||
------------------------------------------------------------------------------ |
|
||||||
|
|
||||||
The Introjucer is part of the JUCE library - "Jules' Utility Class Extensions" |
|
||||||
Copyright (c) 2015 - ROLI Ltd. |
|
||||||
|
|
||||||
============================================================================== |
|
||||||
*/ |
|
||||||
|
|
||||||
#ifndef __JUCE_HEADER_10638A2B49B704D0__ |
|
||||||
#define __JUCE_HEADER_10638A2B49B704D0__ |
|
||||||
|
|
||||||
//[Headers] -- You can add your own extra header files here --
|
|
||||||
#include "JuceHeader.h" |
|
||||||
#include "PluginProcessor.h" |
|
||||||
#include "DXComponents.h" |
|
||||||
#include "AlgoDisplay.h" |
|
||||||
|
|
||||||
class DexedAudioProcessorEditor; |
|
||||||
//[/Headers]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/**
|
|
||||||
//[Comments]
|
|
||||||
An auto-generated component, created by the Introjucer. |
|
||||||
|
|
||||||
Describe your class and how it works here! |
|
||||||
//[/Comments]
|
|
||||||
*/ |
|
||||||
class GlobalEditor : public Component, |
|
||||||
public SliderListener, |
|
||||||
public ButtonListener |
|
||||||
{ |
|
||||||
public: |
|
||||||
//==============================================================================
|
|
||||||
GlobalEditor (); |
|
||||||
~GlobalEditor(); |
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
//[UserMethods] -- You can add your own custom methods in this section.
|
|
||||||
void bind(DexedAudioProcessorEditor *processor); |
|
||||||
void setSystemMessage(String msg); |
|
||||||
void setParamMessage(String msg); |
|
||||||
void updatePitchPos(int pos); |
|
||||||
void updateVu(float v); |
|
||||||
void updateDisplay(); |
|
||||||
void repaintMsg(); |
|
||||||
|
|
||||||
void setMonoState(bool state); |
|
||||||
ProgramSelector *programs; |
|
||||||
ScopedPointer<Component> midiMonitor; |
|
||||||
//[/UserMethods]
|
|
||||||
|
|
||||||
void paint (Graphics& g); |
|
||||||
void resized(); |
|
||||||
void sliderValueChanged (Slider* sliderThatWasMoved); |
|
||||||
void buttonClicked (Button* buttonThatWasClicked); |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private: |
|
||||||
//[UserVariables] -- You can add your own custom variables in this section.
|
|
||||||
DexedAudioProcessorEditor *editor; |
|
||||||
DexedAudioProcessor *processor; |
|
||||||
|
|
||||||
Image background; |
|
||||||
Image imageLight; |
|
||||||
//[/UserVariables]
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
ScopedPointer<Slider> lfoSpeed; |
|
||||||
ScopedPointer<Slider> lfoAmDepth; |
|
||||||
ScopedPointer<Slider> lfoPitchDepth; |
|
||||||
ScopedPointer<Slider> lfoDelay; |
|
||||||
ScopedPointer<Slider> cutoff; |
|
||||||
ScopedPointer<Slider> reso; |
|
||||||
ScopedPointer<Slider> pitchRate2; |
|
||||||
ScopedPointer<Slider> pitchRate3; |
|
||||||
ScopedPointer<Slider> pitchRate4; |
|
||||||
ScopedPointer<Slider> pitchRate1; |
|
||||||
ScopedPointer<Slider> pitchLevel2; |
|
||||||
ScopedPointer<Slider> pitchLevel3; |
|
||||||
ScopedPointer<Slider> pitchLevel4; |
|
||||||
ScopedPointer<Slider> pitchLevel1; |
|
||||||
ScopedPointer<Slider> transpose; |
|
||||||
ScopedPointer<ToggleButton> oscSync; |
|
||||||
ScopedPointer<Slider> pitchModSens; |
|
||||||
ScopedPointer<ToggleButton> lfoSync; |
|
||||||
ScopedPointer<PitchEnvDisplay> pitchEnvDisplay; |
|
||||||
ScopedPointer<AlgoDisplay> algoDisplay; |
|
||||||
ScopedPointer<Slider> feedback; |
|
||||||
ScopedPointer<Slider> algo; |
|
||||||
ScopedPointer<LcdDisplay> lcdDisplay; |
|
||||||
ScopedPointer<Slider> output; |
|
||||||
ScopedPointer<VuMeter> vuOutput; |
|
||||||
ScopedPointer<TextButton> initButton; |
|
||||||
ScopedPointer<TextButton> parmButton; |
|
||||||
ScopedPointer<TextButton> cartButton; |
|
||||||
ScopedPointer<TextButton> storeButton; |
|
||||||
ScopedPointer<ToggleButton> monoMode; |
|
||||||
ScopedPointer<ComboBoxImage> lfoType; |
|
||||||
ScopedPointer<ProgramSelector> programSelector; |
|
||||||
ScopedPointer<ImageButton> aboutButton; |
|
||||||
ScopedPointer<Slider> tune; |
|
||||||
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (GlobalEditor) |
|
||||||
}; |
|
||||||
|
|
||||||
//[EndFile] You can add extra defines here...
|
|
||||||
//[/EndFile]
|
|
||||||
|
|
||||||
#endif // __JUCE_HEADER_10638A2B49B704D0__
|
|
@ -1,660 +0,0 @@ |
|||||||
/*
|
|
||||||
============================================================================== |
|
||||||
|
|
||||||
This is an automatically generated GUI class created by the Introjucer! |
|
||||||
|
|
||||||
Be careful when adding custom code to these files, as only the code within |
|
||||||
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded |
|
||||||
and re-saved. |
|
||||||
|
|
||||||
Created with Introjucer version: 3.2.0 |
|
||||||
|
|
||||||
------------------------------------------------------------------------------ |
|
||||||
|
|
||||||
The Introjucer is part of the JUCE library - "Jules' Utility Class Extensions" |
|
||||||
Copyright (c) 2015 - ROLI Ltd. |
|
||||||
|
|
||||||
============================================================================== |
|
||||||
*/ |
|
||||||
|
|
||||||
//[Headers] You can add your own extra header files here...
|
|
||||||
//[/Headers]
|
|
||||||
|
|
||||||
#include "OperatorEditor.h" |
|
||||||
|
|
||||||
|
|
||||||
//[MiscUserDefs] You can add your own user definitions and misc code here...
|
|
||||||
#ifndef M_LN10 |
|
||||||
#define M_LN10 2.30258509299404568402 |
|
||||||
#endif |
|
||||||
|
|
||||||
class OperatorSwitch : public ToggleButton { |
|
||||||
Image image; |
|
||||||
public : |
|
||||||
OperatorSwitch() : ToggleButton("opSwitch") { |
|
||||||
image = DXLookNFeel::getLookAndFeel()->imageSwitchOperator; |
|
||||||
setSize(32, 32); |
|
||||||
} |
|
||||||
|
|
||||||
void paintButton (Graphics& g, bool isMouseOverButton, bool isButtonDown) { |
|
||||||
g.drawImage(image, 0, 0, 32, 32, 0, getToggleState() ? 0 : 32, 32, 32); |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
//[/MiscUserDefs]
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
OperatorEditor::OperatorEditor () |
|
||||||
{ |
|
||||||
//[Constructor_pre] You can add your own custom stuff here..
|
|
||||||
//[/Constructor_pre]
|
|
||||||
|
|
||||||
addAndMakeVisible (s_egl1 = new Slider ("egl1")); |
|
||||||
s_egl1->setRange (0, 99, 1); |
|
||||||
s_egl1->setSliderStyle (Slider::RotaryVerticalDrag); |
|
||||||
s_egl1->setTextBoxStyle (Slider::NoTextBox, false, 80, 20); |
|
||||||
s_egl1->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (s_egl2 = new Slider ("egl2")); |
|
||||||
s_egl2->setRange (0, 99, 1); |
|
||||||
s_egl2->setSliderStyle (Slider::RotaryVerticalDrag); |
|
||||||
s_egl2->setTextBoxStyle (Slider::NoTextBox, false, 80, 20); |
|
||||||
s_egl2->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (s_egl3 = new Slider ("egl3")); |
|
||||||
s_egl3->setRange (0, 99, 1); |
|
||||||
s_egl3->setSliderStyle (Slider::RotaryVerticalDrag); |
|
||||||
s_egl3->setTextBoxStyle (Slider::NoTextBox, false, 80, 20); |
|
||||||
s_egl3->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (s_egl4 = new Slider ("egl4")); |
|
||||||
s_egl4->setRange (0, 99, 1); |
|
||||||
s_egl4->setSliderStyle (Slider::RotaryVerticalDrag); |
|
||||||
s_egl4->setTextBoxStyle (Slider::NoTextBox, false, 80, 20); |
|
||||||
s_egl4->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (s_egv1 = new Slider ("egr1")); |
|
||||||
s_egv1->setRange (0, 99, 1); |
|
||||||
s_egv1->setSliderStyle (Slider::RotaryVerticalDrag); |
|
||||||
s_egv1->setTextBoxStyle (Slider::NoTextBox, false, 80, 20); |
|
||||||
s_egv1->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (s_egv2 = new Slider ("egr3")); |
|
||||||
s_egv2->setRange (0, 99, 1); |
|
||||||
s_egv2->setSliderStyle (Slider::RotaryVerticalDrag); |
|
||||||
s_egv2->setTextBoxStyle (Slider::NoTextBox, false, 80, 20); |
|
||||||
s_egv2->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (s_egv3 = new Slider ("egr3")); |
|
||||||
s_egv3->setRange (0, 99, 1); |
|
||||||
s_egv3->setSliderStyle (Slider::RotaryVerticalDrag); |
|
||||||
s_egv3->setTextBoxStyle (Slider::NoTextBox, false, 80, 20); |
|
||||||
s_egv3->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (s_egv4 = new Slider ("egr4")); |
|
||||||
s_egv4->setRange (0, 99, 1); |
|
||||||
s_egv4->setSliderStyle (Slider::RotaryVerticalDrag); |
|
||||||
s_egv4->setTextBoxStyle (Slider::NoTextBox, false, 80, 20); |
|
||||||
s_egv4->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (opLevel = new Slider ("opLevel")); |
|
||||||
opLevel->setRange (0, 99, 1); |
|
||||||
opLevel->setSliderStyle (Slider::RotaryVerticalDrag); |
|
||||||
opLevel->setTextBoxStyle (Slider::NoTextBox, false, 80, 20); |
|
||||||
opLevel->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (opFine = new Slider ("opFine")); |
|
||||||
opFine->setRange (0, 99, 1); |
|
||||||
opFine->setSliderStyle (Slider::RotaryVerticalDrag); |
|
||||||
opFine->setTextBoxStyle (Slider::NoTextBox, false, 80, 20); |
|
||||||
opFine->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (opCoarse = new Slider ("opCoarse")); |
|
||||||
opCoarse->setRange (0, 31, 1); |
|
||||||
opCoarse->setSliderStyle (Slider::RotaryVerticalDrag); |
|
||||||
opCoarse->setTextBoxStyle (Slider::NoTextBox, false, 80, 20); |
|
||||||
opCoarse->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (khzDisplay = new Label ("khz", |
|
||||||
TRANS("1,000 kHz"))); |
|
||||||
khzDisplay->setFont (Font (12.60f, Font::plain)); |
|
||||||
khzDisplay->setJustificationType (Justification::centred); |
|
||||||
khzDisplay->setEditable (false, false, false); |
|
||||||
khzDisplay->setColour (Label::backgroundColourId, Colour (0x6a000000)); |
|
||||||
khzDisplay->setColour (Label::textColourId, Colours::white); |
|
||||||
khzDisplay->setColour (Label::outlineColourId, Colour (0x00000000)); |
|
||||||
khzDisplay->setColour (TextEditor::textColourId, Colours::black); |
|
||||||
khzDisplay->setColour (TextEditor::backgroundColourId, Colour (0x00000000)); |
|
||||||
|
|
||||||
addAndMakeVisible (detune = new Slider ("detune")); |
|
||||||
detune->setRange (-7, 7, 1); |
|
||||||
detune->setSliderStyle (Slider::RotaryVerticalDrag); |
|
||||||
detune->setTextBoxStyle (Slider::NoTextBox, true, 80, 20); |
|
||||||
detune->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (envDisplay = new EnvDisplay()); |
|
||||||
envDisplay->setName ("envDisplay"); |
|
||||||
|
|
||||||
addAndMakeVisible (sclLeftLevel = new Slider ("sclLeftLevel")); |
|
||||||
sclLeftLevel->setTooltip (TRANS("Keyboard Scale Level Left Depth ")); |
|
||||||
sclLeftLevel->setRange (0, 99, 1); |
|
||||||
sclLeftLevel->setSliderStyle (Slider::RotaryVerticalDrag); |
|
||||||
sclLeftLevel->setTextBoxStyle (Slider::NoTextBox, false, 80, 20); |
|
||||||
sclLeftLevel->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (sclRightLevel = new Slider ("sclRightLevel")); |
|
||||||
sclRightLevel->setTooltip (TRANS("Keyboard Scale Level Right Depth ")); |
|
||||||
sclRightLevel->setRange (0, 99, 1); |
|
||||||
sclRightLevel->setSliderStyle (Slider::RotaryVerticalDrag); |
|
||||||
sclRightLevel->setTextBoxStyle (Slider::NoTextBox, false, 80, 20); |
|
||||||
sclRightLevel->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (sclLvlBrkPt = new Slider ("sclLvlBrkPt")); |
|
||||||
sclLvlBrkPt->setTooltip (TRANS("Scale Level Breakpoint")); |
|
||||||
sclLvlBrkPt->setRange (0, 99, 1); |
|
||||||
sclLvlBrkPt->setSliderStyle (Slider::LinearHorizontal); |
|
||||||
sclLvlBrkPt->setTextBoxStyle (Slider::NoTextBox, false, 80, 20); |
|
||||||
sclLvlBrkPt->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (sclRateScaling = new Slider ("sclRateScaling")); |
|
||||||
sclRateScaling->setTooltip (TRANS("Keyboard Rate Scaling")); |
|
||||||
sclRateScaling->setRange (0, 7, 1); |
|
||||||
sclRateScaling->setSliderStyle (Slider::RotaryVerticalDrag); |
|
||||||
sclRateScaling->setTextBoxStyle (Slider::NoTextBox, false, 80, 20); |
|
||||||
sclRateScaling->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (keyVelSens = new Slider ("keyVelSens")); |
|
||||||
keyVelSens->setRange (0, 7, 1); |
|
||||||
keyVelSens->setSliderStyle (Slider::RotaryVerticalDrag); |
|
||||||
keyVelSens->setTextBoxStyle (Slider::NoTextBox, false, 80, 20); |
|
||||||
keyVelSens->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (ampModSens = new Slider ("ampModSens")); |
|
||||||
ampModSens->setRange (0, 3, 1); |
|
||||||
ampModSens->setSliderStyle (Slider::RotaryVerticalDrag); |
|
||||||
ampModSens->setTextBoxStyle (Slider::NoTextBox, false, 80, 20); |
|
||||||
ampModSens->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (vu = new VuMeter()); |
|
||||||
vu->setName ("vu"); |
|
||||||
|
|
||||||
addAndMakeVisible (opMode = new ToggleButton ("opMode")); |
|
||||||
opMode->setButtonText (String::empty); |
|
||||||
opMode->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (kbdLeftCurve = new ComboBoxImage()); |
|
||||||
kbdLeftCurve->setName ("kbdLeftCurve"); |
|
||||||
|
|
||||||
addAndMakeVisible (kbdRightCurve = new ComboBoxImage()); |
|
||||||
kbdRightCurve->setName ("kbdRightCurve"); |
|
||||||
|
|
||||||
|
|
||||||
//[UserPreSize]
|
|
||||||
addAndMakeVisible(opSwitch = new OperatorSwitch()); |
|
||||||
//[/UserPreSize]
|
|
||||||
|
|
||||||
setSize (287, 218); |
|
||||||
|
|
||||||
|
|
||||||
//[Constructor] You can add your own custom stuff here..
|
|
||||||
light = DXLookNFeel::getLookAndFeel()->imageLight; |
|
||||||
Image tmp = DXLookNFeel::getLookAndFeel()->imageScaling; |
|
||||||
|
|
||||||
kbdLeftCurve->addItem("-LN", 1); |
|
||||||
kbdLeftCurve->addItem("-EX", 2); |
|
||||||
kbdLeftCurve->addItem("+EX", 3); |
|
||||||
kbdLeftCurve->addItem("+LN", 4); |
|
||||||
int posLeft[] = {0,5,4,3}; |
|
||||||
kbdLeftCurve->setImage(tmp, posLeft); |
|
||||||
|
|
||||||
kbdRightCurve->addItem("-LN", 1); |
|
||||||
kbdRightCurve->addItem("-EX", 2); |
|
||||||
kbdRightCurve->addItem("+EX", 3); |
|
||||||
kbdRightCurve->addItem("+LN", 4); |
|
||||||
int posRight[] = {3,2,1,0}; |
|
||||||
kbdRightCurve->setImage(tmp, posRight); |
|
||||||
|
|
||||||
background = DXLookNFeel::getLookAndFeel()->imageOperator; |
|
||||||
|
|
||||||
//[/Constructor]
|
|
||||||
} |
|
||||||
|
|
||||||
OperatorEditor::~OperatorEditor() |
|
||||||
{ |
|
||||||
//[Destructor_pre]. You can add your own custom destruction code here..
|
|
||||||
//[/Destructor_pre]
|
|
||||||
|
|
||||||
s_egl1 = nullptr; |
|
||||||
s_egl2 = nullptr; |
|
||||||
s_egl3 = nullptr; |
|
||||||
s_egl4 = nullptr; |
|
||||||
s_egv1 = nullptr; |
|
||||||
s_egv2 = nullptr; |
|
||||||
s_egv3 = nullptr; |
|
||||||
s_egv4 = nullptr; |
|
||||||
opLevel = nullptr; |
|
||||||
opFine = nullptr; |
|
||||||
opCoarse = nullptr; |
|
||||||
khzDisplay = nullptr; |
|
||||||
detune = nullptr; |
|
||||||
envDisplay = nullptr; |
|
||||||
sclLeftLevel = nullptr; |
|
||||||
sclRightLevel = nullptr; |
|
||||||
sclLvlBrkPt = nullptr; |
|
||||||
sclRateScaling = nullptr; |
|
||||||
keyVelSens = nullptr; |
|
||||||
ampModSens = nullptr; |
|
||||||
vu = nullptr; |
|
||||||
opMode = nullptr; |
|
||||||
kbdLeftCurve = nullptr; |
|
||||||
kbdRightCurve = nullptr; |
|
||||||
|
|
||||||
|
|
||||||
//[Destructor]. You can add your own custom destruction code here..
|
|
||||||
opSwitch = nullptr; |
|
||||||
//[/Destructor]
|
|
||||||
} |
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
void OperatorEditor::paint (Graphics& g) |
|
||||||
{ |
|
||||||
//[UserPrePaint] Add your own custom painting code here..
|
|
||||||
g.drawImage(background, 0, 0, 287, 218, 0, 0, 287, 218); |
|
||||||
//[/UserPrePaint]
|
|
||||||
|
|
||||||
//[UserPaint] Add your own custom painting code here..
|
|
||||||
g.setColour (Colours::white); |
|
||||||
g.setFont(Font (30.00f, Font::plain)); |
|
||||||
g.drawText(opNum, 250, 14, 30, 30, Justification::centred, true); |
|
||||||
|
|
||||||
bool state = opMode->getToggleState(); |
|
||||||
|
|
||||||
// 129 x 24
|
|
||||||
g.drawImage(light, 127, 24, 14, 14, 0, state ? 0 : 14, 14, 14); |
|
||||||
// 199 x 24
|
|
||||||
g.drawImage(light, 198, 24, 14, 14, 0, !state ? 0 : 14, 14, 14); |
|
||||||
//[/UserPaint]
|
|
||||||
} |
|
||||||
|
|
||||||
void OperatorEditor::resized() |
|
||||||
{ |
|
||||||
//[UserPreResize] Add your own custom resize code here..
|
|
||||||
//[/UserPreResize]
|
|
||||||
|
|
||||||
s_egl1->setBounds (5, 128, 34, 34); |
|
||||||
s_egl2->setBounds (33, 129, 34, 34); |
|
||||||
s_egl3->setBounds (61, 128, 34, 34); |
|
||||||
s_egl4->setBounds (89, 128, 34, 34); |
|
||||||
s_egv1->setBounds (5, 169, 34, 34); |
|
||||||
s_egv2->setBounds (33, 169, 34, 34); |
|
||||||
s_egv3->setBounds (61, 169, 34, 34); |
|
||||||
s_egv4->setBounds (89, 169, 34, 34); |
|
||||||
opLevel->setBounds (245, 76, 34, 34); |
|
||||||
opFine->setBounds (78, 24, 34, 34); |
|
||||||
opCoarse->setBounds (43, 24, 34, 34); |
|
||||||
khzDisplay->setBounds (15, 10, 95, 10); |
|
||||||
detune->setBounds (6, 24, 34, 34); |
|
||||||
envDisplay->setBounds (16, 83, 94, 30); |
|
||||||
sclLeftLevel->setBounds (131, 115, 34, 34); |
|
||||||
sclRightLevel->setBounds (241, 115, 34, 34); |
|
||||||
sclLvlBrkPt->setBounds (178, 130, 54, 24); |
|
||||||
sclRateScaling->setBounds (186, 179, 34, 34); |
|
||||||
keyVelSens->setBounds (204, 76, 34, 34); |
|
||||||
ampModSens->setBounds (140, 76, 34, 34); |
|
||||||
vu->setBounds (132, 52, 140, 8); |
|
||||||
opMode->setBounds (146, 19, 48, 26); |
|
||||||
kbdLeftCurve->setBounds (128, 170, 36, 26); |
|
||||||
kbdRightCurve->setBounds (240, 170, 36, 26); |
|
||||||
//[UserResized] Add your own custom resize handling here..
|
|
||||||
opSwitch->setBounds(226, 13, 64, 32); |
|
||||||
//[/UserResized]
|
|
||||||
} |
|
||||||
|
|
||||||
void OperatorEditor::sliderValueChanged (Slider* sliderThatWasMoved) |
|
||||||
{ |
|
||||||
//[UsersliderValueChanged_Pre]
|
|
||||||
//[/UsersliderValueChanged_Pre]
|
|
||||||
|
|
||||||
if (sliderThatWasMoved == s_egl1) |
|
||||||
{ |
|
||||||
//[UserSliderCode_s_egl1] -- add your slider handling code here..
|
|
||||||
envDisplay->repaint(); |
|
||||||
//[/UserSliderCode_s_egl1]
|
|
||||||
} |
|
||||||
else if (sliderThatWasMoved == s_egl2) |
|
||||||
{ |
|
||||||
//[UserSliderCode_s_egl2] -- add your slider handling code here..
|
|
||||||
envDisplay->repaint(); |
|
||||||
//[/UserSliderCode_s_egl2]
|
|
||||||
} |
|
||||||
else if (sliderThatWasMoved == s_egl3) |
|
||||||
{ |
|
||||||
//[UserSliderCode_s_egl3] -- add your slider handling code here..
|
|
||||||
envDisplay->repaint(); |
|
||||||
//[/UserSliderCode_s_egl3]
|
|
||||||
} |
|
||||||
else if (sliderThatWasMoved == s_egl4) |
|
||||||
{ |
|
||||||
//[UserSliderCode_s_egl4] -- add your slider handling code here..
|
|
||||||
envDisplay->repaint(); |
|
||||||
//[/UserSliderCode_s_egl4]
|
|
||||||
} |
|
||||||
else if (sliderThatWasMoved == s_egv1) |
|
||||||
{ |
|
||||||
//[UserSliderCode_s_egv1] -- add your slider handling code here..
|
|
||||||
envDisplay->repaint(); |
|
||||||
//[/UserSliderCode_s_egv1]
|
|
||||||
} |
|
||||||
else if (sliderThatWasMoved == s_egv2) |
|
||||||
{ |
|
||||||
//[UserSliderCode_s_egv2] -- add your slider handling code here..
|
|
||||||
envDisplay->repaint(); |
|
||||||
//[/UserSliderCode_s_egv2]
|
|
||||||
} |
|
||||||
else if (sliderThatWasMoved == s_egv3) |
|
||||||
{ |
|
||||||
//[UserSliderCode_s_egv3] -- add your slider handling code here..
|
|
||||||
envDisplay->repaint(); |
|
||||||
//[/UserSliderCode_s_egv3]
|
|
||||||
} |
|
||||||
else if (sliderThatWasMoved == s_egv4) |
|
||||||
{ |
|
||||||
//[UserSliderCode_s_egv4] -- add your slider handling code here..
|
|
||||||
envDisplay->repaint(); |
|
||||||
//[/UserSliderCode_s_egv4]
|
|
||||||
} |
|
||||||
else if (sliderThatWasMoved == opLevel) |
|
||||||
{ |
|
||||||
//[UserSliderCode_opLevel] -- add your slider handling code here..
|
|
||||||
//[/UserSliderCode_opLevel]
|
|
||||||
} |
|
||||||
else if (sliderThatWasMoved == opFine) |
|
||||||
{ |
|
||||||
//[UserSliderCode_opFine] -- add your slider handling code here..
|
|
||||||
updateDisplay(); |
|
||||||
//[/UserSliderCode_opFine]
|
|
||||||
} |
|
||||||
else if (sliderThatWasMoved == opCoarse) |
|
||||||
{ |
|
||||||
//[UserSliderCode_opCoarse] -- add your slider handling code here..
|
|
||||||
updateDisplay(); |
|
||||||
//[/UserSliderCode_opCoarse]
|
|
||||||
} |
|
||||||
else if (sliderThatWasMoved == detune) |
|
||||||
{ |
|
||||||
//[UserSliderCode_detune] -- add your slider handling code here..
|
|
||||||
updateDisplay(); |
|
||||||
//[/UserSliderCode_detune]
|
|
||||||
} |
|
||||||
else if (sliderThatWasMoved == sclLeftLevel) |
|
||||||
{ |
|
||||||
//[UserSliderCode_sclLeftLevel] -- add your slider handling code here..
|
|
||||||
//[/UserSliderCode_sclLeftLevel]
|
|
||||||
} |
|
||||||
else if (sliderThatWasMoved == sclRightLevel) |
|
||||||
{ |
|
||||||
//[UserSliderCode_sclRightLevel] -- add your slider handling code here..
|
|
||||||
//[/UserSliderCode_sclRightLevel]
|
|
||||||
} |
|
||||||
else if (sliderThatWasMoved == sclLvlBrkPt) |
|
||||||
{ |
|
||||||
//[UserSliderCode_sclLvlBrkPt] -- add your slider handling code here..
|
|
||||||
//[/UserSliderCode_sclLvlBrkPt]
|
|
||||||
} |
|
||||||
else if (sliderThatWasMoved == sclRateScaling) |
|
||||||
{ |
|
||||||
//[UserSliderCode_sclRateScaling] -- add your slider handling code here..
|
|
||||||
//[/UserSliderCode_sclRateScaling]
|
|
||||||
} |
|
||||||
else if (sliderThatWasMoved == keyVelSens) |
|
||||||
{ |
|
||||||
//[UserSliderCode_keyVelSens] -- add your slider handling code here..
|
|
||||||
//[/UserSliderCode_keyVelSens]
|
|
||||||
} |
|
||||||
else if (sliderThatWasMoved == ampModSens) |
|
||||||
{ |
|
||||||
//[UserSliderCode_ampModSens] -- add your slider handling code here..
|
|
||||||
//[/UserSliderCode_ampModSens]
|
|
||||||
} |
|
||||||
|
|
||||||
//[UsersliderValueChanged_Post]
|
|
||||||
//[/UsersliderValueChanged_Post]
|
|
||||||
} |
|
||||||
|
|
||||||
void OperatorEditor::buttonClicked (Button* buttonThatWasClicked) |
|
||||||
{ |
|
||||||
//[UserbuttonClicked_Pre]
|
|
||||||
//[/UserbuttonClicked_Pre]
|
|
||||||
|
|
||||||
if (buttonThatWasClicked == opMode) |
|
||||||
{ |
|
||||||
//[UserButtonCode_opMode] -- add your button handler code here..
|
|
||||||
repaint(); |
|
||||||
//[/UserButtonCode_opMode]
|
|
||||||
} |
|
||||||
|
|
||||||
//[UserbuttonClicked_Post]
|
|
||||||
//[/UserbuttonClicked_Post]
|
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//[MiscUserCode] You can add your own definitions of your custom methods or any other code here...
|
|
||||||
void OperatorEditor::bind(DexedAudioProcessor *parent, int op) { |
|
||||||
parent->opCtrl[op].egLevel[0]->bind(s_egl1); |
|
||||||
parent->opCtrl[op].egLevel[1]->bind(s_egl2); |
|
||||||
parent->opCtrl[op].egLevel[2]->bind(s_egl3); |
|
||||||
parent->opCtrl[op].egLevel[3]->bind(s_egl4); |
|
||||||
parent->opCtrl[op].egRate[0]->bind(s_egv1); |
|
||||||
parent->opCtrl[op].egRate[1]->bind(s_egv2); |
|
||||||
parent->opCtrl[op].egRate[2]->bind(s_egv3); |
|
||||||
parent->opCtrl[op].egRate[3]->bind(s_egv4); |
|
||||||
parent->opCtrl[op].level->bind(opLevel); |
|
||||||
parent->opCtrl[op].opMode->bind(opMode); |
|
||||||
parent->opCtrl[op].fine->bind(opFine); |
|
||||||
parent->opCtrl[op].coarse->bind(opCoarse); |
|
||||||
parent->opCtrl[op].detune->bind(detune); |
|
||||||
parent->opCtrl[op].sclBrkPt->bind(sclLvlBrkPt); |
|
||||||
parent->opCtrl[op].sclLeftCurve->bind(kbdLeftCurve); |
|
||||||
parent->opCtrl[op].sclRightCurve->bind(kbdRightCurve); |
|
||||||
parent->opCtrl[op].sclLeftDepth->bind(sclLeftLevel); |
|
||||||
parent->opCtrl[op].sclRightDepth->bind(sclRightLevel); |
|
||||||
parent->opCtrl[op].sclRate->bind(sclRateScaling); |
|
||||||
parent->opCtrl[op].ampModSens->bind(ampModSens); |
|
||||||
parent->opCtrl[op].velModSens->bind(keyVelSens); |
|
||||||
parent->opCtrl[op].opSwitch->bind(opSwitch); |
|
||||||
|
|
||||||
int offset = parent->opCtrl[op].egRate[0]->getOffset(); |
|
||||||
envDisplay->pvalues = &(parent->data[offset]); |
|
||||||
processor = parent; |
|
||||||
|
|
||||||
opNum << op + 1; |
|
||||||
internalOp = 5-op; |
|
||||||
} |
|
||||||
|
|
||||||
void OperatorEditor::updateGain(float v) { |
|
||||||
vu->v = v; |
|
||||||
vu->repaint(); |
|
||||||
} |
|
||||||
|
|
||||||
void OperatorEditor::updateDisplay() { |
|
||||||
float freq = opCoarse->getValue(); |
|
||||||
float fine = opFine->getValue(); |
|
||||||
String txtFreq; |
|
||||||
|
|
||||||
if (opMode->getToggleState() == 0) { |
|
||||||
if ( freq == 0 ) |
|
||||||
freq = 0.5; |
|
||||||
txtFreq << "f = " << (freq + (freq * (fine/100))); |
|
||||||
} else { |
|
||||||
freq = pow(10,((int)freq)&3); |
|
||||||
freq = freq * exp(M_LN10*(fine/100)); |
|
||||||
txtFreq << freq << " Hz"; |
|
||||||
} |
|
||||||
|
|
||||||
int det = detune->getValue(); |
|
||||||
if ( det != 0 ) { |
|
||||||
if ( det > 0 ) |
|
||||||
txtFreq << " +" << det; |
|
||||||
else |
|
||||||
txtFreq << " " << det; |
|
||||||
} |
|
||||||
khzDisplay->setText(txtFreq, dontSendNotification); |
|
||||||
repaint(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
void OperatorEditor::updateEnvPos(char pos) { |
|
||||||
envDisplay->vPos = pos; |
|
||||||
envDisplay->repaint(); |
|
||||||
} |
|
||||||
|
|
||||||
void OperatorEditor::mouseDown(const MouseEvent &event) { |
|
||||||
if ( event.mods.isRightButtonDown() ) { |
|
||||||
PopupMenu popup; |
|
||||||
|
|
||||||
popup.addItem(1, "Copy Operator Values"); |
|
||||||
popup.addItem(2, "Paste Envelope Values", processor->hasClipboardContent()); |
|
||||||
popup.addItem(3, "Paste Operator Values", processor->hasClipboardContent()); |
|
||||||
popup.addSeparator(); |
|
||||||
popup.addItem(4, "Send current program to DX7"); |
|
||||||
|
|
||||||
switch(popup.show()) { |
|
||||||
case 1: |
|
||||||
processor->copyToClipboard(internalOp); |
|
||||||
break; |
|
||||||
|
|
||||||
case 2: |
|
||||||
processor->pasteEnvFromClipboard(internalOp); |
|
||||||
break; |
|
||||||
|
|
||||||
case 3: |
|
||||||
processor->pasteOpFromClipboard(internalOp); |
|
||||||
break; |
|
||||||
|
|
||||||
case 4: |
|
||||||
processor->sendCurrentSysexProgram(); |
|
||||||
break; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
//[/MiscUserCode]
|
|
||||||
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
#if 0 |
|
||||||
/* -- Introjucer information section --
|
|
||||||
|
|
||||||
This is where the Introjucer stores the metadata that describe this GUI layout, so |
|
||||||
make changes in here at your peril! |
|
||||||
|
|
||||||
BEGIN_JUCER_METADATA |
|
||||||
|
|
||||||
<JUCER_COMPONENT documentType="Component" className="OperatorEditor" componentName="" |
|
||||||
parentClasses="public Component" constructorParams="" variableInitialisers="" |
|
||||||
snapPixels="2" snapActive="0" snapShown="1" overlayOpacity="0.330" |
|
||||||
fixedSize="1" initialWidth="287" initialHeight="218"> |
|
||||||
<BACKGROUND backgroundColour="ffffff"/> |
|
||||||
<SLIDER name="egl1" id="dc070cc41347df47" memberName="s_egl1" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="5 128 34 34" min="0" max="99" int="1" |
|
||||||
style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="1" |
|
||||||
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> |
|
||||||
<SLIDER name="egl2" id="66f5195e9c374029" memberName="s_egl2" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="33 129 34 34" min="0" max="99" int="1" |
|
||||||
style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="1" |
|
||||||
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> |
|
||||||
<SLIDER name="egl3" id="9d57bd53203dcdb4" memberName="s_egl3" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="61 128 34 34" min="0" max="99" int="1" |
|
||||||
style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="1" |
|
||||||
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> |
|
||||||
<SLIDER name="egl4" id="4f7c3ece3ea2cf9c" memberName="s_egl4" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="89 128 34 34" min="0" max="99" int="1" |
|
||||||
style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="1" |
|
||||||
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> |
|
||||||
<SLIDER name="egr1" id="2ca8137d80da46fb" memberName="s_egv1" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="5 169 34 34" min="0" max="99" int="1" |
|
||||||
style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="1" |
|
||||||
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> |
|
||||||
<SLIDER name="egr3" id="4ad6d0c532d15973" memberName="s_egv2" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="33 169 34 34" min="0" max="99" int="1" |
|
||||||
style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="1" |
|
||||||
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> |
|
||||||
<SLIDER name="egr3" id="8a2027f9ede16b4f" memberName="s_egv3" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="61 169 34 34" min="0" max="99" int="1" |
|
||||||
style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="1" |
|
||||||
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> |
|
||||||
<SLIDER name="egr4" id="8c04f1c943d837e8" memberName="s_egv4" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="89 169 34 34" min="0" max="99" int="1" |
|
||||||
style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="1" |
|
||||||
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> |
|
||||||
<SLIDER name="opLevel" id="f8521c8214fb8993" memberName="opLevel" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="245 76 34 34" min="0" max="99" int="1" |
|
||||||
style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="1" |
|
||||||
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> |
|
||||||
<SLIDER name="opFine" id="e445aa61bd6cddcb" memberName="opFine" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="78 24 34 34" min="0" max="99" int="1" |
|
||||||
style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="1" |
|
||||||
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> |
|
||||||
<SLIDER name="opCoarse" id="4eec63d30d7488d2" memberName="opCoarse" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="43 24 34 34" min="0" max="31" int="1" |
|
||||||
style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="1" |
|
||||||
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> |
|
||||||
<LABEL name="khz" id="eb961eed8902a6fc" memberName="khzDisplay" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="15 10 95 10" bkgCol="6a000000" textCol="ffffffff" |
|
||||||
outlineCol="0" edTextCol="ff000000" edBkgCol="0" labelText="1,000 kHz" |
|
||||||
editableSingleClick="0" editableDoubleClick="0" focusDiscardsChanges="0" |
|
||||||
fontname="Default font" fontsize="12.599999999999999645" bold="0" |
|
||||||
italic="0" justification="36"/> |
|
||||||
<SLIDER name="detune" id="f093ec8defca2fc2" memberName="detune" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="6 24 34 34" min="-7" max="7" int="1" |
|
||||||
style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="0" |
|
||||||
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> |
|
||||||
<GENERICCOMPONENT name="envDisplay" id="b18856de924c6340" memberName="envDisplay" |
|
||||||
virtualName="" explicitFocusOrder="0" pos="16 83 94 30" class="EnvDisplay" |
|
||||||
params=""/> |
|
||||||
<SLIDER name="sclLeftLevel" id="bd6f338ae68e454f" memberName="sclLeftLevel" |
|
||||||
virtualName="" explicitFocusOrder="0" pos="131 115 34 34" tooltip="Keyboard Scale Level Left Depth " |
|
||||||
min="0" max="99" int="1" style="RotaryVerticalDrag" textBoxPos="NoTextBox" |
|
||||||
textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> |
|
||||||
<SLIDER name="sclRightLevel" id="b9e23ed5187fc7e5" memberName="sclRightLevel" |
|
||||||
virtualName="" explicitFocusOrder="0" pos="241 115 34 34" tooltip="Keyboard Scale Level Right Depth " |
|
||||||
min="0" max="99" int="1" style="RotaryVerticalDrag" textBoxPos="NoTextBox" |
|
||||||
textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> |
|
||||||
<SLIDER name="sclLvlBrkPt" id="c563ac3116923bbc" memberName="sclLvlBrkPt" |
|
||||||
virtualName="" explicitFocusOrder="0" pos="178 130 54 24" tooltip="Scale Level Breakpoint" |
|
||||||
min="0" max="99" int="1" style="LinearHorizontal" textBoxPos="NoTextBox" |
|
||||||
textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> |
|
||||||
<SLIDER name="sclRateScaling" id="f0d17c8e09aa4c49" memberName="sclRateScaling" |
|
||||||
virtualName="" explicitFocusOrder="0" pos="186 179 34 34" tooltip="Keyboard Rate Scaling" |
|
||||||
min="0" max="7" int="1" style="RotaryVerticalDrag" textBoxPos="NoTextBox" |
|
||||||
textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> |
|
||||||
<SLIDER name="keyVelSens" id="21795d045d07602b" memberName="keyVelSens" |
|
||||||
virtualName="" explicitFocusOrder="0" pos="204 76 34 34" min="0" |
|
||||||
max="7" int="1" style="RotaryVerticalDrag" textBoxPos="NoTextBox" |
|
||||||
textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> |
|
||||||
<SLIDER name="ampModSens" id="634ceaa7b0f81a6c" memberName="ampModSens" |
|
||||||
virtualName="" explicitFocusOrder="0" pos="140 76 34 34" min="0" |
|
||||||
max="3" int="1" style="RotaryVerticalDrag" textBoxPos="NoTextBox" |
|
||||||
textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> |
|
||||||
<GENERICCOMPONENT name="vu" id="6f952594ea99dc1e" memberName="vu" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="132 52 140 8" class="VuMeter" params=""/> |
|
||||||
<TOGGLEBUTTON name="opMode" id="15db8e5c9dd13966" memberName="opMode" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="146 19 48 26" buttonText="" connectedEdges="0" |
|
||||||
needsCallback="1" radioGroupId="0" state="0"/> |
|
||||||
<GENERICCOMPONENT name="kbdLeftCurve" id="ee4e60dfcd6cb790" memberName="kbdLeftCurve" |
|
||||||
virtualName="" explicitFocusOrder="0" pos="128 170 36 26" class="ComboBoxImage" |
|
||||||
params=""/> |
|
||||||
<GENERICCOMPONENT name="kbdRightCurve" id="f5ca44d67593488a" memberName="kbdRightCurve" |
|
||||||
virtualName="" explicitFocusOrder="0" pos="240 170 36 26" class="ComboBoxImage" |
|
||||||
params=""/> |
|
||||||
</JUCER_COMPONENT> |
|
||||||
|
|
||||||
END_JUCER_METADATA |
|
||||||
*/ |
|
||||||
#endif |
|
||||||
|
|
||||||
|
|
||||||
//[EndFile] You can add extra defines here...
|
|
||||||
//[/EndFile]
|
|
@ -1,110 +0,0 @@ |
|||||||
/*
|
|
||||||
============================================================================== |
|
||||||
|
|
||||||
This is an automatically generated GUI class created by the Introjucer! |
|
||||||
|
|
||||||
Be careful when adding custom code to these files, as only the code within |
|
||||||
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded |
|
||||||
and re-saved. |
|
||||||
|
|
||||||
Created with Introjucer version: 3.2.0 |
|
||||||
|
|
||||||
------------------------------------------------------------------------------ |
|
||||||
|
|
||||||
The Introjucer is part of the JUCE library - "Jules' Utility Class Extensions" |
|
||||||
Copyright (c) 2015 - ROLI Ltd. |
|
||||||
|
|
||||||
============================================================================== |
|
||||||
*/ |
|
||||||
|
|
||||||
#ifndef __JUCE_HEADER_F21C2CC3FAD5D98E__ |
|
||||||
#define __JUCE_HEADER_F21C2CC3FAD5D98E__ |
|
||||||
|
|
||||||
//[Headers] -- You can add your own extra header files here --
|
|
||||||
#include "JuceHeader.h" |
|
||||||
#include "PluginProcessor.h" |
|
||||||
#include "DXComponents.h" |
|
||||||
#include "DXLookNFeel.h" |
|
||||||
//[/Headers]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/**
|
|
||||||
//[Comments]
|
|
||||||
An auto-generated component, created by the Introjucer. |
|
||||||
|
|
||||||
Describe your class and how it works here! |
|
||||||
//[/Comments]
|
|
||||||
*/ |
|
||||||
class OperatorEditor : public Component, |
|
||||||
public SliderListener, |
|
||||||
public ButtonListener |
|
||||||
{ |
|
||||||
public: |
|
||||||
//==============================================================================
|
|
||||||
OperatorEditor (); |
|
||||||
~OperatorEditor(); |
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
//[UserMethods] -- You can add your own custom methods in this section.
|
|
||||||
|
|
||||||
void bind(DexedAudioProcessor *processor, int num); |
|
||||||
void updateGain(float v); |
|
||||||
void updateDisplay(); |
|
||||||
void updateEnvPos(char pos); |
|
||||||
void mouseDown(const MouseEvent& e) override; |
|
||||||
//[/UserMethods]
|
|
||||||
|
|
||||||
void paint (Graphics& g) override; |
|
||||||
void resized() override; |
|
||||||
void sliderValueChanged (Slider* sliderThatWasMoved) override; |
|
||||||
void buttonClicked (Button* buttonThatWasClicked) override; |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private: |
|
||||||
//[UserVariables] -- You can add your own custom variables in this section.
|
|
||||||
String opNum; |
|
||||||
int internalOp; |
|
||||||
Image light; |
|
||||||
DexedAudioProcessor *processor; |
|
||||||
Image background; |
|
||||||
ScopedPointer<ToggleButton> opSwitch; |
|
||||||
//[/UserVariables]
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
ScopedPointer<Slider> s_egl1; |
|
||||||
ScopedPointer<Slider> s_egl2; |
|
||||||
ScopedPointer<Slider> s_egl3; |
|
||||||
ScopedPointer<Slider> s_egl4; |
|
||||||
ScopedPointer<Slider> s_egv1; |
|
||||||
ScopedPointer<Slider> s_egv2; |
|
||||||
ScopedPointer<Slider> s_egv3; |
|
||||||
ScopedPointer<Slider> s_egv4; |
|
||||||
ScopedPointer<Slider> opLevel; |
|
||||||
ScopedPointer<Slider> opFine; |
|
||||||
ScopedPointer<Slider> opCoarse; |
|
||||||
ScopedPointer<Label> khzDisplay; |
|
||||||
ScopedPointer<Slider> detune; |
|
||||||
ScopedPointer<EnvDisplay> envDisplay; |
|
||||||
ScopedPointer<Slider> sclLeftLevel; |
|
||||||
ScopedPointer<Slider> sclRightLevel; |
|
||||||
ScopedPointer<Slider> sclLvlBrkPt; |
|
||||||
ScopedPointer<Slider> sclRateScaling; |
|
||||||
ScopedPointer<Slider> keyVelSens; |
|
||||||
ScopedPointer<Slider> ampModSens; |
|
||||||
ScopedPointer<VuMeter> vu; |
|
||||||
ScopedPointer<ToggleButton> opMode; |
|
||||||
ScopedPointer<ComboBoxImage> kbdLeftCurve; |
|
||||||
ScopedPointer<ComboBoxImage> kbdRightCurve; |
|
||||||
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OperatorEditor) |
|
||||||
}; |
|
||||||
|
|
||||||
//[EndFile] You can add extra defines here...
|
|
||||||
//[/EndFile]
|
|
||||||
|
|
||||||
#endif // __JUCE_HEADER_F21C2CC3FAD5D98E__
|
|
@ -1,703 +0,0 @@ |
|||||||
/*
|
|
||||||
============================================================================== |
|
||||||
|
|
||||||
This is an automatically generated GUI class created by the Introjucer! |
|
||||||
|
|
||||||
Be careful when adding custom code to these files, as only the code within |
|
||||||
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded |
|
||||||
and re-saved. |
|
||||||
|
|
||||||
Created with Introjucer version: 3.2.0 |
|
||||||
|
|
||||||
------------------------------------------------------------------------------ |
|
||||||
|
|
||||||
The Introjucer is part of the JUCE library - "Jules' Utility Class Extensions" |
|
||||||
Copyright (c) 2015 - ROLI Ltd. |
|
||||||
|
|
||||||
============================================================================== |
|
||||||
*/ |
|
||||||
|
|
||||||
//[Headers] You can add your own extra header files here...
|
|
||||||
#include "Dexed.h" |
|
||||||
//[/Headers]
|
|
||||||
|
|
||||||
#include "ParamDialog.h" |
|
||||||
|
|
||||||
|
|
||||||
//[MiscUserDefs] You can add your own user definitions and misc code here...
|
|
||||||
//[/MiscUserDefs]
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
ParamDialog::ParamDialog () |
|
||||||
{ |
|
||||||
//[Constructor_pre] You can add your own custom stuff here..
|
|
||||||
//[/Constructor_pre]
|
|
||||||
|
|
||||||
addAndMakeVisible (pitchRange = new Slider ("pitchRange")); |
|
||||||
pitchRange->setRange (0, 12, 1); |
|
||||||
pitchRange->setSliderStyle (Slider::RotaryVerticalDrag); |
|
||||||
pitchRange->setTextBoxStyle (Slider::TextBoxLeft, false, 80, 20); |
|
||||||
pitchRange->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (pitchStep = new Slider ("pitchStep")); |
|
||||||
pitchStep->setRange (0, 12, 1); |
|
||||||
pitchStep->setSliderStyle (Slider::RotaryVerticalDrag); |
|
||||||
pitchStep->setTextBoxStyle (Slider::TextBoxLeft, false, 80, 20); |
|
||||||
pitchStep->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (sysexIn = new ComboBox ("sysexIn")); |
|
||||||
sysexIn->setEditableText (false); |
|
||||||
sysexIn->setJustificationType (Justification::centredLeft); |
|
||||||
sysexIn->setTextWhenNothingSelected (String::empty); |
|
||||||
sysexIn->setTextWhenNoChoicesAvailable (TRANS("(no choices)")); |
|
||||||
sysexIn->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (sysexOut = new ComboBox ("sysexOut")); |
|
||||||
sysexOut->setEditableText (false); |
|
||||||
sysexOut->setJustificationType (Justification::centredLeft); |
|
||||||
sysexOut->setTextWhenNothingSelected (String::empty); |
|
||||||
sysexOut->setTextWhenNoChoicesAvailable (TRANS("(no choices)")); |
|
||||||
sysexOut->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (sysexChl = new Slider ("sysexChl")); |
|
||||||
sysexChl->setRange (1, 16, 1); |
|
||||||
sysexChl->setSliderStyle (Slider::RotaryVerticalDrag); |
|
||||||
sysexChl->setTextBoxStyle (Slider::TextBoxLeft, false, 80, 20); |
|
||||||
sysexChl->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (engineReso = new ComboBox ("new combo box")); |
|
||||||
engineReso->setEditableText (false); |
|
||||||
engineReso->setJustificationType (Justification::centredLeft); |
|
||||||
engineReso->setTextWhenNothingSelected (String::empty); |
|
||||||
engineReso->setTextWhenNoChoicesAvailable (TRANS("(no choices)")); |
|
||||||
engineReso->addItem (TRANS("Modern (24-bit)"), 1); |
|
||||||
engineReso->addItem (TRANS("Mark I"), 2); |
|
||||||
engineReso->addItem (TRANS("OPL Series"), 3); |
|
||||||
engineReso->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (showKeyboard = new ToggleButton ("showKeyboard")); |
|
||||||
showKeyboard->setButtonText (String::empty); |
|
||||||
|
|
||||||
addAndMakeVisible (whlRange = new Slider ("whlRange")); |
|
||||||
whlRange->setRange (0, 99, 1); |
|
||||||
whlRange->setSliderStyle (Slider::RotaryVerticalDrag); |
|
||||||
whlRange->setTextBoxStyle (Slider::TextBoxLeft, false, 80, 20); |
|
||||||
whlRange->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (ftRange = new Slider ("ftRange")); |
|
||||||
ftRange->setRange (0, 99, 1); |
|
||||||
ftRange->setSliderStyle (Slider::RotaryVerticalDrag); |
|
||||||
ftRange->setTextBoxStyle (Slider::TextBoxLeft, false, 80, 20); |
|
||||||
ftRange->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (brRange = new Slider ("brRange")); |
|
||||||
brRange->setRange (0, 99, 1); |
|
||||||
brRange->setSliderStyle (Slider::RotaryVerticalDrag); |
|
||||||
brRange->setTextBoxStyle (Slider::TextBoxLeft, false, 80, 20); |
|
||||||
brRange->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (atRange = new Slider ("atRange")); |
|
||||||
atRange->setRange (0, 99, 1); |
|
||||||
atRange->setSliderStyle (Slider::RotaryVerticalDrag); |
|
||||||
atRange->setTextBoxStyle (Slider::TextBoxLeft, false, 80, 20); |
|
||||||
atRange->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (whlEg = new ToggleButton ("whlEg")); |
|
||||||
whlEg->setButtonText (String::empty); |
|
||||||
whlEg->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (ftEg = new ToggleButton ("ftEg")); |
|
||||||
ftEg->setButtonText (String::empty); |
|
||||||
ftEg->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (brEg = new ToggleButton ("brEg")); |
|
||||||
brEg->setButtonText (String::empty); |
|
||||||
brEg->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (atEg = new ToggleButton ("atEg")); |
|
||||||
atEg->setButtonText (String::empty); |
|
||||||
atEg->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (whlAmp = new ToggleButton ("whlAmp")); |
|
||||||
whlAmp->setButtonText (String::empty); |
|
||||||
whlAmp->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (ftAmp = new ToggleButton ("ftAmp")); |
|
||||||
ftAmp->setButtonText (String::empty); |
|
||||||
ftAmp->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (brAmp = new ToggleButton ("brAmp")); |
|
||||||
brAmp->setButtonText (String::empty); |
|
||||||
brAmp->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (atAmp = new ToggleButton ("atAmp")); |
|
||||||
atAmp->setButtonText (String::empty); |
|
||||||
atAmp->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (whlPitch = new ToggleButton ("whlPitch")); |
|
||||||
whlPitch->setButtonText (String::empty); |
|
||||||
whlPitch->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (ftPitch = new ToggleButton ("ftPitch")); |
|
||||||
ftPitch->setButtonText (String::empty); |
|
||||||
ftPitch->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (brPitch = new ToggleButton ("brPitch")); |
|
||||||
brPitch->setButtonText (String::empty); |
|
||||||
brPitch->addListener (this); |
|
||||||
|
|
||||||
addAndMakeVisible (atPitch = new ToggleButton ("atPitch")); |
|
||||||
atPitch->setButtonText (String::empty); |
|
||||||
atPitch->addListener (this); |
|
||||||
|
|
||||||
|
|
||||||
//[UserPreSize]
|
|
||||||
//[/UserPreSize]
|
|
||||||
|
|
||||||
setSize (710, 350); |
|
||||||
|
|
||||||
|
|
||||||
//[Constructor] You can add your own custom stuff here..
|
|
||||||
pitchRange->setEnabled(pitchStep->getValue() == 0); |
|
||||||
|
|
||||||
StringArray input; |
|
||||||
input.add("None"); |
|
||||||
input.addArray(MidiInput::getDevices()); |
|
||||||
sysexIn->addItemList(input, 2); |
|
||||||
|
|
||||||
StringArray output; |
|
||||||
output.add("None"); |
|
||||||
output.addArray(MidiOutput::getDevices()); |
|
||||||
sysexOut->addItemList(output, 2); |
|
||||||
|
|
||||||
//[/Constructor]
|
|
||||||
} |
|
||||||
|
|
||||||
ParamDialog::~ParamDialog() |
|
||||||
{ |
|
||||||
//[Destructor_pre]. You can add your own custom destruction code here..
|
|
||||||
//[/Destructor_pre]
|
|
||||||
|
|
||||||
pitchRange = nullptr; |
|
||||||
pitchStep = nullptr; |
|
||||||
sysexIn = nullptr; |
|
||||||
sysexOut = nullptr; |
|
||||||
sysexChl = nullptr; |
|
||||||
engineReso = nullptr; |
|
||||||
showKeyboard = nullptr; |
|
||||||
whlRange = nullptr; |
|
||||||
ftRange = nullptr; |
|
||||||
brRange = nullptr; |
|
||||||
atRange = nullptr; |
|
||||||
whlEg = nullptr; |
|
||||||
ftEg = nullptr; |
|
||||||
brEg = nullptr; |
|
||||||
atEg = nullptr; |
|
||||||
whlAmp = nullptr; |
|
||||||
ftAmp = nullptr; |
|
||||||
brAmp = nullptr; |
|
||||||
atAmp = nullptr; |
|
||||||
whlPitch = nullptr; |
|
||||||
ftPitch = nullptr; |
|
||||||
brPitch = nullptr; |
|
||||||
atPitch = nullptr; |
|
||||||
|
|
||||||
|
|
||||||
//[Destructor]. You can add your own custom destruction code here..
|
|
||||||
//[/Destructor]
|
|
||||||
} |
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
void ParamDialog::paint (Graphics& g) |
|
||||||
{ |
|
||||||
//[UserPrePaint] Add your own custom painting code here..
|
|
||||||
//[/UserPrePaint]
|
|
||||||
|
|
||||||
g.fillAll (Colour (0xff3c322f)); |
|
||||||
|
|
||||||
g.setColour (Colours::white); |
|
||||||
g.setFont (Font (15.00f, Font::plain)); |
|
||||||
g.drawText (TRANS("Pitch Bend Range"), |
|
||||||
20, 16, 276, 23, |
|
||||||
Justification::centredLeft, true); |
|
||||||
|
|
||||||
g.setColour (Colours::white); |
|
||||||
g.setFont (Font (15.00f, Font::plain)); |
|
||||||
g.drawText (TRANS("Pitch Bend Step"), |
|
||||||
20, 56, 276, 23, |
|
||||||
Justification::centredLeft, true); |
|
||||||
|
|
||||||
g.setColour (Colours::white); |
|
||||||
g.setFont (Font (15.00f, Font::plain)); |
|
||||||
g.drawText (TRANS("DX7 In"), |
|
||||||
20, 224, 131, 23, |
|
||||||
Justification::centredLeft, true); |
|
||||||
|
|
||||||
g.setColour (Colours::white); |
|
||||||
g.setFont (Font (15.00f, Font::plain)); |
|
||||||
g.drawText (TRANS("DX7 Out"), |
|
||||||
20, 264, 131, 23, |
|
||||||
Justification::centredLeft, true); |
|
||||||
|
|
||||||
g.setColour (Colours::white); |
|
||||||
g.setFont (Font (15.00f, Font::plain)); |
|
||||||
g.drawText (TRANS("DX7 Channel"), |
|
||||||
20, 304, 245, 23, |
|
||||||
Justification::centredLeft, true); |
|
||||||
|
|
||||||
g.setColour (Colours::white); |
|
||||||
g.setFont (Font (15.00f, Font::plain)); |
|
||||||
g.drawText (TRANS("Engine Resolution"), |
|
||||||
20, 156, 276, 23, |
|
||||||
Justification::centredLeft, true); |
|
||||||
|
|
||||||
g.setColour (Colours::black); |
|
||||||
g.fillRect (22, 138, 306, 1); |
|
||||||
|
|
||||||
g.setColour (Colours::black); |
|
||||||
g.fillRect (22, 195, 306, 1); |
|
||||||
|
|
||||||
g.setColour (Colours::white); |
|
||||||
g.setFont (Font (15.00f, Font::plain)); |
|
||||||
g.drawText (TRANS("Show Keyboard"), |
|
||||||
20, 96, 276, 23, |
|
||||||
Justification::centredLeft, true); |
|
||||||
|
|
||||||
g.setColour (Colours::black); |
|
||||||
g.fillRect (352, 11, 1, 325); |
|
||||||
|
|
||||||
g.setColour (Colours::white); |
|
||||||
g.setFont (Font (15.00f, Font::plain)); |
|
||||||
g.drawText (TRANS("Wheel"), |
|
||||||
368, 16, 276, 23, |
|
||||||
Justification::centredLeft, true); |
|
||||||
|
|
||||||
g.setColour (Colours::white); |
|
||||||
g.setFont (Font (15.00f, Font::plain)); |
|
||||||
g.drawText (TRANS("Foot"), |
|
||||||
368, 96, 276, 23, |
|
||||||
Justification::centredLeft, true); |
|
||||||
|
|
||||||
g.setColour (Colours::white); |
|
||||||
g.setFont (Font (15.00f, Font::plain)); |
|
||||||
g.drawText (TRANS("Breath"), |
|
||||||
368, 56, 276, 23, |
|
||||||
Justification::centredLeft, true); |
|
||||||
|
|
||||||
g.setColour (Colours::white); |
|
||||||
g.setFont (Font (15.00f, Font::plain)); |
|
||||||
g.drawText (TRANS("After Touch"), |
|
||||||
368, 136, 276, 23, |
|
||||||
Justification::centredLeft, true); |
|
||||||
|
|
||||||
g.setColour (Colours::white); |
|
||||||
g.setFont (Font (15.00f, Font::plain)); |
|
||||||
g.drawText (TRANS("PITCH"), |
|
||||||
533, 163, 48, 23, |
|
||||||
Justification::centredLeft, true); |
|
||||||
|
|
||||||
g.setColour (Colours::white); |
|
||||||
g.setFont (Font (15.00f, Font::plain)); |
|
||||||
g.drawText (TRANS("AMP"), |
|
||||||
589, 163, 48, 23, |
|
||||||
Justification::centredLeft, true); |
|
||||||
|
|
||||||
g.setColour (Colours::white); |
|
||||||
g.setFont (Font (15.00f, Font::plain)); |
|
||||||
g.drawText (TRANS("EG BIAS"), |
|
||||||
645, 163, 48, 23, |
|
||||||
Justification::centredLeft, true); |
|
||||||
|
|
||||||
//[UserPaint] Add your own custom painting code here..
|
|
||||||
//[/UserPaint]
|
|
||||||
} |
|
||||||
|
|
||||||
void ParamDialog::resized() |
|
||||||
{ |
|
||||||
//[UserPreResize] Add your own custom resize code here..
|
|
||||||
//[/UserPreResize]
|
|
||||||
|
|
||||||
pitchRange->setBounds (264, 16, 72, 24); |
|
||||||
pitchStep->setBounds (264, 56, 72, 24); |
|
||||||
sysexIn->setBounds (104, 224, 224, 24); |
|
||||||
sysexOut->setBounds (104, 264, 224, 24); |
|
||||||
sysexChl->setBounds (264, 304, 72, 24); |
|
||||||
engineReso->setBounds (160, 156, 168, 24); |
|
||||||
showKeyboard->setBounds (264, 96, 56, 24); |
|
||||||
whlRange->setBounds (448, 16, 72, 24); |
|
||||||
ftRange->setBounds (448, 56, 72, 24); |
|
||||||
brRange->setBounds (448, 96, 72, 24); |
|
||||||
atRange->setBounds (448, 136, 72, 24); |
|
||||||
whlEg->setBounds (640, 16, 56, 24); |
|
||||||
ftEg->setBounds (640, 56, 56, 24); |
|
||||||
brEg->setBounds (640, 96, 56, 24); |
|
||||||
atEg->setBounds (640, 136, 56, 24); |
|
||||||
whlAmp->setBounds (584, 16, 56, 24); |
|
||||||
ftAmp->setBounds (584, 56, 56, 24); |
|
||||||
brAmp->setBounds (584, 96, 56, 24); |
|
||||||
atAmp->setBounds (584, 136, 56, 24); |
|
||||||
whlPitch->setBounds (528, 16, 56, 24); |
|
||||||
ftPitch->setBounds (528, 56, 56, 24); |
|
||||||
brPitch->setBounds (528, 96, 56, 24); |
|
||||||
atPitch->setBounds (528, 136, 56, 24); |
|
||||||
//[UserResized] Add your own custom resize handling here..
|
|
||||||
//[/UserResized]
|
|
||||||
} |
|
||||||
|
|
||||||
void ParamDialog::sliderValueChanged (Slider* sliderThatWasMoved) |
|
||||||
{ |
|
||||||
//[UsersliderValueChanged_Pre]
|
|
||||||
//[/UsersliderValueChanged_Pre]
|
|
||||||
|
|
||||||
if (sliderThatWasMoved == pitchRange) |
|
||||||
{ |
|
||||||
//[UserSliderCode_pitchRange] -- add your slider handling code here..
|
|
||||||
//[/UserSliderCode_pitchRange]
|
|
||||||
} |
|
||||||
else if (sliderThatWasMoved == pitchStep) |
|
||||||
{ |
|
||||||
//[UserSliderCode_pitchStep] -- add your slider handling code here..
|
|
||||||
pitchRange->setEnabled(pitchStep->getValue() == 0); |
|
||||||
//[/UserSliderCode_pitchStep]
|
|
||||||
} |
|
||||||
else if (sliderThatWasMoved == sysexChl) |
|
||||||
{ |
|
||||||
//[UserSliderCode_sysexChl] -- add your slider handling code here..
|
|
||||||
//[/UserSliderCode_sysexChl]
|
|
||||||
} |
|
||||||
else if (sliderThatWasMoved == whlRange) |
|
||||||
{ |
|
||||||
//[UserSliderCode_whlRange] -- add your slider handling code here..
|
|
||||||
//[/UserSliderCode_whlRange]
|
|
||||||
} |
|
||||||
else if (sliderThatWasMoved == ftRange) |
|
||||||
{ |
|
||||||
//[UserSliderCode_ftRange] -- add your slider handling code here..
|
|
||||||
//[/UserSliderCode_ftRange]
|
|
||||||
} |
|
||||||
else if (sliderThatWasMoved == brRange) |
|
||||||
{ |
|
||||||
//[UserSliderCode_brRange] -- add your slider handling code here..
|
|
||||||
//[/UserSliderCode_brRange]
|
|
||||||
} |
|
||||||
else if (sliderThatWasMoved == atRange) |
|
||||||
{ |
|
||||||
//[UserSliderCode_atRange] -- add your slider handling code here..
|
|
||||||
//[/UserSliderCode_atRange]
|
|
||||||
} |
|
||||||
|
|
||||||
//[UsersliderValueChanged_Post]
|
|
||||||
//[/UsersliderValueChanged_Post]
|
|
||||||
} |
|
||||||
|
|
||||||
void ParamDialog::comboBoxChanged (ComboBox* comboBoxThatHasChanged) |
|
||||||
{ |
|
||||||
//[UsercomboBoxChanged_Pre]
|
|
||||||
//[/UsercomboBoxChanged_Pre]
|
|
||||||
|
|
||||||
if (comboBoxThatHasChanged == sysexIn) |
|
||||||
{ |
|
||||||
//[UserComboBoxCode_sysexIn] -- add your combo box handling code here..
|
|
||||||
//[/UserComboBoxCode_sysexIn]
|
|
||||||
} |
|
||||||
else if (comboBoxThatHasChanged == sysexOut) |
|
||||||
{ |
|
||||||
//[UserComboBoxCode_sysexOut] -- add your combo box handling code here..
|
|
||||||
//[/UserComboBoxCode_sysexOut]
|
|
||||||
} |
|
||||||
else if (comboBoxThatHasChanged == engineReso) |
|
||||||
{ |
|
||||||
//[UserComboBoxCode_engineReso] -- add your combo box handling code here..
|
|
||||||
//[/UserComboBoxCode_engineReso]
|
|
||||||
} |
|
||||||
|
|
||||||
//[UsercomboBoxChanged_Post]
|
|
||||||
//[/UsercomboBoxChanged_Post]
|
|
||||||
} |
|
||||||
|
|
||||||
void ParamDialog::buttonClicked (Button* buttonThatWasClicked) |
|
||||||
{ |
|
||||||
//[UserbuttonClicked_Pre]
|
|
||||||
//[/UserbuttonClicked_Pre]
|
|
||||||
|
|
||||||
if (buttonThatWasClicked == whlEg) |
|
||||||
{ |
|
||||||
//[UserButtonCode_whlEg] -- add your button handler code here..
|
|
||||||
//[/UserButtonCode_whlEg]
|
|
||||||
} |
|
||||||
else if (buttonThatWasClicked == ftEg) |
|
||||||
{ |
|
||||||
//[UserButtonCode_ftEg] -- add your button handler code here..
|
|
||||||
//[/UserButtonCode_ftEg]
|
|
||||||
} |
|
||||||
else if (buttonThatWasClicked == brEg) |
|
||||||
{ |
|
||||||
//[UserButtonCode_brEg] -- add your button handler code here..
|
|
||||||
//[/UserButtonCode_brEg]
|
|
||||||
} |
|
||||||
else if (buttonThatWasClicked == atEg) |
|
||||||
{ |
|
||||||
//[UserButtonCode_atEg] -- add your button handler code here..
|
|
||||||
//[/UserButtonCode_atEg]
|
|
||||||
} |
|
||||||
else if (buttonThatWasClicked == whlAmp) |
|
||||||
{ |
|
||||||
//[UserButtonCode_whlAmp] -- add your button handler code here..
|
|
||||||
//[/UserButtonCode_whlAmp]
|
|
||||||
} |
|
||||||
else if (buttonThatWasClicked == ftAmp) |
|
||||||
{ |
|
||||||
//[UserButtonCode_ftAmp] -- add your button handler code here..
|
|
||||||
//[/UserButtonCode_ftAmp]
|
|
||||||
} |
|
||||||
else if (buttonThatWasClicked == brAmp) |
|
||||||
{ |
|
||||||
//[UserButtonCode_brAmp] -- add your button handler code here..
|
|
||||||
//[/UserButtonCode_brAmp]
|
|
||||||
} |
|
||||||
else if (buttonThatWasClicked == atAmp) |
|
||||||
{ |
|
||||||
//[UserButtonCode_atAmp] -- add your button handler code here..
|
|
||||||
//[/UserButtonCode_atAmp]
|
|
||||||
} |
|
||||||
else if (buttonThatWasClicked == whlPitch) |
|
||||||
{ |
|
||||||
//[UserButtonCode_whlPitch] -- add your button handler code here..
|
|
||||||
//[/UserButtonCode_whlPitch]
|
|
||||||
} |
|
||||||
else if (buttonThatWasClicked == ftPitch) |
|
||||||
{ |
|
||||||
//[UserButtonCode_ftPitch] -- add your button handler code here..
|
|
||||||
//[/UserButtonCode_ftPitch]
|
|
||||||
} |
|
||||||
else if (buttonThatWasClicked == brPitch) |
|
||||||
{ |
|
||||||
//[UserButtonCode_brPitch] -- add your button handler code here..
|
|
||||||
//[/UserButtonCode_brPitch]
|
|
||||||
} |
|
||||||
else if (buttonThatWasClicked == atPitch) |
|
||||||
{ |
|
||||||
//[UserButtonCode_atPitch] -- add your button handler code here..
|
|
||||||
//[/UserButtonCode_atPitch]
|
|
||||||
} |
|
||||||
|
|
||||||
//[UserbuttonClicked_Post]
|
|
||||||
//[/UserbuttonClicked_Post]
|
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//[MiscUserCode] You can add your own definitions of your custom methods or any other code here...
|
|
||||||
|
|
||||||
void ParamDialog::setDialogValues(Controllers &c, SysexComm &mgr, int reso, bool showKey) { |
|
||||||
pitchRange->setValue(c.values_[kControllerPitchRange]); |
|
||||||
pitchStep->setValue(c.values_[kControllerPitchStep]); |
|
||||||
sysexChl->setValue(mgr.getChl() + 1); |
|
||||||
|
|
||||||
whlRange->setValue(c.wheel.range); |
|
||||||
whlPitch->setToggleState(c.wheel.pitch, dontSendNotification); |
|
||||||
whlPitch->setToggleState(c.wheel.pitch, dontSendNotification); |
|
||||||
whlAmp->setToggleState(c.wheel.amp, dontSendNotification); |
|
||||||
whlEg->setToggleState(c.wheel.eg, dontSendNotification); |
|
||||||
|
|
||||||
ftRange->setValue(c.foot.range); |
|
||||||
ftPitch->setToggleState(c.foot.pitch, dontSendNotification); |
|
||||||
ftAmp->setToggleState(c.foot.amp, dontSendNotification); |
|
||||||
ftEg->setToggleState(c.foot.eg, dontSendNotification); |
|
||||||
|
|
||||||
brRange->setValue(c.breath.range); |
|
||||||
brPitch->setToggleState(c.breath.pitch, dontSendNotification); |
|
||||||
brAmp->setToggleState(c.breath.amp, dontSendNotification); |
|
||||||
brEg->setToggleState(c.breath.eg, dontSendNotification); |
|
||||||
|
|
||||||
atRange->setValue(c.at.range); |
|
||||||
atPitch->setToggleState(c.at.pitch, dontSendNotification); |
|
||||||
atAmp->setToggleState(c.at.amp, dontSendNotification); |
|
||||||
atEg->setToggleState(c.at.eg, dontSendNotification); |
|
||||||
|
|
||||||
StringArray inputs = MidiInput::getDevices(); |
|
||||||
int idx = inputs.indexOf(mgr.getInput()); |
|
||||||
idx = idx == -1 ? 0 : idx + 1; |
|
||||||
sysexIn->setSelectedItemIndex(idx); |
|
||||||
|
|
||||||
StringArray outputs = MidiOutput::getDevices(); |
|
||||||
idx = outputs.indexOf(mgr.getOutput()); |
|
||||||
idx = idx == -1 ? 0 : idx + 1; |
|
||||||
sysexOut->setSelectedItemIndex(idx); |
|
||||||
|
|
||||||
engineReso->setSelectedItemIndex(reso); |
|
||||||
showKeyboard->setToggleState(showKey, false); |
|
||||||
} |
|
||||||
|
|
||||||
bool ParamDialog::getDialogValues(Controllers &c, SysexComm &mgr, int *reso, bool *showKey) { |
|
||||||
bool ret = true; |
|
||||||
|
|
||||||
c.values_[kControllerPitchRange] = pitchRange->getValue(); |
|
||||||
c.values_[kControllerPitchStep] = pitchStep->getValue(); |
|
||||||
|
|
||||||
c.wheel.range = whlRange->getValue(); |
|
||||||
c.wheel.pitch = whlPitch->getToggleState(); |
|
||||||
c.wheel.amp = whlAmp->getToggleState(); |
|
||||||
c.wheel.eg = whlEg->getToggleState(); |
|
||||||
|
|
||||||
c.foot.range = ftRange->getValue(); |
|
||||||
c.foot.pitch = ftPitch->getToggleState(); |
|
||||||
c.foot.amp = ftAmp->getToggleState(); |
|
||||||
c.foot.eg = ftEg->getToggleState(); |
|
||||||
|
|
||||||
c.breath.range = brRange->getValue(); |
|
||||||
c.breath.pitch = brPitch->getToggleState(); |
|
||||||
c.breath.amp = brAmp->getToggleState(); |
|
||||||
c.breath.eg = brEg->getToggleState(); |
|
||||||
|
|
||||||
c.at.range = atRange->getValue(); |
|
||||||
c.at.pitch = atPitch->getToggleState(); |
|
||||||
c.at.amp = atAmp->getToggleState(); |
|
||||||
c.at.eg = atEg->getToggleState(); |
|
||||||
|
|
||||||
c.refresh(); |
|
||||||
|
|
||||||
ret &= mgr.setInput(sysexIn->getItemText(sysexIn->getSelectedItemIndex())); |
|
||||||
ret &= mgr.setOutput(sysexOut->getItemText(sysexOut->getSelectedItemIndex())); |
|
||||||
mgr.setChl(sysexChl->getValue() - 1); |
|
||||||
|
|
||||||
*reso = engineReso->getSelectedItemIndex(); |
|
||||||
*showKey = showKeyboard->getToggleState(); |
|
||||||
return ret; |
|
||||||
} |
|
||||||
|
|
||||||
//[/MiscUserCode]
|
|
||||||
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
#if 0 |
|
||||||
/* -- Introjucer information section --
|
|
||||||
|
|
||||||
This is where the Introjucer stores the metadata that describe this GUI layout, so |
|
||||||
make changes in here at your peril! |
|
||||||
|
|
||||||
BEGIN_JUCER_METADATA |
|
||||||
|
|
||||||
<JUCER_COMPONENT documentType="Component" className="ParamDialog" componentName="" |
|
||||||
parentClasses="public Component" constructorParams="" variableInitialisers="" |
|
||||||
snapPixels="8" snapActive="1" snapShown="1" overlayOpacity="0.330" |
|
||||||
fixedSize="1" initialWidth="710" initialHeight="350"> |
|
||||||
<BACKGROUND backgroundColour="ff3c322f"> |
|
||||||
<TEXT pos="20 16 276 23" fill="solid: ffffffff" hasStroke="0" text="Pitch Bend Range" |
|
||||||
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/> |
|
||||||
<TEXT pos="20 56 276 23" fill="solid: ffffffff" hasStroke="0" text="Pitch Bend Step" |
|
||||||
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/> |
|
||||||
<TEXT pos="20 224 131 23" fill="solid: ffffffff" hasStroke="0" text="DX7 In" |
|
||||||
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/> |
|
||||||
<TEXT pos="20 264 131 23" fill="solid: ffffffff" hasStroke="0" text="DX7 Out" |
|
||||||
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/> |
|
||||||
<TEXT pos="20 304 245 23" fill="solid: ffffffff" hasStroke="0" text="DX7 Channel" |
|
||||||
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/> |
|
||||||
<TEXT pos="20 156 276 23" fill="solid: ffffffff" hasStroke="0" text="Engine Resolution" |
|
||||||
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/> |
|
||||||
<RECT pos="22 138 306 1" fill="solid: ff000000" hasStroke="0"/> |
|
||||||
<RECT pos="22 195 306 1" fill="solid: ff000000" hasStroke="0"/> |
|
||||||
<TEXT pos="20 96 276 23" fill="solid: ffffffff" hasStroke="0" text="Show Keyboard" |
|
||||||
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/> |
|
||||||
<RECT pos="352 11 1 325" fill="solid: ff000000" hasStroke="0"/> |
|
||||||
<TEXT pos="368 16 276 23" fill="solid: ffffffff" hasStroke="0" text="Wheel" |
|
||||||
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/> |
|
||||||
<TEXT pos="368 96 276 23" fill="solid: ffffffff" hasStroke="0" text="Foot" |
|
||||||
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/> |
|
||||||
<TEXT pos="368 56 276 23" fill="solid: ffffffff" hasStroke="0" text="Breath" |
|
||||||
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/> |
|
||||||
<TEXT pos="368 136 276 23" fill="solid: ffffffff" hasStroke="0" text="After Touch" |
|
||||||
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/> |
|
||||||
<TEXT pos="533 163 48 23" fill="solid: ffffffff" hasStroke="0" text="PITCH" |
|
||||||
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/> |
|
||||||
<TEXT pos="589 163 48 23" fill="solid: ffffffff" hasStroke="0" text="AMP" |
|
||||||
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/> |
|
||||||
<TEXT pos="645 163 48 23" fill="solid: ffffffff" hasStroke="0" text="EG BIAS" |
|
||||||
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/> |
|
||||||
</BACKGROUND> |
|
||||||
<SLIDER name="pitchRange" id="7409be5a8dfaa91" memberName="pitchRange" |
|
||||||
virtualName="" explicitFocusOrder="0" pos="264 16 72 24" min="0" |
|
||||||
max="12" int="1" style="RotaryVerticalDrag" textBoxPos="TextBoxLeft" |
|
||||||
textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> |
|
||||||
<SLIDER name="pitchStep" id="b86af4b792e768ca" memberName="pitchStep" |
|
||||||
virtualName="" explicitFocusOrder="0" pos="264 56 72 24" min="0" |
|
||||||
max="12" int="1" style="RotaryVerticalDrag" textBoxPos="TextBoxLeft" |
|
||||||
textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> |
|
||||||
<COMBOBOX name="sysexIn" id="3750642d8b5be11" memberName="sysexIn" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="104 224 224 24" editable="0" layout="33" |
|
||||||
items="" textWhenNonSelected="" textWhenNoItems="(no choices)"/> |
|
||||||
<COMBOBOX name="sysexOut" id="44730115841c2214" memberName="sysexOut" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="104 264 224 24" editable="0" layout="33" |
|
||||||
items="" textWhenNonSelected="" textWhenNoItems="(no choices)"/> |
|
||||||
<SLIDER name="sysexChl" id="7fdc8830f90a7c86" memberName="sysexChl" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="264 304 72 24" min="1" max="16" int="1" |
|
||||||
style="RotaryVerticalDrag" textBoxPos="TextBoxLeft" textBoxEditable="1" |
|
||||||
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> |
|
||||||
<COMBOBOX name="new combo box" id="4087ff978c3d9e8d" memberName="engineReso" |
|
||||||
virtualName="" explicitFocusOrder="0" pos="160 156 168 24" editable="0" |
|
||||||
layout="33" items="Modern (24-bit) Mark I OPL Series" |
|
||||||
textWhenNonSelected="" textWhenNoItems="(no choices)"/> |
|
||||||
<TOGGLEBUTTON name="showKeyboard" id="c963d2cb8e49ffd7" memberName="showKeyboard" |
|
||||||
virtualName="" explicitFocusOrder="0" pos="264 96 56 24" buttonText="" |
|
||||||
connectedEdges="0" needsCallback="0" radioGroupId="0" state="0"/> |
|
||||||
<SLIDER name="whlRange" id="3d6522f5f581e580" memberName="whlRange" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="448 16 72 24" min="0" max="99" int="1" |
|
||||||
style="RotaryVerticalDrag" textBoxPos="TextBoxLeft" textBoxEditable="1" |
|
||||||
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> |
|
||||||
<SLIDER name="ftRange" id="cf553f74c3fb0d12" memberName="ftRange" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="448 56 72 24" min="0" max="99" int="1" |
|
||||||
style="RotaryVerticalDrag" textBoxPos="TextBoxLeft" textBoxEditable="1" |
|
||||||
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> |
|
||||||
<SLIDER name="brRange" id="c4aa6814f75016a7" memberName="brRange" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="448 96 72 24" min="0" max="99" int="1" |
|
||||||
style="RotaryVerticalDrag" textBoxPos="TextBoxLeft" textBoxEditable="1" |
|
||||||
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> |
|
||||||
<SLIDER name="atRange" id="d0aa1ebb24284577" memberName="atRange" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="448 136 72 24" min="0" max="99" int="1" |
|
||||||
style="RotaryVerticalDrag" textBoxPos="TextBoxLeft" textBoxEditable="1" |
|
||||||
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> |
|
||||||
<TOGGLEBUTTON name="whlEg" id="d8242ae592c912a" memberName="whlEg" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="640 16 56 24" buttonText="" connectedEdges="0" |
|
||||||
needsCallback="1" radioGroupId="0" state="0"/> |
|
||||||
<TOGGLEBUTTON name="ftEg" id="69d816607bd71cb0" memberName="ftEg" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="640 56 56 24" buttonText="" connectedEdges="0" |
|
||||||
needsCallback="1" radioGroupId="0" state="0"/> |
|
||||||
<TOGGLEBUTTON name="brEg" id="ba89ae54d676983f" memberName="brEg" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="640 96 56 24" buttonText="" connectedEdges="0" |
|
||||||
needsCallback="1" radioGroupId="0" state="0"/> |
|
||||||
<TOGGLEBUTTON name="atEg" id="371934a58ce5f1bc" memberName="atEg" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="640 136 56 24" buttonText="" connectedEdges="0" |
|
||||||
needsCallback="1" radioGroupId="0" state="0"/> |
|
||||||
<TOGGLEBUTTON name="whlAmp" id="3d4e46e63c3ddd86" memberName="whlAmp" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="584 16 56 24" buttonText="" connectedEdges="0" |
|
||||||
needsCallback="1" radioGroupId="0" state="0"/> |
|
||||||
<TOGGLEBUTTON name="ftAmp" id="f631892e209b094a" memberName="ftAmp" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="584 56 56 24" buttonText="" connectedEdges="0" |
|
||||||
needsCallback="1" radioGroupId="0" state="0"/> |
|
||||||
<TOGGLEBUTTON name="brAmp" id="d0a68d37220638f1" memberName="brAmp" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="584 96 56 24" buttonText="" connectedEdges="0" |
|
||||||
needsCallback="1" radioGroupId="0" state="0"/> |
|
||||||
<TOGGLEBUTTON name="atAmp" id="4220c7b22e7845ea" memberName="atAmp" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="584 136 56 24" buttonText="" connectedEdges="0" |
|
||||||
needsCallback="1" radioGroupId="0" state="0"/> |
|
||||||
<TOGGLEBUTTON name="whlPitch" id="b7a626ec1e45af16" memberName="whlPitch" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="528 16 56 24" buttonText="" connectedEdges="0" |
|
||||||
needsCallback="1" radioGroupId="0" state="0"/> |
|
||||||
<TOGGLEBUTTON name="ftPitch" id="1acedf6f16a5a3" memberName="ftPitch" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="528 56 56 24" buttonText="" connectedEdges="0" |
|
||||||
needsCallback="1" radioGroupId="0" state="0"/> |
|
||||||
<TOGGLEBUTTON name="brPitch" id="23fa82533e004b96" memberName="brPitch" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="528 96 56 24" buttonText="" connectedEdges="0" |
|
||||||
needsCallback="1" radioGroupId="0" state="0"/> |
|
||||||
<TOGGLEBUTTON name="atPitch" id="43805c6a4673e291" memberName="atPitch" virtualName="" |
|
||||||
explicitFocusOrder="0" pos="528 136 56 24" buttonText="" connectedEdges="0" |
|
||||||
needsCallback="1" radioGroupId="0" state="0"/> |
|
||||||
</JUCER_COMPONENT> |
|
||||||
|
|
||||||
END_JUCER_METADATA |
|
||||||
*/ |
|
||||||
#endif |
|
||||||
|
|
||||||
|
|
||||||
//[EndFile] You can add extra defines here...
|
|
||||||
//[/EndFile]
|
|
@ -1,100 +0,0 @@ |
|||||||
/*
|
|
||||||
============================================================================== |
|
||||||
|
|
||||||
This is an automatically generated GUI class created by the Introjucer! |
|
||||||
|
|
||||||
Be careful when adding custom code to these files, as only the code within |
|
||||||
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded |
|
||||||
and re-saved. |
|
||||||
|
|
||||||
Created with Introjucer version: 3.2.0 |
|
||||||
|
|
||||||
------------------------------------------------------------------------------ |
|
||||||
|
|
||||||
The Introjucer is part of the JUCE library - "Jules' Utility Class Extensions" |
|
||||||
Copyright (c) 2015 - ROLI Ltd. |
|
||||||
|
|
||||||
============================================================================== |
|
||||||
*/ |
|
||||||
|
|
||||||
#ifndef __JUCE_HEADER_D00F97AD887A66__ |
|
||||||
#define __JUCE_HEADER_D00F97AD887A66__ |
|
||||||
|
|
||||||
//[Headers] -- You can add your own extra header files here --
|
|
||||||
#include "JuceHeader.h" |
|
||||||
#include "msfa/controllers.h" |
|
||||||
#include "SysexComm.h" |
|
||||||
//[/Headers]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/**
|
|
||||||
//[Comments]
|
|
||||||
An auto-generated component, created by the Introjucer. |
|
||||||
|
|
||||||
Describe your class and how it works here! |
|
||||||
//[/Comments]
|
|
||||||
*/ |
|
||||||
class ParamDialog : public Component, |
|
||||||
public SliderListener, |
|
||||||
public ComboBoxListener, |
|
||||||
public ButtonListener |
|
||||||
{ |
|
||||||
public: |
|
||||||
//==============================================================================
|
|
||||||
ParamDialog (); |
|
||||||
~ParamDialog(); |
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
//[UserMethods] -- You can add your own custom methods in this section.
|
|
||||||
void setDialogValues(Controllers &c, SysexComm &mgr, int reso, bool showKeyboard); |
|
||||||
bool getDialogValues(Controllers &c, SysexComm &mgr, int *reso, bool *showKeyboard); |
|
||||||
//[/UserMethods]
|
|
||||||
|
|
||||||
void paint (Graphics& g); |
|
||||||
void resized(); |
|
||||||
void sliderValueChanged (Slider* sliderThatWasMoved); |
|
||||||
void comboBoxChanged (ComboBox* comboBoxThatHasChanged); |
|
||||||
void buttonClicked (Button* buttonThatWasClicked); |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private: |
|
||||||
//[UserVariables] -- You can add your own custom variables in this section.
|
|
||||||
//[/UserVariables]
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
ScopedPointer<Slider> pitchRange; |
|
||||||
ScopedPointer<Slider> pitchStep; |
|
||||||
ScopedPointer<ComboBox> sysexIn; |
|
||||||
ScopedPointer<ComboBox> sysexOut; |
|
||||||
ScopedPointer<Slider> sysexChl; |
|
||||||
ScopedPointer<ComboBox> engineReso; |
|
||||||
ScopedPointer<ToggleButton> showKeyboard; |
|
||||||
ScopedPointer<Slider> whlRange; |
|
||||||
ScopedPointer<Slider> ftRange; |
|
||||||
ScopedPointer<Slider> brRange; |
|
||||||
ScopedPointer<Slider> atRange; |
|
||||||
ScopedPointer<ToggleButton> whlEg; |
|
||||||
ScopedPointer<ToggleButton> ftEg; |
|
||||||
ScopedPointer<ToggleButton> brEg; |
|
||||||
ScopedPointer<ToggleButton> atEg; |
|
||||||
ScopedPointer<ToggleButton> whlAmp; |
|
||||||
ScopedPointer<ToggleButton> ftAmp; |
|
||||||
ScopedPointer<ToggleButton> brAmp; |
|
||||||
ScopedPointer<ToggleButton> atAmp; |
|
||||||
ScopedPointer<ToggleButton> whlPitch; |
|
||||||
ScopedPointer<ToggleButton> ftPitch; |
|
||||||
ScopedPointer<ToggleButton> brPitch; |
|
||||||
ScopedPointer<ToggleButton> atPitch; |
|
||||||
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ParamDialog) |
|
||||||
}; |
|
||||||
|
|
||||||
//[EndFile] You can add extra defines here...
|
|
||||||
//[/EndFile]
|
|
||||||
|
|
||||||
#endif // __JUCE_HEADER_D00F97AD887A66__
|
|
@ -1,452 +0,0 @@ |
|||||||
/**
|
|
||||||
* |
|
||||||
* Copyright (c) 2014-2016 Pascal Gauthier. |
|
||||||
* |
|
||||||
* This program is free software; you can redistribute it and/or modify |
|
||||||
* it under the terms of the GNU General Public License as published by |
|
||||||
* the Free Software Foundation; either version 3 of the License, or |
|
||||||
* (at your option) any later version. |
|
||||||
* |
|
||||||
* This program is distributed in the hope that it will be useful, |
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
* GNU General Public License for more details. |
|
||||||
* |
|
||||||
* You should have received a copy of the GNU General Public License |
|
||||||
* along with this program; if not, write to the Free Software Foundation, |
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
||||||
* |
|
||||||
*/ |
|
||||||
|
|
||||||
#include <time.h> |
|
||||||
|
|
||||||
#include "PluginParam.h" |
|
||||||
#include "PluginProcessor.h" |
|
||||||
#include "PluginData.h" |
|
||||||
#include "Dexed.h" |
|
||||||
|
|
||||||
#include <fstream> |
|
||||||
using namespace ::std; |
|
||||||
|
|
||||||
uint8_t sysexChecksum(const uint8_t *sysex, int size) { |
|
||||||
int sum = 0; |
|
||||||
int i; |
|
||||||
|
|
||||||
for (i = 0; i < size; sum -= sysex[i++]); |
|
||||||
return sum & 0x7F; |
|
||||||
} |
|
||||||
|
|
||||||
void exportSysexPgm(uint8_t *dest, uint8_t *src) { |
|
||||||
uint8_t header[] = { 0xF0, 0x43, 0x00, 0x00, 0x01, 0x1B }; |
|
||||||
|
|
||||||
memcpy(dest, header, 6); |
|
||||||
|
|
||||||
// copy 1 unpacked voices
|
|
||||||
memcpy(dest+6, src, 155); |
|
||||||
|
|
||||||
// put some logic to "mute" an operator if the level is 0
|
|
||||||
|
|
||||||
// make checksum for dump
|
|
||||||
uint8_t footer[] = { sysexChecksum(src, 155), 0xF7 }; |
|
||||||
|
|
||||||
memcpy(dest+161, footer, 2); |
|
||||||
} |
|
||||||
|
|
||||||
/**
|
|
||||||
* Pack a program into a 32 packed sysex |
|
||||||
*/ |
|
||||||
void Cartridge::packProgram(uint8_t *src, int idx, String name, char *opSwitch) { |
|
||||||
uint8_t *bulk = voiceData + 6 + (idx * 128); |
|
||||||
|
|
||||||
for(int op = 0; op < 6; op++) { |
|
||||||
// eg rate and level, brk pt, depth, scaling
|
|
||||||
memcpy(bulk + op * 17, src + op * 21, 11); |
|
||||||
int pp = op*17; |
|
||||||
int up = op*21; |
|
||||||
|
|
||||||
// left curves
|
|
||||||
bulk[pp+11] = (src[up+11]&0x03) | ((src[up+12]&0x03) << 2); |
|
||||||
bulk[pp+12] = (src[up+13]&0x07) | ((src[up+20]&0x0f) << 3); |
|
||||||
// kvs_ams
|
|
||||||
bulk[pp+13] = (src[up+14]&0x03) | ((src[up+15]&0x07) << 2); |
|
||||||
// output lvl
|
|
||||||
if ( opSwitch[op] == '0' ) |
|
||||||
bulk[pp+14] = 0; |
|
||||||
else |
|
||||||
bulk[pp+14] = src[up+16]; |
|
||||||
// fcoarse_mode
|
|
||||||
bulk[pp+15] = (src[up+17]&0x01) | ((src[up+18]&0x1f) << 1); |
|
||||||
// fine freq
|
|
||||||
bulk[pp+16] = src[up+19]; |
|
||||||
} |
|
||||||
memcpy(bulk + 102, src + 126, 9); // pitch env, algo
|
|
||||||
bulk[111] = (src[135]&0x07) | ((src[136]&0x01) << 3); |
|
||||||
memcpy(bulk + 112, src + 137, 4); // lfo
|
|
||||||
bulk[116] = (src[141]&0x01) | (((src[142]&0x07) << 1) | ((src[143]&0x07) << 4)); |
|
||||||
bulk[117] = src[144]; |
|
||||||
|
|
||||||
int eos = 0; |
|
||||||
|
|
||||||
for(int i=0; i < 10; i++) { |
|
||||||
char c = (char) name[i]; |
|
||||||
if ( c == 0 ) |
|
||||||
eos = 1; |
|
||||||
if ( eos ) { |
|
||||||
bulk[118+i] = ' '; |
|
||||||
continue; |
|
||||||
} |
|
||||||
c = c < 32 ? ' ' : c; |
|
||||||
c = c > 127 ? ' ' : c; |
|
||||||
bulk[118+i] = c; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/**
|
|
||||||
* This function normalize data that comes from corrupted sysex. |
|
||||||
* It used to avoid engine crashing upon extrem values |
|
||||||
*/ |
|
||||||
char normparm(char value, char max, int id) { |
|
||||||
if ( value <= max && value >= 0 ) |
|
||||||
return value; |
|
||||||
|
|
||||||
// if this is beyond the max, we expect a 0-255 range, normalize this
|
|
||||||
// to the expected return value; and this value as a random data.
|
|
||||||
|
|
||||||
value = abs(value); |
|
||||||
|
|
||||||
char v = ((float)value)/255 * max; |
|
||||||
|
|
||||||
return v; |
|
||||||
} |
|
||||||
|
|
||||||
void Cartridge::unpackProgram(uint8_t *unpackPgm, int idx) { |
|
||||||
// TODO put this in uint8_t :D
|
|
||||||
char *bulk = (char *)voiceData + 6 + (idx * 128); |
|
||||||
|
|
||||||
for (int op = 0; op < 6; op++) { |
|
||||||
// eg rate and level, brk pt, depth, scaling
|
|
||||||
|
|
||||||
for(int i=0; i<11; i++) { |
|
||||||
unpackPgm[op * 21 + i] = normparm(bulk[op * 17 + i], 99, i); |
|
||||||
} |
|
||||||
|
|
||||||
memcpy(unpackPgm + op * 21, bulk + op * 17, 11); |
|
||||||
char leftrightcurves = bulk[op * 17 + 11]; |
|
||||||
unpackPgm[op * 21 + 11] = leftrightcurves & 3; |
|
||||||
unpackPgm[op * 21 + 12] = (leftrightcurves >> 2) & 3; |
|
||||||
char detune_rs = bulk[op * 17 + 12]; |
|
||||||
unpackPgm[op * 21 + 13] = detune_rs & 7; |
|
||||||
char kvs_ams = bulk[op * 17 + 13]; |
|
||||||
unpackPgm[op * 21 + 14] = kvs_ams & 3; |
|
||||||
unpackPgm[op * 21 + 15] = kvs_ams >> 2; |
|
||||||
unpackPgm[op * 21 + 16] = bulk[op * 17 + 14]; // output level
|
|
||||||
char fcoarse_mode = bulk[op * 17 + 15]; |
|
||||||
unpackPgm[op * 21 + 17] = fcoarse_mode & 1; |
|
||||||
unpackPgm[op * 21 + 18] = fcoarse_mode >> 1; |
|
||||||
unpackPgm[op * 21 + 19] = bulk[op * 17 + 16]; // fine freq
|
|
||||||
unpackPgm[op * 21 + 20] = detune_rs >> 3; |
|
||||||
} |
|
||||||
|
|
||||||
for (int i=0; i<8; i++) { |
|
||||||
unpackPgm[126+i] = normparm(bulk[102+i], 99, 126+i); |
|
||||||
} |
|
||||||
unpackPgm[134] = normparm(bulk[110], 31, 134); |
|
||||||
|
|
||||||
char oks_fb = bulk[111]; |
|
||||||
unpackPgm[135] = oks_fb & 7; |
|
||||||
unpackPgm[136] = oks_fb >> 3; |
|
||||||
memcpy(unpackPgm + 137, bulk + 112, 4); // lfo
|
|
||||||
char lpms_lfw_lks = bulk[116]; |
|
||||||
unpackPgm[141] = lpms_lfw_lks & 1; |
|
||||||
unpackPgm[142] = (lpms_lfw_lks >> 1) & 7; |
|
||||||
unpackPgm[143] = lpms_lfw_lks >> 4; |
|
||||||
memcpy(unpackPgm + 144, bulk + 117, 11); // transpose, name
|
|
||||||
unpackPgm[155] = 1; // operator on/off (DEPRECATED)
|
|
||||||
unpackPgm[156] = 1; |
|
||||||
unpackPgm[157] = 1; |
|
||||||
unpackPgm[158] = 1; |
|
||||||
unpackPgm[159] = 1; |
|
||||||
unpackPgm[160] = 1; |
|
||||||
} |
|
||||||
|
|
||||||
void DexedAudioProcessor::loadCartridge(Cartridge &sysex) { |
|
||||||
currentCart = sysex; |
|
||||||
currentCart.getProgramNames(programNames); |
|
||||||
} |
|
||||||
|
|
||||||
void DexedAudioProcessor::updateProgramFromSysex(const uint8_t *rawdata) { |
|
||||||
memcpy(data, rawdata, 161); |
|
||||||
lfo.reset(data + 137); |
|
||||||
triggerAsyncUpdate(); |
|
||||||
} |
|
||||||
|
|
||||||
void DexedAudioProcessor::setupStartupCart() { |
|
||||||
File startup = dexedCartDir.getChildFile("Dexed_01.syx"); |
|
||||||
|
|
||||||
if ( currentCart.load(startup) != -1 ) |
|
||||||
return; |
|
||||||
|
|
||||||
// The user deleted the file :/, load from the builtin zip file.
|
|
||||||
MemoryInputStream *mis = new MemoryInputStream(BinaryData::builtin_pgm_zip, BinaryData::builtin_pgm_zipSize, false); |
|
||||||
ZipFile *builtin_pgm = new ZipFile(mis, true); |
|
||||||
InputStream *is = builtin_pgm->createStreamForEntry(builtin_pgm->getIndexOfFileName(("Dexed_01.syx"))); |
|
||||||
Cartridge init; |
|
||||||
|
|
||||||
if ( init.load(*is) != -1 ) |
|
||||||
loadCartridge(init); |
|
||||||
|
|
||||||
delete is; |
|
||||||
delete builtin_pgm; |
|
||||||
} |
|
||||||
|
|
||||||
void DexedAudioProcessor::resetToInitVoice() { |
|
||||||
const char init_voice[] = |
|
||||||
{ 99, 99, 99, 99, 99, 99, 99, 00, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 7, |
|
||||||
99, 99, 99, 99, 99, 99, 99, 00, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 7, |
|
||||||
99, 99, 99, 99, 99, 99, 99, 00, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 7, |
|
||||||
99, 99, 99, 99, 99, 99, 99, 00, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 7, |
|
||||||
99, 99, 99, 99, 99, 99, 99, 00, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 7, |
|
||||||
99, 99, 99, 99, 99, 99, 99, 00, 39, 0, 0, 0, 0, 0, 0, 0, 99, 0, 1, 0, 7, |
|
||||||
99, 99, 99, 99, 50, 50, 50, 50, 0, 0, 1, 35, 0, 0, 0, 1, 0, 3, 24, |
|
||||||
73, 78, 73, 84, 32, 86, 79, 73, 67, 69 }; |
|
||||||
|
|
||||||
for(int i=0;i<sizeof(init_voice);i++) { |
|
||||||
data[i] = init_voice[i]; |
|
||||||
} |
|
||||||
panic(); |
|
||||||
triggerAsyncUpdate(); |
|
||||||
} |
|
||||||
|
|
||||||
void DexedAudioProcessor::copyToClipboard(int srcOp) { |
|
||||||
memcpy(clipboard, data, 161); |
|
||||||
clipboardContent = srcOp; |
|
||||||
} |
|
||||||
|
|
||||||
void DexedAudioProcessor::pasteOpFromClipboard(int destOp) { |
|
||||||
memcpy(data+(destOp*21), clipboard+(clipboardContent*21), 21); |
|
||||||
triggerAsyncUpdate(); |
|
||||||
} |
|
||||||
|
|
||||||
void DexedAudioProcessor::pasteEnvFromClipboard(int destOp) { |
|
||||||
memcpy(data+(destOp*21), clipboard+(clipboardContent*21), 8); |
|
||||||
triggerAsyncUpdate(); |
|
||||||
} |
|
||||||
|
|
||||||
void DexedAudioProcessor::sendCurrentSysexProgram() { |
|
||||||
uint8_t raw[163]; |
|
||||||
|
|
||||||
exportSysexPgm(raw, data); |
|
||||||
if ( sysexComm.isOutputActive() ) { |
|
||||||
sysexComm.send(MidiMessage(raw, 163)); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void DexedAudioProcessor::sendCurrentSysexCartridge() { |
|
||||||
uint8_t raw[4104]; |
|
||||||
|
|
||||||
currentCart.saveVoice(raw); |
|
||||||
if ( sysexComm.isOutputActive() ) { |
|
||||||
sysexComm.send(MidiMessage(raw, 4104)); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void DexedAudioProcessor::sendSysexCartridge(File cart) { |
|
||||||
if ( ! sysexComm.isOutputActive() ) |
|
||||||
return; |
|
||||||
|
|
||||||
FileInputStream *fis = cart.createInputStream(); |
|
||||||
if ( fis == NULL ) { |
|
||||||
String f = cart.getFullPathName(); |
|
||||||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, |
|
||||||
"Error", |
|
||||||
"Unable to open: " + f); |
|
||||||
} |
|
||||||
|
|
||||||
uint8 syx_data[65535]; |
|
||||||
int sz = fis->read(syx_data, 65535); |
|
||||||
delete fis; |
|
||||||
|
|
||||||
if (syx_data[0] != 0xF0) { |
|
||||||
String f = cart.getFullPathName(); |
|
||||||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, |
|
||||||
"Error", |
|
||||||
"File: " + f + " doesn't seems to contain any sysex data"); |
|
||||||
return; |
|
||||||
} |
|
||||||
sysexComm.send(MidiMessage(syx_data, sz)); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
bool DexedAudioProcessor::hasClipboardContent() { |
|
||||||
return clipboardContent != -1; |
|
||||||
} |
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
void DexedAudioProcessor::getStateInformation(MemoryBlock& destData) { |
|
||||||
// You should use this method to store your parameters in the memory block.
|
|
||||||
// You could do that either as raw data, or use the XML or ValueTree classes
|
|
||||||
// as intermediaries to make it easy to save and load complex data.
|
|
||||||
|
|
||||||
// used to SAVE plugin state
|
|
||||||
|
|
||||||
XmlElement dexedState("dexedState"); |
|
||||||
XmlElement *dexedBlob = dexedState.createNewChildElement("dexedBlob"); |
|
||||||
|
|
||||||
dexedState.setAttribute("cutoff", fx.uiCutoff); |
|
||||||
dexedState.setAttribute("reso", fx.uiReso); |
|
||||||
dexedState.setAttribute("gain", fx.uiGain); |
|
||||||
dexedState.setAttribute("currentProgram", currentProgram); |
|
||||||
dexedState.setAttribute("monoMode", monoMode); |
|
||||||
dexedState.setAttribute("engineType", (int) engineType); |
|
||||||
dexedState.setAttribute("masterTune", controllers.masterTune); |
|
||||||
dexedState.setAttribute("opSwitch", controllers.opSwitch); |
|
||||||
|
|
||||||
char mod_cfg[15]; |
|
||||||
controllers.wheel.setConfig(mod_cfg); |
|
||||||
dexedState.setAttribute("wheelMod", mod_cfg); |
|
||||||
controllers.foot.setConfig(mod_cfg); |
|
||||||
dexedState.setAttribute("footMod", mod_cfg); |
|
||||||
controllers.breath.setConfig(mod_cfg); |
|
||||||
dexedState.setAttribute("breathMod", mod_cfg); |
|
||||||
controllers.at.setConfig(mod_cfg); |
|
||||||
dexedState.setAttribute("aftertouchMod", mod_cfg); |
|
||||||
|
|
||||||
if ( activeFileCartridge.exists() ) |
|
||||||
dexedState.setAttribute("activeFileCartridge", activeFileCartridge.getFullPathName()); |
|
||||||
|
|
||||||
NamedValueSet blobSet; |
|
||||||
blobSet.set("sysex", var((void *) currentCart.getVoiceSysex(), 4104)); |
|
||||||
blobSet.set("program", var((void *) &data, 161)); |
|
||||||
|
|
||||||
blobSet.copyToXmlAttributes(*dexedBlob); |
|
||||||
copyXmlToBinary(dexedState, destData); |
|
||||||
} |
|
||||||
|
|
||||||
void DexedAudioProcessor::setStateInformation(const void* source, int sizeInBytes) { |
|
||||||
// You should use this method to restore your parameters from this memory block,
|
|
||||||
// whose contents will have been created by the getStateInformation() call.
|
|
||||||
|
|
||||||
// used to LOAD plugin state
|
|
||||||
ScopedPointer<XmlElement> root(getXmlFromBinary(source, sizeInBytes)); |
|
||||||
|
|
||||||
if (root == nullptr) { |
|
||||||
TRACE("unkown state format"); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
fx.uiCutoff = root->getDoubleAttribute("cutoff"); |
|
||||||
fx.uiReso = root->getDoubleAttribute("reso"); |
|
||||||
fx.uiGain = root->getDoubleAttribute("gain"); |
|
||||||
currentProgram = root->getIntAttribute("currentProgram"); |
|
||||||
|
|
||||||
String opSwitchValue = root->getStringAttribute("opSwitch"); |
|
||||||
if ( opSwitchValue.length() != 6 ) { |
|
||||||
strcpy(controllers.opSwitch, "111111"); |
|
||||||
} else { |
|
||||||
strncpy(controllers.opSwitch, opSwitchValue.toRawUTF8(), 6); |
|
||||||
} |
|
||||||
|
|
||||||
controllers.wheel.parseConfig(root->getStringAttribute("wheelMod").toRawUTF8()); |
|
||||||
controllers.foot.parseConfig(root->getStringAttribute("footMod").toRawUTF8()); |
|
||||||
controllers.breath.parseConfig(root->getStringAttribute("breathMod").toRawUTF8()); |
|
||||||
controllers.at.parseConfig(root->getStringAttribute("aftertouchMod").toRawUTF8()); |
|
||||||
|
|
||||||
setEngineType(root->getIntAttribute("engineType", 1)); |
|
||||||
monoMode = root->getIntAttribute("monoMode", 0); |
|
||||||
controllers.masterTune = root->getIntAttribute("masterTune", 0); |
|
||||||
|
|
||||||
File possibleCartridge = File(root->getStringAttribute("activeFileCartridge")); |
|
||||||
if ( possibleCartridge.exists() ) |
|
||||||
activeFileCartridge = possibleCartridge; |
|
||||||
|
|
||||||
XmlElement *dexedBlob = root->getChildByName("dexedBlob"); |
|
||||||
if ( dexedBlob == NULL ) { |
|
||||||
TRACE("dexedBlob element not found"); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
NamedValueSet blobSet; |
|
||||||
blobSet.setFromXmlAttributes(*dexedBlob); |
|
||||||
|
|
||||||
var sysex_blob = blobSet["sysex"]; |
|
||||||
var program = blobSet["program"]; |
|
||||||
|
|
||||||
if ( sysex_blob.isVoid() || program.isVoid() ) { |
|
||||||
TRACE("unkown serialized blob data"); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
Cartridge cart; |
|
||||||
cart.load((uint8 *)sysex_blob.getBinaryData()->getData(), 4104); |
|
||||||
loadCartridge(cart); |
|
||||||
memcpy(data, program.getBinaryData()->getData(), 161); |
|
||||||
|
|
||||||
lastStateSave = (long) time(NULL); |
|
||||||
TRACE("setting VST STATE"); |
|
||||||
updateUI(); |
|
||||||
} |
|
||||||
|
|
||||||
File DexedAudioProcessor::dexedAppDir; |
|
||||||
File DexedAudioProcessor::dexedCartDir; |
|
||||||
|
|
||||||
void DexedAudioProcessor::resolvAppDir() { |
|
||||||
#if JUCE_MAC || JUCE_IOS |
|
||||||
File parent = File::getSpecialLocation(File::currentExecutableFile).getParentDirectory().getParentDirectory().getParentDirectory().getSiblingFile("Dexed"); |
|
||||||
|
|
||||||
if ( parent.isDirectory() ) { |
|
||||||
dexedAppDir = parent; |
|
||||||
} else { |
|
||||||
dexedAppDir = File("~/Library/Application Support/DigitalSuburban/Dexed"); |
|
||||||
} |
|
||||||
#elif JUCE_WINDOWS |
|
||||||
if ( File::getSpecialLocation(File::currentExecutableFile).getSiblingFile("Dexed").isDirectory() ) { |
|
||||||
dexedAppDir = File::getSpecialLocation(File::currentExecutableFile).getSiblingFile("Dexed"); |
|
||||||
} else { |
|
||||||
dexedAppDir = File::getSpecialLocation(File::userApplicationDataDirectory).getChildFile("DigitalSuburban").getChildFile("Dexed"); |
|
||||||
} |
|
||||||
#else |
|
||||||
if ( File::getSpecialLocation(File::currentExecutableFile).getSiblingFile("Dexed").isDirectory() ) { |
|
||||||
dexedAppDir = File::getSpecialLocation(File::currentExecutableFile).getSiblingFile("Dexed"); |
|
||||||
} else { |
|
||||||
char *xdgHome = getenv("XDG_DATA_HOME"); |
|
||||||
if ( xdgHome == nullptr ) { |
|
||||||
dexedAppDir = File("~/.local/share").getChildFile("DigitalSuburban").getChildFile("Dexed"); |
|
||||||
} else { |
|
||||||
dexedAppDir = File(xdgHome).getChildFile("DigitalSuburban").getChildFile("Dexed"); |
|
||||||
} |
|
||||||
} |
|
||||||
#endif |
|
||||||
|
|
||||||
if ( ! dexedAppDir.exists() ) { |
|
||||||
dexedAppDir.createDirectory(); |
|
||||||
// ==========================================================================
|
|
||||||
// For older versions, we move the Dexed.xml config file
|
|
||||||
// This code will be removed in 0.9.0
|
|
||||||
File cfgFile = dexedAppDir.getParentDirectory().getChildFile("Dexed.xml"); |
|
||||||
if ( cfgFile.exists() ) |
|
||||||
cfgFile.moveFileTo(dexedAppDir.getChildFile("Dexed.xml")); |
|
||||||
// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
|
|
||||||
// ==========================================================================
|
|
||||||
} |
|
||||||
|
|
||||||
dexedCartDir = dexedAppDir.getChildFile("Cartridges"); |
|
||||||
|
|
||||||
if ( ! dexedCartDir.exists() ) { |
|
||||||
// Initial setup, we unzip the built-in cartridges
|
|
||||||
dexedCartDir.createDirectory(); |
|
||||||
File synprezFmDir = dexedCartDir.getChildFile("SynprezFM"); |
|
||||||
synprezFmDir.createDirectory(); |
|
||||||
|
|
||||||
MemoryInputStream *mis = new MemoryInputStream(BinaryData::builtin_pgm_zip, BinaryData::builtin_pgm_zipSize, false); |
|
||||||
ZipFile *builtin_pgm = new ZipFile(mis, true); |
|
||||||
|
|
||||||
for(int i=0;i<builtin_pgm->getNumEntries();i++) { |
|
||||||
if ( builtin_pgm->getEntry(i)->filename == "Dexed_01.syx" ) { |
|
||||||
builtin_pgm->uncompressEntry(i, dexedCartDir); |
|
||||||
} else { |
|
||||||
builtin_pgm->uncompressEntry(i, synprezFmDir); |
|
||||||
} |
|
||||||
} |
|
||||||
delete builtin_pgm; |
|
||||||
} |
|
||||||
} |
|
@ -1,247 +0,0 @@ |
|||||||
/**
|
|
||||||
* |
|
||||||
* Copyright (c) 2014-2016 Pascal Gauthier. |
|
||||||
* |
|
||||||
* This program is free software; you can redistribute it and/or modify |
|
||||||
* it under the terms of the GNU General Public License as published by |
|
||||||
* the Free Software Foundation; either version 3 of the License, or |
|
||||||
* (at your option) any later version. |
|
||||||
* |
|
||||||
* This program is distributed in the hope that it will be useful, |
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
* GNU General Public License for more details. |
|
||||||
* |
|
||||||
* You should have received a copy of the GNU General Public License |
|
||||||
* along with this program; if not, write to the Free Software Foundation, |
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
||||||
* |
|
||||||
*/ |
|
||||||
|
|
||||||
#ifndef PLUGINDATA_H_INCLUDED |
|
||||||
#define PLUGINDATA_H_INCLUDED |
|
||||||
|
|
||||||
#include "../JuceLibraryCode/JuceHeader.h" |
|
||||||
|
|
||||||
#include <stdint.h> |
|
||||||
#include <string.h> |
|
||||||
#include "Dexed.h" |
|
||||||
|
|
||||||
uint8_t sysexChecksum(const uint8_t *sysex, int size); |
|
||||||
void exportSysexPgm(uint8_t *dest, uint8_t *src); |
|
||||||
|
|
||||||
#define SYSEX_HEADER { 0xF0, 0x43, 0x00, 0x09, 0x20, 0x00 } |
|
||||||
#define SYSEX_SIZE 4104 |
|
||||||
|
|
||||||
class Cartridge { |
|
||||||
uint8_t voiceData[SYSEX_SIZE]; |
|
||||||
uint8_t perfData[SYSEX_SIZE]; |
|
||||||
|
|
||||||
void setHeader() { |
|
||||||
uint8 voiceHeader[] = SYSEX_HEADER; |
|
||||||
memcpy(voiceData, voiceHeader, 6); |
|
||||||
voiceData[4102] = sysexChecksum(voiceData+6, 4096); |
|
||||||
voiceData[4103] = 0xF7; |
|
||||||
} |
|
||||||
|
|
||||||
public: |
|
||||||
Cartridge() { } |
|
||||||
|
|
||||||
Cartridge(const Cartridge &cpy) { |
|
||||||
memcpy(voiceData, cpy.voiceData, SYSEX_SIZE); |
|
||||||
memcpy(perfData, cpy.perfData, SYSEX_SIZE); |
|
||||||
} |
|
||||||
|
|
||||||
static String normalizePgmName(const char *sysexName) { |
|
||||||
char buffer[11]; |
|
||||||
|
|
||||||
memcpy(buffer, sysexName, 10); |
|
||||||
|
|
||||||
for (int j = 0; j < 10; j++) { |
|
||||||
char c = (unsigned char) buffer[j]; |
|
||||||
switch (c) { |
|
||||||
case 92: |
|
||||||
c = 'Y'; |
|
||||||
break; /* yen */ |
|
||||||
case 126: |
|
||||||
c = '>'; |
|
||||||
break; /* >> */ |
|
||||||
case 127: |
|
||||||
c = '<'; |
|
||||||
break; /* << */ |
|
||||||
default: |
|
||||||
if (c < 32 || c > 127) |
|
||||||
c = 32; |
|
||||||
break; |
|
||||||
} |
|
||||||
buffer[j] = c; |
|
||||||
} |
|
||||||
buffer[10] = 0; |
|
||||||
|
|
||||||
return String(buffer); |
|
||||||
} |
|
||||||
|
|
||||||
int load(File f) { |
|
||||||
FileInputStream *fis = f.createInputStream(); |
|
||||||
if ( fis == NULL ) |
|
||||||
return -1; |
|
||||||
int rc = load(*fis); |
|
||||||
delete fis; |
|
||||||
return rc; |
|
||||||
} |
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads sysex stream |
|
||||||
* Returns 0 if it was parsed sucessfully |
|
||||||
* Returns -1 if it cannot open the stream |
|
||||||
*/ |
|
||||||
int load(InputStream &fis) { |
|
||||||
uint8 buffer[65535]; |
|
||||||
int sz = fis.read(buffer, 65535); |
|
||||||
if ( sz == 0 ) |
|
||||||
return -1; |
|
||||||
return load(buffer, sz); |
|
||||||
} |
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads sysex buffer |
|
||||||
* Returns 0 if it was parsed sucessfully |
|
||||||
* Returns 1 if sysex checksum didn't match |
|
||||||
* Returns 2 if no sysex data found, probably random data |
|
||||||
*/ |
|
||||||
int load(const uint8_t *stream, int size) { |
|
||||||
const uint8 voiceHeaderBroken[] = { 0xF0, 0x43, 0x00, 0x00, 0x20, 0x00 }; |
|
||||||
// I've added a stupid bug that saved the wrong sysex data for dx7 sysex (0.9.1)
|
|
||||||
// This is there to support this version. One day we will be able to remove this. :(
|
|
||||||
|
|
||||||
uint8 voiceHeader[] = SYSEX_HEADER; |
|
||||||
uint8 tmp[65535]; |
|
||||||
uint8 *pos = tmp; |
|
||||||
int status = 3; |
|
||||||
|
|
||||||
if ( size > 65535 ) |
|
||||||
size = 65535; |
|
||||||
|
|
||||||
memcpy(tmp, stream, size); |
|
||||||
|
|
||||||
while(size >= 4104) { |
|
||||||
// random data
|
|
||||||
if ( pos[0] != 0xF0 ) { |
|
||||||
if ( status != 3 ) |
|
||||||
return status; |
|
||||||
memcpy(voiceData, pos+6, 4096); |
|
||||||
return 2; |
|
||||||
} |
|
||||||
|
|
||||||
pos[3] = 0; |
|
||||||
if ( memcmp(pos, voiceHeader, 6) == 0 || memcmp(pos, voiceHeaderBroken, 6) == 0) { |
|
||||||
memcpy(voiceData, pos, SYSEX_SIZE); |
|
||||||
if ( sysexChecksum(voiceData + 6, 4096) == pos[4102] ) |
|
||||||
status = 0; |
|
||||||
else |
|
||||||
status = 1; |
|
||||||
size -= 4104; |
|
||||||
pos += 4104; |
|
||||||
continue; |
|
||||||
} |
|
||||||
|
|
||||||
// other sysex
|
|
||||||
int i; |
|
||||||
for(i=0;i<size-1;i++) { |
|
||||||
if ( pos[i] == 0xF7 ) |
|
||||||
break; |
|
||||||
} |
|
||||||
size -= i; |
|
||||||
stream += i; |
|
||||||
} |
|
||||||
|
|
||||||
// nothing good has been found, map it then to random data
|
|
||||||
if ( status > 1 ) { |
|
||||||
memcpy(voiceData, pos+6, 4096); |
|
||||||
return 2; |
|
||||||
} |
|
||||||
|
|
||||||
return status; |
|
||||||
} |
|
||||||
|
|
||||||
int saveVoice(File f) { |
|
||||||
setHeader(); |
|
||||||
|
|
||||||
if ( ! f.existsAsFile() ) { |
|
||||||
// file doesn't exists, create it
|
|
||||||
return f.replaceWithData(voiceData, SYSEX_SIZE); |
|
||||||
} |
|
||||||
|
|
||||||
FileInputStream *fis = f.createInputStream(); |
|
||||||
if ( fis == NULL ) |
|
||||||
return -1; |
|
||||||
|
|
||||||
uint8 buffer[65535]; |
|
||||||
int sz = fis->read(buffer, 65535); |
|
||||||
delete fis; |
|
||||||
|
|
||||||
// if the file is smaller than 4104, it probably needs to be overriden.
|
|
||||||
if ( sz <= 4104 ) { |
|
||||||
return f.replaceWithData(voiceData, SYSEX_SIZE); |
|
||||||
} |
|
||||||
|
|
||||||
// To avoid to erase the performance data, we skip the sysex stream until
|
|
||||||
// we see the header 0xF0, 0x43, 0x00, 0x09, 0x20, 0x00
|
|
||||||
|
|
||||||
int pos = 0; |
|
||||||
bool found = 0; |
|
||||||
while(pos < sz) { |
|
||||||
// corrupted sysex, erase everything :
|
|
||||||
if ( buffer[pos] != 0xF0 ) |
|
||||||
return f.replaceWithData(voiceData, SYSEX_SIZE); |
|
||||||
|
|
||||||
uint8_t header[] = SYSEX_HEADER; |
|
||||||
if ( memcmp(buffer+pos, header, 6) ) { |
|
||||||
found = true; |
|
||||||
memcpy(buffer+pos, voiceData, SYSEX_SIZE); |
|
||||||
break; |
|
||||||
} else { |
|
||||||
for(;pos<sz;pos++) { |
|
||||||
if ( buffer[pos] == 0xF7 ) |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
if ( ! found ) |
|
||||||
return -1; |
|
||||||
|
|
||||||
return f.replaceWithData(buffer, sz); |
|
||||||
} |
|
||||||
|
|
||||||
void saveVoice(uint8_t *sysex) { |
|
||||||
setHeader(); |
|
||||||
memcpy(sysex, voiceData, SYSEX_SIZE); |
|
||||||
} |
|
||||||
|
|
||||||
char *getRawVoice() { |
|
||||||
return (char *) voiceData + 6; |
|
||||||
} |
|
||||||
|
|
||||||
char *getVoiceSysex() { |
|
||||||
setHeader(); |
|
||||||
return (char *) voiceData; |
|
||||||
} |
|
||||||
|
|
||||||
void getProgramNames(StringArray &dest) { |
|
||||||
dest.clear(); |
|
||||||
for (int i = 0; i < 32; i++) |
|
||||||
dest.add( normalizePgmName(getRawVoice() + ((i * 128) + 118)) ); |
|
||||||
} |
|
||||||
|
|
||||||
Cartridge operator =(const Cartridge other) { |
|
||||||
memcpy(voiceData, other.voiceData, SYSEX_SIZE); |
|
||||||
memcpy(perfData, other.perfData, SYSEX_SIZE); |
|
||||||
return *this; |
|
||||||
} |
|
||||||
|
|
||||||
void unpackProgram(uint8_t *unpackPgm, int idx); |
|
||||||
void packProgram(uint8_t *src, int idx, String name, char *opSwitch); |
|
||||||
}; |
|
||||||
|
|
||||||
#endif // PLUGINDATA_H_INCLUDED
|
|
@ -1,341 +0,0 @@ |
|||||||
/**
|
|
||||||
* |
|
||||||
* Copyright (c) 2013-2015 Pascal Gauthier. |
|
||||||
* |
|
||||||
* This program is free software; you can redistribute it and/or modify |
|
||||||
* it under the terms of the GNU General Public License as published by |
|
||||||
* the Free Software Foundation; either version 3 of the License, or |
|
||||||
* (at your option) any later version. |
|
||||||
* |
|
||||||
* This program is distributed in the hope that it will be useful, |
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
* GNU General Public License for more details. |
|
||||||
* |
|
||||||
* You should have received a copy of the GNU General Public License |
|
||||||
* along with this program; if not, write to the Free Software Foundation, |
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
||||||
* |
|
||||||
*/ |
|
||||||
|
|
||||||
#include "PluginProcessor.h" |
|
||||||
#include "PluginEditor.h" |
|
||||||
#include "GlobalEditor.h" |
|
||||||
#include "ParamDialog.h" |
|
||||||
#include "SysexComm.h" |
|
||||||
#include "Dexed.h" |
|
||||||
#include "math.h" |
|
||||||
#include "DXLookNFeel.h" |
|
||||||
#include <fstream> |
|
||||||
|
|
||||||
#include "msfa/fm_op_kernel.h" |
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
DexedAudioProcessorEditor::DexedAudioProcessorEditor (DexedAudioProcessor* ownerFilter) |
|
||||||
: AudioProcessorEditor (ownerFilter), |
|
||||||
midiKeyboard (ownerFilter->keyboardState, MidiKeyboardComponent::horizontalKeyboard), |
|
||||||
cartManager(this) |
|
||||||
{ |
|
||||||
LookAndFeel::setDefaultLookAndFeel(DXLookNFeel::getLookAndFeel()); |
|
||||||
|
|
||||||
setSize(866, ownerFilter->showKeyboard ? 674 : 581); |
|
||||||
|
|
||||||
processor = ownerFilter; |
|
||||||
|
|
||||||
background = DXLookNFeel::getLookAndFeel()->background; |
|
||||||
|
|
||||||
// OPERATORS
|
|
||||||
addAndMakeVisible(&(operators[0])); |
|
||||||
operators[0].setBounds(2, 1, 287, 218); |
|
||||||
operators[0].bind(processor, 0); |
|
||||||
|
|
||||||
addAndMakeVisible(&(operators[1])); |
|
||||||
operators[1].setBounds(290, 1, 287, 218); |
|
||||||
operators[1].bind(processor, 1); |
|
||||||
|
|
||||||
addAndMakeVisible(&(operators[2])); |
|
||||||
operators[2].setBounds(578, 1, 287, 218); |
|
||||||
operators[2].bind(processor, 2); |
|
||||||
|
|
||||||
addAndMakeVisible(&(operators[3])); |
|
||||||
operators[3].setBounds(2, 219, 287, 218); |
|
||||||
operators[3].bind(processor, 3); |
|
||||||
|
|
||||||
addAndMakeVisible(&(operators[4])); |
|
||||||
operators[4].setBounds(290, 219, 287, 218); |
|
||||||
operators[4].bind(processor, 4); |
|
||||||
|
|
||||||
addAndMakeVisible(&(operators[5])); |
|
||||||
operators[5].setBounds(578, 219, 287, 218); |
|
||||||
operators[5].bind(processor, 5); |
|
||||||
|
|
||||||
// add the midi keyboard component..
|
|
||||||
addAndMakeVisible (&midiKeyboard); |
|
||||||
|
|
||||||
// The DX7 is a badass on the bass, keep it that way
|
|
||||||
midiKeyboard.setLowestVisibleKey(24); |
|
||||||
|
|
||||||
midiKeyboard.setBounds(4, 581, getWidth() - 8, 90); |
|
||||||
|
|
||||||
addAndMakeVisible(&global); |
|
||||||
global.setBounds(2,436,864,144); |
|
||||||
global.bind(this); |
|
||||||
|
|
||||||
global.setMonoState(processor->isMonoMode()); |
|
||||||
|
|
||||||
rebuildProgramCombobox(); |
|
||||||
global.programs->addListener(this); |
|
||||||
|
|
||||||
addChildComponent(&cartManager); |
|
||||||
|
|
||||||
updateUI(); |
|
||||||
startTimer(100); |
|
||||||
} |
|
||||||
|
|
||||||
DexedAudioProcessorEditor::~DexedAudioProcessorEditor() { |
|
||||||
stopTimer(); |
|
||||||
processor->unbindUI(); |
|
||||||
} |
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
void DexedAudioProcessorEditor::paint (Graphics& g) {
|
|
||||||
g.setColour(background); |
|
||||||
g.fillRoundedRectangle(0.0f, 0.0f, (float) getWidth(), (float) getHeight(), 0); |
|
||||||
} |
|
||||||
|
|
||||||
void DexedAudioProcessorEditor::cartShow() { |
|
||||||
stopTimer();
|
|
||||||
cartManager.resetActiveSysex(); |
|
||||||
cartManager.setBounds(4, 2, 859, 576); |
|
||||||
cartManager.setVisible(true); |
|
||||||
cartManager.initialFocus(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
void DexedAudioProcessorEditor::loadCart(File file) { |
|
||||||
Cartridge cart; |
|
||||||
|
|
||||||
int rc = cart.load(file); |
|
||||||
|
|
||||||
if ( rc < 0 ) { |
|
||||||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, |
|
||||||
"Error", |
|
||||||
"Unable to open: " + file.getFullPathName()); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
if ( rc != 0 ) { |
|
||||||
rc = AlertWindow::showOkCancelBox(AlertWindow::QuestionIcon, "Unable to find DX7 sysex cartridge in file", |
|
||||||
"This sysex file is not for the DX7 or it is corrupted. " |
|
||||||
"Do you still want to load this file as random data ?"); |
|
||||||
if ( rc == 0 ) |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
processor->loadCartridge(cart); |
|
||||||
rebuildProgramCombobox(); |
|
||||||
processor->setCurrentProgram(0); |
|
||||||
global.programs->setSelectedId(processor->getCurrentProgram()+1, dontSendNotification); |
|
||||||
processor->updateHostDisplay(); |
|
||||||
|
|
||||||
processor->activeFileCartridge = file; |
|
||||||
} |
|
||||||
|
|
||||||
void DexedAudioProcessorEditor::saveCart() { |
|
||||||
File startFileName = processor->activeFileCartridge.exists() ? processor->activeFileCartridge : processor->dexedCartDir; |
|
||||||
|
|
||||||
FileChooser fc ("Export DX sysex...", processor->dexedCartDir, "*.syx", 1); |
|
||||||
if ( fc.browseForFileToSave(true) ) { |
|
||||||
if ( ! processor->currentCart.saveVoice(fc.getResults().getReference(0)) ) { |
|
||||||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, |
|
||||||
"Error", |
|
||||||
"Unable to write: " + fc.getResults().getReference(0).getFullPathName()); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void DexedAudioProcessorEditor::parmShow() { |
|
||||||
int tp = processor->getEngineType(); |
|
||||||
|
|
||||||
AlertWindow window("","", AlertWindow::NoIcon, this); |
|
||||||
ParamDialog param; |
|
||||||
param.setColour(AlertWindow::backgroundColourId, Colour(0x32FFFFFF)); |
|
||||||
param.setDialogValues(processor->controllers, processor->sysexComm, tp, processor->showKeyboard); |
|
||||||
|
|
||||||
window.addCustomComponent(¶m); |
|
||||||
window.addButton("OK", 0); |
|
||||||
window.addButton("Cancel" ,1); |
|
||||||
if ( window.runModalLoop() != 0 ) |
|
||||||
return; |
|
||||||
|
|
||||||
bool ret = param.getDialogValues(processor->controllers, processor->sysexComm, &tp, &processor->showKeyboard); |
|
||||||
processor->setEngineType(tp); |
|
||||||
processor->savePreference(); |
|
||||||
|
|
||||||
setSize(866, processor->showKeyboard ? 674 : 581); |
|
||||||
midiKeyboard.repaint(); |
|
||||||
|
|
||||||
if ( ret == false ) { |
|
||||||
AlertWindow::showMessageBoxAsync(AlertWindow::WarningIcon, "Midi Interface", "Error opening midi ports"); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void DexedAudioProcessorEditor::initProgram() { |
|
||||||
processor->resetToInitVoice(); |
|
||||||
} |
|
||||||
|
|
||||||
void DexedAudioProcessorEditor::comboBoxChanged (ComboBox* comboBoxThatHasChanged) { |
|
||||||
processor->setCurrentProgram(global.programs->getSelectedId()-1); |
|
||||||
processor->updateHostDisplay(); |
|
||||||
} |
|
||||||
|
|
||||||
void DexedAudioProcessorEditor::timerCallback() { |
|
||||||
if ( processor->forceRefreshUI ) { |
|
||||||
processor->forceRefreshUI = false; |
|
||||||
updateUI(); |
|
||||||
} |
|
||||||
|
|
||||||
if ( ! processor->peekVoiceStatus() ) |
|
||||||
return; |
|
||||||
|
|
||||||
for(int i=0;i<6;i++) { |
|
||||||
operators[i].updateGain(sqrt(processor->voiceStatus.amp[5 - i]) / 8196); // TODO: FUGLY !!!! change this sqrt nonsens
|
|
||||||
operators[i].updateEnvPos(processor->voiceStatus.ampStep[5 - i]); |
|
||||||
} |
|
||||||
global.updatePitchPos(processor->voiceStatus.pitchStep); |
|
||||||
global.updateVu(processor->vuSignal); |
|
||||||
}
|
|
||||||
|
|
||||||
void DexedAudioProcessorEditor::updateUI() { |
|
||||||
for(int i=0;i<processor->ctrl.size();i++) { |
|
||||||
processor->ctrl[i]->updateComponent(); |
|
||||||
} |
|
||||||
for(int i=0;i<6;i++) { |
|
||||||
operators[i].updateDisplay(); |
|
||||||
} |
|
||||||
rebuildProgramCombobox(); |
|
||||||
global.updateDisplay(); |
|
||||||
} |
|
||||||
|
|
||||||
void DexedAudioProcessorEditor::rebuildProgramCombobox() { |
|
||||||
global.programs->clear(dontSendNotification); |
|
||||||
|
|
||||||
processor->currentCart.getProgramNames(processor->programNames); |
|
||||||
|
|
||||||
for(int i=0;i<processor->getNumPrograms();i++) { |
|
||||||
String id; |
|
||||||
id << (i+1) << ". " << processor->getProgramName(i); |
|
||||||
global.programs->addItem(id, i+1); |
|
||||||
} |
|
||||||
|
|
||||||
global.programs->setSelectedId(processor->getCurrentProgram()+1, dontSendNotification); |
|
||||||
|
|
||||||
String name = Cartridge::normalizePgmName((const char *) processor->data+145); |
|
||||||
cartManager.setActiveProgram(processor->getCurrentProgram(), name); |
|
||||||
if ( name != processor->getProgramName(processor->getCurrentProgram()) ) |
|
||||||
global.programs->setText("**. " + name, dontSendNotification); |
|
||||||
|
|
||||||
cartManager.resetActiveSysex(); |
|
||||||
} |
|
||||||
|
|
||||||
void DexedAudioProcessorEditor::storeProgram() { |
|
||||||
String currentName = Cartridge::normalizePgmName((const char *) processor->data+145); |
|
||||||
Cartridge destSysex = processor->currentCart; |
|
||||||
File *externalFile = NULL; |
|
||||||
|
|
||||||
bool activeCartridgeFound = processor->activeFileCartridge.exists(); |
|
||||||
|
|
||||||
while (true) { |
|
||||||
String msg; |
|
||||||
|
|
||||||
if ( externalFile == NULL ) { |
|
||||||
if ( activeCartridgeFound ) |
|
||||||
msg = "Store program to current (" + processor->activeFileCartridge.getFileName() + ") / new cartridge"; |
|
||||||
else |
|
||||||
msg = "Store program to current / new cartridge"; |
|
||||||
} else { |
|
||||||
msg = "Store program to " + externalFile->getFileName(); |
|
||||||
} |
|
||||||
|
|
||||||
AlertWindow dialog("Store Program", msg, AlertWindow::NoIcon, this); |
|
||||||
dialog.addTextEditor("Name", currentName, String("Name"), false); |
|
||||||
// TODO: fix the name length to 10
|
|
||||||
|
|
||||||
StringArray programs; |
|
||||||
destSysex.getProgramNames(programs); |
|
||||||
dialog.addComboBox("Dest", programs, "Program Destination"); |
|
||||||
|
|
||||||
|
|
||||||
if ( externalFile == NULL ) { |
|
||||||
StringArray saveAction; |
|
||||||
saveAction.add("Store program to DAW plugin song state"); |
|
||||||
saveAction.add("Store program and create a new copy of the .syx cartridge"); |
|
||||||
if ( activeCartridgeFound ) |
|
||||||
saveAction.add("Store program and overwrite current .syx cartridge"); |
|
||||||
|
|
||||||
dialog.addComboBox("SaveAction", saveAction, "Store Action"); |
|
||||||
} |
|
||||||
|
|
||||||
dialog.addButton("OK", 0, KeyPress(KeyPress::returnKey)); |
|
||||||
dialog.addButton("CANCEL", 1, KeyPress(KeyPress::escapeKey)); |
|
||||||
dialog.addButton("EXTERNAL FILE", 2, KeyPress()); |
|
||||||
int response = dialog.runModalLoop(); |
|
||||||
|
|
||||||
if ( response == 2 ) { |
|
||||||
FileChooser fc("Destination Sysex", processor->dexedCartDir, "*.syx;*.SYX;*.*", 1); |
|
||||||
|
|
||||||
if ( fc.browseForFileToOpen() ) { |
|
||||||
if ( externalFile != NULL )
|
|
||||||
delete externalFile; |
|
||||||
|
|
||||||
externalFile = new File(fc.getResults().getReference(0)); |
|
||||||
if ( destSysex.load(*externalFile) ) |
|
||||||
continue; |
|
||||||
AlertWindow::showMessageBoxAsync(AlertWindow::WarningIcon, "Read error", "Unable to read file"); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
if ( response == 0 ) { |
|
||||||
TextEditor *name = dialog.getTextEditor("Name"); |
|
||||||
ComboBox *dest = dialog.getComboBoxComponent("Dest"); |
|
||||||
|
|
||||||
int programNum = dest->getSelectedItemIndex(); |
|
||||||
String programName(name->getText()); |
|
||||||
if ( programName.length() > 10 ) { |
|
||||||
int toStrip = programName.length() - 10; |
|
||||||
programName = programName.dropLastCharacters(toStrip); |
|
||||||
} |
|
||||||
|
|
||||||
if ( externalFile == NULL ) { |
|
||||||
processor->currentCart.packProgram((uint8_t *) processor->data, programNum, programName, processor->controllers.opSwitch); |
|
||||||
rebuildProgramCombobox(); |
|
||||||
processor->setCurrentProgram(programNum); |
|
||||||
processor->updateHostDisplay(); |
|
||||||
|
|
||||||
int action = dialog.getComboBoxComponent("SaveAction")->getSelectedItemIndex(); |
|
||||||
if ( action > 0 ) {
|
|
||||||
File destination = processor->activeFileCartridge; |
|
||||||
if ( ! destination.exists() ) { |
|
||||||
FileChooser fc("Destination Sysex", processor->dexedCartDir, "*.syx", 1); |
|
||||||
if ( ! fc.browseForFileToSave(true) ) |
|
||||||
break; |
|
||||||
destination = fc.getResult(); |
|
||||||
} |
|
||||||
|
|
||||||
processor->currentCart.saveVoice(destination); |
|
||||||
processor->activeFileCartridge = destination; |
|
||||||
} |
|
||||||
} else { |
|
||||||
destSysex.packProgram((uint8_t *) processor->data, programNum, programName, processor->controllers.opSwitch); |
|
||||||
if ( ! destSysex.saveVoice(*externalFile)) { |
|
||||||
AlertWindow::showMessageBoxAsync(AlertWindow::WarningIcon, "Write error", "Unable to write file"); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
break; |
|
||||||
} |
|
||||||
|
|
||||||
if ( externalFile != NULL ) |
|
||||||
delete externalFile; |
|
||||||
cartManager.resetActiveSysex(); |
|
||||||
} |
|
@ -1,61 +0,0 @@ |
|||||||
/**
|
|
||||||
* |
|
||||||
* Copyright (c) 2013-2016 Pascal Gauthier. |
|
||||||
* |
|
||||||
* This program is free software; you can redistribute it and/or modify |
|
||||||
* it under the terms of the GNU General Public License as published by |
|
||||||
* the Free Software Foundation; either version 3 of the License, or |
|
||||||
* (at your option) any later version. |
|
||||||
* |
|
||||||
* This program is distributed in the hope that it will be useful, |
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
* GNU General Public License for more details. |
|
||||||
* |
|
||||||
* You should have received a copy of the GNU General Public License |
|
||||||
* along with this program; if not, write to the Free Software Foundation, |
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
||||||
*/ |
|
||||||
|
|
||||||
#ifndef PLUGINEDITOR_H_INCLUDED |
|
||||||
#define PLUGINEDITOR_H_INCLUDED |
|
||||||
|
|
||||||
#include "../JuceLibraryCode/JuceHeader.h" |
|
||||||
#include "PluginProcessor.h" |
|
||||||
#include "OperatorEditor.h" |
|
||||||
#include "GlobalEditor.h" |
|
||||||
#include "DXComponents.h" |
|
||||||
#include "DXLookNFeel.h" |
|
||||||
#include "CartManager.h" |
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/**
|
|
||||||
*/ |
|
||||||
class DexedAudioProcessorEditor : public AudioProcessorEditor, public ComboBoxListener, public Timer { |
|
||||||
MidiKeyboardComponent midiKeyboard; |
|
||||||
OperatorEditor operators[6]; |
|
||||||
Colour background; |
|
||||||
CartManager cartManager; |
|
||||||
|
|
||||||
public: |
|
||||||
DexedAudioProcessor *processor; |
|
||||||
GlobalEditor global; |
|
||||||
|
|
||||||
DexedAudioProcessorEditor (DexedAudioProcessor* ownerFilter); |
|
||||||
~DexedAudioProcessorEditor(); |
|
||||||
void timerCallback(); |
|
||||||
|
|
||||||
void paint (Graphics& g); |
|
||||||
void comboBoxChanged (ComboBox* comboBoxThatHasChanged); |
|
||||||
void updateUI(); |
|
||||||
void rebuildProgramCombobox(); |
|
||||||
void loadCart(File file); |
|
||||||
void saveCart(); |
|
||||||
void initProgram(); |
|
||||||
void storeProgram(); |
|
||||||
void cartShow(); |
|
||||||
void parmShow(); |
|
||||||
}; |
|
||||||
|
|
||||||
|
|
||||||
#endif // PLUGINEDITOR_H_INCLUDED
|
|
@ -1,705 +0,0 @@ |
|||||||
/**
|
|
||||||
* |
|
||||||
* Copyright (c) 2013-2016 Pascal Gauthier. |
|
||||||
* |
|
||||||
* This program is free software; you can redistribute it and/or modify |
|
||||||
* it under the terms of the GNU General Public License as published by |
|
||||||
* the Free Software Foundation; either version 3 of the License, or |
|
||||||
* (at your option) any later version. |
|
||||||
* |
|
||||||
* This program is distributed in the hope that it will be useful, |
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
* GNU General Public License for more details. |
|
||||||
* |
|
||||||
* You should have received a copy of the GNU General Public License |
|
||||||
* along with this program; if not, write to the Free Software Foundation, |
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
||||||
* |
|
||||||
*/ |
|
||||||
|
|
||||||
#include <time.h> |
|
||||||
#include <stdlib.h> |
|
||||||
|
|
||||||
#include "PluginParam.h" |
|
||||||
#include "PluginProcessor.h" |
|
||||||
#include "PluginEditor.h" |
|
||||||
#include "Dexed.h" |
|
||||||
|
|
||||||
// ************************************************************************
|
|
||||||
// Custom displays
|
|
||||||
|
|
||||||
class CtrlDXLabel : public CtrlDX { |
|
||||||
StringArray labels; |
|
||||||
public: |
|
||||||
CtrlDXLabel(String name, int steps, int offset, StringArray &labels) : CtrlDX(name, steps, offset, 0) { |
|
||||||
this->labels = labels; |
|
||||||
}; |
|
||||||
|
|
||||||
String getValueDisplay() { |
|
||||||
return labels[getValue()]; |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
class CtrlDXTranspose : public CtrlDX { |
|
||||||
public: |
|
||||||
CtrlDXTranspose(String name, int steps, int offset) : CtrlDX(name, steps, offset, 0) { |
|
||||||
}; |
|
||||||
|
|
||||||
String getValueDisplay() { |
|
||||||
String ret; |
|
||||||
int value = getValue(); |
|
||||||
|
|
||||||
switch(value % 12) { |
|
||||||
case 0: ret << "C"; break; |
|
||||||
case 1: ret << "C#"; break; |
|
||||||
case 2: ret << "D"; break; |
|
||||||
case 3: ret << "D#"; break; |
|
||||||
case 4: ret << "E"; break; |
|
||||||
case 5: ret << "F"; break; |
|
||||||
case 6: ret << "F#"; break; |
|
||||||
case 7: ret << "G"; break; |
|
||||||
case 8: ret << "G#"; break; |
|
||||||
case 9: ret << "A"; break; |
|
||||||
case 10: ret << "A#"; break; |
|
||||||
case 11: ret << "B"; break; |
|
||||||
} |
|
||||||
return ret << (value/12+1); |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
class CtrlTune : public Ctrl { |
|
||||||
public: |
|
||||||
DexedAudioProcessor *processor; |
|
||||||
|
|
||||||
CtrlTune(String name, DexedAudioProcessor *owner) : Ctrl(name) { |
|
||||||
processor = owner; |
|
||||||
} |
|
||||||
|
|
||||||
float getValueHost() { |
|
||||||
// meh. good enough for now
|
|
||||||
int32_t tune = processor->controllers.masterTune / (1.0/12); |
|
||||||
tune = (tune >> 11) + 0x2000; |
|
||||||
return (float)tune / 0x4000; |
|
||||||
} |
|
||||||
|
|
||||||
void setValueHost(float v) { |
|
||||||
int32_t tune = (v * 0x4000) - 0x2000; |
|
||||||
processor->controllers.masterTune = ((float) (tune << 11)) * (1.0/12); |
|
||||||
} |
|
||||||
|
|
||||||
String getValueDisplay() { |
|
||||||
String display; |
|
||||||
display << (getValueHost() * 2) -1; |
|
||||||
return display; |
|
||||||
} |
|
||||||
|
|
||||||
void updateComponent() { |
|
||||||
if (slider != NULL) { |
|
||||||
slider->setValue(getValueHost(), dontSendNotification); |
|
||||||
} |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
class CtrlOpSwitch : public Ctrl { |
|
||||||
char *value; |
|
||||||
public : |
|
||||||
CtrlOpSwitch(String name, char *switchValue) : Ctrl(name) { |
|
||||||
value = switchValue; |
|
||||||
} |
|
||||||
|
|
||||||
void setValueHost(float f) { |
|
||||||
if ( f == 0 ) |
|
||||||
*value = '0'; |
|
||||||
else |
|
||||||
*value = '1'; |
|
||||||
} |
|
||||||
|
|
||||||
float getValueHost() { |
|
||||||
if ( *value == '0' ) |
|
||||||
return 0; |
|
||||||
else |
|
||||||
return 1; |
|
||||||
} |
|
||||||
|
|
||||||
String getValueDisplay() { |
|
||||||
String ret; |
|
||||||
ret << label << " " << (*value == '0' ? "OFF" : "ON"); |
|
||||||
return ret; |
|
||||||
} |
|
||||||
|
|
||||||
void updateComponent() { |
|
||||||
if (button != NULL) { |
|
||||||
if (*value == '0') { |
|
||||||
button->setToggleState(false, dontSendNotification); |
|
||||||
} else { |
|
||||||
button->setToggleState(true, dontSendNotification); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
// ************************************************************************
|
|
||||||
//
|
|
||||||
Ctrl::Ctrl(String name) { |
|
||||||
label << name; |
|
||||||
slider = NULL; |
|
||||||
button = NULL; |
|
||||||
comboBox = NULL; |
|
||||||
} |
|
||||||
|
|
||||||
void Ctrl::bind(Slider *s) { |
|
||||||
slider = s; |
|
||||||
updateComponent(); |
|
||||||
s->addListener(this); |
|
||||||
s->addMouseListener(this, true); |
|
||||||
} |
|
||||||
|
|
||||||
void Ctrl::bind(Button *b) { |
|
||||||
button = b; |
|
||||||
updateComponent(); |
|
||||||
b->addListener(this); |
|
||||||
b->addMouseListener(this, true); |
|
||||||
} |
|
||||||
|
|
||||||
void Ctrl::bind(ComboBox *c) { |
|
||||||
comboBox = c; |
|
||||||
updateComponent(); |
|
||||||
c->addListener(this); |
|
||||||
c->addMouseListener(this, true); |
|
||||||
} |
|
||||||
|
|
||||||
void Ctrl::unbind() { |
|
||||||
if (slider != NULL) { |
|
||||||
slider->removeListener(this); |
|
||||||
slider->removeMouseListener(this); |
|
||||||
slider = NULL; |
|
||||||
} |
|
||||||
|
|
||||||
if (button != NULL) { |
|
||||||
button->removeListener(this); |
|
||||||
button->removeMouseListener(this); |
|
||||||
button = NULL; |
|
||||||
} |
|
||||||
|
|
||||||
if (comboBox != NULL) { |
|
||||||
comboBox->removeListener(this); |
|
||||||
comboBox->removeMouseListener(this); |
|
||||||
comboBox = NULL; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void Ctrl::publishValue(float value) { |
|
||||||
parent->beginParameterChangeGesture(idx); |
|
||||||
parent->setParameterNotifyingHost(idx, value); |
|
||||||
parent->endParameterChangeGesture(idx); |
|
||||||
} |
|
||||||
|
|
||||||
void Ctrl::sliderValueChanged(Slider* moved) { |
|
||||||
publishValue(moved->getValue()); |
|
||||||
} |
|
||||||
|
|
||||||
void Ctrl::buttonClicked(Button* clicked) { |
|
||||||
publishValue(clicked->getToggleState()); |
|
||||||
} |
|
||||||
|
|
||||||
void Ctrl::comboBoxChanged(ComboBox* combo) { |
|
||||||
publishValue((combo->getSelectedId() - 1) / combo->getNumItems()); |
|
||||||
} |
|
||||||
|
|
||||||
void Ctrl::mouseEnter(const juce::MouseEvent &event) { |
|
||||||
updateDisplayName(); |
|
||||||
} |
|
||||||
|
|
||||||
void Ctrl::updateDisplayName() { |
|
||||||
} |
|
||||||
|
|
||||||
// ************************************************************************
|
|
||||||
// CtrlDX - control DX mapping
|
|
||||||
CtrlFloat::CtrlFloat(String name, float *storageValue) : Ctrl(name) { |
|
||||||
vPointer = storageValue; |
|
||||||
} |
|
||||||
|
|
||||||
float CtrlFloat::getValueHost() { |
|
||||||
return *vPointer; |
|
||||||
} |
|
||||||
|
|
||||||
void CtrlFloat::setValueHost(float v) { |
|
||||||
*vPointer = v; |
|
||||||
} |
|
||||||
|
|
||||||
String CtrlFloat::getValueDisplay() { |
|
||||||
String display; |
|
||||||
display << *vPointer; |
|
||||||
return display; |
|
||||||
} |
|
||||||
|
|
||||||
void CtrlFloat::updateComponent() { |
|
||||||
if (slider != NULL) { |
|
||||||
slider->setValue(*vPointer, dontSendNotification); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// ************************************************************************
|
|
||||||
// CtrlDX - control DX mapping
|
|
||||||
CtrlDX::CtrlDX(String name, int steps, int offset, int displayValue) : Ctrl(name) { |
|
||||||
this->displayValue = displayValue; |
|
||||||
this->steps = steps; |
|
||||||
dxValue = 0; |
|
||||||
dxOffset = offset; |
|
||||||
} |
|
||||||
|
|
||||||
float CtrlDX::getValueHost() { |
|
||||||
return getValue() / (float) steps; |
|
||||||
} |
|
||||||
|
|
||||||
void CtrlDX::setValueHost(float f) { |
|
||||||
setValue(roundToInt(f * steps)); |
|
||||||
} |
|
||||||
|
|
||||||
void CtrlDX::setValue(int v) { |
|
||||||
TRACE("setting value %d %d", dxOffset, v); |
|
||||||
dxValue = v; |
|
||||||
if (dxOffset >= 0) { |
|
||||||
if (parent != NULL) |
|
||||||
parent->setDxValue(dxOffset, dxValue); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
int CtrlDX::getValue() { |
|
||||||
if (dxOffset >= 0) |
|
||||||
dxValue = parent->data[dxOffset]; |
|
||||||
return dxValue; |
|
||||||
} |
|
||||||
|
|
||||||
int CtrlDX::getOffset() { |
|
||||||
return dxOffset; |
|
||||||
} |
|
||||||
|
|
||||||
String CtrlDX::getValueDisplay() { |
|
||||||
String ret; |
|
||||||
ret << ( getValue() + displayValue ); |
|
||||||
return ret; |
|
||||||
} |
|
||||||
|
|
||||||
void CtrlDX::updateDisplayName() { |
|
||||||
DexedAudioProcessorEditor *editor = (DexedAudioProcessorEditor *) parent->getActiveEditor(); |
|
||||||
if ( editor == NULL ) { |
|
||||||
return; |
|
||||||
} |
|
||||||
String msg; |
|
||||||
msg << label << " = " << getValueDisplay(); |
|
||||||
editor->global.setParamMessage(msg); |
|
||||||
editor->global.repaint(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
void CtrlDX::publishValue(float value) { |
|
||||||
Ctrl::publishValue(value / steps); |
|
||||||
updateDisplayName(); |
|
||||||
} |
|
||||||
|
|
||||||
void CtrlDX::sliderValueChanged(Slider* moved) { |
|
||||||
publishValue(((int) moved->getValue() - displayValue)); |
|
||||||
} |
|
||||||
|
|
||||||
void CtrlDX::comboBoxChanged(ComboBox* combo) { |
|
||||||
publishValue(combo->getSelectedId() - 1); |
|
||||||
} |
|
||||||
|
|
||||||
void CtrlDX::buttonClicked(Button *button) { |
|
||||||
publishValue((int) button->getToggleState()); |
|
||||||
} |
|
||||||
|
|
||||||
void CtrlDX::updateComponent() { |
|
||||||
if (slider != NULL) { |
|
||||||
slider->setValue(getValue() + displayValue, |
|
||||||
dontSendNotification); |
|
||||||
} |
|
||||||
|
|
||||||
if (button != NULL) { |
|
||||||
if (getValue() == 0) { |
|
||||||
button->setToggleState(false, dontSendNotification); |
|
||||||
} else { |
|
||||||
button->setToggleState(true, dontSendNotification); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
if (comboBox != NULL) { |
|
||||||
int cvalue = getValue() + 1; |
|
||||||
if (comboBox->getNumItems() <= cvalue) { |
|
||||||
cvalue = comboBox->getNumItems(); |
|
||||||
} |
|
||||||
comboBox->setSelectedId(cvalue, dontSendNotification); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/***************************************************************
|
|
||||||
* |
|
||||||
*/ |
|
||||||
void DexedAudioProcessor::initCtrl() { |
|
||||||
setupStartupCart(); |
|
||||||
currentProgram = 0; |
|
||||||
|
|
||||||
fxCutoff = new CtrlFloat("Cutoff", &fx.uiCutoff); |
|
||||||
ctrl.add(fxCutoff); |
|
||||||
|
|
||||||
fxReso = new CtrlFloat("Resonance", &fx.uiReso); |
|
||||||
ctrl.add(fxReso); |
|
||||||
|
|
||||||
output = new CtrlFloat("Output", &fx.uiGain); |
|
||||||
ctrl.add(output); |
|
||||||
|
|
||||||
tune = new CtrlTune("MASTER TUNE ADJ", this); |
|
||||||
ctrl.add(tune); |
|
||||||
|
|
||||||
algo = new CtrlDX("ALGORITHM", 31, 134, 1); |
|
||||||
ctrl.add(algo); |
|
||||||
|
|
||||||
feedback = new CtrlDX("FEEDBACK", 7, 135); |
|
||||||
ctrl.add(feedback); |
|
||||||
|
|
||||||
oscSync = new CtrlDX("OSC KEY SYNC", 1, 136); |
|
||||||
ctrl.add(oscSync); |
|
||||||
|
|
||||||
lfoRate = new CtrlDX("LFO SPEED", 99, 137); |
|
||||||
ctrl.add(lfoRate); |
|
||||||
|
|
||||||
lfoDelay = new CtrlDX("LFO DELAY", 99, 138); |
|
||||||
ctrl.add(lfoDelay); |
|
||||||
|
|
||||||
lfoPitchDepth = new CtrlDX("LFO PM DEPTH", 99, 139); |
|
||||||
ctrl.add(lfoPitchDepth); |
|
||||||
|
|
||||||
lfoAmpDepth = new CtrlDX("LFO AM DEPTH", 99, 140); |
|
||||||
ctrl.add(lfoAmpDepth); |
|
||||||
|
|
||||||
lfoSync = new CtrlDX("LFO KEY SYNC", 1, 141); |
|
||||||
ctrl.add(lfoSync); |
|
||||||
|
|
||||||
StringArray lbl; |
|
||||||
lbl.add("TRIANGE"); |
|
||||||
lbl.add("SAW DOWN"); |
|
||||||
lbl.add("SAW UP"); |
|
||||||
lbl.add("SQUARE"); |
|
||||||
lbl.add("SINE"); |
|
||||||
lbl.add("S&HOLD"); |
|
||||||
|
|
||||||
lfoWaveform = new CtrlDXLabel("LFO WAVE", 5, 142, lbl); |
|
||||||
ctrl.add(lfoWaveform); |
|
||||||
|
|
||||||
transpose = new CtrlDXTranspose("MIDDLE C", 48, 144); |
|
||||||
ctrl.add(transpose); |
|
||||||
|
|
||||||
pitchModSens = new CtrlDX("P MODE SENS.", 7, 143); |
|
||||||
ctrl.add(pitchModSens); |
|
||||||
|
|
||||||
for (int i=0;i<4;i++) { |
|
||||||
String rate; |
|
||||||
rate << "PITCH EG RATE " << (i+1); |
|
||||||
pitchEgRate[i] = new CtrlDX(rate, 99, 126+i); |
|
||||||
ctrl.add(pitchEgRate[i]); |
|
||||||
} |
|
||||||
|
|
||||||
for (int i=0;i<4;i++) { |
|
||||||
String level; |
|
||||||
level << "PITCH EG LEVEL " << (i+1); |
|
||||||
pitchEgLevel[i] = new CtrlDX(level, 99, 130+i); |
|
||||||
ctrl.add(pitchEgLevel[i]); |
|
||||||
} |
|
||||||
|
|
||||||
StringArray keyScaleLabels; |
|
||||||
keyScaleLabels.add("-LN"); |
|
||||||
keyScaleLabels.add("-EX"); |
|
||||||
keyScaleLabels.add("+EX"); |
|
||||||
keyScaleLabels.add("+LN"); |
|
||||||
|
|
||||||
// fill operator values;
|
|
||||||
for (int i = 0; i < 6; i++) { |
|
||||||
//// In the Sysex, OP6 comes first, then OP5...
|
|
||||||
int opTarget = (5-i) * 21; |
|
||||||
int opVal = i; |
|
||||||
String opName; |
|
||||||
opName << "OP" << (opVal + 1); |
|
||||||
|
|
||||||
for (int j = 0; j < 4; j++) {
|
|
||||||
String opRate; |
|
||||||
opRate << opName << " EG RATE " << (j + 1); |
|
||||||
opCtrl[opVal].egRate[j] = new CtrlDX(opRate, 99, opTarget + j); |
|
||||||
ctrl.add(opCtrl[opVal].egRate[j]); |
|
||||||
} |
|
||||||
|
|
||||||
for (int j = 0; j < 4; j++) {
|
|
||||||
String opLevel; |
|
||||||
opLevel << opName << " EG LEVEL " << (j + 1); |
|
||||||
opCtrl[opVal].egLevel[j] = new CtrlDX(opLevel, 99, opTarget + j + 4); |
|
||||||
ctrl.add(opCtrl[opVal].egLevel[j]); |
|
||||||
} |
|
||||||
|
|
||||||
String opVol; |
|
||||||
opVol << opName << " OUTPUT LEVEL"; |
|
||||||
opCtrl[opVal].level = new CtrlDX(opVol, 99, opTarget + 16); |
|
||||||
ctrl.add(opCtrl[opVal].level); |
|
||||||
|
|
||||||
String opMode; |
|
||||||
opMode << opName << " MODE"; |
|
||||||
opCtrl[opVal].opMode = new CtrlDX(opMode, 1, opTarget + 17); |
|
||||||
ctrl.add(opCtrl[opVal].opMode); |
|
||||||
|
|
||||||
String coarse; |
|
||||||
coarse << opName << " F COARSE"; |
|
||||||
opCtrl[opVal].coarse = new CtrlDX(coarse, 31, opTarget + 18); |
|
||||||
ctrl.add(opCtrl[opVal].coarse); |
|
||||||
|
|
||||||
String fine; |
|
||||||
fine << opName << " F FINE"; |
|
||||||
opCtrl[opVal].fine = new CtrlDX(fine, 99, opTarget + 19); |
|
||||||
ctrl.add(opCtrl[opVal].fine); |
|
||||||
|
|
||||||
String detune; |
|
||||||
detune << opName << " OSC DETUNE"; |
|
||||||
opCtrl[opVal].detune = new CtrlDX(detune, 14, opTarget + 20, -7); |
|
||||||
ctrl.add(opCtrl[opVal].detune); |
|
||||||
|
|
||||||
String sclBrkPt; |
|
||||||
sclBrkPt << opName << " BREAK POINT"; |
|
||||||
opCtrl[opVal].sclBrkPt = new CtrlDX(sclBrkPt, 99, opTarget + 8); |
|
||||||
ctrl.add(opCtrl[opVal].sclBrkPt); |
|
||||||
|
|
||||||
String sclLeftDepth; |
|
||||||
sclLeftDepth << opName << " L SCALE DEPTH"; |
|
||||||
opCtrl[opVal].sclLeftDepth = new CtrlDX(sclLeftDepth, 99, opTarget + 9); |
|
||||||
ctrl.add(opCtrl[opVal].sclLeftDepth); |
|
||||||
|
|
||||||
String sclRightDepth; |
|
||||||
sclRightDepth << opName << " R SCALE DEPTH"; |
|
||||||
opCtrl[opVal].sclRightDepth = new CtrlDX(sclRightDepth, 99, opTarget + 10); |
|
||||||
ctrl.add(opCtrl[opVal].sclRightDepth); |
|
||||||
|
|
||||||
String sclLeftCurve; |
|
||||||
sclLeftCurve << opName << " L KEY SCALE"; |
|
||||||
opCtrl[opVal].sclLeftCurve = new CtrlDXLabel(sclLeftCurve, 3, opTarget + 11, keyScaleLabels); |
|
||||||
ctrl.add(opCtrl[opVal].sclLeftCurve); |
|
||||||
|
|
||||||
String sclRightCurve; |
|
||||||
sclRightCurve << opName << " R KEY SCALE"; |
|
||||||
opCtrl[opVal].sclRightCurve = new CtrlDXLabel(sclRightCurve, 3, opTarget + 12, keyScaleLabels); |
|
||||||
ctrl.add(opCtrl[opVal].sclRightCurve); |
|
||||||
|
|
||||||
String sclRate; |
|
||||||
sclRate << opName << " RATE SCALING"; |
|
||||||
opCtrl[opVal].sclRate = new CtrlDX(sclRate, 7, opTarget + 13); |
|
||||||
ctrl.add(opCtrl[opVal].sclRate); |
|
||||||
|
|
||||||
String ampModSens; |
|
||||||
ampModSens << opName << " A MOD SENS."; |
|
||||||
opCtrl[opVal].ampModSens = new CtrlDX(ampModSens, 3, opTarget + 14); |
|
||||||
ctrl.add(opCtrl[opVal].ampModSens); |
|
||||||
|
|
||||||
String velModSens; |
|
||||||
velModSens << opName << " KEY VELOCITY"; |
|
||||||
opCtrl[opVal].velModSens = new CtrlDX(velModSens, 7, opTarget + 15); |
|
||||||
ctrl.add(opCtrl[opVal].velModSens); |
|
||||||
|
|
||||||
String opSwitchLabel; |
|
||||||
opSwitchLabel << opName << " SWITCH"; |
|
||||||
opCtrl[opVal].opSwitch = new CtrlOpSwitch(opSwitchLabel, (char *)&(controllers.opSwitch)+(5-i)); |
|
||||||
ctrl.add(opCtrl[opVal].opSwitch); |
|
||||||
} |
|
||||||
|
|
||||||
for (int i=0; i < ctrl.size(); i++) { |
|
||||||
ctrl[i]->idx = i; |
|
||||||
ctrl[i]->parent = this; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void DexedAudioProcessor::setDxValue(int offset, int v) { |
|
||||||
if (offset < 0) |
|
||||||
return; |
|
||||||
|
|
||||||
if ( data[offset] != v ) { |
|
||||||
TRACE("setting dx %d %d", offset, v); |
|
||||||
data[offset] = v; |
|
||||||
} else { |
|
||||||
TRACE("ignoring dx7 same values %d %d", offset, v); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
refreshVoice = true; |
|
||||||
|
|
||||||
// MIDDLE C (transpose)
|
|
||||||
if (offset == 144) |
|
||||||
panic(); |
|
||||||
|
|
||||||
if (!sendSysexChange) |
|
||||||
return; |
|
||||||
|
|
||||||
uint8 msg[7] = { 0xF0, 0x43, 0x10, offset > 127, 0, (uint8) v, 0xF7 }; |
|
||||||
msg[2] = 0x10 | sysexComm.getChl(); |
|
||||||
msg[4] = offset & 0x7F; |
|
||||||
|
|
||||||
if ( sysexComm.isOutputActive() ) { |
|
||||||
sysexComm.send(MidiMessage(msg,7)); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void DexedAudioProcessor::unbindUI() { |
|
||||||
for (int i = 0; i < ctrl.size(); i++) { |
|
||||||
ctrl[i]->unbind(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
int DexedAudioProcessor::getNumParameters() { |
|
||||||
return ctrl.size(); |
|
||||||
} |
|
||||||
|
|
||||||
float DexedAudioProcessor::getParameter(int index) { |
|
||||||
return ctrl[index]->getValueHost(); |
|
||||||
} |
|
||||||
|
|
||||||
void DexedAudioProcessor::setParameter(int index, float newValue) { |
|
||||||
ctrl[index]->setValueHost(newValue); |
|
||||||
forceRefreshUI = true; |
|
||||||
} |
|
||||||
|
|
||||||
int DexedAudioProcessor::getNumPrograms() { |
|
||||||
return 32; |
|
||||||
} |
|
||||||
|
|
||||||
int DexedAudioProcessor::getCurrentProgram() { |
|
||||||
return currentProgram; |
|
||||||
} |
|
||||||
|
|
||||||
void DexedAudioProcessor::setCurrentProgram(int index) { |
|
||||||
TRACE("setting program %d state", index); |
|
||||||
|
|
||||||
if ( lastStateSave + 2 > time(NULL) ) { |
|
||||||
TRACE("skipping save, storage recall to close"); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
panic(); |
|
||||||
|
|
||||||
index = index > 31 ? 31 : index; |
|
||||||
currentCart.unpackProgram(data, index); |
|
||||||
strcpy(controllers.opSwitch, "111111"); |
|
||||||
lfo.reset(data + 137); |
|
||||||
currentProgram = index; |
|
||||||
triggerAsyncUpdate(); |
|
||||||
|
|
||||||
// reset parameter display
|
|
||||||
DexedAudioProcessorEditor *editor = (DexedAudioProcessorEditor *) getActiveEditor(); |
|
||||||
if ( editor == NULL ) { |
|
||||||
return; |
|
||||||
} |
|
||||||
editor->global.setParamMessage(""); |
|
||||||
|
|
||||||
panic(); |
|
||||||
} |
|
||||||
|
|
||||||
const String DexedAudioProcessor::getProgramName(int index) { |
|
||||||
if (index >= 32) |
|
||||||
index = 31; |
|
||||||
return programNames[index]; |
|
||||||
} |
|
||||||
|
|
||||||
void DexedAudioProcessor::changeProgramName(int index, const String& newName) { |
|
||||||
} |
|
||||||
|
|
||||||
const String DexedAudioProcessor::getParameterName(int index) { |
|
||||||
return ctrl[index]->label; |
|
||||||
} |
|
||||||
|
|
||||||
const String DexedAudioProcessor::getParameterText(int index) { |
|
||||||
return ctrl[index]->getValueDisplay(); |
|
||||||
} |
|
||||||
|
|
||||||
void DexedAudioProcessor::loadPreference() { |
|
||||||
File propFile = DexedAudioProcessor::dexedAppDir.getChildFile("Dexed.xml"); |
|
||||||
PropertiesFile::Options prefOptions; |
|
||||||
PropertiesFile prop(propFile, prefOptions); |
|
||||||
|
|
||||||
if ( ! prop.isValidFile() ) { |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
if ( prop.containsKey( String("normalizeDxVelocity") ) ) { |
|
||||||
normalizeDxVelocity = prop.getIntValue( String("normalizeDxVelocity") ); |
|
||||||
} |
|
||||||
|
|
||||||
if ( prop.containsKey( String("pitchRange") ) ) { |
|
||||||
controllers.values_[kControllerPitchRange] = prop.getIntValue( String("pitchRange") ); |
|
||||||
} |
|
||||||
|
|
||||||
if ( prop.containsKey( String("pitchStep") ) ) { |
|
||||||
controllers.values_[kControllerPitchStep] = prop.getIntValue( String("pitchStep") ); |
|
||||||
} |
|
||||||
|
|
||||||
if ( prop.containsKey( String("sysexIn") ) ) { |
|
||||||
sysexComm.setInput( prop.getValue("sysexIn") ); |
|
||||||
} |
|
||||||
|
|
||||||
if ( prop.containsKey( String("sysexOut") ) ) { |
|
||||||
sysexComm.setOutput( prop.getValue("sysexOut") ); |
|
||||||
} |
|
||||||
|
|
||||||
if ( prop.containsKey( String("sysexChl") ) ) { |
|
||||||
sysexComm.setChl( prop.getIntValue( String("sysexChl") ) ); |
|
||||||
} |
|
||||||
|
|
||||||
if ( prop.containsKey( String("engineType") ) ) { |
|
||||||
setEngineType(prop.getIntValue(String("engineType"))); |
|
||||||
} |
|
||||||
|
|
||||||
if ( prop.containsKey( String("showKeyboard") ) ) { |
|
||||||
showKeyboard = prop.getIntValue( String("showKeyboard") ); |
|
||||||
} |
|
||||||
|
|
||||||
if ( prop.containsKey( String("wheelMod") ) ) { |
|
||||||
controllers.wheel.parseConfig(prop.getValue(String("wheelMod")).toRawUTF8()); |
|
||||||
} |
|
||||||
|
|
||||||
if ( prop.containsKey( String("footMod") ) ) { |
|
||||||
controllers.foot.parseConfig(prop.getValue(String("footMod")).toRawUTF8()); |
|
||||||
} |
|
||||||
|
|
||||||
if ( prop.containsKey( String("breathMod") ) ) { |
|
||||||
controllers.breath.parseConfig(prop.getValue(String("breathMod")).toRawUTF8()); |
|
||||||
} |
|
||||||
|
|
||||||
if ( prop.containsKey( String("aftertouchMod") ) ) { |
|
||||||
controllers.at.parseConfig(prop.getValue(String("aftertouchMod")).toRawUTF8()); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void DexedAudioProcessor::savePreference() { |
|
||||||
File propFile = DexedAudioProcessor::dexedAppDir.getChildFile("Dexed.xml"); |
|
||||||
PropertiesFile::Options prefOptions; |
|
||||||
PropertiesFile prop(propFile, prefOptions); |
|
||||||
|
|
||||||
prop.setValue(String("normalizeDxVelocity"), normalizeDxVelocity); |
|
||||||
prop.setValue(String("pitchRange"), controllers.values_[kControllerPitchRange]); |
|
||||||
prop.setValue(String("pitchStep"), controllers.values_[kControllerPitchStep]); |
|
||||||
|
|
||||||
prop.setValue(String("sysexIn"), sysexComm.getInput()); |
|
||||||
prop.setValue(String("sysexOut"), sysexComm.getOutput()); |
|
||||||
prop.setValue(String("sysexChl"), sysexComm.getChl()); |
|
||||||
|
|
||||||
prop.setValue(String("showKeyboard"), showKeyboard); |
|
||||||
|
|
||||||
char mod_cfg[15]; |
|
||||||
controllers.wheel.setConfig(mod_cfg); |
|
||||||
prop.setValue(String("wheelMod"), mod_cfg); |
|
||||||
controllers.foot.setConfig(mod_cfg); |
|
||||||
prop.setValue(String("footMod"), mod_cfg); |
|
||||||
controllers.breath.setConfig(mod_cfg); |
|
||||||
prop.setValue(String("breathMod"), mod_cfg); |
|
||||||
controllers.at.setConfig(mod_cfg); |
|
||||||
prop.setValue(String("aftertouchMod"), mod_cfg); |
|
||||||
|
|
||||||
prop.setValue(String("engineType"), (int) engineType); |
|
||||||
|
|
||||||
prop.save(); |
|
||||||
} |
|
||||||
|
|
@ -1,127 +0,0 @@ |
|||||||
/**
|
|
||||||
* |
|
||||||
* Copyright (c) 2013 Pascal Gauthier. |
|
||||||
* |
|
||||||
* This program is free software; you can redistribute it and/or modify |
|
||||||
* it under the terms of the GNU General Public License as published by |
|
||||||
* the Free Software Foundation; either version 3 of the License, or |
|
||||||
* (at your option) any later version. |
|
||||||
* |
|
||||||
* This program is distributed in the hope that it will be useful, |
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
* GNU General Public License for more details. |
|
||||||
* |
|
||||||
* You should have received a copy of the GNU General Public License |
|
||||||
* along with this program; if not, write to the Free Software Foundation, |
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
||||||
* |
|
||||||
*/ |
|
||||||
|
|
||||||
#ifndef PLUGINPARAM_H_INCLUDED |
|
||||||
#define PLUGINPARAM_H_INCLUDED |
|
||||||
|
|
||||||
#include "../JuceLibraryCode/JuceHeader.h" |
|
||||||
|
|
||||||
class DexedAudioProcessor; |
|
||||||
|
|
||||||
class Ctrl : public SliderListener, public ButtonListener, public ComboBoxListener, public MouseListener { |
|
||||||
protected: |
|
||||||
/**
|
|
||||||
* Binded components of the UI |
|
||||||
*/ |
|
||||||
Slider *slider; |
|
||||||
Button *button; |
|
||||||
ComboBox *comboBox; |
|
||||||
|
|
||||||
public: |
|
||||||
String label; |
|
||||||
|
|
||||||
Ctrl(String name); |
|
||||||
void bind(Slider *s); |
|
||||||
void bind(Button *b); |
|
||||||
void bind(ComboBox *c); |
|
||||||
void unbind(); |
|
||||||
|
|
||||||
// use this to signal a parameter change to the host
|
|
||||||
void publishValue(float value); |
|
||||||
|
|
||||||
/**
|
|
||||||
* Host value is related 0.0 to 1.0 values |
|
||||||
*/ |
|
||||||
virtual void setValueHost(float f) = 0; |
|
||||||
virtual float getValueHost() = 0; |
|
||||||
virtual String getValueDisplay() = 0; |
|
||||||
virtual void updateComponent() = 0; |
|
||||||
|
|
||||||
void comboBoxChanged (ComboBox* combo); |
|
||||||
void sliderValueChanged (Slider* moved); |
|
||||||
void buttonClicked (Button* buttonThatWasClicked); |
|
||||||
void mouseEnter(const MouseEvent &event); |
|
||||||
virtual void updateDisplayName(); |
|
||||||
|
|
||||||
/**
|
|
||||||
* Index of this parameter |
|
||||||
*/ |
|
||||||
int idx; |
|
||||||
DexedAudioProcessor *parent; |
|
||||||
}; |
|
||||||
|
|
||||||
class CtrlFloat : public Ctrl { |
|
||||||
float *vPointer; |
|
||||||
public: |
|
||||||
|
|
||||||
CtrlFloat(String name, float *storageValue); |
|
||||||
void setValueHost(float f); |
|
||||||
float getValueHost(); |
|
||||||
String getValueDisplay(); |
|
||||||
void updateComponent(); |
|
||||||
}; |
|
||||||
|
|
||||||
// CtrlDX is a controller that is related to DX parameters
|
|
||||||
class CtrlDX : public Ctrl { |
|
||||||
int dxValue; |
|
||||||
int steps; |
|
||||||
int dxOffset; |
|
||||||
int displayValue; |
|
||||||
|
|
||||||
public: |
|
||||||
CtrlDX(String name, int steps, int offset = -1, int displayValue = 0); |
|
||||||
void setValueHost(float f); |
|
||||||
float getValueHost(); |
|
||||||
void publishValue(float value); |
|
||||||
|
|
||||||
void setValue(int value); |
|
||||||
int getValue(); |
|
||||||
int getOffset(); |
|
||||||
String getValueDisplay(); |
|
||||||
|
|
||||||
void sliderValueChanged (Slider* moved); |
|
||||||
void comboBoxChanged (ComboBox* combo); |
|
||||||
void buttonClicked (Button* buttonThatWasClicked); |
|
||||||
void updateComponent(); |
|
||||||
|
|
||||||
void updateDisplayName(); |
|
||||||
}; |
|
||||||
|
|
||||||
|
|
||||||
struct OperatorCtrl { |
|
||||||
ScopedPointer<CtrlDX> egRate[4]; |
|
||||||
ScopedPointer<CtrlDX> egLevel[4]; |
|
||||||
ScopedPointer<CtrlDX> level; |
|
||||||
ScopedPointer<CtrlDX> opMode; |
|
||||||
ScopedPointer<CtrlDX> coarse; |
|
||||||
ScopedPointer<CtrlDX> fine; |
|
||||||
ScopedPointer<CtrlDX> detune; |
|
||||||
ScopedPointer<CtrlDX> sclBrkPt; |
|
||||||
ScopedPointer<CtrlDX> sclLeftDepth; |
|
||||||
ScopedPointer<CtrlDX> sclRightDepth; |
|
||||||
ScopedPointer<CtrlDX> sclLeftCurve; |
|
||||||
ScopedPointer<CtrlDX> sclRightCurve; |
|
||||||
ScopedPointer<CtrlDX> sclRate; |
|
||||||
ScopedPointer<CtrlDX> ampModSens; |
|
||||||
ScopedPointer<CtrlDX> velModSens; |
|
||||||
ScopedPointer<Ctrl> opSwitch; |
|
||||||
}; |
|
||||||
|
|
||||||
#endif // PLUGINPARAM_H_INCLUDED
|
|
@ -1,616 +0,0 @@ |
|||||||
/**
|
|
||||||
* |
|
||||||
* Copyright (c) 2013-2015 Pascal Gauthier. |
|
||||||
* |
|
||||||
* This program is free software; you can redistribute it and/or modify |
|
||||||
* it under the terms of the GNU General Public License as published by |
|
||||||
* the Free Software Foundation; either version 3 of the License, or |
|
||||||
* (at your option) any later version. |
|
||||||
* |
|
||||||
* This program is distributed in the hope that it will be useful, |
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
* GNU General Public License for more details. |
|
||||||
* |
|
||||||
* You should have received a copy of the GNU General Public License |
|
||||||
* along with this program; if not, write to the Free Software Foundation, |
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
||||||
* |
|
||||||
*/ |
|
||||||
|
|
||||||
#include "PluginProcessor.h" |
|
||||||
#include "PluginEditor.h" |
|
||||||
|
|
||||||
#include "Dexed.h" |
|
||||||
#include "msfa/synth.h" |
|
||||||
#include "msfa/freqlut.h" |
|
||||||
#include "msfa/sin.h" |
|
||||||
#include "msfa/exp2.h" |
|
||||||
#include "msfa/env.h" |
|
||||||
#include "msfa/pitchenv.h" |
|
||||||
#include "msfa/aligned_buf.h" |
|
||||||
#include "msfa/fm_op_kernel.h" |
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
DexedAudioProcessor::DexedAudioProcessor() { |
|
||||||
#ifdef DEBUG |
|
||||||
Logger *tmp = Logger::getCurrentLogger(); |
|
||||||
if ( tmp == NULL ) { |
|
||||||
Logger::setCurrentLogger(FileLogger::createDateStampedLogger("Dexed", "DebugSession-", "log", "DexedAudioProcessor Created")); |
|
||||||
} |
|
||||||
TRACE("Hi"); |
|
||||||
#endif |
|
||||||
|
|
||||||
Exp2::init(); |
|
||||||
Tanh::init(); |
|
||||||
Sin::init(); |
|
||||||
|
|
||||||
lastStateSave = 0; |
|
||||||
currentNote = -1; |
|
||||||
engineType = -1; |
|
||||||
|
|
||||||
vuSignal = 0; |
|
||||||
monoMode = 0; |
|
||||||
|
|
||||||
resolvAppDir(); |
|
||||||
|
|
||||||
TRACE("controler %s", controllers.opSwitch); |
|
||||||
|
|
||||||
initCtrl(); |
|
||||||
sendSysexChange = true; |
|
||||||
normalizeDxVelocity = false; |
|
||||||
sysexComm.listener = this; |
|
||||||
showKeyboard = true; |
|
||||||
|
|
||||||
memset(&voiceStatus, 0, sizeof(VoiceStatus)); |
|
||||||
setEngineType(DEXED_ENGINE_MARKI); |
|
||||||
|
|
||||||
controllers.values_[kControllerPitchRange] = 3; |
|
||||||
controllers.values_[kControllerPitchStep] = 0; |
|
||||||
controllers.masterTune = 0; |
|
||||||
|
|
||||||
loadPreference(); |
|
||||||
|
|
||||||
for (int note = 0; note < MAX_ACTIVE_NOTES; ++note) { |
|
||||||
voices[note].dx7_note = NULL; |
|
||||||
} |
|
||||||
setCurrentProgram(0);
|
|
||||||
nextMidi = NULL; |
|
||||||
midiMsg = NULL; |
|
||||||
|
|
||||||
clipboardContent = -1; |
|
||||||
} |
|
||||||
|
|
||||||
DexedAudioProcessor::~DexedAudioProcessor() { |
|
||||||
TRACE("Bye"); |
|
||||||
} |
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
void DexedAudioProcessor::prepareToPlay(double sampleRate, int samplesPerBlock) { |
|
||||||
Freqlut::init(sampleRate); |
|
||||||
Lfo::init(sampleRate); |
|
||||||
PitchEnv::init(sampleRate); |
|
||||||
Env::init_sr(sampleRate); |
|
||||||
fx.init(sampleRate); |
|
||||||
|
|
||||||
for (int note = 0; note < MAX_ACTIVE_NOTES; ++note) { |
|
||||||
voices[note].dx7_note = new Dx7Note; |
|
||||||
voices[note].keydown = false; |
|
||||||
voices[note].sustained = false; |
|
||||||
voices[note].live = false; |
|
||||||
} |
|
||||||
|
|
||||||
currentNote = 0; |
|
||||||
controllers.values_[kControllerPitch] = 0x2000; |
|
||||||
controllers.modwheel_cc = 0; |
|
||||||
controllers.foot_cc = 0; |
|
||||||
controllers.breath_cc = 0; |
|
||||||
controllers.aftertouch_cc = 0; |
|
||||||
|
|
||||||
sustain = false; |
|
||||||
extra_buf_size = 0; |
|
||||||
|
|
||||||
keyboardState.reset(); |
|
||||||
|
|
||||||
lfo.reset(data + 137); |
|
||||||
|
|
||||||
nextMidi = new MidiMessage(0xF0); |
|
||||||
midiMsg = new MidiMessage(0xF0); |
|
||||||
} |
|
||||||
|
|
||||||
void DexedAudioProcessor::releaseResources() { |
|
||||||
currentNote = -1; |
|
||||||
|
|
||||||
for (int note = 0; note < MAX_ACTIVE_NOTES; ++note) { |
|
||||||
if ( voices[note].dx7_note != NULL ) { |
|
||||||
delete voices[note].dx7_note; |
|
||||||
voices[note].dx7_note = NULL; |
|
||||||
} |
|
||||||
voices[note].keydown = false; |
|
||||||
voices[note].sustained = false; |
|
||||||
voices[note].live = false; |
|
||||||
} |
|
||||||
|
|
||||||
keyboardState.reset(); |
|
||||||
if ( nextMidi != NULL ) { |
|
||||||
delete nextMidi; |
|
||||||
nextMidi = NULL; |
|
||||||
} |
|
||||||
if ( midiMsg != NULL ) { |
|
||||||
delete midiMsg; |
|
||||||
midiMsg = NULL; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void DexedAudioProcessor::processBlock(AudioSampleBuffer& buffer, MidiBuffer& midiMessages) { |
|
||||||
int numSamples = buffer.getNumSamples(); |
|
||||||
int i; |
|
||||||
|
|
||||||
if ( refreshVoice ) { |
|
||||||
for(i=0;i < MAX_ACTIVE_NOTES;i++) { |
|
||||||
if ( voices[i].live ) |
|
||||||
voices[i].dx7_note->update(data, voices[i].midi_note, feedback_bitdepth); |
|
||||||
} |
|
||||||
lfo.reset(data + 137); |
|
||||||
refreshVoice = false; |
|
||||||
} |
|
||||||
|
|
||||||
keyboardState.processNextMidiBuffer(midiMessages, 0, numSamples, true); |
|
||||||
|
|
||||||
MidiBuffer::Iterator it(midiMessages); |
|
||||||
hasMidiMessage = it.getNextEvent(*nextMidi,midiEventPos); |
|
||||||
|
|
||||||
float *channelData = buffer.getWritePointer(0); |
|
||||||
|
|
||||||
// flush first events
|
|
||||||
for (i=0; i < numSamples && i < extra_buf_size; i++) { |
|
||||||
channelData[i] = extra_buf[i]; |
|
||||||
} |
|
||||||
|
|
||||||
// remaining buffer is still to be processed
|
|
||||||
if (extra_buf_size > numSamples) { |
|
||||||
for (int j = 0; j < extra_buf_size - numSamples; j++) { |
|
||||||
extra_buf[j] = extra_buf[j + numSamples]; |
|
||||||
} |
|
||||||
extra_buf_size -= numSamples; |
|
||||||
|
|
||||||
// flush the events, they will be process in the next cycle
|
|
||||||
while(getNextEvent(&it, numSamples)) { |
|
||||||
processMidiMessage(midiMsg); |
|
||||||
} |
|
||||||
} else { |
|
||||||
for (; i < numSamples; i += N) { |
|
||||||
AlignedBuf<int32_t, N> audiobuf; |
|
||||||
float sumbuf[N]; |
|
||||||
|
|
||||||
while(getNextEvent(&it, i)) { |
|
||||||
processMidiMessage(midiMsg); |
|
||||||
} |
|
||||||
|
|
||||||
for (int j = 0; j < N; ++j) { |
|
||||||
audiobuf.get()[j] = 0; |
|
||||||
sumbuf[j] = 0; |
|
||||||
} |
|
||||||
int32_t lfovalue = lfo.getsample(); |
|
||||||
int32_t lfodelay = lfo.getdelay(); |
|
||||||
|
|
||||||
for (int note = 0; note < MAX_ACTIVE_NOTES; ++note) { |
|
||||||
if (voices[note].live) { |
|
||||||
voices[note].dx7_note->compute(audiobuf.get(), lfovalue, lfodelay, &controllers); |
|
||||||
|
|
||||||
for (int j=0; j < N; ++j) { |
|
||||||
int32_t val = audiobuf.get()[j]; |
|
||||||
|
|
||||||
val = val >> 4; |
|
||||||
int clip_val = val < -(1 << 24) ? 0x8000 : val >= (1 << 24) ? 0x7fff : val >> 9; |
|
||||||
float f = ((float) clip_val) / (float) 0x8000; |
|
||||||
if( f > 1 ) f = 1; |
|
||||||
if( f < -1 ) f = -1; |
|
||||||
sumbuf[j] += f; |
|
||||||
audiobuf.get()[j] = 0; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
int jmax = numSamples - i; |
|
||||||
for (int j = 0; j < N; ++j) { |
|
||||||
if (j < jmax) { |
|
||||||
channelData[i + j] = sumbuf[j]; |
|
||||||
} else { |
|
||||||
extra_buf[j - jmax] = sumbuf[j]; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
extra_buf_size = i - numSamples; |
|
||||||
} |
|
||||||
|
|
||||||
while(getNextEvent(&it, numSamples)) { |
|
||||||
processMidiMessage(midiMsg); |
|
||||||
} |
|
||||||
|
|
||||||
fx.process(channelData, numSamples); |
|
||||||
for(i=0; i<numSamples; i++) { |
|
||||||
float s = std::abs(channelData[i]); |
|
||||||
|
|
||||||
const double decayFactor = 0.99992; |
|
||||||
if (s > vuSignal) |
|
||||||
vuSignal = s; |
|
||||||
else if (vuSignal > 0.001f) |
|
||||||
vuSignal *= decayFactor; |
|
||||||
else |
|
||||||
vuSignal = 0; |
|
||||||
} |
|
||||||
|
|
||||||
// DX7 is a mono synth
|
|
||||||
buffer.copyFrom(1, 0, channelData, numSamples, 1); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
// This creates new instances of the plugin..
|
|
||||||
AudioProcessor* JUCE_CALLTYPE createPluginFilter() { |
|
||||||
return new DexedAudioProcessor(); |
|
||||||
} |
|
||||||
|
|
||||||
bool DexedAudioProcessor::getNextEvent(MidiBuffer::Iterator* iter,const int samplePos) { |
|
||||||
if (hasMidiMessage && midiEventPos <= samplePos) { |
|
||||||
*midiMsg = *nextMidi; |
|
||||||
hasMidiMessage = iter->getNextEvent(*nextMidi, midiEventPos); |
|
||||||
return true; |
|
||||||
} |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
void DexedAudioProcessor::processMidiMessage(const MidiMessage *msg) { |
|
||||||
const uint8 *buf = msg->getRawData(); |
|
||||||
uint8_t cmd = buf[0]; |
|
||||||
|
|
||||||
switch(cmd & 0xf0) { |
|
||||||
case 0x80 : |
|
||||||
keyup(buf[1]); |
|
||||||
return; |
|
||||||
|
|
||||||
case 0x90 : |
|
||||||
keydown(buf[1], buf[2]); |
|
||||||
return; |
|
||||||
|
|
||||||
case 0xb0 : { |
|
||||||
int ctrl = buf[1]; |
|
||||||
int value = buf[2]; |
|
||||||
|
|
||||||
switch(ctrl) { |
|
||||||
case 1: |
|
||||||
controllers.modwheel_cc = value; |
|
||||||
controllers.refresh(); |
|
||||||
break; |
|
||||||
case 2: |
|
||||||
controllers.breath_cc = value; |
|
||||||
controllers.refresh(); |
|
||||||
break; |
|
||||||
case 4: |
|
||||||
controllers.foot_cc = value; |
|
||||||
controllers.refresh(); |
|
||||||
break; |
|
||||||
case 64: |
|
||||||
sustain = value > 63; |
|
||||||
if (!sustain) { |
|
||||||
for (int note = 0; note < MAX_ACTIVE_NOTES; note++) { |
|
||||||
if (voices[note].sustained && !voices[note].keydown) { |
|
||||||
voices[note].dx7_note->keyup(); |
|
||||||
voices[note].sustained = false; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
return; |
|
||||||
|
|
||||||
case 0xc0 : |
|
||||||
setCurrentProgram(buf[1]); |
|
||||||
return; |
|
||||||
|
|
||||||
// aftertouch
|
|
||||||
case 0xd0 : |
|
||||||
controllers.aftertouch_cc = buf[1]; |
|
||||||
controllers.refresh(); |
|
||||||
return; |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
switch (cmd) { |
|
||||||
case 0xe0 : |
|
||||||
controllers.values_[kControllerPitch] = buf[1] | (buf[2] << 7); |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void DexedAudioProcessor::keydown(uint8_t pitch, uint8_t velo) { |
|
||||||
if ( velo == 0 ) { |
|
||||||
keyup(pitch); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
pitch += data[144] - 24; |
|
||||||
|
|
||||||
if ( normalizeDxVelocity ) { |
|
||||||
velo = ((float)velo) * 0.7874015; // 100/127
|
|
||||||
} |
|
||||||
|
|
||||||
int note = currentNote; |
|
||||||
for (int i=0; i<MAX_ACTIVE_NOTES; i++) { |
|
||||||
if (!voices[note].keydown) { |
|
||||||
currentNote = (note + 1) % MAX_ACTIVE_NOTES; |
|
||||||
lfo.keydown(); // TODO: should only do this if # keys down was 0
|
|
||||||
voices[note].midi_note = pitch; |
|
||||||
voices[note].sustained = sustain; |
|
||||||
voices[note].keydown = true; |
|
||||||
voices[note].dx7_note->init(data, pitch, velo, feedback_bitdepth); |
|
||||||
if ( data[136] ) |
|
||||||
voices[note].dx7_note->oscSync(); |
|
||||||
break; |
|
||||||
} |
|
||||||
note = (note + 1) % MAX_ACTIVE_NOTES; |
|
||||||
} |
|
||||||
|
|
||||||
if ( monoMode ) { |
|
||||||
for(int i=0; i<MAX_ACTIVE_NOTES; i++) {
|
|
||||||
if ( voices[i].live ) { |
|
||||||
// all keys are up, only transfert signal
|
|
||||||
if ( ! voices[i].keydown ) { |
|
||||||
voices[i].live = false; |
|
||||||
voices[note].dx7_note->transferSignal(*voices[i].dx7_note); |
|
||||||
break; |
|
||||||
} |
|
||||||
if ( voices[i].midi_note < pitch ) { |
|
||||||
voices[i].live = false; |
|
||||||
voices[note].dx7_note->transferState(*voices[i].dx7_note); |
|
||||||
break; |
|
||||||
} |
|
||||||
return; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
voices[note].live = true; |
|
||||||
} |
|
||||||
|
|
||||||
void DexedAudioProcessor::keyup(uint8_t pitch) { |
|
||||||
pitch += data[144] - 24; |
|
||||||
|
|
||||||
int note; |
|
||||||
for (note=0; note<MAX_ACTIVE_NOTES; ++note) { |
|
||||||
if ( voices[note].midi_note == pitch && voices[note].keydown ) { |
|
||||||
voices[note].keydown = false; |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// note not found ?
|
|
||||||
if ( note >= MAX_ACTIVE_NOTES ) { |
|
||||||
TRACE("note-off not found???"); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
if ( monoMode ) { |
|
||||||
int highNote = -1; |
|
||||||
int target = 0; |
|
||||||
for (int i=0; i<MAX_ACTIVE_NOTES;i++) { |
|
||||||
if ( voices[i].keydown && voices[i].midi_note > highNote ) { |
|
||||||
target = i; |
|
||||||
highNote = voices[i].midi_note; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
if ( highNote != -1 ) { |
|
||||||
voices[note].live = false; |
|
||||||
voices[target].live = true; |
|
||||||
voices[target].dx7_note->transferState(*voices[note].dx7_note); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
if ( sustain ) { |
|
||||||
voices[note].sustained = true; |
|
||||||
} else { |
|
||||||
voices[note].dx7_note->keyup(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void DexedAudioProcessor::panic() { |
|
||||||
for(int i=0;i<MAX_ACTIVE_NOTES;i++) { |
|
||||||
voices[i].keydown = false; |
|
||||||
voices[i].live = false; |
|
||||||
if ( voices[i].dx7_note != NULL ) { |
|
||||||
voices[i].dx7_note->oscSync(); |
|
||||||
} |
|
||||||
} |
|
||||||
keyboardState.reset(); |
|
||||||
} |
|
||||||
|
|
||||||
void DexedAudioProcessor::handleIncomingMidiMessage(MidiInput* source, const MidiMessage& message) { |
|
||||||
if ( message.isActiveSense() )
|
|
||||||
return; |
|
||||||
|
|
||||||
sysexComm.inActivity = true; |
|
||||||
|
|
||||||
if ( ! message.isSysEx() ) |
|
||||||
return; |
|
||||||
|
|
||||||
//const uint8 *buf = msg->getSysExData();
|
|
||||||
const uint8 *buf = message.getRawData(); |
|
||||||
int sz = message.getRawDataSize(); |
|
||||||
|
|
||||||
if ( sz < 3 ) |
|
||||||
return; |
|
||||||
|
|
||||||
TRACE("SYSEX RECEIVED %d", sz); |
|
||||||
|
|
||||||
// test if it is a Yamaha Sysex
|
|
||||||
if ( buf[1] != 0x43 ) { |
|
||||||
TRACE("not a yamaha sysex %d", buf[0]); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
// single voice dump
|
|
||||||
if ( buf[3] == 0 ) { |
|
||||||
if ( sz < 155 ) { |
|
||||||
TRACE("wrong single voice datasize %d", sz); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
updateProgramFromSysex(buf+6); |
|
||||||
} |
|
||||||
|
|
||||||
// 32 voice dump
|
|
||||||
if ( buf[3] == 9 ) { |
|
||||||
Cartridge received; |
|
||||||
if ( received.load(buf, sz) ) { |
|
||||||
loadCartridge(received); |
|
||||||
setCurrentProgram(0); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
updateHostDisplay(); |
|
||||||
forceRefreshUI = true; |
|
||||||
} |
|
||||||
|
|
||||||
int DexedAudioProcessor::getEngineType() { |
|
||||||
return engineType; |
|
||||||
} |
|
||||||
|
|
||||||
void DexedAudioProcessor::setEngineType(int tp) { |
|
||||||
TRACE("settings engine %d", tp); |
|
||||||
|
|
||||||
switch (tp) { |
|
||||||
case DEXED_ENGINE_MARKI: |
|
||||||
controllers.core = &engineMkI; |
|
||||||
feedback_bitdepth = 11; |
|
||||||
break; |
|
||||||
case DEXED_ENGINE_OPL: |
|
||||||
controllers.core = &engineOpl; |
|
||||||
feedback_bitdepth = 11; |
|
||||||
break; |
|
||||||
default: |
|
||||||
controllers.core = &engineMsfa; |
|
||||||
feedback_bitdepth = 8; |
|
||||||
break; |
|
||||||
} |
|
||||||
engineType = tp; |
|
||||||
} |
|
||||||
|
|
||||||
void DexedAudioProcessor::setMonoMode(bool mode) { |
|
||||||
panic(); |
|
||||||
monoMode = mode; |
|
||||||
} |
|
||||||
|
|
||||||
// ====================================================================
|
|
||||||
bool DexedAudioProcessor::peekVoiceStatus() { |
|
||||||
if ( currentNote == -1 ) |
|
||||||
return false; |
|
||||||
|
|
||||||
// we are trying to find the last "keydown" note
|
|
||||||
int note = currentNote; |
|
||||||
for (int i = 0; i < MAX_ACTIVE_NOTES; i++) { |
|
||||||
if (voices[note].keydown) { |
|
||||||
voices[note].dx7_note->peekVoiceStatus(voiceStatus); |
|
||||||
return true; |
|
||||||
} |
|
||||||
if ( --note < 0 ) |
|
||||||
note = MAX_ACTIVE_NOTES-1; |
|
||||||
} |
|
||||||
|
|
||||||
// not found; try a live note
|
|
||||||
note = currentNote; |
|
||||||
for (int i = 0; i < MAX_ACTIVE_NOTES; i++) { |
|
||||||
if (voices[note].live) { |
|
||||||
voices[note].dx7_note->peekVoiceStatus(voiceStatus); |
|
||||||
return true; |
|
||||||
} |
|
||||||
if ( --note < 0 ) |
|
||||||
note = MAX_ACTIVE_NOTES-1; |
|
||||||
} |
|
||||||
|
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
const String DexedAudioProcessor::getInputChannelName (int channelIndex) const { |
|
||||||
return String (channelIndex + 1); |
|
||||||
} |
|
||||||
|
|
||||||
const String DexedAudioProcessor::getOutputChannelName (int channelIndex) const { |
|
||||||
return String (channelIndex + 1); |
|
||||||
} |
|
||||||
|
|
||||||
bool DexedAudioProcessor::isInputChannelStereoPair (int index) const { |
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
bool DexedAudioProcessor::isOutputChannelStereoPair (int index) const { |
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
bool DexedAudioProcessor::acceptsMidi() const { |
|
||||||
#if JucePlugin_WantsMidiInput |
|
||||||
return true; |
|
||||||
#else |
|
||||||
return false; |
|
||||||
#endif |
|
||||||
} |
|
||||||
|
|
||||||
bool DexedAudioProcessor::producesMidi() const { |
|
||||||
#if JucePlugin_ProducesMidiOutput |
|
||||||
return true; |
|
||||||
#else |
|
||||||
return false; |
|
||||||
#endif |
|
||||||
} |
|
||||||
|
|
||||||
bool DexedAudioProcessor::silenceInProducesSilenceOut() const { |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
double DexedAudioProcessor::getTailLengthSeconds() const { |
|
||||||
return 0.0; |
|
||||||
} |
|
||||||
|
|
||||||
const String DexedAudioProcessor::getName() const { |
|
||||||
return JucePlugin_Name; |
|
||||||
} |
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
bool DexedAudioProcessor::hasEditor() const { |
|
||||||
return true; // (change this to false if you choose to not supply an editor)
|
|
||||||
} |
|
||||||
|
|
||||||
void DexedAudioProcessor::updateUI() { |
|
||||||
// notify host something has changed
|
|
||||||
updateHostDisplay(); |
|
||||||
|
|
||||||
AudioProcessorEditor *editor = getActiveEditor(); |
|
||||||
if ( editor == NULL ) { |
|
||||||
return; |
|
||||||
} |
|
||||||
DexedAudioProcessorEditor *dexedEditor = (DexedAudioProcessorEditor *) editor; |
|
||||||
dexedEditor->updateUI(); |
|
||||||
} |
|
||||||
|
|
||||||
AudioProcessorEditor* DexedAudioProcessor::createEditor() { |
|
||||||
return new DexedAudioProcessorEditor (this); |
|
||||||
} |
|
||||||
|
|
||||||
void DexedAudioProcessor::handleAsyncUpdate() { |
|
||||||
updateUI(); |
|
||||||
} |
|
||||||
|
|
||||||
void dexed_trace(const char *source, const char *fmt, ...) { |
|
||||||
char output[4096]; |
|
||||||
va_list argptr; |
|
||||||
va_start(argptr, fmt); |
|
||||||
vsnprintf(output, 4095, fmt, argptr); |
|
||||||
va_end(argptr); |
|
||||||
|
|
||||||
String dest; |
|
||||||
dest << source << " " << output; |
|
||||||
Logger::writeToLog(dest); |
|
||||||
} |
|
||||||
|
|
@ -1,235 +0,0 @@ |
|||||||
/**
|
|
||||||
* |
|
||||||
* Copyright (c) 2013-2015 Pascal Gauthier. |
|
||||||
* |
|
||||||
* This program is free software; you can redistribute it and/or modify |
|
||||||
* it under the terms of the GNU General Public License as published by |
|
||||||
* the Free Software Foundation; either version 3 of the License, or |
|
||||||
* (at your option) any later version. |
|
||||||
* |
|
||||||
* This program is distributed in the hope that it will be useful, |
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
* GNU General Public License for more details. |
|
||||||
* |
|
||||||
* You should have received a copy of the GNU General Public License |
|
||||||
* along with this program; if not, write to the Free Software Foundation, |
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
||||||
* |
|
||||||
*/ |
|
||||||
|
|
||||||
#ifndef PLUGINPROCESSOR_H_INCLUDED |
|
||||||
#define PLUGINPROCESSOR_H_INCLUDED |
|
||||||
|
|
||||||
#include "msfa/controllers.h" |
|
||||||
#include "msfa/dx7note.h" |
|
||||||
#include "msfa/lfo.h" |
|
||||||
#include "msfa/synth.h" |
|
||||||
#include "msfa/fm_core.h" |
|
||||||
#include "PluginFx.h" |
|
||||||
//#include "SysexComm.h"
|
|
||||||
#include "EngineMkI.h" |
|
||||||
#include "EngineOpl.h" |
|
||||||
|
|
||||||
struct ProcessorVoice { |
|
||||||
int midi_note; |
|
||||||
bool keydown; |
|
||||||
bool sustained; |
|
||||||
bool live; |
|
||||||
Dx7Note *dx7_note; |
|
||||||
}; |
|
||||||
|
|
||||||
enum DexedEngineResolution { |
|
||||||
DEXED_ENGINE_MODERN, |
|
||||||
DEXED_ENGINE_MARKI, |
|
||||||
DEXED_ENGINE_OPL |
|
||||||
}; |
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/**
|
|
||||||
*/ |
|
||||||
class DexedAudioProcessor : public AudioProcessor, public AsyncUpdater, public MidiInputCallback |
|
||||||
{ |
|
||||||
static const int MAX_ACTIVE_NOTES = 16; |
|
||||||
ProcessorVoice voices[MAX_ACTIVE_NOTES]; |
|
||||||
int currentNote; |
|
||||||
|
|
||||||
// The original DX7 had one single LFO. Later units had an LFO per note.
|
|
||||||
Lfo lfo; |
|
||||||
|
|
||||||
bool sustain; |
|
||||||
bool monoMode; |
|
||||||
|
|
||||||
// Extra buffering for when GetSamples wants a buffer not a multiple of N
|
|
||||||
float extra_buf[N]; |
|
||||||
int extra_buf_size; |
|
||||||
|
|
||||||
int currentProgram; |
|
||||||
|
|
||||||
/**
|
|
||||||
* The last time the state was save, to be able to bypass a VST host bug. |
|
||||||
*/ |
|
||||||
long lastStateSave; |
|
||||||
|
|
||||||
/**
|
|
||||||
* Plugin fx (the filter) |
|
||||||
*/ |
|
||||||
PluginFx fx; |
|
||||||
|
|
||||||
/**
|
|
||||||
* This flag is used in the audio thread to know if the voice has changed |
|
||||||
* and needs to be updated. |
|
||||||
*/ |
|
||||||
bool refreshVoice; |
|
||||||
bool normalizeDxVelocity; |
|
||||||
bool sendSysexChange; |
|
||||||
|
|
||||||
void processMidiMessage(const MidiMessage *msg); |
|
||||||
void keydown(uint8_t pitch, uint8_t velo); |
|
||||||
void keyup(uint8_t pitch); |
|
||||||
|
|
||||||
/**
|
|
||||||
* this is called from the Audio thread to tell |
|
||||||
* to update the UI / hostdata
|
|
||||||
*/ |
|
||||||
void handleAsyncUpdate(); |
|
||||||
void initCtrl(); |
|
||||||
|
|
||||||
MidiMessage* nextMidi,*midiMsg; |
|
||||||
bool hasMidiMessage; |
|
||||||
int midiEventPos; |
|
||||||
bool getNextEvent(MidiBuffer::Iterator* iter,const int samplePos); |
|
||||||
|
|
||||||
void handleIncomingMidiMessage(MidiInput* source, const MidiMessage& message); |
|
||||||
uint32_t engineType; |
|
||||||
|
|
||||||
FmCore engineMsfa; |
|
||||||
EngineMkI engineMkI; |
|
||||||
EngineOpl engineOpl; |
|
||||||
|
|
||||||
char clipboard[161]; |
|
||||||
char clipboardContent; |
|
||||||
|
|
||||||
void resolvAppDir(); |
|
||||||
|
|
||||||
int feedback_bitdepth; |
|
||||||
|
|
||||||
public : |
|
||||||
// in MIDI units (0x4000 is neutral)
|
|
||||||
Controllers controllers; |
|
||||||
StringArray programNames; |
|
||||||
Cartridge currentCart; |
|
||||||
uint8_t data[161]; |
|
||||||
|
|
||||||
SysexComm sysexComm; |
|
||||||
VoiceStatus voiceStatus; |
|
||||||
File activeFileCartridge; |
|
||||||
|
|
||||||
bool forceRefreshUI; |
|
||||||
float vuSignal; |
|
||||||
bool showKeyboard; |
|
||||||
int getEngineType(); |
|
||||||
void setEngineType(int rs); |
|
||||||
|
|
||||||
Array<Ctrl*> ctrl; |
|
||||||
|
|
||||||
OperatorCtrl opCtrl[6]; |
|
||||||
ScopedPointer<CtrlDX> pitchEgRate[4]; |
|
||||||
ScopedPointer<CtrlDX> pitchEgLevel[4]; |
|
||||||
ScopedPointer<CtrlDX> pitchModSens; |
|
||||||
ScopedPointer<CtrlDX> algo; |
|
||||||
ScopedPointer<CtrlDX> oscSync; |
|
||||||
ScopedPointer<CtrlDX> feedback; |
|
||||||
ScopedPointer<CtrlDX> lfoRate; |
|
||||||
ScopedPointer<CtrlDX> lfoDelay; |
|
||||||
ScopedPointer<CtrlDX> lfoAmpDepth; |
|
||||||
ScopedPointer<CtrlDX> lfoPitchDepth; |
|
||||||
ScopedPointer<CtrlDX> lfoWaveform; |
|
||||||
ScopedPointer<CtrlDX> lfoSync; |
|
||||||
ScopedPointer<CtrlDX> transpose; |
|
||||||
|
|
||||||
ScopedPointer<CtrlFloat> fxCutoff; |
|
||||||
ScopedPointer<CtrlFloat> fxReso; |
|
||||||
ScopedPointer<CtrlFloat> output; |
|
||||||
ScopedPointer<Ctrl> tune; |
|
||||||
|
|
||||||
void loadCartridge(Cartridge &cart); |
|
||||||
void setDxValue(int offset, int v); |
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
DexedAudioProcessor(); |
|
||||||
~DexedAudioProcessor(); |
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
void prepareToPlay (double sampleRate, int samplesPerBlock); |
|
||||||
void releaseResources(); |
|
||||||
void processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages); |
|
||||||
void panic(); |
|
||||||
bool isMonoMode() { |
|
||||||
return monoMode; |
|
||||||
} |
|
||||||
void setMonoMode(bool mode); |
|
||||||
|
|
||||||
void copyToClipboard(int srcOp); |
|
||||||
void pasteOpFromClipboard(int destOp); |
|
||||||
void pasteEnvFromClipboard(int destOp); |
|
||||||
void sendCurrentSysexProgram(); |
|
||||||
void sendCurrentSysexCartridge(); |
|
||||||
void sendSysexCartridge(File cart); |
|
||||||
bool hasClipboardContent(); |
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
AudioProcessorEditor* createEditor(); |
|
||||||
bool hasEditor() const; |
|
||||||
void updateUI(); |
|
||||||
bool peekVoiceStatus(); |
|
||||||
void updateProgramFromSysex(const uint8 *rawdata); |
|
||||||
void setupStartupCart(); |
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
const String getName() const; |
|
||||||
int getNumParameters(); |
|
||||||
float getParameter (int index); |
|
||||||
void setParameter (int index, float newValue); |
|
||||||
const String getParameterName (int index); |
|
||||||
const String getParameterText (int index); |
|
||||||
|
|
||||||
const String getInputChannelName (int channelIndex) const; |
|
||||||
const String getOutputChannelName (int channelIndex) const; |
|
||||||
bool isInputChannelStereoPair (int index) const; |
|
||||||
bool isOutputChannelStereoPair (int index) const; |
|
||||||
|
|
||||||
bool acceptsMidi() const; |
|
||||||
bool producesMidi() const; |
|
||||||
bool silenceInProducesSilenceOut() const; |
|
||||||
double getTailLengthSeconds() const; |
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
int getNumPrograms(); |
|
||||||
int getCurrentProgram(); |
|
||||||
void setCurrentProgram(int index); |
|
||||||
const String getProgramName (int index); |
|
||||||
void changeProgramName(int index, const String& newName); |
|
||||||
void resetToInitVoice(); |
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
void getStateInformation (MemoryBlock& destData); |
|
||||||
void setStateInformation (const void* data, int sizeInBytes); |
|
||||||
|
|
||||||
// this is kept up to date with the midi messages that arrive, and the UI component
|
|
||||||
// registers with it so it can represent the incoming messages
|
|
||||||
MidiKeyboardState keyboardState; |
|
||||||
void unbindUI(); |
|
||||||
|
|
||||||
void loadPreference(); |
|
||||||
void savePreference(); |
|
||||||
|
|
||||||
static File dexedAppDir; |
|
||||||
static File dexedCartDir; |
|
||||||
private: |
|
||||||
//==============================================================================
|
|
||||||
DexedAudioProcessor; |
|
||||||
|
|
||||||
}; |
|
||||||
|
|
||||||
#endif // PLUGINPROCESSOR_H_INCLUDED
|
|
@ -1,203 +0,0 @@ |
|||||||
/**
|
|
||||||
* |
|
||||||
* Copyright (c) 2015 Pascal Gauthier. |
|
||||||
* |
|
||||||
* This program is free software; you can redistribute it and/or modify |
|
||||||
* it under the terms of the GNU General Public License as published by |
|
||||||
* the Free Software Foundation; either version 3 of the License, or |
|
||||||
* (at your option) any later version. |
|
||||||
* |
|
||||||
* This program is distributed in the hope that it will be useful, |
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
* GNU General Public License for more details. |
|
||||||
* |
|
||||||
* You should have received a copy of the GNU General Public License |
|
||||||
* along with this program; if not, write to the Free Software Foundation, |
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
||||||
* |
|
||||||
*/ |
|
||||||
|
|
||||||
#include "ProgramListBox.h" |
|
||||||
#include "PluginData.h" |
|
||||||
#include "DXLookNFeel.h" |
|
||||||
#include "Dexed.h" |
|
||||||
|
|
||||||
ProgramListBox::ProgramListBox(const String name, int numCols) : Component(name) { |
|
||||||
cols = numCols; |
|
||||||
rows = 32 / numCols; |
|
||||||
selectedPgm = -1; |
|
||||||
hasContent = false; |
|
||||||
dragCandidate = -1; |
|
||||||
pgmCandidate = -1; |
|
||||||
readOnly = false; |
|
||||||
programNames.clear(); |
|
||||||
} |
|
||||||
|
|
||||||
void ProgramListBox::paint(Graphics &g) { |
|
||||||
int pgm = 0; |
|
||||||
|
|
||||||
g.setColour(Colour(20,18,18)); |
|
||||||
g.fillRect(0,0,getWidth(), getHeight()); |
|
||||||
g.setColour(Colour(0,0,0)); |
|
||||||
g.drawLine(0,0,getWidth(), 0, 2); |
|
||||||
g.setColour(Colour(3,3,1)); |
|
||||||
g.drawLine(0,0,0,getHeight(),2); |
|
||||||
g.setColour(Colour(34,32,32)); |
|
||||||
g.drawLine(getWidth(), 3, getWidth(), getHeight(), 2); |
|
||||||
g.setColour(Colour(75,73,73)); |
|
||||||
g.drawLine(0,getHeight(),getWidth(),getHeight(), 2); |
|
||||||
|
|
||||||
const float dashLength[] = { 4, 4 }; |
|
||||||
|
|
||||||
g.setColour(Colour(83,76,69)); |
|
||||||
for(int i=1;i<cols;i++) { |
|
||||||
Line<float> line(cellWidth*i,0,cellWidth*i,getHeight()); |
|
||||||
g.drawDashedLine(line, dashLength, 2); |
|
||||||
} |
|
||||||
for(int i=1;i<rows;i++) { |
|
||||||
Line<float> line(2, cellHeight*i,getWidth(),cellHeight*i); |
|
||||||
g.drawDashedLine(line, dashLength, 2); |
|
||||||
} |
|
||||||
|
|
||||||
for(int i=0;i<cols;i++) { |
|
||||||
for(int j=0;j<rows;j++) { |
|
||||||
if ( selectedPgm == pgm && dragCandidate == -1 ) { |
|
||||||
g.setColour(DXLookNFeel::fillColour); |
|
||||||
g.fillRoundedRectangle(cellWidth*i+2, cellHeight*j + 2, cellWidth - 4, cellHeight - 4, 0); |
|
||||||
} |
|
||||||
|
|
||||||
if ( hasContent == true ) { |
|
||||||
if ( dragCandidate != pgm ) { |
|
||||||
g.setColour(Colours::white); |
|
||||||
g.drawFittedText(programNames[pgm], cellWidth * i , cellHeight * j, cellWidth, cellHeight, Justification::centred, true); |
|
||||||
} else { |
|
||||||
g.setColour(DXLookNFeel::fillColour); |
|
||||||
g.fillRoundedRectangle(cellWidth*i+2, cellHeight*j + 2, cellWidth - 4, cellHeight - 4, 0); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
pgm++; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void ProgramListBox::resized() { |
|
||||||
cellWidth = getWidth() / cols; |
|
||||||
cellHeight = getHeight() / rows; |
|
||||||
} |
|
||||||
|
|
||||||
void ProgramListBox::setCartridge(Cartridge &cart) { |
|
||||||
cartContent = cart; |
|
||||||
cartContent.getProgramNames(programNames); |
|
||||||
hasContent = true; |
|
||||||
repaint(); |
|
||||||
} |
|
||||||
|
|
||||||
void ProgramListBox::addListener(ProgramListBoxListener *listener) { |
|
||||||
this->listener = listener; |
|
||||||
} |
|
||||||
|
|
||||||
int ProgramListBox::programPosition(int x, int y) { |
|
||||||
return (y / cellHeight) + ((x / cellWidth) * rows); |
|
||||||
} |
|
||||||
|
|
||||||
void ProgramListBox::mouseDown(const MouseEvent &event) { |
|
||||||
pgmCandidate = -1; |
|
||||||
|
|
||||||
if ( ! hasContent ) |
|
||||||
return; |
|
||||||
|
|
||||||
if ( event.mods.isRightButtonDown() ) { |
|
||||||
int pos = programPosition(event.getMouseDownX(), event.getMouseDownY()); |
|
||||||
if ( listener != nullptr ) |
|
||||||
listener->programRightClicked(this, pos); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
pgmCandidate = programPosition(event.getMouseDownX(), event.getMouseDownY()); |
|
||||||
} |
|
||||||
|
|
||||||
void ProgramListBox::mouseUp(const MouseEvent &event) { |
|
||||||
if ( pgmCandidate == -1 ) |
|
||||||
return; |
|
||||||
|
|
||||||
int pos = programPosition(event.getMouseDownX(), event.getMouseDownY()); |
|
||||||
if ( pgmCandidate == pos) { |
|
||||||
if ( listener != nullptr ) |
|
||||||
listener->programSelected(this, pgmCandidate); |
|
||||||
pgmCandidate = -1; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void ProgramListBox::mouseDrag(const MouseEvent &event) { |
|
||||||
pgmCandidate = -1; |
|
||||||
if ( ! hasContent ) |
|
||||||
return; |
|
||||||
if ( dragCandidate != -1 ) |
|
||||||
return; |
|
||||||
if ( event.getDistanceFromDragStart() < 7 ) |
|
||||||
return; |
|
||||||
|
|
||||||
if (DragAndDropContainer* const dragContainer = DragAndDropContainer::findParentDragContainerFor(this)) { |
|
||||||
Image snapshot (Image::ARGB, cellWidth, cellHeight, true); |
|
||||||
int position = programPosition(event.getMouseDownX(), event.getMouseDownY()); |
|
||||||
Graphics g(snapshot); |
|
||||||
g.setColour(DXLookNFeel::lightBackground); |
|
||||||
g.fillRect(0,0,cellWidth, cellHeight); |
|
||||||
g.setColour(Colours::white); |
|
||||||
g.drawFittedText(programNames[position], 0, 0, cellWidth, cellHeight, Justification::centred, true); |
|
||||||
void *src = cartContent.getRawVoice() + (position*128); |
|
||||||
var description = var(src, 128); |
|
||||||
dragContainer->startDragging(description, this, snapshot, false); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void ProgramListBox::setSelected(int idx) { |
|
||||||
selectedPgm = idx; |
|
||||||
} |
|
||||||
|
|
||||||
Cartridge &ProgramListBox::getCurrentCart() { |
|
||||||
return cartContent; |
|
||||||
} |
|
||||||
|
|
||||||
bool ProgramListBox::isInterestedInDragSource (const SourceDetails& dragSourceDetail) { |
|
||||||
if ( readOnly ) |
|
||||||
return false; |
|
||||||
if ( ! hasContent ) |
|
||||||
return false; |
|
||||||
|
|
||||||
Component *comp = dragSourceDetail.sourceComponent.get(); |
|
||||||
if ( comp == nullptr ) |
|
||||||
return false; |
|
||||||
if ( dynamic_cast<ProgramListBox*>(comp) == nullptr ) |
|
||||||
return false; |
|
||||||
|
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
void ProgramListBox::itemDropped(const SourceDetails& dragSourceDetails) { |
|
||||||
dragCandidate = programPosition(dragSourceDetails.localPosition.x, dragSourceDetails.localPosition.y); |
|
||||||
|
|
||||||
MemoryBlock* block = dragSourceDetails.description.getBinaryData(); |
|
||||||
if ( listener != nullptr ) |
|
||||||
listener->programDragged(this, dragCandidate, (char *)block->getData()); |
|
||||||
dragCandidate = -1; |
|
||||||
repaint(); |
|
||||||
} |
|
||||||
|
|
||||||
void ProgramListBox::itemDragEnter(const SourceDetails &dragSourceDetails) { |
|
||||||
dragCandidate = programPosition(dragSourceDetails.localPosition.x, dragSourceDetails.localPosition.y); |
|
||||||
repaint(); |
|
||||||
} |
|
||||||
|
|
||||||
void ProgramListBox::itemDragMove(const SourceDetails &dragSourceDetails) { |
|
||||||
dragCandidate = programPosition(dragSourceDetails.localPosition.x, dragSourceDetails.localPosition.y); |
|
||||||
repaint(); |
|
||||||
} |
|
||||||
|
|
||||||
void ProgramListBox::itemDragExit(const SourceDetails &dragSourceDetails) { |
|
||||||
dragCandidate = -1; |
|
||||||
repaint(); |
|
||||||
} |
|
||||||
|
|
@ -1,74 +0,0 @@ |
|||||||
/**
|
|
||||||
* |
|
||||||
* Copyright (c) 2015 Pascal Gauthier. |
|
||||||
* |
|
||||||
* This program is free software; you can redistribute it and/or modify |
|
||||||
* it under the terms of the GNU General Public License as published by |
|
||||||
* the Free Software Foundation; either version 3 of the License, or |
|
||||||
* (at your option) any later version. |
|
||||||
* |
|
||||||
* This program is distributed in the hope that it will be useful, |
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
* GNU General Public License for more details. |
|
||||||
* |
|
||||||
* You should have received a copy of the GNU General Public License |
|
||||||
* along with this program; if not, write to the Free Software Foundation, |
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
||||||
* |
|
||||||
*/ |
|
||||||
|
|
||||||
#ifndef PROGRAMLISTBOX_H_INCLUDED |
|
||||||
#define PROGRAMLISTBOX_H_INCLUDED |
|
||||||
|
|
||||||
#include "JuceHeader.h" |
|
||||||
#include "PluginData.h" |
|
||||||
|
|
||||||
class ProgramListBox; |
|
||||||
class ProgramListBoxListener { |
|
||||||
public: |
|
||||||
virtual ~ProgramListBoxListener() {} |
|
||||||
virtual void programSelected(ProgramListBox *source, int pos) = 0; |
|
||||||
virtual void programRightClicked(ProgramListBox *source, int pos) = 0; |
|
||||||
virtual void programDragged(ProgramListBox *destListBox, int dest, char *packedPgm) = 0; |
|
||||||
}; |
|
||||||
|
|
||||||
class ProgramListBox : public Component, public DragAndDropTarget { |
|
||||||
ProgramListBoxListener *listener; |
|
||||||
bool hasContent; |
|
||||||
bool showPgmNumber; |
|
||||||
int cols, rows; |
|
||||||
int cellWidth, cellHeight; |
|
||||||
int programPosition(int x, int y); |
|
||||||
int selectedPgm; |
|
||||||
|
|
||||||
Cartridge cartContent; |
|
||||||
|
|
||||||
int dragCandidate; |
|
||||||
int pgmCandidate; |
|
||||||
public: |
|
||||||
StringArray programNames;
|
|
||||||
|
|
||||||
bool readOnly; |
|
||||||
|
|
||||||
ProgramListBox(const String name, int numCols); |
|
||||||
void addListener(ProgramListBoxListener *listener); |
|
||||||
void paint(Graphics &g) override; |
|
||||||
void resized() override; |
|
||||||
void mouseDown(const MouseEvent &event) override; |
|
||||||
void mouseDrag(const MouseEvent &event) override; |
|
||||||
void mouseUp(const MouseEvent &event) override; |
|
||||||
void setSelected(int idx); |
|
||||||
|
|
||||||
Cartridge &getCurrentCart(); |
|
||||||
void setCartridge(Cartridge &cart); |
|
||||||
|
|
||||||
bool isInterestedInDragSource(const SourceDetails& dragSourceDetails) override; |
|
||||||
void itemDragEnter(const SourceDetails &dragSourceDetails) override; |
|
||||||
void itemDragMove(const SourceDetails &dragSourceDetails) override; |
|
||||||
void itemDragExit(const SourceDetails &dragSourceDetails) override; |
|
||||||
void itemDropped(const SourceDetails& dragSourceDetails) override; |
|
||||||
}; |
|
||||||
|
|
||||||
|
|
||||||
#endif // PROGRAMLISTBOX_H_INCLUDED
|
|
@ -1,155 +0,0 @@ |
|||||||
/**
|
|
||||||
* |
|
||||||
* Copyright (c) 2014 Pascal Gauthier. |
|
||||||
* |
|
||||||
* This program is free software; you can redistribute it and/or modify |
|
||||||
* it under the terms of the GNU General Public License as published by |
|
||||||
* the Free Software Foundation; either version 3 of the License, or |
|
||||||
* (at your option) any later version. |
|
||||||
* |
|
||||||
* This program is distributed in the hope that it will be useful, |
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
* GNU General Public License for more details. |
|
||||||
* |
|
||||||
* You should have received a copy of the GNU General Public License |
|
||||||
* along with this program; if not, write to the Free Software Foundation, |
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
||||||
* |
|
||||||
*/ |
|
||||||
|
|
||||||
#include "SysexComm.h" |
|
||||||
#include "Dexed.h" |
|
||||||
|
|
||||||
SysexComm::SysexComm() { |
|
||||||
sysexChl = 0; |
|
||||||
listener = NULL; // this will get injected later
|
|
||||||
|
|
||||||
inputName = ""; |
|
||||||
outputName = ""; |
|
||||||
|
|
||||||
input = NULL; |
|
||||||
output = NULL; |
|
||||||
inputOutput = false; |
|
||||||
} |
|
||||||
|
|
||||||
SysexComm::~SysexComm() { |
|
||||||
if ( input != NULL ) { |
|
||||||
input->stop(); |
|
||||||
delete input; |
|
||||||
} |
|
||||||
|
|
||||||
if ( output != NULL ) |
|
||||||
delete output; |
|
||||||
} |
|
||||||
|
|
||||||
String SysexComm::getInput() { |
|
||||||
return inputName; |
|
||||||
} |
|
||||||
|
|
||||||
bool SysexComm::setInput(String target) { |
|
||||||
if ( input != NULL ) { |
|
||||||
input->stop(); |
|
||||||
delete input; |
|
||||||
input = NULL; |
|
||||||
|
|
||||||
} |
|
||||||
inputOutput = false; |
|
||||||
|
|
||||||
if ( listener == NULL ) |
|
||||||
return true; |
|
||||||
|
|
||||||
StringArray devices = MidiInput::getDevices(); |
|
||||||
int idx = devices.indexOf(target); |
|
||||||
|
|
||||||
if ( idx == -1 ) { |
|
||||||
TRACE("device %s not found", target.toRawUTF8()); |
|
||||||
inputName = ""; |
|
||||||
if ( target == "None" || target == "" ) |
|
||||||
return true; |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
input = MidiInput::openDevice(idx, listener); |
|
||||||
if ( input == NULL ) { |
|
||||||
TRACE("unable to open %s", target.toRawUTF8()); |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
inputName = target; |
|
||||||
TRACE("sysex %s opened", target.toRawUTF8()); |
|
||||||
input->start(); |
|
||||||
|
|
||||||
if ( output ) |
|
||||||
inputOutput = true; |
|
||||||
|
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
String SysexComm::getOutput() { |
|
||||||
return outputName; |
|
||||||
} |
|
||||||
|
|
||||||
bool SysexComm::setOutput(String target) { |
|
||||||
if ( output != NULL ) { |
|
||||||
delete output; |
|
||||||
output = NULL; |
|
||||||
} |
|
||||||
inputOutput = false; |
|
||||||
|
|
||||||
StringArray devices = MidiOutput::getDevices(); |
|
||||||
int idx = devices.indexOf(target); |
|
||||||
|
|
||||||
if ( idx == -1 ) { |
|
||||||
TRACE("device %s not found", target.toRawUTF8()); |
|
||||||
outputName = ""; |
|
||||||
if ( target == "None" || target == "" ) |
|
||||||
return true; |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
output = MidiOutput::openDevice(idx); |
|
||||||
if ( output == NULL ) { |
|
||||||
TRACE("unable to open %s", target.toRawUTF8()); |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
outputName = target; |
|
||||||
|
|
||||||
if ( input ) |
|
||||||
inputOutput = true; |
|
||||||
|
|
||||||
TRACE("sysex %s opened", target.toRawUTF8()); |
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
bool SysexComm::isInputActive() { |
|
||||||
return input != NULL; |
|
||||||
} |
|
||||||
|
|
||||||
bool SysexComm::isOutputActive() { |
|
||||||
return output != NULL; |
|
||||||
} |
|
||||||
|
|
||||||
int SysexComm::getChl() { |
|
||||||
return sysexChl; |
|
||||||
} |
|
||||||
|
|
||||||
void SysexComm::setChl(int chl) { |
|
||||||
sysexChl = chl; |
|
||||||
} |
|
||||||
|
|
||||||
int SysexComm::send(const MidiMessage &message) { |
|
||||||
if ( output == NULL ) |
|
||||||
return 2; |
|
||||||
|
|
||||||
TRACE("send sysex"); |
|
||||||
|
|
||||||
outActivity = true; |
|
||||||
output->sendMessageNow(message); |
|
||||||
return 0; |
|
||||||
} |
|
||||||
|
|
||||||
void SysexComm::playBuffer(MidiBuffer &keyboardEvents, int numSamples ) { |
|
||||||
noteOutput.addEvents(keyboardEvents, 0, numSamples, 0); |
|
||||||
} |
|
@ -1,60 +0,0 @@ |
|||||||
/**
|
|
||||||
* |
|
||||||
* Copyright (c) 2014 Pascal Gauthier. |
|
||||||
* |
|
||||||
* This program is free software; you can redistribute it and/or modify |
|
||||||
* it under the terms of the GNU General Public License as published by |
|
||||||
* the Free Software Foundation; either version 3 of the License, or |
|
||||||
* (at your option) any later version. |
|
||||||
* |
|
||||||
* This program is distributed in the hope that it will be useful, |
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
* GNU General Public License for more details. |
|
||||||
* |
|
||||||
* You should have received a copy of the GNU General Public License |
|
||||||
* along with this program; if not, write to the Free Software Foundation, |
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
||||||
* |
|
||||||
*/ |
|
||||||
|
|
||||||
#ifndef SYSEXCOMM_H_INCLUDED |
|
||||||
#define SYSEXCOMM_H_INCLUDED |
|
||||||
|
|
||||||
class SysexComm { |
|
||||||
MidiInput *input; |
|
||||||
MidiOutput *output; |
|
||||||
String inputName; |
|
||||||
String outputName; |
|
||||||
int sysexChl; |
|
||||||
|
|
||||||
bool inputOutput; |
|
||||||
|
|
||||||
MidiBuffer noteOutput; |
|
||||||
public : |
|
||||||
MidiInputCallback *listener; |
|
||||||
bool inActivity; |
|
||||||
bool outActivity; |
|
||||||
|
|
||||||
SysexComm(); |
|
||||||
~SysexComm(); |
|
||||||
|
|
||||||
bool setInput(String name); |
|
||||||
bool setOutput(String name); |
|
||||||
void setChl(int chl); |
|
||||||
|
|
||||||
String getInput(); |
|
||||||
String getOutput(); |
|
||||||
int getChl(); |
|
||||||
|
|
||||||
bool isInputActive(); |
|
||||||
bool isOutputActive(); |
|
||||||
inline bool isInputOutputActive() { |
|
||||||
return inputOutput; |
|
||||||
} |
|
||||||
|
|
||||||
int send(const MidiMessage& message); |
|
||||||
void playBuffer(MidiBuffer &keyboardEvents, int numSamples); |
|
||||||
}; |
|
||||||
|
|
||||||
#endif // SYSEXCOMM_H_INCLUDED
|
|
@ -1,76 +0,0 @@ |
|||||||
/*
|
|
||||||
* Copyright 2012 Google Inc. |
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
#include <time.h> |
|
||||||
#include <string.h> |
|
||||||
|
|
||||||
#include "synth.h" |
|
||||||
#include "ringbuffer.h" |
|
||||||
|
|
||||||
RingBuffer::RingBuffer() { |
|
||||||
rd_ix_ = 0; |
|
||||||
wr_ix_ = 0; |
|
||||||
} |
|
||||||
|
|
||||||
int RingBuffer::BytesAvailable() { |
|
||||||
return (wr_ix_ - rd_ix_) & (kBufSize - 1); |
|
||||||
} |
|
||||||
|
|
||||||
int RingBuffer::WriteBytesAvailable() { |
|
||||||
return (rd_ix_ - wr_ix_ - 1) & (kBufSize - 1); |
|
||||||
} |
|
||||||
|
|
||||||
int RingBuffer::Read(int size, uint8_t *bytes) { |
|
||||||
int rd_ix = rd_ix_; |
|
||||||
SynthMemoryBarrier(); // read barrier, make sure data is committed before ix
|
|
||||||
int fragment_size = min(size, kBufSize - rd_ix); |
|
||||||
memcpy(bytes, buf_ + rd_ix, fragment_size); |
|
||||||
if (size > fragment_size) { |
|
||||||
memcpy(bytes + fragment_size, buf_, size - fragment_size); |
|
||||||
} |
|
||||||
SynthMemoryBarrier(); // full barrier, make sure read commits before updating
|
|
||||||
rd_ix_ = (rd_ix + size) & (kBufSize - 1); |
|
||||||
return size; |
|
||||||
} |
|
||||||
|
|
||||||
int RingBuffer::Write(const uint8_t *bytes, int size) { |
|
||||||
int remaining = size; |
|
||||||
while (remaining > 0) { |
|
||||||
int rd_ix = rd_ix_; |
|
||||||
int wr_ix = wr_ix_; |
|
||||||
int space_available = (rd_ix - wr_ix - 1) & (kBufSize - 1); |
|
||||||
if (space_available == 0) { |
|
||||||
struct timespec sleepTime; |
|
||||||
sleepTime.tv_sec = 0; |
|
||||||
sleepTime.tv_nsec = 1000000; |
|
||||||
nanosleep(&sleepTime, NULL); |
|
||||||
} else { |
|
||||||
int wr_size = min(remaining, space_available); |
|
||||||
int fragment_size = min(wr_size, kBufSize - wr_ix); |
|
||||||
memcpy(buf_ + wr_ix, bytes, fragment_size); |
|
||||||
if (wr_size > fragment_size) { |
|
||||||
memcpy(buf_, bytes + fragment_size, wr_size - fragment_size); |
|
||||||
} |
|
||||||
SynthMemoryBarrier(); // write barrier, make sure data commits
|
|
||||||
wr_ix_ = (wr_ix + wr_size) & (kBufSize - 1); |
|
||||||
remaining -= wr_size; |
|
||||||
bytes += wr_size; |
|
||||||
} |
|
||||||
} |
|
||||||
// JJK : defined as returning int
|
|
||||||
return 0; |
|
||||||
} |
|
||||||
|
|
@ -1,44 +0,0 @@ |
|||||||
/*
|
|
||||||
* Copyright 2012 Google Inc. |
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
#ifndef SYNTH_RINGBUFFER_H_ |
|
||||||
#define SYNTH_RINGBUFFER_H_ |
|
||||||
|
|
||||||
class RingBuffer { |
|
||||||
public: |
|
||||||
RingBuffer(); |
|
||||||
|
|
||||||
// Returns number of bytes available for reading.
|
|
||||||
int BytesAvailable(); |
|
||||||
|
|
||||||
// Returns number of bytes that can be written without blocking.
|
|
||||||
int WriteBytesAvailable(); |
|
||||||
|
|
||||||
// Reads bytes. It is the caller's responsibility to make sure that
|
|
||||||
// size <= a previous value of BytesAvailable().
|
|
||||||
int Read(int size, uint8_t *bytes); |
|
||||||
|
|
||||||
// Writes bytes into the buffer. If the buffer is full, the method will
|
|
||||||
// block until space is available.
|
|
||||||
int Write(const uint8_t *bytes, int size); |
|
||||||
private: |
|
||||||
static const int kBufSize = 8192; |
|
||||||
uint8_t buf_[kBufSize]; |
|
||||||
volatile unsigned int rd_ix_; |
|
||||||
volatile unsigned int wr_ix_; |
|
||||||
}; |
|
||||||
|
|
||||||
#endif // SYNTH_RINGBUFFER_H_
|
|
Loading…
Reference in new issue