Skip to content

Commit 7174bac

Browse files
authored
Merge pull request #82 from ericahrens/api-18
MCU/SSL fixed issue with non-ascii characters causing extension to crash due to illegal sysex values
2 parents a793718 + 9f6bb70 commit 7174bac

12 files changed

+218
-176
lines changed

src/main/java/com/bitwig/extensions/controllers/mcu/StringUtil.java

+41-21
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,26 @@
11
package com.bitwig.extensions.controllers.mcu;
22

33
public class StringUtil {
4-
4+
55
private static final int PAN_RANGE = 50;
6-
private static final char[] SPECIALS = {'ä', 'ü', 'ö', 'Ä', 'Ü', 'Ö', 'ß', 'é', 'è', 'ê', 'â', 'á', 'à', //
7-
'û', 'ú', 'ù', 'ô', 'ó', 'ò'};
8-
private static final String[] REPLACE = {"a", "u", "o", "A", "U", "O", "ss", "e", "e", "e", "a", "a", "a", //
9-
"u", "u", "u", "o", "o", "o"};
10-
6+
private static final char[] SPECIALS = {
7+
'ä', 'ü', 'ö', 'Ä', 'Ü', 'Ö', 'ß', 'é', 'è', 'ê', 'â', 'á', 'à', //
8+
'û', 'ú', 'ù', 'ô', 'ó', 'ò'
9+
};
10+
private static final String[] REPLACE = {
11+
"a", "u", "o", "A", "U", "O", "ss", "e", "e", "e", "a", "a", "a", //
12+
"u", "u", "u", "o", "o", "o"
13+
};
14+
1115
private StringUtil() {
1216
}
13-
17+
1418
public static String toBarBeats(final double value) {
1519
final int bars = (int) Math.floor(value);
1620
final int beats = (int) Math.floor((value - bars) * 4);
1721
return String.format("%02d:%02d", bars, beats);
1822
}
19-
23+
2024
public static String panToString(final double v) {
2125
final int intv = (int) (v * PAN_RANGE * 2);
2226
if (intv == PAN_RANGE) {
@@ -26,7 +30,7 @@ public static String panToString(final double v) {
2630
}
2731
return " " + (intv - PAN_RANGE) + "R";
2832
}
29-
33+
3034
/**
3135
* Tailored to condense Volume value strings. Removes leading + and spaces.
3236
*
@@ -45,27 +49,27 @@ public static String condenseVolumeValue(final String valueText, final int maxLe
4549
}
4650
return sb.toString();
4751
}
48-
52+
4953
public static String toTwoCharVal(final int value) {
5054
if (value < 10) {
5155
return " " + value;
5256
}
5357
return Integer.toString(value);
5458
}
55-
59+
5660
public static String toDisplayName(final String text) {
5761
if (text.length() < 2) {
5862
return text;
5963
}
6064
return text.charAt(0) + text.substring(1, Math.min(6, text.length())).toLowerCase();
6165
}
62-
63-
66+
67+
6468
public static String padString(final String text, final int pad) {
6569
return " ".repeat(Math.max(0, pad)) + text;
6670
}
67-
68-
public static String padEnd(final String text, int paddingLength) {
71+
72+
public static String padEnd(final String text, final int paddingLength) {
6973
if (text.length() == paddingLength) {
7074
return text;
7175
}
@@ -74,19 +78,35 @@ public static String padEnd(final String text, int paddingLength) {
7478
}
7579
return text + " ".repeat(paddingLength - text.length());
7680
}
77-
81+
7882
public static String limit(final String value, final int max) {
7983
return value.substring(0, Math.min(max, value.length()));
8084
}
81-
85+
8286
public static String reduceAscii(final String name, final int maxLen) {
83-
String result = toAsciiDisplay(name, maxLen + 10);
87+
final String result = toAsciiDisplay(name, maxLen + 10);
8488
if (result.length() <= maxLen) {
8589
return result;
8690
}
8791
return result.replace(" ", "");
8892
}
89-
93+
94+
public static String toAscii(final String value) {
95+
final StringBuilder b = new StringBuilder();
96+
for (int i = 0; i < value.length(); i++) {
97+
final char c = value.charAt(i);
98+
if (c < 128) {
99+
b.append(c);
100+
} else {
101+
final int replacement = getReplace(c);
102+
if (replacement >= 0) {
103+
b.append(REPLACE[replacement]);
104+
}
105+
}
106+
}
107+
return b.toString();
108+
}
109+
90110
public static String toAsciiDisplay(final String name, final int maxLen) {
91111
final StringBuilder b = new StringBuilder();
92112
for (int i = 0; i < name.length() && b.length() < maxLen; i++) {
@@ -105,7 +125,7 @@ public static String toAsciiDisplay(final String name, final int maxLen) {
105125
}
106126
return b.toString();
107127
}
108-
128+
109129
private static int getReplace(final char c) {
110130
for (int i = 0; i < SPECIALS.length; i++) {
111131
if (c == SPECIALS[i]) {
@@ -114,5 +134,5 @@ private static int getReplace(final char c) {
114134
}
115135
return -1;
116136
}
117-
137+
118138
}

src/main/java/com/bitwig/extensions/controllers/mcu/bindings/display/ParameterDisplayBinding.java

-32
This file was deleted.

src/main/java/com/bitwig/extensions/controllers/mcu/bindings/display/ParameterValueDisplayBinding.java

-5
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,6 @@
88
public class ParameterValueDisplayBinding extends AbstractDisplayBinding<Parameter> {
99
private final DoubleValueConverter converter;
1010

11-
public ParameterValueDisplayBinding(final DisplayManager target, final ControlMode mode,
12-
final DisplayTarget displayTargetIndex, final Parameter parameter) {
13-
this(target, mode, displayTargetIndex, parameter, value -> Double.toString(value));
14-
}
15-
1611
public ParameterValueDisplayBinding(final DisplayManager target, final ControlMode mode,
1712
final DisplayTarget displayTargetIndex, final Parameter parameter, final DoubleValueConverter converter) {
1813
super(target, mode, displayTargetIndex, parameter);

src/main/java/com/bitwig/extensions/controllers/mcu/bindings/display/StringDisplayBinding.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.bitwig.extension.controller.api.BooleanValue;
44
import com.bitwig.extension.controller.api.StringValue;
5+
import com.bitwig.extensions.controllers.mcu.StringUtil;
56
import com.bitwig.extensions.controllers.mcu.bindings.ResetableBinding;
67
import com.bitwig.extensions.controllers.mcu.display.DisplayManager;
78
import com.bitwig.extensions.controllers.mcu.layer.ControlMode;
@@ -24,7 +25,7 @@ public StringDisplayBinding(final DisplayManager target, final ControlMode mode,
2425

2526
public StringDisplayBinding(final DisplayManager target, final ControlMode mode,
2627
final DisplayTarget displayTargetIndex, final StringValue stringValue, final BooleanValue existsValue) {
27-
this(target, mode, displayTargetIndex, stringValue, existsValue, s -> s);
28+
this(target, mode, displayTargetIndex, stringValue, existsValue, s -> StringUtil.toAsciiDisplay(s, 8));
2829
}
2930

3031
private void handleValueChange(final String newValue) {
@@ -36,7 +37,7 @@ private void handleValueChange(final String newValue) {
3637

3738
@Override
3839
public void reset() {
39-
this.lastValue = getSource().get();
40+
this.lastValue = stringConversion.convert(getSource().get());
4041
if (isActive()) {
4142
updateDisplay();
4243
}

src/main/java/com/bitwig/extensions/controllers/mcu/bindings/display/StringRowDisplayBinding.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.bitwig.extensions.controllers.mcu.bindings.display;
22

33
import com.bitwig.extension.controller.api.StringValue;
4+
import com.bitwig.extensions.controllers.mcu.StringUtil;
45
import com.bitwig.extensions.controllers.mcu.display.DisplayManager;
56
import com.bitwig.extensions.controllers.mcu.display.DisplayRow;
67
import com.bitwig.extensions.controllers.mcu.layer.ControlMode;
@@ -12,15 +13,15 @@ public StringRowDisplayBinding(final DisplayManager target, final ControlMode mo
1213
super(target, mode, DisplayTarget.of(row.getRowIndex(), -1, sectionIndex), stringValue);
1314
exists = true;
1415
stringValue.addValueObserver(this::handleValueChange);
15-
this.lastValue = stringValue.get();
16+
this.lastValue = StringUtil.toAscii(stringValue.get());
1617
}
1718

1819
protected void updateDisplay() {
1920
getTarget().sendText(controlMode, targetIndex.rowIndex(), lastValue);
2021
}
2122

2223
private void handleValueChange(final String newValue) {
23-
this.lastValue = newValue;
24+
this.lastValue = StringUtil.toAscii(newValue);
2425
if (isActive()) {
2526
updateDisplay();
2627
}

src/main/java/com/bitwig/extensions/controllers/mcu/devices/DeviceManager.java

+14-14
Original file line numberDiff line numberDiff line change
@@ -3,31 +3,31 @@
33
import com.bitwig.extension.controller.api.Parameter;
44

55
public interface DeviceManager {
6-
6+
77
//void initiateBrowsing(final BrowserConfiguration browser, Type type);
8-
8+
99
//void addBrowsing(final BrowserConfiguration browser, boolean after);
10-
10+
1111
//void setInfoLayer(DisplayLayer infoLayer);
12-
12+
1313
//void enableInfo(InfoSource type);
14-
14+
1515
void disableInfo();
16-
16+
1717
//InfoSource getInfoSource();
18-
18+
1919
Parameter getParameter(int index);
20-
20+
2121
//ParameterPage getParameterPage(int index);
22-
22+
2323
void navigateDeviceParameters(final int direction);
24-
24+
2525
//void handleResetInvoked(final int index, final ModifierValueObject modifier);
2626

27-
DeviceTypeFollower getCurrentFollower();
28-
27+
DeviceTypeFollower getDeviceFollower();
28+
2929
boolean isSpecificDevicePresent();
30-
30+
3131
int getPageCount();
32-
32+
3333
}

src/main/java/com/bitwig/extensions/controllers/mcu/devices/DeviceTypeFollower.java

+26-14
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
package com.bitwig.extensions.controllers.mcu.devices;
22

33
import com.bitwig.extension.callback.BooleanValueChangedCallback;
4-
import com.bitwig.extension.controller.api.*;
4+
import com.bitwig.extension.controller.api.BooleanValue;
5+
import com.bitwig.extension.controller.api.CursorTrack;
6+
import com.bitwig.extension.controller.api.Device;
7+
import com.bitwig.extension.controller.api.DeviceBank;
8+
import com.bitwig.extension.controller.api.DeviceMatcher;
9+
import com.bitwig.extension.controller.api.PinnableCursorDevice;
510
import com.bitwig.extensions.controllers.mcu.CursorDeviceControl;
611
import com.bitwig.extensions.controllers.mcu.VPotMode;
12+
import com.bitwig.extensions.controllers.mcu.value.BasicIntValue;
713
import com.bitwig.extensions.framework.values.BooleanValueObject;
814

915
public class DeviceTypeFollower {
@@ -12,20 +18,24 @@ public class DeviceTypeFollower {
1218
private final Device focusDevice;
1319
private final CursorDeviceControl cursorDeviceControl;
1420
private final BooleanValue cursorOnDevice;
21+
private final BasicIntValue trackIndex = new BasicIntValue();
22+
1523
private int chainIndex = -1;
16-
24+
1725
public DeviceTypeFollower(final CursorDeviceControl cursorDeviceControl, final DeviceMatcher matcher,
18-
final VPotMode potMode) {
26+
final VPotMode potMode) {
1927
this.cursorDeviceControl = cursorDeviceControl;
2028
final CursorTrack cursorTrack = cursorDeviceControl.getCursorTrack();
2129
deviceBank = cursorTrack.createDeviceBank(1);
2230
this.potMode = potMode;
2331
deviceBank.setDeviceMatcher(matcher);
24-
32+
2533
focusDevice = deviceBank.getItemAt(0);
2634
focusDevice.exists().markInterested();
2735
focusDevice.name().markInterested();
28-
36+
37+
cursorTrack.position().addValueObserver(pos -> trackIndex.set(pos));
38+
2939
final PinnableCursorDevice cursorDevice = cursorDeviceControl.getCursorDevice();
3040
if (potMode.getAssign() == VPotMode.BitwigType.DEVICE) {
3141
final BooleanValueObject matchesTyp = new BooleanValueObject();
@@ -50,48 +60,50 @@ public DeviceTypeFollower(final CursorDeviceControl cursorDeviceControl, final D
5060
}
5161
});
5262
}
53-
63+
5464
public void addOnCursorListener(final BooleanValueChangedCallback booleanValueChangedCallback) {
5565
cursorOnDevice.addValueObserver(booleanValueChangedCallback);
5666
}
57-
67+
5868
public Device getFocusDevice() {
5969
return focusDevice;
6070
}
61-
71+
6272
public Device getCurrentDevice() {
6373
return cursorDeviceControl.getCursorDevice();
6474
}
65-
75+
6676
public void addNewDeviceAfter() {
6777
if (focusDevice.exists().get()) {
6878
focusDevice.afterDeviceInsertionPoint().browse();
6979
} else {
7080
deviceBank.browseToInsertDevice(0);
7181
}
7282
}
73-
83+
7484
public void addNewDeviceBefore() {
7585
if (focusDevice.exists().get()) {
7686
focusDevice.beforeDeviceInsertionPoint().browse();
7787
} else {
7888
deviceBank.browseToInsertDevice(0);
7989
}
8090
}
81-
91+
8292
public void initiateBrowsing() {
8393
if (focusDevice.exists().get()) {
8494
focusDevice.replaceDeviceInsertionPoint().browse();
8595
} else {
8696
deviceBank.browseToInsertDevice(0);
8797
}
8898
}
89-
99+
90100
public void ensurePosition() {
91-
final int currentDiveChainLocation = cursorDeviceControl.getCursorDevice().position().get();
92101
if (!cursorOnDevice.get()) {
93102
cursorDeviceControl.getCursorDevice().selectDevice(focusDevice);
94103
}
95104
}
96-
105+
106+
public BasicIntValue getTrackIndex() {
107+
return trackIndex;
108+
}
97109
}

src/main/java/com/bitwig/extensions/controllers/mcu/devices/SpecificDevice.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ public BooleanValue getExists() {
8181
}
8282

8383
@Override
84-
public DeviceTypeFollower getCurrentFollower() {
84+
public DeviceTypeFollower getDeviceFollower() {
8585
return deviceFollower;
8686
}
8787

0 commit comments

Comments
 (0)