You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

RecordingFrame.java 8.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. //
  2. // Copyright (C) 2002 Constantin Kaplinsky. All Rights Reserved.
  3. //
  4. // This is free software; you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation; either version 2 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // This software is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with this software; if not, write to the Free Software
  16. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  17. // USA.
  18. //
  19. //
  20. // Recording frame. It allows to control recording RFB sessions into
  21. // FBS (FrameBuffer Stream) files.
  22. //
  23. import java.io.*;
  24. import java.awt.*;
  25. import java.awt.event.*;
  26. class RecordingFrame extends Frame
  27. implements WindowListener, ActionListener {
  28. boolean recording;
  29. TextField fnameField;
  30. Button browseButton;
  31. Label statusLabel;
  32. Button recordButton, nextButton, closeButton;
  33. VncViewer viewer;
  34. //
  35. // Check if current security manager allows to create a
  36. // RecordingFrame object.
  37. //
  38. public static boolean checkSecurity() {
  39. SecurityManager security = System.getSecurityManager();
  40. if (security != null) {
  41. try {
  42. security.checkPropertyAccess("user.dir");
  43. security.checkPropertyAccess("file.separator");
  44. // Work around (rare) checkPropertyAccess bug
  45. System.getProperty("user.dir");
  46. } catch (SecurityException e) {
  47. System.out.println("SecurityManager restricts session recording.");
  48. return false;
  49. }
  50. }
  51. return true;
  52. }
  53. //
  54. // Constructor.
  55. //
  56. RecordingFrame(VncViewer v) {
  57. super("TightVNC Session Recording");
  58. viewer = v;
  59. // Determine initial filename for next saved session.
  60. // FIXME: Check SecurityManager.
  61. String fname = nextNewFilename(System.getProperty("user.dir") +
  62. System.getProperty("file.separator") +
  63. "vncsession.fbs");
  64. // Construct new panel with file name field and "Browse" button.
  65. Panel fnamePanel = new Panel();
  66. GridBagLayout fnameGridbag = new GridBagLayout();
  67. fnamePanel.setLayout(fnameGridbag);
  68. GridBagConstraints fnameConstraints = new GridBagConstraints();
  69. fnameConstraints.gridwidth = GridBagConstraints.RELATIVE;
  70. fnameConstraints.fill = GridBagConstraints.BOTH;
  71. fnameConstraints.weightx = 4.0;
  72. fnameField = new TextField(fname, 64);
  73. fnameGridbag.setConstraints(fnameField, fnameConstraints);
  74. fnamePanel.add(fnameField);
  75. fnameField.addActionListener(this);
  76. fnameConstraints.gridwidth = GridBagConstraints.REMAINDER;
  77. fnameConstraints.weightx = 1.0;
  78. browseButton = new Button("Browse");
  79. fnameGridbag.setConstraints(browseButton, fnameConstraints);
  80. fnamePanel.add(browseButton);
  81. browseButton.addActionListener(this);
  82. // Construct the frame.
  83. GridBagLayout gridbag = new GridBagLayout();
  84. setLayout(gridbag);
  85. GridBagConstraints gbc = new GridBagConstraints();
  86. gbc.gridwidth = GridBagConstraints.REMAINDER;
  87. gbc.fill = GridBagConstraints.BOTH;
  88. gbc.weighty = 1.0;
  89. gbc.insets = new Insets(10, 0, 0, 0);
  90. Label helpLabel =
  91. new Label("File name to save next recorded session in:", Label.CENTER);
  92. gridbag.setConstraints(helpLabel, gbc);
  93. add(helpLabel);
  94. gbc.fill = GridBagConstraints.HORIZONTAL;
  95. gbc.weighty = 0.0;
  96. gbc.insets = new Insets(0, 0, 0, 0);
  97. gridbag.setConstraints(fnamePanel, gbc);
  98. add(fnamePanel);
  99. gbc.fill = GridBagConstraints.BOTH;
  100. gbc.weighty = 1.0;
  101. gbc.insets = new Insets(10, 0, 10, 0);
  102. statusLabel = new Label("", Label.CENTER);
  103. gridbag.setConstraints(statusLabel, gbc);
  104. add(statusLabel);
  105. gbc.fill = GridBagConstraints.HORIZONTAL;
  106. gbc.weightx = 1.0;
  107. gbc.weighty = 0.0;
  108. gbc.gridwidth = 1;
  109. gbc.insets = new Insets(0, 0, 0, 0);
  110. recordButton = new Button("Record");
  111. gridbag.setConstraints(recordButton, gbc);
  112. add(recordButton);
  113. recordButton.addActionListener(this);
  114. nextButton = new Button("Next file");
  115. gridbag.setConstraints(nextButton, gbc);
  116. add(nextButton);
  117. nextButton.addActionListener(this);
  118. closeButton = new Button("Close");
  119. gridbag.setConstraints(closeButton, gbc);
  120. add(closeButton);
  121. closeButton.addActionListener(this);
  122. // Set correct text, font and color for the statusLabel.
  123. stopRecording();
  124. pack();
  125. addWindowListener(this);
  126. }
  127. //
  128. // If the given string ends with ".NNN" where NNN is a decimal
  129. // number, increase this number by one. Otherwise, append ".001"
  130. // to the given string.
  131. //
  132. protected String nextFilename(String fname) {
  133. int len = fname.length();
  134. int suffixPos = len;
  135. int suffixNum = 1;
  136. if (len > 4 && fname.charAt(len - 4) == '.') {
  137. try {
  138. suffixNum = Integer.parseInt(fname.substring(len - 3, len)) + 1;
  139. suffixPos = len - 4;
  140. } catch (NumberFormatException e) { }
  141. }
  142. char[] zeroes = {'0', '0', '0'};
  143. String suffix = String.valueOf(suffixNum);
  144. if (suffix.length() < 3) {
  145. suffix = new String(zeroes, 0, 3 - suffix.length()) + suffix;
  146. }
  147. return fname.substring(0, suffixPos) + '.' + suffix;
  148. }
  149. //
  150. // Find next name of a file which does not exist yet.
  151. //
  152. protected String nextNewFilename(String fname) {
  153. String newName = fname;
  154. File f;
  155. try {
  156. do {
  157. newName = nextFilename(newName);
  158. f = new File(newName);
  159. } while (f.exists());
  160. } catch (SecurityException e) { }
  161. return newName;
  162. }
  163. //
  164. // Let the user choose a file name showing a FileDialog.
  165. //
  166. protected boolean browseFile() {
  167. File currentFile = new File(fnameField.getText());
  168. FileDialog fd =
  169. new FileDialog(this, "Save next session as...", FileDialog.SAVE);
  170. fd.setDirectory(currentFile.getParent());
  171. fd.setVisible(true);
  172. if (fd.getFile() != null) {
  173. String newDir = fd.getDirectory();
  174. String sep = System.getProperty("file.separator");
  175. if (newDir.length() > 0) {
  176. if (!sep.equals(newDir.substring(newDir.length() - sep.length())))
  177. newDir += sep;
  178. }
  179. String newFname = newDir + fd.getFile();
  180. if (newFname.equals(fnameField.getText())) {
  181. fnameField.setText(newFname);
  182. return true;
  183. }
  184. }
  185. return false;
  186. }
  187. //
  188. // Start recording.
  189. //
  190. public void startRecording() {
  191. statusLabel.setText("Status: Recording...");
  192. statusLabel.setFont(new Font("Helvetica", Font.BOLD, 12));
  193. statusLabel.setForeground(Color.red);
  194. recordButton.setLabel("Stop recording");
  195. recording = true;
  196. viewer.setRecordingStatus(fnameField.getText());
  197. }
  198. //
  199. // Stop recording.
  200. //
  201. public void stopRecording() {
  202. statusLabel.setText("Status: Not recording.");
  203. statusLabel.setFont(new Font("Helvetica", Font.PLAIN, 12));
  204. statusLabel.setForeground(Color.black);
  205. recordButton.setLabel("Record");
  206. recording = false;
  207. viewer.setRecordingStatus(null);
  208. }
  209. //
  210. // Close our window properly.
  211. //
  212. public void windowClosing(WindowEvent evt) {
  213. setVisible(false);
  214. }
  215. //
  216. // Ignore window events we're not interested in.
  217. //
  218. public void windowActivated(WindowEvent evt) {}
  219. public void windowDeactivated (WindowEvent evt) {}
  220. public void windowOpened(WindowEvent evt) {}
  221. public void windowClosed(WindowEvent evt) {}
  222. public void windowIconified(WindowEvent evt) {}
  223. public void windowDeiconified(WindowEvent evt) {}
  224. //
  225. // Respond to button presses
  226. //
  227. public void actionPerformed(ActionEvent evt) {
  228. if (evt.getSource() == browseButton) {
  229. if (browseFile() && recording)
  230. startRecording();
  231. } else if (evt.getSource() == recordButton) {
  232. if (!recording) {
  233. startRecording();
  234. } else {
  235. stopRecording();
  236. fnameField.setText(nextNewFilename(fnameField.getText()));
  237. }
  238. } else if (evt.getSource() == nextButton) {
  239. fnameField.setText(nextNewFilename(fnameField.getText()));
  240. if (recording)
  241. startRecording();
  242. } else if (evt.getSource() == closeButton) {
  243. setVisible(false);
  244. }
  245. }
  246. }