001/**
002 *
003 * Copyright the original author or authors
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *     http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.jivesoftware.smackx.jingleold.mediaimpl.sshare.api;
018
019import java.awt.Canvas;
020import java.awt.Graphics;
021import java.awt.image.BufferedImage;
022import java.io.ByteArrayInputStream;
023import java.io.IOException;
024import java.net.DatagramPacket;
025import java.net.DatagramSocket;
026import java.net.InetAddress;
027import java.net.SocketException;
028import java.util.logging.Level;
029import java.util.logging.Logger;
030
031/**
032 * UDP Image Receiver.
033 * It uses PNG Tiles into UDP packets.
034 *
035 * @author Thiago Rocha Camargo
036 */
037public class ImageReceiver extends Canvas {
038    private static final Logger LOGGER = Logger.getLogger(ImageReceiver.class.getName());
039
040    private static final long serialVersionUID = -7000112305305269025L;
041    private boolean on = true;
042    private DatagramSocket socket;
043    private BufferedImage[][] tiles;
044    private static final int tileWidth = ImageTransmitter.tileWidth;
045    private InetAddress localHost;
046    private InetAddress remoteHost;
047    private int localPort;
048    private int remotePort;
049    private ImageDecoder decoder;
050
051    public ImageReceiver(final InetAddress remoteHost, final int remotePort, final int localPort, int width, int height) {
052        tiles = new BufferedImage[width][height];
053
054        try {
055
056            socket = new DatagramSocket(localPort);
057            localHost = socket.getLocalAddress();
058            this.remoteHost = remoteHost;
059            this.remotePort = remotePort;
060            this.localPort = localPort;
061            this.decoder = new DefaultDecoder();
062
063            new Thread(new Runnable() {
064                @Override
065                public void run() {
066                    byte[] buf = new byte[1024];
067                    DatagramPacket p = new DatagramPacket(buf, 1024);
068                    try {
069                        while (on) {
070                            socket.receive(p);
071
072                            int length = p.getLength();
073
074                            BufferedImage bufferedImage = decoder.decode(new ByteArrayInputStream(p.getData(), 0, length - 2));
075
076                            if (bufferedImage != null) {
077
078                                int x = p.getData()[length - 2];
079                                int y = p.getData()[length - 1];
080
081                                drawTile(x, y, bufferedImage);
082
083                            }
084
085                        }
086                    }
087                    catch (IOException e) {
088                        LOGGER.log(Level.WARNING, "exception", e);
089                    }
090                }
091            }).start();
092
093            new Thread(new Runnable() {
094                @Override
095                public void run() {
096                    byte[] buf = new byte[1024];
097                    DatagramPacket p = new DatagramPacket(buf, 1024);
098                    try {
099                        while (on) {
100
101                            p.setAddress(remoteHost);
102                            p.setPort(remotePort);
103                            socket.send(p);
104
105                            try {
106                                Thread.sleep(1000);
107                            }
108                            catch (InterruptedException e) {
109                                LOGGER.log(Level.WARNING, "exception", e);
110                            }
111
112                        }
113                    }
114                    catch (IOException e) {
115                        LOGGER.log(Level.WARNING, "exception", e);
116                    }
117                }
118            }).start();
119
120        }
121        catch (SocketException e) {
122            LOGGER.log(Level.WARNING, "exception", e);
123        }
124        this.setSize(width, height);
125    }
126
127    public InetAddress getLocalHost() {
128        return localHost;
129    }
130
131    public InetAddress getRemoteHost() {
132        return remoteHost;
133    }
134
135    public int getLocalPort() {
136        return localPort;
137    }
138
139    public int getRemotePort() {
140        return remotePort;
141    }
142
143    public DatagramSocket getDatagramSocket() {
144        return socket;
145    }
146
147    public void drawTile(int x, int y, BufferedImage bufferedImage) {
148        tiles[x][y] = bufferedImage;
149        // repaint(x * tileWidth, y * tileWidth, tileWidth, tileWidth);
150        this.getGraphics().drawImage(bufferedImage, tileWidth * x, tileWidth * y, this);
151    }
152
153    @Override
154    public void paint(Graphics g) {
155        for (int i = 0; i < tiles.length; i++) {
156            for (int j = 0; j < tiles[0].length; j++) {
157                g.drawImage(tiles[i][j], tileWidth * i, tileWidth * j, this);
158            }
159        }
160    }
161
162    public ImageDecoder getDecoder() {
163        return decoder;
164    }
165
166    public void setDecoder(ImageDecoder decoder) {
167        this.decoder = decoder;
168    }
169
170    public void stop() {
171        this.on = false;
172        socket.close();
173    }
174}