Update controller views from MIDI keyboard

This patch adds plumbing so that changing the controller values from
a USB MIDI keyboard updates the knob views as well.
master
Raph Levien 11 years ago
parent b22117bb52
commit 7a5706054e
  1. 27
      android/src/com/levien/synthesizer/android/service/SynthesizerService.java
  2. 22
      android/src/com/levien/synthesizer/android/ui/PianoActivity2.java
  3. 59
      android/src/com/levien/synthesizer/android/widgets/knob/KnobView.java

@ -41,6 +41,7 @@ import android.util.Log;
import com.levien.synthesizer.R;
import com.levien.synthesizer.android.AndroidGlue;
import com.levien.synthesizer.android.usb.UsbMidiDevice;
import com.levien.synthesizer.core.midi.MessageForwarder;
import com.levien.synthesizer.core.midi.MidiListener;
import com.levien.synthesizer.core.model.composite.MultiChannelSynthesizer;
@ -85,6 +86,15 @@ public class SynthesizerService extends Service {
params.bufferSize = 64;
androidGlue_ = new AndroidGlue();
midiListener_ = new MessageForwarder(androidGlue_) {
@Override
public void onController(int channel, int control, int value) {
super.onController(channel, control, value);
if (onCcListener_!= null) {
onCcListener_.onCcChange(channel, control, value);
}
}
};
androidGlue_.start(params.sampleRate, params.bufferSize);
InputStream patchIs = getResources().openRawResource(R.raw.rom1a);
byte[] patchData = new byte[4104];
@ -129,7 +139,7 @@ public class SynthesizerService extends Service {
}
public MidiListener getMidiListener() {
return androidGlue_;
return midiListener_;
}
/**
@ -214,7 +224,7 @@ public class SynthesizerService extends Service {
usbDevice_ = device;
usbMidiConnection_ = connection;
usbMidiInterface_ = intf;
usbMidiDevice_ = new UsbMidiDevice(androidGlue_, usbMidiConnection_, intf);
usbMidiDevice_ = new UsbMidiDevice(midiListener_, usbMidiConnection_, intf);
usbMidiDevice_.start();
return true;
} else {
@ -262,6 +272,16 @@ public class SynthesizerService extends Service {
}
};
public interface OnCcListener {
abstract void onCcChange(int channel, int cc, int value);
}
public void setOnCcListener(OnCcListener onCcListener) {
onCcListener_ = onCcListener;
}
private MidiListener midiListener_;
// Binder to use for Activities in this process.
private final IBinder binder_ = new LocalBinder();
@ -275,4 +295,7 @@ public class SynthesizerService extends Service {
private UsbMidiDevice usbMidiDevice_;
private UsbInterface usbMidiInterface_;
private UsbDevice usbDeviceNeedsPermission_;
// Plumbing for MIDI events
private OnCcListener onCcListener_;
}

@ -205,11 +205,16 @@ public class PianoActivity2 extends Activity {
SynthesizerService.LocalBinder binder = (SynthesizerService.LocalBinder)service;
synthesizerService_ = binder.getService();
piano_.bindTo(synthesizerService_.getMidiListener());
// Populate patch names (note: we could update an existing list rather than
// creating a new adapter, but it probably wouldn't save all that much).
List<String> patchNames = synthesizerService_.getPatchNames();
ArrayAdapter<String> adapter = new ArrayAdapter<String>(
PianoActivity2.this, android.R.layout.simple_spinner_item, patchNames);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
presetSpinner_.setAdapter(adapter);
// Handle any pending USB device events
if (usbDevicePending_ != null) {
synthesizerService_.connectUsbMidi(usbDevicePending_);
usbDevicePending_ = null;
@ -225,6 +230,23 @@ public class PianoActivity2 extends Activity {
}
}
}
// Connect controller changes to knob views
synthesizerService_.setOnCcListener(new SynthesizerService.OnCcListener() {
public void onCcChange(final int channel, final int cc, final int value) {
runOnUiThread(new Runnable() {
public void run() {
if (cc == 1) {
cutoffKnob_.setValue(value * (1.0 / 127));
} else if (cc == 2) {
resonanceKnob_.setValue(value * (1.0 / 127));
} else if (cc == 3) {
overdriveKnob_.setValue(value * (1.0 / 127));
}
}
});
}
});
}
public void onServiceDisconnected(ComponentName className) {
synthesizerService_ = null;

@ -1,12 +1,12 @@
/*
* Copyright 2010 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.
@ -83,10 +83,10 @@ public class KnobView extends View {
diffAngle_ = 0;
break;
}
case MotionEvent.ACTION_MOVE: {
getDrawingRect(rect_);
// Compare the previous angle of the finger position (relative to the center of the control)
// to the new angle, and update the value accordingly.
currentTouchAngle_ = knobValue_ * 2 * Math.PI * 0.8 + (Math.PI / 5.0);
@ -102,7 +102,7 @@ public class KnobView extends View {
knobValue_ = currentTouchAngle_ / (2.0 * Math.PI);
if (knobValue_ < 0.1) knobValue_ = 0.1;
if (knobValue_ > 0.9) knobValue_ = 0.9;
knobValue_ -= 0.1;
knobValue_ -= 0.1;
knobValue_ /= 0.8;
previousX_ = currentX_;
previousY_ = currentY_;
@ -115,7 +115,7 @@ public class KnobView extends View {
break;
}
case MotionEvent.ACTION_UP: {
break;
}
@ -147,7 +147,9 @@ public class KnobView extends View {
}
/**
* Sets the current value of the knob.
* Sets the current value of the knob. Note that this call does not
* invoke the listener. The assumption is that any caller will also
* update the client.
*/
public void setValue(double value) {
if (value < min_) {
@ -157,9 +159,6 @@ public class KnobView extends View {
} else {
knobValue_ = (value - min_) / (max_ - min_);
}
if (listener_ != null) {
listener_.onKnobChanged(value);
}
invalidate();
}
@ -189,30 +188,30 @@ public class KnobView extends View {
rectF_.left = center - rectF_.height() / 2;
rectF_.right = center + rectF_.height() / 2;
}
// Draw outer white glow.
int[] radialGradientColors = {Color.WHITE, Color.WHITE, 0x00000000};
float[] radialGradientPositions = {0.0f, 0.87f, 1.0f};
radialGradient_ = new RadialGradient(rect_.exactCenterX(),
rect_.exactCenterY(),
Math.min(rect_.width(), rect_.height()) / 2,
rect_.exactCenterY(),
Math.min(rect_.width(), rect_.height()) / 2,
radialGradientColors,
radialGradientPositions,
radialGradientPositions,
TileMode.CLAMP);
knobPaint_.setShader(radialGradient_);
canvas.drawCircle(rect_.exactCenterX(),
rect_.exactCenterY(),
Math.min(rect_.width(), rect_.height()) / 2,
rect_.exactCenterY(),
Math.min(rect_.width(), rect_.height()) / 2,
knobPaint_);
// Draw outer gauge.
final int fullDark = Color.BLACK;
final int fullDark = Color.BLACK;
final int guageStartColor = 0xff202050;
final int guageEndColor = 0xff4040A0;
final int adjustedStartColor = Color.argb(
0xFF,
0xFF,
(int)(0.1875 * Color.red(guageStartColor) + (1.0 - 0.1875) * Color.red(guageEndColor)),
(int)(0.1875 * Color.green(guageStartColor) + (1.0 - 0.1875) * Color.green(guageEndColor)),
(int)(0.1875 * Color.blue(guageStartColor) + (1.0 - 0.1875) * Color.blue(guageEndColor)));
@ -243,20 +242,20 @@ public class KnobView extends View {
rect_.exactCenterY(),
Math.min(rect_.width(), rect_.height()) / 4,
knobPaint_);
// Draw inner white glow.
int[] innerRadialGradientColors = { 0x00000000, 0x00000000, Color.WHITE };
float[] innerRadialGradientPositions = { 0.0f, 0.6f, 1.0f };
innerRadialGradient_ = new RadialGradient(rect_.exactCenterX(),
rect_.exactCenterY(),
Math.min(rect_.width(), rect_.height()) / 4f,
rect_.exactCenterY(),
Math.min(rect_.width(), rect_.height()) / 4f,
innerRadialGradientColors,
innerRadialGradientPositions,
innerRadialGradientPositions,
TileMode.CLAMP);
knobPaint_.setShader(innerRadialGradient_);
canvas.drawCircle(rect_.exactCenterX(),
rect_.exactCenterY(),
Math.min(rect_.width(),rect_.height()) / 4,
rect_.exactCenterY(),
Math.min(rect_.width(),rect_.height()) / 4,
knobPaint_);
// Draw indicator.
@ -270,7 +269,7 @@ public class KnobView extends View {
(float)arcWidth,
false,
knobPaint_);
// Draw text.
String knobValueString = String.format("%.2f", getValue());
Typeface typeface = Typeface.create(knobPaint_.getTypeface(), Typeface.BOLD);
@ -329,7 +328,7 @@ public class KnobView extends View {
if (height > width && heightMode != MeasureSpec.EXACTLY) {
height = width;
}
setMeasuredDimension(width, height);
}

Loading…
Cancel
Save