From c6ca27edd5e5f04e6c76acfc1a31c28d6fe9c6d3 Mon Sep 17 00:00:00 2001 From: Maschell Date: Sat, 15 Sep 2018 12:41:02 +0200 Subject: [PATCH] First commit --- .circleci/circle.yml | 18 ++ README.MD | 18 ++ pom.xml | 86 ++++++++ .../de/mas/wiiu/streaming/ImageStreamer.java | 196 ++++++++++++++++++ src/main/java/de/mas/wiiu/streaming/Main.java | 75 +++++++ .../wiiu/streaming/gui/IImageProvider.java | 31 +++ .../de/mas/wiiu/streaming/gui/ImagePanel.java | 61 ++++++ .../mas/wiiu/streaming/gui/ImageProvider.java | 43 ++++ .../mas/wiiu/streaming/gui/StreamWindow.java | 42 ++++ .../mas/wiiu/streaming/network/TCPClient.java | 119 +++++++++++ .../mas/wiiu/streaming/network/UDPClient.java | 65 ++++++ .../wiiu/streaming/utilities/Utilities.java | 56 +++++ 12 files changed, 810 insertions(+) create mode 100644 .circleci/circle.yml create mode 100644 README.MD create mode 100644 pom.xml create mode 100644 src/main/java/de/mas/wiiu/streaming/ImageStreamer.java create mode 100644 src/main/java/de/mas/wiiu/streaming/Main.java create mode 100644 src/main/java/de/mas/wiiu/streaming/gui/IImageProvider.java create mode 100644 src/main/java/de/mas/wiiu/streaming/gui/ImagePanel.java create mode 100644 src/main/java/de/mas/wiiu/streaming/gui/ImageProvider.java create mode 100644 src/main/java/de/mas/wiiu/streaming/gui/StreamWindow.java create mode 100644 src/main/java/de/mas/wiiu/streaming/network/TCPClient.java create mode 100644 src/main/java/de/mas/wiiu/streaming/network/UDPClient.java create mode 100644 src/main/java/de/mas/wiiu/streaming/utilities/Utilities.java diff --git a/.circleci/circle.yml b/.circleci/circle.yml new file mode 100644 index 0000000..7839f96 --- /dev/null +++ b/.circleci/circle.yml @@ -0,0 +1,18 @@ +machine: + java: + version: oraclejdk8 + +compile: + override: + - mvn package -Dci-build=true + +general: + artifacts: + - "ci" + +deployment: + nightlies: + branch: master + commands: + - go get github.com/tcnksm/ghr + - ghr -t $GITHUB_TOKEN -u $CIRCLE_PROJECT_USERNAME -r $CIRCLE_PROJECT_REPONAME -prerelease -b 'Nightly release - Use caution! We recommend downloading a stable release from the README.' `echo "v0.1-nightly-$(git rev-parse --short=7 HEAD)"` ci/ diff --git a/README.MD b/README.MD new file mode 100644 index 0000000..4be38ec --- /dev/null +++ b/README.MD @@ -0,0 +1,18 @@ +# Streaming Plugin Client + +A Java client for the [Wii U Streaming Plugin](https://github.com/Maschell/StreamingPluginWiiU). + +# Usage + +Start the plugin via the [WiiUPluginSystemLoader](https://github.com/Maschell/WiiUPluginSystem) on your WiiU. Now start Java client by either +- provide the ip address of your Wii U as a argument. Example: ``java -jar StreamingPluginClient[...].jar --ip 192.168.0.11` +- **or** just double click on the .jar. A little dialog should appear where you can enter the IP address of your Wii U console. + +Requires Java 8. + +# Building + +This is a maven project. Use following command to create a .jar with dependencies in the `target` folder. +``` +mvn package +``` \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..a783036 --- /dev/null +++ b/pom.xml @@ -0,0 +1,86 @@ + + 4.0.0 + StreamingPluginClient + StreamingPluginClient + 0.0.1-SNAPSHOT + + StreamingPluginClient + https://github.com/Maschell/StreamingPluginClient + + + + normal-build + + true + + + ./target + + + + ci-build + + + ci-build + true + + + + ./ci + + + + + + src + + + maven-compiler-plugin + 3.7.0 + + 1.8 + 1.8 + + + + maven-assembly-plugin + + + make-assembly + + + + de.mas.wiiu.streaming.Main + + + + jar-with-dependencies + + + ${jar_dir} + StreamingPluginClient-${project.version}-nightly + + package + + attached + + + + + + + + + org.projectlombok + lombok + 1.16.20 + + + + commons-cli + commons-cli + 1.4 + + + \ No newline at end of file diff --git a/src/main/java/de/mas/wiiu/streaming/ImageStreamer.java b/src/main/java/de/mas/wiiu/streaming/ImageStreamer.java new file mode 100644 index 0000000..616f062 --- /dev/null +++ b/src/main/java/de/mas/wiiu/streaming/ImageStreamer.java @@ -0,0 +1,196 @@ +/******************************************************************************* + * Copyright (c) 2018 Maschell + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *******************************************************************************/ + +package de.mas.wiiu.streaming; + +import java.io.IOException; +import java.net.SocketException; +import java.net.SocketTimeoutException; +import java.net.UnknownHostException; +import java.nio.ByteBuffer; +import java.util.zip.CRC32; + +import javax.swing.JOptionPane; + +import de.mas.wiiu.streaming.gui.IImageProvider; +import de.mas.wiiu.streaming.gui.ImageProvider; +import de.mas.wiiu.streaming.network.TCPClient; +import de.mas.wiiu.streaming.network.UDPClient; +import de.mas.wiiu.streaming.utilities.Utilities; +import lombok.Synchronized; +import lombok.extern.java.Log; + +@Log +public class ImageStreamer { + + private final ImageProvider imageProvider = new ImageProvider(); + private final TCPClient tcpClient; + private final UDPClient udpClient; + + public ImageStreamer(String ip) throws SocketException { + tcpClient = new TCPClient(ip, 8092, 200); + udpClient = new UDPClient(9445); + new Thread(udpClient, "UDPClient").start(); + udpClient.setOnDataCallback(this::udpDataHandler); + + new Thread(() -> { + while (true) { + if (!tcpClient.isConnected()) { + System.out.print("Connecting.."); + try { + tcpClient.connect(); + System.out.println("success!"); + } catch (IllegalArgumentException | UnknownHostException e1) { + JOptionPane.showMessageDialog(null, "Make sure to enter a valid ip address.", e1.getClass().getName(), JOptionPane.WARNING_MESSAGE); + System.exit(-1); + } catch (SocketTimeoutException e) { + System.out.println("time out..."); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } else { + sendPing(); + } + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + }).start(); + + new Thread(() -> { + while (true) { + if (tcpClient.isConnected()) { + System.out.println("FPS:" + framesThisSecond); + framesThisSecond = 0; + } + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + }).start(); + } + + private boolean sendTCP(byte[] rawCommand) { + boolean result = false; + try { + tcpClient.send(rawCommand); + result = true; + } catch (Exception e) { + result = false; + } + + return result; + } + + void sendPing() { + if (sendTCP(new byte[] { 0x15 })) { + byte pong; + try { + pong = tcpClient.recvByte(); + if (pong == 0x16) { + // log.info("Ping...Pong!"); + } else { + log.info("Got no valid response to a Ping. Disconnecting."); + tcpClient.abort(); + } + } catch (IOException e) { + log.info("Failed to get PONG. Disconnecting."); + tcpClient.abort(); + } + } else { + log.info("Sending the PING failed"); + } + } + + private final Object lock = new Object(); + + private DataState state = DataState.UNKNOWN; + private int curcrc32 = 0; + private int curJPEGSize = 0; + private byte[] jpegBuffer = {}; + private int curLenPos = 0; + + private int framesThisSecond = 0; + + @Synchronized("lock") + private void udpDataHandler(byte[] data) { + if (state == DataState.UNKNOWN) { + // System.out.println("GET CRC"); + if (data.length == 4) { + ByteBuffer wrapped = ByteBuffer.wrap(data); // big-endian by default + curcrc32 = wrapped.getInt(); // 1 + state = DataState.CRC32_RECEIVED; + } else { + + state = DataState.UNKNOWN; + return; + } + } else if (state == DataState.CRC32_RECEIVED) { + // System.out.println("GET Size"); + if (data.length == 8) { + ByteBuffer wrapped = ByteBuffer.wrap(data); // big-endian by default + curJPEGSize = (int) wrapped.getLong(); + jpegBuffer = new byte[curJPEGSize]; + state = DataState.RECEIVING_IMAGE; + curLenPos = 0; + } else { + // System.out.println("..."); + state = DataState.UNKNOWN; + return; + } + } else if (state == DataState.RECEIVING_IMAGE) { + // System.out.println("GET IMAGE"); + System.arraycopy(data, 0, jpegBuffer, curLenPos, data.length > curJPEGSize ? curJPEGSize : data.length); + + curJPEGSize -= data.length; + curLenPos += data.length; + if (curJPEGSize <= 0) { + CRC32 crc = new CRC32(); + crc.update(jpegBuffer); + if ((int) crc.getValue() == curcrc32) { + imageProvider.updateImage(Utilities.byteArrayToImage(jpegBuffer)); + framesThisSecond++; + } else { + System.out.println("Hash mismatch, dropping frame."); + } + state = DataState.UNKNOWN; + } + } + + } + + public IImageProvider getImageProvider() { + return imageProvider; + } + + public enum DataState { + UNKNOWN, CRC32_RECEIVED, RECEIVING_IMAGE, IMAGE_RECEIVED + } + +} diff --git a/src/main/java/de/mas/wiiu/streaming/Main.java b/src/main/java/de/mas/wiiu/streaming/Main.java new file mode 100644 index 0000000..769c15d --- /dev/null +++ b/src/main/java/de/mas/wiiu/streaming/Main.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * Copyright (c) 2018 Maschell + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *******************************************************************************/ + +package de.mas.wiiu.streaming; + +import java.net.BindException; +import java.net.SocketException; + +import javax.swing.JOptionPane; +import javax.swing.SwingUtilities; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.CommandLineParser; +import org.apache.commons.cli.DefaultParser; +import org.apache.commons.cli.HelpFormatter; +import org.apache.commons.cli.Options; + +import de.mas.wiiu.streaming.gui.StreamWindow; + +public class Main { + + public static void main(String[] args) throws Exception { + CommandLineParser parser = new DefaultParser(); + + Options options = new Options(); + options.addOption("ip", "ip", true, "IP address of your Wii U Console."); + + CommandLine line = parser.parse(options, args); + String ip = null; + + if (line.hasOption("ip")) { + ip = line.getOptionValue("ip"); + } else { + HelpFormatter formatter = new HelpFormatter(); + formatter.printHelp("streamingTool", options); + ip = JOptionPane.showInputDialog(null, "Please enter the local IP address of your Wii U", "Wii U streaming client", JOptionPane.PLAIN_MESSAGE); + } + try { + new Main(ip); + } catch (BindException e) { + JOptionPane.showMessageDialog(null, "Can't bind socket. The client is probably already running.", e.getClass().getName(), + JOptionPane.WARNING_MESSAGE); + System.exit(-1); + } + } + + public Main(String ip) throws SocketException { + ImageStreamer imageStreamer = new ImageStreamer(ip); + + SwingUtilities.invokeLater(new Runnable() { + public void run() { + new StreamWindow(imageStreamer.getImageProvider()); + } + }); + } +} diff --git a/src/main/java/de/mas/wiiu/streaming/gui/IImageProvider.java b/src/main/java/de/mas/wiiu/streaming/gui/IImageProvider.java new file mode 100644 index 0000000..a77ae21 --- /dev/null +++ b/src/main/java/de/mas/wiiu/streaming/gui/IImageProvider.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2018 Maschell + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *******************************************************************************/ + +package de.mas.wiiu.streaming.gui; +import java.awt.Image; +import java.util.function.Consumer; + +public interface IImageProvider { + + void setOnImageChange(Consumer function); + +} diff --git a/src/main/java/de/mas/wiiu/streaming/gui/ImagePanel.java b/src/main/java/de/mas/wiiu/streaming/gui/ImagePanel.java new file mode 100644 index 0000000..2eb8bae --- /dev/null +++ b/src/main/java/de/mas/wiiu/streaming/gui/ImagePanel.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * Copyright (c) 2018 Maschell + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *******************************************************************************/ + +package de.mas.wiiu.streaming.gui; + +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Image; + +import javax.swing.JPanel; + +public final class ImagePanel extends JPanel { + /** + * + */ + private static final long serialVersionUID = -127096088663141229L; + private Image image; + private final int preferedWidth; + private final int preferedHeight; + + public ImagePanel(int width, int height) { + super(true); + preferedWidth = width; + preferedHeight = height; + } + + public void setImage(Image image) { + this.image = image; + repaint(); + } + + public Dimension getPreferredSize() { + return new Dimension(preferedWidth, preferedHeight); + } + + public void paint(Graphics g) { + super.paint(g); + if (image != null) { + g.drawImage(image, 0, 0, getWidth(), getHeight(), 0, 0, image.getWidth(this), image.getHeight(this), this); + } + } +} \ No newline at end of file diff --git a/src/main/java/de/mas/wiiu/streaming/gui/ImageProvider.java b/src/main/java/de/mas/wiiu/streaming/gui/ImageProvider.java new file mode 100644 index 0000000..afcd37c --- /dev/null +++ b/src/main/java/de/mas/wiiu/streaming/gui/ImageProvider.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2018 Maschell + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *******************************************************************************/ + +package de.mas.wiiu.streaming.gui; + +import java.awt.Image; +import java.util.function.Consumer; + +public final class ImageProvider implements IImageProvider { + + private Consumer onImageChangeFunction = null; + + public void updateImage(Image image) { + if (onImageChangeFunction != null) { + onImageChangeFunction.accept(image); + } + } + + @Override + public void setOnImageChange(Consumer function) { + this.onImageChangeFunction = function; + } + +} diff --git a/src/main/java/de/mas/wiiu/streaming/gui/StreamWindow.java b/src/main/java/de/mas/wiiu/streaming/gui/StreamWindow.java new file mode 100644 index 0000000..a0a5aba --- /dev/null +++ b/src/main/java/de/mas/wiiu/streaming/gui/StreamWindow.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2018 Maschell + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *******************************************************************************/ + +package de.mas.wiiu.streaming.gui; +import javax.swing.JFrame; +import javax.swing.WindowConstants; + +public class StreamWindow { + private final ImagePanel image = new ImagePanel(1280, 720); + + public StreamWindow(IImageProvider imageProvider) { + JFrame editorFrame = new JFrame("Stream"); + editorFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + + imageProvider.setOnImageChange((bi) -> image.setImage(bi)); + editorFrame.add(image); + + editorFrame.pack(); + editorFrame.setLocationRelativeTo(null); + editorFrame.setVisible(true); + } + +} diff --git a/src/main/java/de/mas/wiiu/streaming/network/TCPClient.java b/src/main/java/de/mas/wiiu/streaming/network/TCPClient.java new file mode 100644 index 0000000..e7a517a --- /dev/null +++ b/src/main/java/de/mas/wiiu/streaming/network/TCPClient.java @@ -0,0 +1,119 @@ +/******************************************************************************* + * Copyright (c) 2017,2018 Ash (QuarkTheAwesome) & Maschell + * Taken from the HID to VPAD Networkclient. Modified for the StreamingPluginClient. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *******************************************************************************/ +package de.mas.wiiu.streaming.network; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.nio.ByteBuffer; + +import lombok.Synchronized; +import lombok.extern.java.Log; + +@Log +final public class TCPClient { + private final Object lock = new Object(); + + private Socket sock; + private DataInputStream in; + private DataOutputStream out; + + private final String ip; + private final int port; + private final int timeout; + + public TCPClient(String ip, int port, int timeout) { + this.ip = ip; + this.port = port; + this.timeout = timeout; + } + + @Synchronized("lock") + public void connect() throws IOException { + sock = new Socket(); + sock.connect(new InetSocketAddress(ip, port), timeout); + in = new DataInputStream(sock.getInputStream()); + out = new DataOutputStream(sock.getOutputStream()); + } + + @Synchronized("lock") + public boolean abort() { + try { + sock.close(); + } catch (IOException e) { + log.info(e.getMessage()); // TODO: handle + return false; + } + return true; + } + + @Synchronized("lock") + public void send(byte[] rawCommand) throws IOException { + try { + out.write(rawCommand); + out.flush(); + } catch (IOException e) { + throw e; + } + } + + void send(int value) throws IOException { + send(ByteBuffer.allocate(4).putInt(value).array()); + } + + public void send(byte _byte) throws IOException { + send(ByteBuffer.allocate(1).put(_byte).array()); + } + + @Synchronized("lock") + public byte recvByte() throws IOException { + return in.readByte(); + } + + @Synchronized("lock") + short recvShort() throws IOException { + try { + return in.readShort(); + } catch (IOException e) { + log.info(e.getMessage()); + throw e; + } + } + + @Synchronized("lock") + int recvInt() throws IOException { + try { + return in.readInt(); + } catch (IOException e) { + log.info(e.getMessage()); + throw e; + } + } + + @Synchronized("lock") + public boolean isConnected() { + return (sock != null && sock.isConnected() && !sock.isClosed()); + } +} diff --git a/src/main/java/de/mas/wiiu/streaming/network/UDPClient.java b/src/main/java/de/mas/wiiu/streaming/network/UDPClient.java new file mode 100644 index 0000000..6d6240e --- /dev/null +++ b/src/main/java/de/mas/wiiu/streaming/network/UDPClient.java @@ -0,0 +1,65 @@ +/******************************************************************************* + * Copyright (c) 2018 Maschell + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *******************************************************************************/ + +package de.mas.wiiu.streaming.network; +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.SocketException; +import java.util.Arrays; +import java.util.function.Consumer; + +import lombok.extern.java.Log; + +@Log +public final class UDPClient implements Runnable { + private final DatagramSocket sock; + + public UDPClient(int port) throws SocketException { + sock = new DatagramSocket(port); + } + + private Consumer onDataCallback = null; + + public void setOnDataCallback(Consumer function) { + onDataCallback = function; + } + + @Override + public void run() { + log.info("UDPClient running."); + byte[] receiveData = new byte[1400]; + while (true) { + DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length); + try { + sock.receive(receivePacket); + } catch (IOException e) { + continue; + } + byte[] data = Arrays.copyOf(receivePacket.getData(), receivePacket.getLength()); + if (onDataCallback != null) { + onDataCallback.accept(data); + } + } + + } +} diff --git a/src/main/java/de/mas/wiiu/streaming/utilities/Utilities.java b/src/main/java/de/mas/wiiu/streaming/utilities/Utilities.java new file mode 100644 index 0000000..7d45ca7 --- /dev/null +++ b/src/main/java/de/mas/wiiu/streaming/utilities/Utilities.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * Copyright (c) 2018 Maschell + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *******************************************************************************/ + +package de.mas.wiiu.streaming.utilities; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; + +import javax.imageio.ImageIO; + +public class Utilities { + private Utilities() { + // + } + + public static String ByteArrayToString(byte[] ba) { + if (ba == null) + return null; + StringBuilder hex = new StringBuilder(ba.length * 2); + for (byte b : ba) { + hex.append(String.format("%02X", b)); + } + return hex.toString(); + } + + public static BufferedImage byteArrayToImage(byte[] bytes) { + BufferedImage bufferedImage = null; + try { + InputStream inputStream = new ByteArrayInputStream(bytes); + bufferedImage = ImageIO.read(inputStream); + } catch (IOException ex) { + System.out.println(ex.getMessage()); + } + return bufferedImage; + } +}