RecordingFrame.java 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  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.awt.Button;
  24. import java.awt.Color;
  25. import java.awt.FileDialog;
  26. import java.awt.Font;
  27. import java.awt.Frame;
  28. import java.awt.GridBagConstraints;
  29. import java.awt.GridBagLayout;
  30. import java.awt.Insets;
  31. import java.awt.Label;
  32. import java.awt.Panel;
  33. import java.awt.TextField;
  34. import java.awt.event.ActionEvent;
  35. import java.awt.event.ActionListener;
  36. import java.awt.event.WindowEvent;
  37. import java.awt.event.WindowListener;
  38. import java.io.File;
  39. class RecordingFrame extends Frame
  40. implements WindowListener, ActionListener {
  41. boolean recording;
  42. TextField fnameField;
  43. Button browseButton;
  44. Label statusLabel;
  45. Button recordButton, nextButton, closeButton;
  46. VncViewer viewer;
  47. //
  48. // Check if current security manager allows to create a
  49. // RecordingFrame object.
  50. //
  51. public static boolean checkSecurity() {
  52. SecurityManager security = System.getSecurityManager();
  53. if (security != null) {
  54. try {
  55. security.checkPropertyAccess("user.dir");
  56. security.checkPropertyAccess("file.separator");
  57. } catch (SecurityException e) {
  58. System.out.println("SecurityManager restricts session recording.");
  59. return false;
  60. }
  61. }
  62. return true;
  63. }
  64. //
  65. // Constructor.
  66. //
  67. RecordingFrame(VncViewer v) {
  68. super("TightVNC Session Recording");
  69. viewer = v;
  70. // Determine initial filename for next saved session.
  71. // FIXME: Check SecurityManager.
  72. String fname = nextNewFilename(System.getProperty("user.dir") +
  73. System.getProperty("file.separator") +
  74. "vncsession.fbs");
  75. // Construct new panel with file name field and "Browse" button.
  76. Panel fnamePanel = new Panel();
  77. GridBagLayout fnameGridbag = new GridBagLayout();
  78. fnamePanel.setLayout(fnameGridbag);
  79. GridBagConstraints fnameConstraints = new GridBagConstraints();
  80. fnameConstraints.gridwidth = GridBagConstraints.RELATIVE;
  81. fnameConstraints.fill = GridBagConstraints.BOTH;
  82. fnameConstraints.weightx = 4.0;
  83. fnameField = new TextField(fname, 64);
  84. fnameGridbag.setConstraints(fnameField, fnameConstraints);
  85. fnamePanel.add(fnameField);
  86. fnameField.addActionListener(this);
  87. fnameConstraints.gridwidth = GridBagConstraints.REMAINDER;
  88. fnameConstraints.weightx = 1.0;
  89. browseButton = new Button("Browse");
  90. fnameGridbag.setConstraints(browseButton, fnameConstraints);
  91. fnamePanel.add(browseButton);
  92. browseButton.addActionListener(this);
  93. // Construct the frame.
  94. GridBagLayout gridbag = new GridBagLayout();
  95. setLayout(gridbag);
  96. GridBagConstraints gbc = new GridBagConstraints();
  97. gbc.gridwidth = GridBagConstraints.REMAINDER;
  98. gbc.fill = GridBagConstraints.BOTH;
  99. gbc.weighty = 1.0;
  100. gbc.insets = new Insets(10, 0, 0, 0);
  101. Label helpLabel =
  102. new Label("File name to save next recorded session in:", Label.CENTER);
  103. gridbag.setConstraints(helpLabel, gbc);
  104. add(helpLabel);
  105. gbc.fill = GridBagConstraints.HORIZONTAL;
  106. gbc.weighty = 0.0;
  107. gbc.insets = new Insets(0, 0, 0, 0);
  108. gridbag.setConstraints(fnamePanel, gbc);
  109. add(fnamePanel);
  110. gbc.fill = GridBagConstraints.BOTH;
  111. gbc.weighty = 1.0;
  112. gbc.insets = new Insets(10, 0, 10, 0);
  113. statusLabel = new Label("", Label.CENTER);
  114. gridbag.setConstraints(statusLabel, gbc);
  115. add(statusLabel);
  116. gbc.fill = GridBagConstraints.HORIZONTAL;
  117. gbc.weightx = 1.0;
  118. gbc.weighty = 0.0;
  119. gbc.gridwidth = 1;
  120. gbc.insets = new Insets(0, 0, 0, 0);
  121. recordButton = new Button("Record");
  122. gridbag.setConstraints(recordButton, gbc);
  123. add(recordButton);
  124. recordButton.addActionListener(this);
  125. nextButton = new Button("Next file");
  126. gridbag.setConstraints(nextButton, gbc);
  127. add(nextButton);
  128. nextButton.addActionListener(this);
  129. closeButton = new Button("Close");
  130. gridbag.setConstraints(closeButton, gbc);
  131. add(closeButton);
  132. closeButton.addActionListener(this);
  133. // Set correct text, font and color for the statusLabel.
  134. stopRecording();
  135. pack();
  136. addWindowListener(this);
  137. }
  138. //
  139. // If the given string ends with ".NNN" where NNN is a decimal
  140. // number, increase this number by one. Otherwise, append ".001"
  141. // to the given string.
  142. //
  143. protected String nextFilename(String fname) {
  144. int len = fname.length();
  145. int suffixPos = len;
  146. int suffixNum = 1;
  147. if (len > 4 && fname.charAt(len - 4) == '.') {
  148. try {
  149. suffixNum = Integer.parseInt(fname.substring(len - 3, len)) + 1;
  150. suffixPos = len - 4;
  151. } catch (NumberFormatException e) { }
  152. }
  153. char[] zeroes = {'0', '0', '0'};
  154. String suffix = String.valueOf(suffixNum);
  155. if (suffix.length() < 3) {
  156. suffix = new String(zeroes, 0, 3 - suffix.length()) + suffix;
  157. }
  158. return fname.substring(0, suffixPos) + '.' + suffix;
  159. }
  160. //
  161. // Find next name of a file which does not exist yet.
  162. //
  163. protected String nextNewFilename(String fname) {
  164. String newName = fname;
  165. File f;
  166. try {
  167. do {
  168. newName = nextFilename(newName);
  169. f = new File(newName);
  170. } while (f.exists());
  171. } catch (SecurityException e) { }
  172. return newName;
  173. }
  174. //
  175. // Let the user choose a file name showing a FileDialog.
  176. //
  177. protected boolean browseFile() {
  178. File currentFile = new File(fnameField.getText());
  179. FileDialog fd =
  180. new FileDialog(this, "Save next session as...", FileDialog.SAVE);
  181. fd.setDirectory(currentFile.getParent());
  182. fd.setVisible(true);
  183. if (fd.getFile() != null) {
  184. String newDir = fd.getDirectory();
  185. String sep = System.getProperty("file.separator");
  186. if (newDir.length() > 0) {
  187. if (!sep.equals(newDir.substring(newDir.length() - sep.length())))
  188. newDir += sep;
  189. }
  190. String newFname = newDir + fd.getFile();
  191. if (newFname.equals(fnameField.getText())) {
  192. fnameField.setText(newFname);
  193. return true;
  194. }
  195. }
  196. return false;
  197. }
  198. //
  199. // Start recording.
  200. //
  201. public void startRecording() {
  202. statusLabel.setText("Status: Recording...");
  203. statusLabel.setFont(new Font("Helvetica", Font.BOLD, 12));
  204. statusLabel.setForeground(Color.red);
  205. recordButton.setLabel("Stop recording");
  206. recording = true;
  207. viewer.setRecordingStatus(fnameField.getText());
  208. }
  209. //
  210. // Stop recording.
  211. //
  212. public void stopRecording() {
  213. statusLabel.setText("Status: Not recording.");
  214. statusLabel.setFont(new Font("Helvetica", Font.PLAIN, 12));
  215. statusLabel.setForeground(Color.black);
  216. recordButton.setLabel("Record");
  217. recording = false;
  218. viewer.setRecordingStatus(null);
  219. }
  220. //
  221. // Close our window properly.
  222. //
  223. public void windowClosing(WindowEvent evt) {
  224. setVisible(false);
  225. }
  226. //
  227. // Ignore window events we're not interested in.
  228. //
  229. public void windowActivated(WindowEvent evt) {}
  230. public void windowDeactivated (WindowEvent evt) {}
  231. public void windowOpened(WindowEvent evt) {}
  232. public void windowClosed(WindowEvent evt) {}
  233. public void windowIconified(WindowEvent evt) {}
  234. public void windowDeiconified(WindowEvent evt) {}
  235. //
  236. // Respond to button presses
  237. //
  238. public void actionPerformed(ActionEvent evt) {
  239. if (evt.getSource() == browseButton) {
  240. if (browseFile() && recording)
  241. startRecording();
  242. } else if (evt.getSource() == recordButton) {
  243. if (!recording) {
  244. startRecording();
  245. } else {
  246. stopRecording();
  247. fnameField.setText(nextNewFilename(fnameField.getText()));
  248. }
  249. } else if (evt.getSource() == nextButton) {
  250. fnameField.setText(nextNewFilename(fnameField.getText()));
  251. if (recording)
  252. startRecording();
  253. } else if (evt.getSource() == closeButton) {
  254. setVisible(false);
  255. }
  256. }
  257. }