org.jopenray.server.thinclient.DisplayReaderThread.java Source code

Java tutorial

Introduction

Here is the source code for org.jopenray.server.thinclient.DisplayReaderThread.java

Source

/*
 *  Copyright 2010 jOpenRay, ILM Informatique  
 *
 * 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 2 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, see <http://www.gnu.org/licenses/>
 */

package org.jopenray.server.thinclient;

import java.awt.event.MouseEvent;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.io.HexDump;
import org.jopenray.operation.PadOperation;
import org.jopenray.util.HID;

public class DisplayReaderThread extends Thread {

    private ThinClient client;
    private List<InputListener> listeners = new ArrayList<InputListener>();
    int lastMouseState = Integer.MIN_VALUE;
    int lastMouseX = Integer.MIN_VALUE;
    int lastMouseY = Integer.MIN_VALUE;
    List<Integer> keysPressed = new ArrayList<Integer>(4);
    boolean DEBUG = false;

    DisplayReaderThread(ThinClient client) {
        this.client = client;
        setDaemon(true);
        setName("DisplayClient connection (reader)" + client.getServer().getHostAddress());
    }

    @Override
    public void run() {
        byte[] buf = new byte[1500];
        DatagramPacket packet = new DatagramPacket(buf, buf.length);

        try {
            while (!this.isInterrupted()) {
                client.getSocket().receive(packet);
                handlePacket(buf, packet.getLength());
            }
        } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

    }

