00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 import java.awt.*;
00048 import java.awt.image.*;
00049 import java.awt.event.*;
00050 import java.io.*;
00051 import java.net.*;
00052 import javax.swing.*;
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062 public class JWebPresenterSS extends JApplet {
00063
00064
00065
00066 final static String ver = "JWebPresenter SS 1.3 (2005-01-23), L. Zhao";
00067
00068
00069
00070
00071 final JApplet me = this;
00072
00073
00074
00075
00076 JWPFrameSS frame = null;
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101 public void init() {
00102 Container pane = getContentPane();
00103
00104 String cmdText = me.getParameter("cmdText");
00105 if (cmdText == null) cmdText = "";
00106 if (cmdText.length() == 0) {
00107 pane.add(new JWPPanelSS(null,
00108 me.getParameter("slideURL"),
00109 me.getParameter("debugMode"),
00110 me.getParameter("ctlURL"),
00111 me.getParameter("baseURL"),
00112 me.getParameter("fetchTime"),
00113 true));
00114 }
00115 else {
00116 JButton startButton = new JButton(cmdText);
00117 startButton.addActionListener(new ActionListener() {
00118 public void actionPerformed(ActionEvent e) {
00119 if (frame == null) {
00120 frame = new JWPFrameSS(me.getParameter("slideURL"),
00121 me.getParameter("debugMode"),
00122 me.getParameter("ctlURL"),
00123 me.getParameter("baseURL"),
00124 me.getParameter("fetchTime"),
00125 me.getParameter("windowWidth"),
00126 me.getParameter("windowHeight"),
00127 true);
00128 }
00129 frame.setVisible(true);
00130 }
00131 });
00132 pane.add(startButton);
00133 }
00134 }
00135
00136
00137
00138
00139 public static void main(String argv[]) {
00140 if (argv.length < 1) {
00141 System.out.println("JWebPresenter Project :: " + ver + "\n"
00142 + "Usage: java JWebPresenterSS parameters\n"
00143 + "Parameters can be given like name=value (no space around =) in any order.\n"
00144 + " slideURL: initial URL to get slides, can be omitted if given by ctlURL.\n"
00145 + " ctlURL: initial URL to get control parameters;\n"
00146 + " debugMode: debug mode, 0 to disable (default), 1 or above to enable;\n"
00147 + " baseURL: base URL, used if a URL obtained from ctlURL is not absolute;\n"
00148 + " fetchTime: time in 100ms to fetch targets (default 50);\n"
00149 + " width: width of presentation window (can be modified after start);\n"
00150 + " height: height of presentation window (can be modified after start).\n"
00151 + "If no width or height is specified, full screen mode is used.\n"
00152 + "Parameter's name can be abbreviated if no confusion happens.\n"
00153 + "For example: s=ftp://host/slide.png c=http://host/ctl.txt b=ftp://host/\n");
00154 System.exit(1);
00155 }
00156
00157 String slideURL = "";
00158 String ctlURL = "";
00159 String debugMode = "";
00160 String baseURL = "";
00161 String fetchTime = "";
00162 String width = "";
00163 String height = "";
00164
00165 for (int i=0; i<argv.length; i++) {
00166 int j = argv[i].indexOf("=");
00167 if (j == -1) {
00168 System.out.println("Bad parameter ("+argv[i] +") omitted");
00169 continue;
00170 }
00171
00172 switch (argv[i].charAt(0)) {
00173 case 's' : slideURL = argv[i].substring(j+1); break;
00174 case 'c' : ctlURL = argv[i].substring(j+1); break;
00175 case 'd' : debugMode = argv[i].substring(j+1); break;
00176 case 'b' : baseURL = argv[i].substring(j+1); break;
00177 case 'f' : fetchTime = argv[i].substring(j+1); break;
00178 case 'w' : width = argv[i].substring(j+1); break;
00179 case 'h' : height = argv[i].substring(j+1); break;
00180 default :
00181 System.out.println("Bad parameter ("+argv[i]+") omitted.");
00182 }
00183 }
00184
00185 new JWPFrameSS(slideURL, debugMode, ctlURL, baseURL, fetchTime, width, height, false).setVisible(true);
00186 }
00187 }
00188
00189
00190
00191
00192
00193
00194 class JWPFrameSS extends JFrame {
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206 JWPFrameSS(String s, String d, String c, String b, String f, String w, String h, boolean app) {
00207 setDefaultCloseOperation(app?DISPOSE_ON_CLOSE:EXIT_ON_CLOSE);
00208
00209 int width = 0;
00210 try {
00211 width = Integer.parseInt(w);
00212 }
00213 catch (NumberFormatException e) {
00214 width = 0;
00215 }
00216
00217 int height = 0;
00218 try {
00219 height = Integer.parseInt(h);
00220 }
00221 catch (NumberFormatException e) {
00222 height = 0;
00223 }
00224
00225 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
00226 if (width < 1 || width > screen.width) width = screen.width;
00227 if (height < 1 || height > screen.height) height = screen.height;
00228 setSize(width, height);
00229
00230
00231 if (width == screen.width && height == screen.height) setUndecorated(true);
00232
00233 getContentPane().add(new JWPPanelSS(this, s, d, c, b, f, app));
00234 }
00235 }
00236
00237
00238
00239
00240
00241
00242
00243 class JWPPanelSS extends JPanel implements ActionListener {
00244
00245
00246
00247 JFrame frame;
00248
00249
00250
00251
00252 boolean isApplet;
00253
00254
00255
00256
00257 Timer timer;
00258
00259
00260
00261
00262 Toolkit tk;
00263
00264
00265
00266
00267 String baseURL;
00268
00269
00270
00271
00272 URL orig_ctlURL;
00273
00274
00275
00276
00277 URL orig_slideURL;
00278
00279
00280
00281
00282 URL urlCtl;
00283
00284
00285
00286
00287 URL urlSlide;
00288
00289
00290
00291
00292 int fetchTime;
00293
00294
00295
00296
00297 boolean debugMode;
00298
00299
00300
00301
00302 URLConnection c;
00303
00304
00305
00306
00307 int countSlide = 0;
00308
00309
00310
00311
00312 int countCtl = 0;
00313
00314
00315
00316
00317 boolean advancedMode;
00318
00319
00320
00321
00322 Image img;
00323
00324
00325
00326
00327 MediaTracker tracker = new MediaTracker(this);
00328
00329
00330
00331
00332
00333
00334 boolean fastMode = false;
00335
00336
00337
00338
00339
00340
00341 BufferedReader in;
00342
00343
00344
00345
00346 String str;
00347
00348
00349
00350
00351 int jwpVersion;
00352
00353
00354
00355
00356 long lastSeq = -1;
00357
00358
00359
00360
00361 int seq;
00362
00363
00364
00365
00366
00367
00368 JPopupMenu menu = new JPopupMenu("Popup Menu");
00369
00370
00371
00372
00373
00374 JCheckBoxMenuItem decorateItem;
00375
00376
00377
00378
00379 JCheckBoxMenuItem fillItem = new JCheckBoxMenuItem("Fill Image to Window");
00380
00381
00382
00383
00384 boolean bResizeToFill = false;
00385
00386
00387
00388
00389
00390 boolean bDecorate;
00391
00392
00393
00394
00395 JDialog infoDialog;
00396
00397
00398
00399
00400 JLabel infoLabel;
00401
00402
00403
00404
00405 JButton moreButton;
00406
00407
00408
00409
00410 public void debugMsg(String msg) {
00411 if (debugMode) System.err.println("(info) " + msg);
00412 }
00413
00414
00415
00416
00417 public void quit() {
00418 if (isApplet && frame != null) frame.setVisible(false);
00419 else System.exit(0);
00420 }
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432 JWPPanelSS(JFrame f, String slide, String debug, String ctl, String base, String fetch, boolean app) {
00433 frame = f;
00434 baseURL = (base==null)?"":base;
00435 isApplet = app;
00436 tk = Toolkit.getDefaultToolkit();
00437
00438
00439 addKeyListener(new KeyAdapter() {
00440 public void keyPressed(KeyEvent e) {
00441 if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
00442 quit();
00443 }
00444 }
00445 });
00446
00447
00448 addMouseListener(new MouseAdapter() {
00449 public void mouseClicked(MouseEvent e) {
00450
00451 if (e.getClickCount() > 2) {
00452 quit();
00453 }
00454 }
00455
00456 public void mouseReleased(MouseEvent e) {
00457 if (e.isPopupTrigger()) {
00458 menu.show(e.getComponent(), e.getX(), e.getY());
00459 }
00460 }
00461
00462 public void mousePressed(MouseEvent e) {
00463 if (e.isPopupTrigger()) {
00464 menu.show(e.getComponent(), e.getX(), e.getY());
00465 }
00466 }
00467 });
00468
00469
00470 try {
00471 debugMode = (Integer.parseInt(debug) != 0);
00472 }
00473 catch (NumberFormatException e) {
00474 debugMode = false;
00475 }
00476
00477
00478 try {
00479 urlCtl = new URL(ctl);
00480 orig_ctlURL = urlCtl;
00481 }
00482 catch (MalformedURLException e) {
00483 debugMsg("Bad or no ctlURL (" + ctl + "). Set to NONE.");
00484 orig_ctlURL = null;
00485 urlCtl = null;
00486 }
00487
00488
00489 try {
00490 urlSlide = new URL(slide);
00491 orig_slideURL = urlSlide;
00492 }
00493 catch (MalformedURLException e) {
00494 debugMsg("Bad or no slideURL (" + slide + "). Set to NONE.");
00495 orig_slideURL = null;
00496 urlSlide = null;
00497 }
00498
00499
00500 if ((urlCtl == null) && (urlSlide == null)) {
00501 debugMsg("Oops, what can I do for null ctlURL and null slideURL?");
00502 JButton btnQuit = new JButton("(Invalid input) Check ctlURL and slideURL! (Click to quit)");
00503 btnQuit.addActionListener(new ActionListener() {
00504 public void actionPerformed(ActionEvent e) {
00505 quit();
00506 }
00507 });
00508 add(btnQuit);
00509 return;
00510 }
00511
00512
00513 try {
00514 fetchTime = Integer.parseInt(fetch) * 100;
00515 }
00516 catch (NumberFormatException e) {
00517 debugMsg("Bad or no fetchTime. Set to 5s.");
00518 fetchTime = 5000;
00519 }
00520
00521 try {
00522 debugMsg("Java version = " + System.getProperty("java.version"));
00523 }
00524 catch (SecurityException e) {}
00525
00526 debugMsg("--- Parsed parameters are as follows ---\n" +
00527 " slideURL = " + urlSlide + "\n" +
00528 " debugMode = " + debugMode + "\n" +
00529 " ctlURL = " + urlCtl + "\n" +
00530 " baseURL = " + baseURL + "\n" +
00531 " fetchTime = " + fetchTime + "ms\n" +
00532 " Parameters accepted :-).");
00533
00534
00535
00536 if (frame != null) {
00537 menu.add(new AbstractAction("Full Screen") {
00538 public void actionPerformed(ActionEvent e) {
00539 Dimension screen = tk.getScreenSize();
00540 bDecorate = false;
00541 decorateItem.setSelected(false);
00542 bResizeToFill = false;
00543 fillItem.setSelected(false);
00544 frame.dispose();
00545 frame.setUndecorated(true);
00546 frame.setLocation(0, 0);
00547 frame.setSize(screen.width, screen.height);
00548 setSize(screen.width, screen.height);
00549 frame.setVisible(true);
00550 repaint();
00551 }
00552 });
00553 }
00554
00555
00556
00557
00558
00559 menu.add(new AbstractAction("Reset (= restore URLs to initial values)") {
00560 public void actionPerformed(ActionEvent e) {
00561 urlCtl = orig_ctlURL;
00562 urlSlide = orig_slideURL;
00563 timer.setDelay(fetchTime);
00564 timer.setInitialDelay(0);
00565 timer.restart();
00566 debugMsg("URLs resetted. Starting new fetching...");
00567 }
00568 });
00569
00570
00571
00572
00573
00574 menu.addSeparator();
00575
00576
00577 if (frame != null) {
00578 decorateItem = new JCheckBoxMenuItem("Decorate Window (then resize, move, etc)");
00579 bDecorate = !frame.isUndecorated();
00580 decorateItem.setSelected(bDecorate);
00581 decorateItem.addActionListener(new ActionListener() {
00582 public void actionPerformed(ActionEvent e) {
00583 bDecorate = !bDecorate;
00584 frame.dispose();
00585 frame.setUndecorated(!bDecorate);
00586 decorateItem.setSelected(bDecorate);
00587 frame.setVisible(true);
00588 repaint();
00589 }
00590 });
00591 menu.add(decorateItem);
00592 }
00593
00594 fillItem.setSelected(bResizeToFill);
00595 fillItem.addActionListener(new ActionListener() {
00596 public void actionPerformed(ActionEvent e) {
00597 bResizeToFill = !bResizeToFill;
00598 repaint();
00599 }
00600 });
00601 menu.add(fillItem);
00602
00603 JCheckBoxMenuItem fastItem = new JCheckBoxMenuItem("Fast Mode (= skip intermediate slides)");
00604 fastItem.setSelected(fastMode);
00605 fastItem.addActionListener(new ActionListener() {
00606 public void actionPerformed(ActionEvent e) {
00607 fastMode = !fastMode;
00608 }
00609 });
00610 menu.add(fastItem);
00611
00612 JCheckBoxMenuItem debugItem = new JCheckBoxMenuItem("Debug to Java Console");
00613 debugItem.setSelected(debugMode);
00614 debugItem.addActionListener(new ActionListener() {
00615 public void actionPerformed(ActionEvent e) {
00616 debugMode = !debugMode;
00617 }
00618 });
00619 menu.add(debugItem);
00620
00621 menu.addSeparator();
00622
00623 menu.add(new AbstractAction("Information...") {
00624 public void actionPerformed(ActionEvent e) {
00625 if (infoDialog != null) infoDialog.setVisible(true);
00626 }
00627 });
00628
00629
00630 if (frame != null) {
00631 menu.add(new AbstractAction("Quit") {
00632 public void actionPerformed(ActionEvent e) {
00633 quit();
00634 }
00635 });
00636 }
00637
00638 add(menu);
00639
00640
00641 infoDialog = new JDialog(frame, "Information", true);
00642 Container con = infoDialog.getContentPane();
00643 infoLabel = new JLabel("<HTML><BR><CENTER><B>"+JWebPresenterSS.ver
00644 +"</B></CENTER><BR></HTML>", SwingConstants.CENTER);
00645 con.add(infoLabel);
00646 JPanel pOK = new JPanel();
00647 JButton ok = new JButton("OK");
00648 ok.addActionListener(new ActionListener() {
00649 public void actionPerformed(ActionEvent e) {
00650 infoDialog.setVisible(false);
00651 infoLabel.setText("<HTML><BR><CENTER><B>"+JWebPresenterSS.ver
00652 +"</B></CENTER><BR></HTML>");
00653 moreButton.setText("More...");
00654 infoDialog.pack();
00655 }
00656 });
00657 pOK.add(ok);
00658
00659 moreButton = new JButton("More...");
00660 moreButton.addActionListener(new ActionListener() {
00661 public void actionPerformed(ActionEvent e) {
00662 String command = e.getActionCommand();
00663
00664 if (command.equals("More...")) {
00665 infoLabel.setText("<HTML><BR><CENTER><B>"+JWebPresenterSS.ver
00666 +"</B></CENTER><BR>"
00667 +"Base URL = "+baseURL+"<BR>"
00668 +"Slide URL = "+((urlSlide==null)?"N/A":urlSlide.toString())+"<BR>"
00669 +"Control URL = "+((urlCtl==null)?"N/A":urlCtl.toString())+"<BR>"
00670 +"Fetch interval = "+fetchTime+"ms<BR>"
00671 +"JWP version = "+((jwpVersion==0)?"N/A":String.valueOf(jwpVersion))+"<BR>"
00672 +"Advanced mode = "+(advancedMode?"Enabled":"Disabled")+"<BR>"
00673 +"Fetch counter (control/slide) = "+countCtl+"/"+countSlide+"<BR>"
00674 +"</HTML>");
00675 moreButton.setText("Less...");
00676 }
00677 else {
00678 infoLabel.setText("<HTML><BR><CENTER><B>"+JWebPresenterSS.ver
00679 +"</B></CENTER><BR></HTML>");
00680 moreButton.setText("More...");
00681 }
00682 infoDialog.pack();
00683 }
00684 });
00685 pOK.add(moreButton);
00686
00687 con.add(pOK, BorderLayout.SOUTH);
00688 infoDialog.pack();
00689
00690 debugMsg("Initilization finished. Ready to run...");
00691
00692 timer = new Timer(fetchTime, this);
00693 timer.setInitialDelay(0);
00694 timer.start();
00695 }
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707 public void actionPerformed(ActionEvent e) {
00708 int oldFetchTime = fetchTime;
00709 boolean succ;
00710
00711 do {
00712 debugMsg("Time stamp: " + System.currentTimeMillis());
00713 succ = parseCommands();
00714 } while (fastMode & succ);
00715
00716
00717 if (fetchTime != oldFetchTime) {
00718 debugMsg("Fetch timer is re-schduled to " + fetchTime + "ms.");
00719 timer.setDelay(fetchTime);
00720 timer.restart();
00721 }
00722
00723
00724 if (frame != null && !frame.isShowing()) return;
00725
00726
00727
00728
00729 if ((advancedMode == true) && (seq == lastSeq)) {
00730 debugMsg("Target fetch omitted due to the same sequence number.");
00731 }
00732 else {
00733 if (urlSlide == null) return;
00734 countSlide++;
00735 tracker.removeImage(img);
00736 img = tk.createImage(urlSlide);
00737 tracker.addImage(img, 0);
00738 try { tracker.waitForID(0); }
00739 catch (InterruptedException ie) {
00740 debugMsg("Interrupted in loading image from "+urlSlide);
00741 tracker.removeImage(img);
00742 img = null;
00743 }
00744 if (img == null) {
00745 debugMsg("Target fetch failed (count = " + countSlide + ").");
00746 } else {
00747 debugMsg("Target fetch succeeded (count = " + countSlide + ").");
00748 if (advancedMode == true) { lastSeq = seq; }
00749 repaint();
00750 }
00751 }
00752 }
00753
00754
00755
00756
00757
00758
00759 public void paintComponent(Graphics g) {
00760 super.paintComponent(g);
00761
00762 if (img == null) {
00763 debugMsg("No image is available for painting!");
00764 g.drawString("No image! Error or remote not ready?", 15, 15);
00765 return;
00766 }
00767
00768 if (tracker.statusAll(false) == MediaTracker.COMPLETE) {
00769 if (bResizeToFill == false) {
00770 int upper_left = (getWidth() - img.getWidth(this)) >> 1;
00771 int lower_right = (getHeight() - img.getHeight(this)) >> 1;
00772 g.drawImage(img, upper_left, lower_right, this);
00773 } else {
00774 g.drawImage(img, 0, 0, getWidth(), getHeight(), this);
00775 }
00776 }
00777 else {
00778 debugMsg("Painted image is not ready!");
00779 g.drawString("Waiting for the load of image...", 15, 15);
00780 }
00781 }
00782
00783
00784
00785
00786
00787
00788
00789
00790 public static int getUInt(String msg, String pattern) {
00791 int value = -1;
00792
00793 if (msg.startsWith(pattern+"=") == true) {
00794 try {
00795 value = Integer.parseInt(msg.substring(msg.indexOf("=")+1));
00796 }
00797 catch (NumberFormatException e) {
00798 value = -1;
00799 }
00800 }
00801 return value;
00802 }
00803
00804
00805
00806
00807
00808
00809
00810
00811 public URL getURL(String msg, String pattern) {
00812 URL u = null;
00813
00814 if (msg.startsWith(pattern+"=") == true) {
00815 try { u = new URL(msg.substring(msg.indexOf("=")+1)); }
00816 catch (MalformedURLException e) { u = null; }
00817
00818 if (u == null) {
00819 try {
00820 u = new URL(baseURL + msg.substring(msg.indexOf("=")+1));
00821 }
00822 catch (MalformedURLException e) { u = null; }
00823 }
00824 }
00825 return u;
00826 }
00827
00828
00829
00830
00831
00832
00833
00834 private boolean parseCommands() {
00835 int v, s, t;
00836 URL cURL, sURL;
00837
00838 advancedMode = false;
00839 if (urlCtl == null) return false;
00840
00841 advancedMode = true;
00842 countCtl++;
00843 try {
00844 c = urlCtl.openConnection();
00845 c.connect();
00846 in = new BufferedReader(new InputStreamReader(c.getInputStream()));
00847 debugMsg("Parsing the control commands ...");
00848 v = s = t = -1;
00849 cURL = sURL = null;
00850 while ((str = in.readLine()) != null) {
00851 debugMsg("Remote control paramters>> " + str);
00852 if (sURL == null) sURL = getURL(str, "Slide");
00853 if (cURL == null) cURL = getURL(str, "NextCtl");
00854 str = str.trim().toLowerCase();
00855
00856 if (v < 1) v = getUInt(str, "jwpversion");
00857 if (s < 0) s = getUInt(str, "seq");
00858 if (t < 0) t = getUInt(str, "fetchtime");
00859 }
00860 if (v >= 1) jwpVersion = v;
00861 if (s >= 0) seq = s;
00862 if (t >= 1) fetchTime = t*100;
00863 if (cURL != null) urlCtl = cURL;
00864 if (sURL != null) urlSlide = sURL;
00865
00866 if ((v < 1) || (s < 0)) advancedMode = false;
00867 }
00868 catch (IOException e) {
00869 debugMsg("IO error in reading from " + urlCtl);
00870 return false;
00871 }
00872 debugMsg("*** Settings after parsing control command ***\n" +
00873 " JWPVersion = " + jwpVersion + "\n" +
00874 " Seq = " + seq + "\n" +
00875 " FetchTime = " + fetchTime+ "ms\n" +
00876 " Slide = " + urlSlide + "\n" +
00877 " NextCtl = " + urlCtl +
00878 (advancedMode?"":"\n Advanced mode disabled."));
00879 return true;
00880 }
00881 }