1
0
Fork 0
mirror of https://github.com/rfc2822/GfxTablet synced 2025-10-06 02:39:56 +02:00

* driver, app: new protocol

* new protocol specification that allows versioning (version 1)

* App: refactoring, version: 1.1
This commit is contained in:
Richard Hirner 2013-02-05 03:42:15 +01:00
parent 38d99623df
commit 5f1d8f29d8
14 changed files with 166 additions and 163 deletions

View file

@ -35,7 +35,7 @@ public class CanvasActivity extends Activity {
@Override
protected void onDestroy() {
netClient.getQueue().add(new NetDisconnectEvent());
netClient.getQueue().add(new NetEvent(NetEvent.Type.TYPE_DISCONNECT));
super.onDestroy();
}

View file

@ -2,6 +2,7 @@ package at.bitfire.gfxtablet;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.os.AsyncTask;
@ -9,14 +10,14 @@ import android.preference.PreferenceManager;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;
import at.bitfire.gfxtablet.NetEvent.Type;
@SuppressLint("ViewConstructor")
public class CanvasView extends View implements OnSharedPreferenceChangeListener {
final static int PRESSURE_RESOLUTION = 10000;
NetworkClient netClient;
SharedPreferences settings;
boolean acceptStylusOnly;
int maxX, maxY;
public CanvasView(Context context, NetworkClient netClient) {
super(context);
@ -47,8 +48,8 @@ public class CanvasView extends View implements OnSharedPreferenceChangeListener
@Override
protected void onSizeChanged (int w, int h, int oldw, int oldh) {
Toast.makeText(getContext(), String.format("%dx%d", w, h), Toast.LENGTH_SHORT).show();
netClient.getQueue().add(new NetConfigurationEvent(w, h, PRESSURE_RESOLUTION));
maxX = w;
maxY = h;
}
@ -59,7 +60,11 @@ public class CanvasView extends View implements OnSharedPreferenceChangeListener
if (!acceptStylusOnly || (event.getToolType(ptr) == MotionEvent.TOOL_TYPE_STYLUS)) {
//Log.i("XorgTablet", String.format("Generic motion event logged: %f|%f, pressure %f", event.getX(ptr), event.getY(ptr), event.getPressure(ptr)));
if (event.getActionMasked() == MotionEvent.ACTION_HOVER_MOVE)
netClient.getQueue().add(new NetMotionEvent((int)event.getX(ptr), (int)event.getY(ptr), (int)(event.getPressure(ptr)*PRESSURE_RESOLUTION)));
netClient.getQueue().add(new NetEvent(Type.TYPE_MOTION,
normalizeX(event.getX(ptr)),
normalizeY(event.getY(ptr)),
normalizePressure(event.getPressure(ptr))
));
}
return true;
}
@ -71,17 +76,20 @@ public class CanvasView extends View implements OnSharedPreferenceChangeListener
if (isEnabled()) {
for (int ptr = 0; ptr < event.getPointerCount(); ptr++)
if (!acceptStylusOnly || (event.getToolType(ptr) == MotionEvent.TOOL_TYPE_STYLUS)) {
short nx = normalizeX(event.getX(ptr)),
ny = normalizeY(event.getY(ptr)),
npressure = normalizePressure(event.getPressure(ptr));
//Log.i("XorgTablet", String.format("Touch event logged: %f|%f, pressure %f", event.getX(ptr), event.getY(ptr), event.getPressure(ptr)));
switch (event.getActionMasked()) {
case MotionEvent.ACTION_MOVE:
netClient.getQueue().add(new NetMotionEvent((int)event.getX(ptr), (int)event.getY(ptr), (int)(event.getPressure(ptr)*PRESSURE_RESOLUTION)));
netClient.getQueue().add(new NetEvent(Type.TYPE_MOTION, nx, ny, npressure));
break;
case MotionEvent.ACTION_DOWN:
netClient.getQueue().add(new NetButtonEvent((int)event.getX(ptr), (int)event.getY(ptr), (int)(event.getPressure(ptr)*PRESSURE_RESOLUTION), true));
netClient.getQueue().add(new NetEvent(Type.TYPE_BUTTON, nx, ny, npressure, 0, true));
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
netClient.getQueue().add(new NetButtonEvent((int)event.getX(ptr), (int)event.getY(ptr), (int)(event.getPressure(ptr)*PRESSURE_RESOLUTION), false));
netClient.getQueue().add(new NetEvent(Type.TYPE_BUTTON, nx, ny, npressure, 0, false));
break;
}
@ -92,6 +100,19 @@ public class CanvasView extends View implements OnSharedPreferenceChangeListener
}
short normalizeX(float x) {
return (short)(Math.min(Math.max(0, x), maxX) * Short.MAX_VALUE/maxX);
}
short normalizeY(float x) {
return (short)(Math.min(Math.max(0, x), maxY) * Short.MAX_VALUE/maxY);
}
short normalizePressure(float x) {
return (short)(Math.min(Math.max(0, x), 2.0) * Short.MAX_VALUE/2.0);
}
private class ConfigureNetworkingTask extends AsyncTask<Void, Void, Boolean> {
@Override
protected Boolean doInBackground(Void... params) {
@ -103,7 +124,8 @@ public class CanvasView extends View implements OnSharedPreferenceChangeListener
setEnabled(true);
else {
setEnabled(false);
Toast.makeText(getContext(), "Unknown host name, network tablet disabled!", Toast.LENGTH_LONG).show();
Toast.makeText(getContext(), "Unknown host name, please configure", Toast.LENGTH_LONG).show();
getContext().startActivity(new Intent(getContext(), SettingsActivity.class));
}
}
}

View file

@ -1,34 +0,0 @@
package at.bitfire.gfxtablet;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
public class NetButtonEvent extends NetEvent {
boolean down;
public NetButtonEvent(int x, int y, int pressure, boolean down) {
super(x, y, pressure);
this.down = down;
}
@Override
public byte[] toByteArray() {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
try {
dos.write(1); /* EVENT_TYPE_BUTTON */
dos.writeShort(x);
dos.writeShort(y);
dos.writeShort(pressure);
dos.write(1);
dos.write(down ? 1 : 0);
} catch (IOException e) {
return null;
}
return baos.toByteArray();
}
}

View file

@ -1,28 +0,0 @@
package at.bitfire.gfxtablet;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
public class NetConfigurationEvent extends NetEvent {
public NetConfigurationEvent(int x, int y, int pressure) {
super(x, y, pressure);
}
@Override
public byte[] toByteArray() {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
try {
dos.write(2); /* EVENT_TYPE_SET_RESOLUTION */
dos.writeShort(x);
dos.writeShort(y);
dos.writeShort(pressure);
} catch (IOException e) {
return null;
}
return baos.toByteArray();
}
}

View file

@ -1,12 +0,0 @@
package at.bitfire.gfxtablet;
public class NetDisconnectEvent extends NetEvent {
public NetDisconnectEvent() {
super(0, 0, 0);
}
@Override
public byte[] toByteArray() {
return null;
}
}

View file

@ -1,17 +1,77 @@
package at.bitfire.gfxtablet;
public abstract class NetEvent {
int x, y, pressure;
public int getX() { return x; }
public int getY() { return y; }
public int getPressure() { return pressure; }
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
public NetEvent(int x, int y, int pressure) {
this.x = Math.max(x, 0);
this.y = Math.max(y, 0);
public class NetEvent {
enum Type {
TYPE_MOTION,
TYPE_BUTTON,
// not specified in protocol, only needed to shut down network thread
TYPE_DISCONNECT
};
static final String signature = "GfxTablet";
static final short protocol_version = 1;
Type type;
short x, y, pressure;
byte button, button_down;
public short getX() { return x; }
public short getY() { return y; }
public short getPressure() { return pressure; }
public NetEvent(Type type) {
this.type = type;
}
public NetEvent(Type type, short x, short y, short pressure) {
this.type = type;
this.x = x;
this.y = y;
this.pressure = pressure;
}
public NetEvent(Type type, short x, short y, short pressure, int button, boolean button_down) {
this(type, x, y, pressure);
this.button = (byte)button;
this.button_down = (byte)(button_down ? 1 : 0);
}
public abstract byte[] toByteArray();
public byte[] toByteArray() {
if (type == Type.TYPE_DISCONNECT)
return null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
try {
dos.writeBytes(signature);
dos.writeShort(protocol_version);
switch (type) {
case TYPE_MOTION:
dos.writeByte(0);
break;
case TYPE_BUTTON:
dos.writeByte(1);
break;
}
dos.writeShort(x);
dos.writeShort(y);
dos.writeShort(pressure);
if (type == Type.TYPE_BUTTON) {
dos.writeByte(button);
dos.writeByte(button_down);
}
} catch(IOException e) {
}
return baos.toByteArray();
}
}

View file

@ -1,28 +0,0 @@
package at.bitfire.gfxtablet;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
public class NetMotionEvent extends NetEvent {
public NetMotionEvent(int x, int y, int pressure) {
super(x, y, pressure);
}
@Override
public byte[] toByteArray() {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
try {
dos.write(0); /* EVENT_TYPE_MOTION */
dos.writeShort(x);
dos.writeShort(y);
dos.writeShort(pressure);
} catch (IOException e) {
return null;
}
return baos.toByteArray();
}
}

View file

@ -8,17 +8,17 @@ import java.util.concurrent.LinkedBlockingQueue;
import android.content.SharedPreferences;
import android.util.Log;
// see "drivers" directory in Github repository for details about the protocol
import at.bitfire.gfxtablet.NetEvent.Type;
public class NetworkClient implements Runnable {
static int GFXTABLET_PORT = 40118;
LinkedBlockingQueue<NetEvent> motionQueue = new LinkedBlockingQueue<NetEvent>();
LinkedBlockingQueue<NetEvent> getQueue() { return motionQueue; }
InetAddress destAddress;
SharedPreferences preferences;
NetConfigurationEvent lastConfiguration = null;
NetworkClient(SharedPreferences preferences) {
this.preferences = preferences;
@ -28,10 +28,6 @@ public class NetworkClient implements Runnable {
try {
String hostName = preferences.getString(SettingsActivity.KEY_PREF_HOST, "unknown.invalid");
destAddress = InetAddress.getByName(hostName);
if (lastConfiguration != null)
motionQueue.add(lastConfiguration);
} catch (UnknownHostException e) {
destAddress = null;
return false;
@ -47,18 +43,15 @@ public class NetworkClient implements Runnable {
while (true) {
NetEvent event = motionQueue.take();
// save resolution, even if not sending it
if (event.getClass() == NetConfigurationEvent.class)
lastConfiguration = (NetConfigurationEvent)event;
// graceful shutdown
else if (event.getClass() == NetDisconnectEvent.class)
if (event.type == Type.TYPE_DISCONNECT)
break;
if (destAddress == null) // no valid destination host
continue;
byte[] data = event.toByteArray();
DatagramPacket pkt = new DatagramPacket(data, data.length, destAddress, 40117);
DatagramPacket pkt = new DatagramPacket(data, data.length, destAddress, GFXTABLET_PORT);
socket.send(pkt);
}
} catch (Exception e) {