    private void handlePacket(byte[] udpData, int l) {
        boolean dump = false;
        ByteArrayInputStream bIn = new ByteArrayInputStream(udpData, 0, l);
        int r = readInt16(bIn);
        int flag = readInt16(bIn);
        int type = readInt16(bIn);
        int dir = readInt16(bIn);
        if (DEBUG)
            System.out.print("Seq number:" + r + " Flag:" + flag + " Type:" + type + " Dir:" + dir);

        // Sunray ->Server
        int a = readInt16(bIn);
        int b = readInt16(bIn);
        int c = readInt16(bIn);
        int d = readInt16(bIn);
        if (DEBUG)
            System.out.println("Sunray -> Server:" + a + "," + b + "," + c + "," + d);
        if (bIn.available() == 0) {
            DisplayMessage m = new DisplayMessage(client.getWriter());
            m.addOperation(new PadOperation());
            this.client.getWriter().addMessage(m);
        } else
            while (bIn.available() > 0) {
                int opcode = bIn.read();
                int hdat = readInt16(bIn);
                int idat = bIn.read();
                String opCodeHeader = "";

                opCodeHeader += "[ Opcode: " + opcode + " , " + hdat + " ," + idat + " ]";

                switch (opcode) {
                case 0xc1:
                    dump = true;
                    int jdat = readInt16(bIn);
                    int modifier = readInt16(bIn);
                    // 6 octet
                    int key1 = bIn.read();
                    int key2 = bIn.read();
                    int key3 = bIn.read();
                    int key4 = bIn.read();
                    int key5 = bIn.read();
                    int key6 = bIn.read();

                    //
                    int mdat = readInt16(bIn);
                    System.out.println("Keyboard " + opCodeHeader + " " + jdat + " modifier:" + modifier + " keys:("
                            + key1 + "," + key2 + "," + key3 + "," + key4 + "," + key5 + "," + key6 + ") " + mdat);

                    /*
                     * if(lastPressed>0){
                     * System.out.println("Send Key Released:"+lastPressed);
                     * sendKeyReleased(lastPressed); lastPressed=-1; }
                     */

                    if (key1 > 0) {
                        if (!keysPressed.contains(key1)) {

                            int hidToKeyCode = HID.hidToKeyCode(key1);
                            System.out.println(modifier + " : " + (modifier & 0x2));
                            sendKeyPressed(hidToKeyCode, (modifier & 2) != 0 || (modifier & 32) != 0,
                                    (modifier & 1) != 0, (modifier & 4) != 0, (modifier & 8) != 0,
                                    (modifier & 64) != 0);
                            keysPressed.add(key1);
                        }

                    } else {
                        for (int i = 0; i < this.keysPressed.size(); i++) {
                            int k = keysPressed.get(i);
                            int hidToKeyCode = HID.hidToKeyCode(k);
                            sendKeyReleased(hidToKeyCode);

                        }
                        keysPressed.clear();
                    }

                    break;
                case 0xc2:
                    int buttons = readInt16(bIn);
                    int mouseX = readInt16(bIn);
                    int mouseY = readInt16(bIn);
                    int c2 = readInt16(bIn);
                    if (DEBUG)
                        System.out.println("Mouse" + opCodeHeader + " buttons:" + buttons + " (" + mouseX + ","
                                + mouseY + ")" + c2);
                    processMouseEvent(buttons, mouseX, mouseY);
                    break;
                case 0xc4: {
                    int c41 = readInt32(bIn);
                    int c42 = readInt32(bIn);
                    int c43 = readInt32(bIn);

                    System.out.println("NACK  seq= " + c41 + "  type: " + c42 + " , " + c43);
                    client.resend(c42, c43);
                    break;
                }
                case 0xc5:
                    int c51 = bIn.read();
                    int c52 = bIn.read();
                    int c53 = bIn.read();
                    int c54 = bIn.read();

                    System.out.println("0xC5 " + opCodeHeader + " " + c51 + "," + c52 + "," + c53 + "," + c54);
                    break;
                case 0xc6:
                    int dataLength = readInt16(bIn);
                    int stringLength = bIn.read();
                    byte[] string = new byte[stringLength];

                    try {
                        int rL = bIn.read(string);
                        System.out.println(dataLength + " , " + stringLength + " readLength" + rL);
                        System.out.println("Firmware: " + new String(string));
                        // dump = true;
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }

                    break;

                case 0xc7: {
                    int x1 = readInt16(bIn);
                    int y1 = readInt16(bIn);
                    int w1 = readInt16(bIn);
                    int h1 = readInt16(bIn);
                    int x2 = readInt16(bIn);
                    int y2 = readInt16(bIn);
                    int w2 = readInt16(bIn);
                    int h2 = readInt16(bIn);
                    int x3 = readInt16(bIn);
                    int y3 = readInt16(bIn);
                    int w3 = readInt16(bIn);
                    int h3 = readInt16(bIn);
                    if (DEBUG)
                        System.out.println("Rect: " + opCodeHeader + " [" + x1 + "," + y1 + "," + w1 + "," + h1
                                + "][" + x2 + "," + y2 + "," + w2 + "," + h2 + "][" + x3 + "," + y3 + "," + w3 + ","
                                + h3 + "]");

                    break;
                }
                case 0xcb:
                    int bc1 = bIn.read();
                    int bc2 = readInt16(bIn);
                    int bc3 = readInt16(bIn);
                    int bc4 = readInt16(bIn);
                    int bc5 = readInt16(bIn);
                    int bc6 = readInt16(bIn);
                    int bc7 = readInt16(bIn);
                    int bc8 = readInt16(bIn);
                    int bc9 = readInt16(bIn);
                    int bc10 = readInt16(bIn);
                    int bc11 = readInt16(bIn);
                    if (DEBUG)
                        System.out.println(
                                "0xCB " + opCodeHeader + " " + bc1 + "," + bc2 + "," + bc3 + "," + bc4 + "," + bc5
                                        + "," + bc6 + "," + bc7 + "," + bc8 + "," + bc9 + "," + bc10 + "," + bc11);
                    break;
                default:
                    System.out.println("Unknown opcode: " + opCodeHeader);
                    dump = true;
                    break;
                }
            }
        if (dump) {
            try {
                HexDump.dump(udpData, 0, System.err, 0);
            } catch (Exception ignr) {
            }
        }

    }

