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    @SuppressWarnings("this-escape")
052    public ImageReceiver(final InetAddress remoteHost, final int remotePort, final int localPort, int width, int height) {
053        tiles = new BufferedImage[width][height];
054
055        try {
056
057            socket = new DatagramSocket(localPort);
058            localHost = socket.getLocalAddress();
059            this.remoteHost = remoteHost;
060            this.remotePort = remotePort;
061            this.localPort = localPort;
062            this.decoder = new DefaultDecoder();
063
064            new Thread(new Runnable() {
065                @Override
066                public void run() {
067                    byte[] buf = new byte[1024];
068                    DatagramPacket p = new DatagramPacket(buf, 1024);
069                    try {
070                        while (on) {
071                            socket.receive(p);
072
073                            int length = p.getLength();
074
075                            BufferedImage bufferedImage = decoder.decode(new ByteArrayInputStream(p.getData(), 0, length - 2));
076
077                            if (bufferedImage != null) {
078
079                                int x = p.getData()[length - 2];
080                                int y = p.getData()[length - 1];
081
082                                drawTile(x, y, bufferedImage);
083
084                            }
085
086                        }
087                    }
088                    catch (IOException e) {
089                        LOGGER.log(Level.WARNING, "exception", e);
090                    }
091                }
092            }).start();
093
094            new Thread(new Runnable() {
095                @Override
096                public void run() {
097                    byte[] buf = new byte[1024];
098                    DatagramPacket p = new DatagramPacket(buf, 1024);
099                    try {
100                        while (on) {
101
102                            p.setAddress(remoteHost);
103                            p.setPort(remotePort);
104                            socket.send(p);
105
106                            try {
107                                Thread.sleep(1000);
108                            }
109                            catch (InterruptedException e) {
110                                LOGGER.log(Level.WARNING, "exception", e);
111                            }
112
113                        }
114                    }
115                    catch (IOException e) {
116                        LOGGER.log(Level.WARNING, "exception", e);
117                    }
118                }
119            }).start();
120
121        }
122        catch (SocketException e) {
123            LOGGER.log(Level.WARNING, "exception", e);
124        }
125        this.setSize(width, height);
126    }
127
128    public InetAddress getLocalHost() {
129        return localHost;
130    }
131
132    public InetAddress getRemoteHost() {
133        return remoteHost;
134    }
135
136    public int getLocalPort() {
137        return localPort;
138    }
139
140    public int getRemotePort() {
141        return remotePort;
142    }
143
144    public DatagramSocket getDatagramSocket() {
145        return socket;
146    }
147
148    public void drawTile(int x, int y, BufferedImage bufferedImage) {
149        tiles[x][y] = bufferedImage;
150        // repaint(x * tileWidth, y * tileWidth, tileWidth, tileWidth);
151        this.getGraphics().drawImage(bufferedImage, tileWidth * x, tileWidth * y, this);
152    }
153
154    @Override
155    public void paint(Graphics g) {
156        for (int i = 0; i < tiles.length; i++) {
157            for (int j = 0; j < tiles[0].length; j++) {
158                g.drawImage(tiles[i][j], tileWidth * i, tileWidth * j, this);
159            }
160        }
161    }
162
163    public ImageDecoder getDecoder() {
164        return decoder;
165    }
166
167    public void setDecoder(ImageDecoder decoder) {
168        this.decoder = decoder;
169    }
170
171    public void stop() {
172        this.on = false;
173        socket.close();
174    }
175}