blob: 16b3889abd25817f22965f9d0668cfdab6c9d6a9 [file] [log] [blame]
Constantin Kaplinsky1215b992008-04-18 09:51:44 +00001//
2// Copyright (C) 2001,2002 HorizonLive.com, Inc. All Rights Reserved.
3// Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
4//
5// This is free software; you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation; either version 2 of the License, or
8// (at your option) any later version.
9//
10// This software is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with this software; if not, write to the Free Software
17// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
18// USA.
19//
20
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000021import java.awt.*;
22import java.awt.event.*;
23import java.io.*;
Constantin Kaplinsky5d99c952002-05-25 09:49:23 +000024import java.net.*;
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000025
Constantin Kaplinsky903009e2002-05-20 10:55:47 +000026public class RfbPlayer extends java.applet.Applet
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000027 implements java.lang.Runnable, WindowListener {
28
29 boolean inAnApplet = true;
30 boolean inSeparateFrame = false;
31
32 //
33 // main() is called when run as a java program from the command line.
34 // It simply runs the applet inside a newly-created frame.
35 //
36
37 public static void main(String[] argv) {
Constantin Kaplinsky903009e2002-05-20 10:55:47 +000038 RfbPlayer p = new RfbPlayer();
39 p.mainArgs = argv;
40 p.inAnApplet = false;
41 p.inSeparateFrame = true;
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000042
Constantin Kaplinsky903009e2002-05-20 10:55:47 +000043 p.init();
44 p.start();
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000045 }
46
47 String[] mainArgs;
48
49 RfbProto rfb;
50 Thread rfbThread;
51
Constantin Kaplinsky903009e2002-05-20 10:55:47 +000052 public static final int MODE_STOPPED = 0;
53 public static final int MODE_PLAYBACK = 1;
54 public static final int MODE_PAUSED = 2;
55 protected int mode;
56
57 FbsInputStream fbsStream;
58
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000059 Frame vncFrame;
60 Container vncContainer;
61 ScrollPane desktopScrollPane;
62 GridBagLayout gridbag;
63 ButtonPanel buttonPanel;
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000064 VncCanvas vc;
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000065
Constantin Kaplinsky5d99c952002-05-25 09:49:23 +000066 String sessionURL;
Constantin Kaplinsky903009e2002-05-20 10:55:47 +000067 boolean showControls;
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000068 int deferScreenUpdates;
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000069
70 //
71 // init()
72 //
73
74 public void init() {
75
76 readParameters();
77
78 if (inSeparateFrame) {
Constantin Kaplinsky903009e2002-05-20 10:55:47 +000079 vncFrame = new Frame("RFB Session Player");
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000080 if (!inAnApplet) {
81 vncFrame.add("Center", this);
82 }
83 vncContainer = vncFrame;
84 } else {
85 vncContainer = this;
86 }
87
Constantin Kaplinsky1215b992008-04-18 09:51:44 +000088 if (inSeparateFrame)
89 vncFrame.addWindowListener(this);
90
91 rfbThread = new Thread(this);
92 rfbThread.start();
93 }
94
95 public void update(Graphics g) {
96 }
97
98 //
Constantin Kaplinsky903009e2002-05-20 10:55:47 +000099 // run() - executed by the rfbThread to read RFB data.
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000100 //
101
102 public void run() {
103
104 gridbag = new GridBagLayout();
105 vncContainer.setLayout(gridbag);
106
107 GridBagConstraints gbc = new GridBagConstraints();
108 gbc.gridwidth = GridBagConstraints.REMAINDER;
109 gbc.anchor = GridBagConstraints.NORTHWEST;
110
Constantin Kaplinsky903009e2002-05-20 10:55:47 +0000111 if (showControls) {
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000112 buttonPanel = new ButtonPanel(this);
113 buttonPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
114 gridbag.setConstraints(buttonPanel, gbc);
115 vncContainer.add(buttonPanel);
116 }
117
Constantin Kaplinsky903009e2002-05-20 10:55:47 +0000118 if (inSeparateFrame) {
119 vncFrame.pack();
120 vncFrame.show();
121 } else {
122 validate();
123 }
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000124
Constantin Kaplinsky903009e2002-05-20 10:55:47 +0000125 try {
Constantin Kaplinsky5d99c952002-05-25 09:49:23 +0000126 URL url = new URL(sessionURL);
127 fbsStream = new FbsInputStream(url.openStream());
Constantin Kaplinsky903009e2002-05-20 10:55:47 +0000128 rfb = new RfbProto(fbsStream);
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000129
130 vc = new VncCanvas(this);
131 gbc.weightx = 1.0;
132 gbc.weighty = 1.0;
133
134 if (inSeparateFrame) {
135
136 // Create a panel which itself is resizeable and can hold
137 // non-resizeable VncCanvas component at the top left corner.
138 Panel canvasPanel = new Panel();
139 canvasPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
140 canvasPanel.add(vc);
141
142 // Create a ScrollPane which will hold a panel with VncCanvas
143 // inside.
144 desktopScrollPane = new ScrollPane(ScrollPane.SCROLLBARS_AS_NEEDED);
145 gbc.fill = GridBagConstraints.BOTH;
146 gridbag.setConstraints(desktopScrollPane, gbc);
147 desktopScrollPane.add(canvasPanel);
148
149 // Finally, add our ScrollPane to the Frame window.
150 vncFrame.add(desktopScrollPane);
151 vncFrame.setTitle(rfb.desktopName);
152 vncFrame.pack();
153 vc.resizeDesktopFrame();
154
155 } else {
156
157 // Just add the VncCanvas component to the Applet.
158 gridbag.setConstraints(vc, gbc);
159 add(vc);
160 validate();
161
162 }
163
Constantin Kaplinsky903009e2002-05-20 10:55:47 +0000164 while (true) {
165 try {
166 buttonPanel.setMode(MODE_STOPPED);
167 vc.processNormalProtocol();
168 } catch (EOFException e) {
Constantin Kaplinsky5d99c952002-05-25 09:49:23 +0000169 fbsStream.close();
170 fbsStream = new FbsInputStream(url.openStream());
Constantin Kaplinsky903009e2002-05-20 10:55:47 +0000171 rfb.newInputStream(fbsStream);
172 }
173 }
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000174
Constantin Kaplinsky903009e2002-05-20 10:55:47 +0000175 } catch (FileNotFoundException e) {
176 fatalError(e.toString());
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000177 } catch (Exception e) {
178 e.printStackTrace();
179 fatalError(e.toString());
180 }
181
182 }
183
Constantin Kaplinsky903009e2002-05-20 10:55:47 +0000184 public int getMode() {
185 return mode;
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000186 }
187
Constantin Kaplinsky903009e2002-05-20 10:55:47 +0000188 public void setMode(int mode) {
189 this.mode = mode;
190 if (vc != null) {
191 synchronized(vc) {
192 vc.notify();
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000193 }
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000194 }
195 }
196
Constantin Kaplinsky30f786a2002-05-29 10:59:52 +0000197 public void setPos(int pos) {
198 fbsStream.setPos(pos);
199 }
200
Constantin Kaplinskyfe079832002-05-29 00:52:32 +0000201 public void updatePos() {
202 buttonPanel.setPos(fbsStream.getPos());
203 }
204
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000205 //
206 // readParameters() - read parameters from the html source or from the
207 // command line. On the command line, the arguments are just a sequence of
208 // param_name/param_value pairs where the names and values correspond to
209 // those expected in the html applet tag source.
210 //
211
212 public void readParameters() {
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000213
Constantin Kaplinsky5d99c952002-05-25 09:49:23 +0000214 sessionURL = readParameter("URL", true);
Constantin Kaplinsky903009e2002-05-20 10:55:47 +0000215
216 showControls = true;
217 String str = readParameter("Show Controls", false);
218 if (str != null && str.equalsIgnoreCase("No"))
219 showControls = false;
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000220
221 if (inAnApplet) {
222 str = readParameter("Open New Window", false);
223 if (str != null && str.equalsIgnoreCase("Yes"))
224 inSeparateFrame = true;
225 }
226
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000227 // Fine tuning options.
228 deferScreenUpdates = readIntParameter("Defer screen updates", 20);
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000229 }
230
231 public String readParameter(String name, boolean required) {
232 if (inAnApplet) {
233 String s = getParameter(name);
234 if ((s == null) && required) {
235 fatalError(name + " parameter not specified");
236 }
237 return s;
238 }
239
240 for (int i = 0; i < mainArgs.length; i += 2) {
241 if (mainArgs[i].equalsIgnoreCase(name)) {
242 try {
243 return mainArgs[i+1];
244 } catch (Exception e) {
245 if (required) {
246 fatalError(name + " parameter not specified");
247 }
248 return null;
249 }
250 }
251 }
252 if (required) {
253 fatalError(name + " parameter not specified");
254 }
255 return null;
256 }
257
258 int readIntParameter(String name, int defaultValue) {
259 String str = readParameter(name, false);
260 int result = defaultValue;
261 if (str != null) {
262 try {
263 result = Integer.parseInt(str);
264 } catch (NumberFormatException e) { }
265 }
266 return result;
267 }
268
269 //
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000270 // fatalError() - print out a fatal error message.
271 //
272
273 public void fatalError(String str) {
274 System.out.println(str);
275
276 if (inAnApplet) {
277 vncContainer.removeAll();
278 if (rfb != null) {
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000279 rfb = null;
280 }
281 Label errLabel = new Label(str);
282 errLabel.setFont(new Font("Helvetica", Font.PLAIN, 12));
283 vncContainer.setLayout(new FlowLayout(FlowLayout.LEFT, 30, 30));
284 vncContainer.add(errLabel);
285 if (inSeparateFrame) {
286 vncFrame.pack();
287 } else {
288 validate();
289 }
290 Thread.currentThread().stop();
291 } else {
292 System.exit(1);
293 }
294 }
295
296
297 //
298 // This method is called before the applet is destroyed.
299 //
300
301 public void destroy() {
302 vncContainer.removeAll();
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000303 if (rfb != null) {
Constantin Kaplinsky903009e2002-05-20 10:55:47 +0000304 rfb = null;
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000305 }
306 if (inSeparateFrame) {
307 vncFrame.dispose();
308 }
309 }
310
311
312 //
313 // Close application properly on window close event.
314 //
315
316 public void windowClosing(WindowEvent evt) {
Constantin Kaplinsky903009e2002-05-20 10:55:47 +0000317 vncContainer.removeAll();
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000318 if (rfb != null)
Constantin Kaplinsky903009e2002-05-20 10:55:47 +0000319 rfb = null;
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000320
321 vncFrame.dispose();
322 if (!inAnApplet) {
323 System.exit(0);
324 }
325 }
326
327 //
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000328 // Ignore window events we're not interested in.
329 //
330
Constantin Kaplinsky903009e2002-05-20 10:55:47 +0000331 public void windowActivated (WindowEvent evt) {}
Constantin Kaplinsky1215b992008-04-18 09:51:44 +0000332 public void windowDeactivated (WindowEvent evt) {}
333 public void windowOpened(WindowEvent evt) {}
334 public void windowClosed(WindowEvent evt) {}
335 public void windowIconified(WindowEvent evt) {}
336 public void windowDeiconified(WindowEvent evt) {}
337}