    private void processMouseEvent(int buttons, int mouseX, int mouseY) {
        buttons = buttons - 64;
        if (this.lastMouseState == Integer.MIN_VALUE) {
            this.lastMouseState = buttons;
            this.lastMouseX = mouseX;
            this.lastMouseY = mouseY;
            return;
        }

        // Mouse move
        if (lastMouseX != mouseX || lastMouseY != mouseY) {
            sendMouseMoved(mouseX, mouseY);
        }

        // Mouse pressed/released

        int change = buttons ^ this.lastMouseState;

        if ((change & 1) > 0) {
            if ((buttons & 1) > 0) {
                System.out.println("DisplayReaderThread.processMouseEvent() BUTTON1 pressed");
                sendMousePressed(MouseEvent.BUTTON1, mouseX, mouseY);
            } else {
                System.out.println("DisplayReaderThread.processMouseEvent() BUTTON1 released");
                sendMouseReleased(MouseEvent.BUTTON1, mouseX, mouseY);
            }
        }
        if ((change & 2) > 0) {
            if ((buttons & 2) > 0) {
                System.out.println("DisplayReaderThread.processMouseEvent() BUTTON2 pressed");
                sendMousePressed(MouseEvent.BUTTON2, mouseX, mouseY);
            } else {
                sendMouseReleased(MouseEvent.BUTTON2, mouseX, mouseY);
            }
        }
        if ((change & 4) > 0) {
            if ((buttons & 4) > 0) {
                System.out.println("DisplayReaderThread.processMouseEvent() BUTTON3 pressed");
                sendMousePressed(MouseEvent.BUTTON3, mouseX, mouseY);
            } else {
                sendMouseReleased(MouseEvent.BUTTON3, mouseX, mouseY);
            }
        }
        if ((change & 8) > 0) {
            if ((buttons & 8) > 0) {
                System.out.println("DisplayReaderThread.processMouseEvent() mouse wheel up");
                sendMouseWheelUp(mouseX, mouseY);
            } else {
                // sendMouseReleased(MouseEvent.BUTTON3, mouseX, mouseY);
            }
        }
        if ((change & 16) > 0) {
            if ((buttons & 16) > 0) {
                System.out.println("DisplayReaderThread.processMouseEvent() mouse wheel down");
                sendMouseWheelDown(mouseX, mouseY);
            } else {
                // sendMouseReleased(MouseEvent.BUTTON3, mouseX, mouseY);
            }
        }

        this.lastMouseState = buttons;
        this.lastMouseX = mouseX;
        this.lastMouseY = mouseY;

    }

    private void sendMouseReleased(int button, int mouseX, int mouseY) {
        final int size = this.listeners.size();
        for (int i = 0; i < size; i++) {
            listeners.get(i).mouseReleased(button, mouseX, mouseY);
        }
    }

    private void sendMousePressed(int button, int mouseX, int mouseY) {
        final int size = this.listeners.size();
        for (int i = 0; i < size; i++) {
            listeners.get(i).mousePressed(button, mouseX, mouseY);
        }

    }

    private void sendMouseMoved(int mouseX, int mouseY) {
        final int size = this.listeners.size();
        for (int i = 0; i < size; i++) {
            listeners.get(i).mouseMoved(mouseX, mouseY);
        }

    }

    private void sendMouseWheelUp(int mouseX, int mouseY) {
        final int size = this.listeners.size();
        for (int i = 0; i < size; i++) {
            listeners.get(i).mouseWheelUp(mouseX, mouseY);
        }

    }

    private void sendMouseWheelDown(int mouseX, int mouseY) {
        final int size = this.listeners.size();
        for (int i = 0; i < size; i++) {
            listeners.get(i).mouseWheelDown(mouseX, mouseY);
        }

    }

    private void sendKeyPressed(int key, boolean shift, boolean ctrl, boolean alt, boolean meta, boolean altGr) {
        System.out.println(
                "Key pressed: code:" + key + " shift:" + shift + " ctrl:" + ctrl + " alt:" + alt + " meta:" + meta);
        final int size = this.listeners.size();
        for (int i = 0; i < size; i++) {
            listeners.get(i).keyPressed(key, shift, ctrl, alt, meta, altGr);
        }

    }

    private void sendKeyReleased(int key) {
        final int size = this.listeners.size();
        for (int i = 0; i < size; i++) {
            listeners.get(i).keyReleased(key);
        }

    }

    public void addInputListener(InputListener l) {
        this.listeners.add(l);

    }

    public void removeInputListener(InputListener l) {
        this.listeners.remove(l);

    }

    public static int readInt16(ByteArrayInputStream in) {
        int a = in.read();
        int b = in.read();
        if (a < 0 || b < 0) {
            throw new IllegalStateException("Unexpected end of stream");
        }
        return a * 256 + b;
    }

    public static int readInt32(ByteArrayInputStream in) {
        int a = in.read();
        int b = in.read();
        int c = in.read();
        int d = in.read();
        if (a < 0 || b < 0 || c < 0 || d < 0) {
            throw new IllegalStateException("Unexpected end of stream");
        }
        return a * 256 * 256 * 256 + b * 256 * 256 + c * 256 + d;
    }
}