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.
322 lines
8.4 KiB
322 lines
8.4 KiB
//
|
|
// Copyright (C) 2002 Constantin Kaplinsky. All Rights Reserved.
|
|
//
|
|
// This is free software; you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation; either version 2 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This software is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this software; if not, write to the Free Software
|
|
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
|
// USA.
|
|
//
|
|
|
|
//
|
|
// Recording frame. It allows to control recording RFB sessions into
|
|
// FBS (FrameBuffer Stream) files.
|
|
//
|
|
|
|
import java.awt.Button;
|
|
import java.awt.Color;
|
|
import java.awt.FileDialog;
|
|
import java.awt.Font;
|
|
import java.awt.Frame;
|
|
import java.awt.GridBagConstraints;
|
|
import java.awt.GridBagLayout;
|
|
import java.awt.Insets;
|
|
import java.awt.Label;
|
|
import java.awt.Panel;
|
|
import java.awt.TextField;
|
|
import java.awt.event.ActionEvent;
|
|
import java.awt.event.ActionListener;
|
|
import java.awt.event.WindowEvent;
|
|
import java.awt.event.WindowListener;
|
|
import java.io.File;
|
|
|
|
class RecordingFrame extends Frame
|
|
implements WindowListener, ActionListener {
|
|
|
|
boolean recording;
|
|
|
|
TextField fnameField;
|
|
Button browseButton;
|
|
|
|
Label statusLabel;
|
|
|
|
Button recordButton, nextButton, closeButton;
|
|
VncViewer viewer;
|
|
|
|
//
|
|
// Check if current security manager allows to create a
|
|
// RecordingFrame object.
|
|
//
|
|
|
|
public static boolean checkSecurity() {
|
|
SecurityManager security = System.getSecurityManager();
|
|
if (security != null) {
|
|
try {
|
|
security.checkPropertyAccess("user.dir");
|
|
security.checkPropertyAccess("file.separator");
|
|
} catch (SecurityException e) {
|
|
System.out.println("SecurityManager restricts session recording.");
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
//
|
|
// Constructor.
|
|
//
|
|
|
|
RecordingFrame(VncViewer v) {
|
|
super("TightVNC Session Recording");
|
|
|
|
viewer = v;
|
|
|
|
// Determine initial filename for next saved session.
|
|
// FIXME: Check SecurityManager.
|
|
|
|
String fname = nextNewFilename(System.getProperty("user.dir") +
|
|
System.getProperty("file.separator") +
|
|
"vncsession.fbs");
|
|
|
|
// Construct new panel with file name field and "Browse" button.
|
|
|
|
Panel fnamePanel = new Panel();
|
|
GridBagLayout fnameGridbag = new GridBagLayout();
|
|
fnamePanel.setLayout(fnameGridbag);
|
|
|
|
GridBagConstraints fnameConstraints = new GridBagConstraints();
|
|
fnameConstraints.gridwidth = GridBagConstraints.RELATIVE;
|
|
fnameConstraints.fill = GridBagConstraints.BOTH;
|
|
fnameConstraints.weightx = 4.0;
|
|
|
|
fnameField = new TextField(fname, 64);
|
|
fnameGridbag.setConstraints(fnameField, fnameConstraints);
|
|
fnamePanel.add(fnameField);
|
|
fnameField.addActionListener(this);
|
|
|
|
fnameConstraints.gridwidth = GridBagConstraints.REMAINDER;
|
|
fnameConstraints.weightx = 1.0;
|
|
|
|
browseButton = new Button("Browse");
|
|
fnameGridbag.setConstraints(browseButton, fnameConstraints);
|
|
fnamePanel.add(browseButton);
|
|
browseButton.addActionListener(this);
|
|
|
|
// Construct the frame.
|
|
|
|
GridBagLayout gridbag = new GridBagLayout();
|
|
setLayout(gridbag);
|
|
|
|
GridBagConstraints gbc = new GridBagConstraints();
|
|
gbc.gridwidth = GridBagConstraints.REMAINDER;
|
|
gbc.fill = GridBagConstraints.BOTH;
|
|
gbc.weighty = 1.0;
|
|
gbc.insets = new Insets(10, 0, 0, 0);
|
|
|
|
Label helpLabel =
|
|
new Label("File name to save next recorded session in:", Label.CENTER);
|
|
gridbag.setConstraints(helpLabel, gbc);
|
|
add(helpLabel);
|
|
|
|
gbc.fill = GridBagConstraints.HORIZONTAL;
|
|
gbc.weighty = 0.0;
|
|
gbc.insets = new Insets(0, 0, 0, 0);
|
|
|
|
gridbag.setConstraints(fnamePanel, gbc);
|
|
add(fnamePanel);
|
|
|
|
gbc.fill = GridBagConstraints.BOTH;
|
|
gbc.weighty = 1.0;
|
|
gbc.insets = new Insets(10, 0, 10, 0);
|
|
|
|
statusLabel = new Label("", Label.CENTER);
|
|
gridbag.setConstraints(statusLabel, gbc);
|
|
add(statusLabel);
|
|
|
|
gbc.fill = GridBagConstraints.HORIZONTAL;
|
|
gbc.weightx = 1.0;
|
|
gbc.weighty = 0.0;
|
|
gbc.gridwidth = 1;
|
|
gbc.insets = new Insets(0, 0, 0, 0);
|
|
|
|
recordButton = new Button("Record");
|
|
gridbag.setConstraints(recordButton, gbc);
|
|
add(recordButton);
|
|
recordButton.addActionListener(this);
|
|
|
|
nextButton = new Button("Next file");
|
|
gridbag.setConstraints(nextButton, gbc);
|
|
add(nextButton);
|
|
nextButton.addActionListener(this);
|
|
|
|
closeButton = new Button("Close");
|
|
gridbag.setConstraints(closeButton, gbc);
|
|
add(closeButton);
|
|
closeButton.addActionListener(this);
|
|
|
|
// Set correct text, font and color for the statusLabel.
|
|
stopRecording();
|
|
|
|
pack();
|
|
|
|
addWindowListener(this);
|
|
}
|
|
|
|
//
|
|
// If the given string ends with ".NNN" where NNN is a decimal
|
|
// number, increase this number by one. Otherwise, append ".001"
|
|
// to the given string.
|
|
//
|
|
|
|
protected String nextFilename(String fname) {
|
|
int len = fname.length();
|
|
int suffixPos = len;
|
|
int suffixNum = 1;
|
|
|
|
if (len > 4 && fname.charAt(len - 4) == '.') {
|
|
try {
|
|
suffixNum = Integer.parseInt(fname.substring(len - 3, len)) + 1;
|
|
suffixPos = len - 4;
|
|
} catch (NumberFormatException e) { }
|
|
}
|
|
|
|
char[] zeroes = {'0', '0', '0'};
|
|
String suffix = String.valueOf(suffixNum);
|
|
if (suffix.length() < 3) {
|
|
suffix = new String(zeroes, 0, 3 - suffix.length()) + suffix;
|
|
}
|
|
|
|
return fname.substring(0, suffixPos) + '.' + suffix;
|
|
}
|
|
|
|
//
|
|
// Find next name of a file which does not exist yet.
|
|
//
|
|
|
|
protected String nextNewFilename(String fname) {
|
|
String newName = fname;
|
|
File f;
|
|
try {
|
|
do {
|
|
newName = nextFilename(newName);
|
|
f = new File(newName);
|
|
} while (f.exists());
|
|
} catch (SecurityException e) { }
|
|
|
|
return newName;
|
|
}
|
|
|
|
//
|
|
// Let the user choose a file name showing a FileDialog.
|
|
//
|
|
|
|
protected boolean browseFile() {
|
|
File currentFile = new File(fnameField.getText());
|
|
|
|
FileDialog fd =
|
|
new FileDialog(this, "Save next session as...", FileDialog.SAVE);
|
|
fd.setDirectory(currentFile.getParent());
|
|
fd.setVisible(true);
|
|
if (fd.getFile() != null) {
|
|
String newDir = fd.getDirectory();
|
|
String sep = System.getProperty("file.separator");
|
|
if (newDir.length() > 0) {
|
|
if (!sep.equals(newDir.substring(newDir.length() - sep.length())))
|
|
newDir += sep;
|
|
}
|
|
String newFname = newDir + fd.getFile();
|
|
if (newFname.equals(fnameField.getText())) {
|
|
fnameField.setText(newFname);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//
|
|
// Start recording.
|
|
//
|
|
|
|
public void startRecording() {
|
|
statusLabel.setText("Status: Recording...");
|
|
statusLabel.setFont(new Font("Helvetica", Font.BOLD, 12));
|
|
statusLabel.setForeground(Color.red);
|
|
recordButton.setLabel("Stop recording");
|
|
|
|
recording = true;
|
|
|
|
viewer.setRecordingStatus(fnameField.getText());
|
|
}
|
|
|
|
//
|
|
// Stop recording.
|
|
//
|
|
|
|
public void stopRecording() {
|
|
statusLabel.setText("Status: Not recording.");
|
|
statusLabel.setFont(new Font("Helvetica", Font.PLAIN, 12));
|
|
statusLabel.setForeground(Color.black);
|
|
recordButton.setLabel("Record");
|
|
|
|
recording = false;
|
|
|
|
viewer.setRecordingStatus(null);
|
|
}
|
|
|
|
//
|
|
// Close our window properly.
|
|
//
|
|
|
|
public void windowClosing(WindowEvent evt) {
|
|
setVisible(false);
|
|
}
|
|
|
|
//
|
|
// Ignore window events we're not interested in.
|
|
//
|
|
|
|
public void windowActivated(WindowEvent evt) {}
|
|
public void windowDeactivated (WindowEvent evt) {}
|
|
public void windowOpened(WindowEvent evt) {}
|
|
public void windowClosed(WindowEvent evt) {}
|
|
public void windowIconified(WindowEvent evt) {}
|
|
public void windowDeiconified(WindowEvent evt) {}
|
|
|
|
|
|
//
|
|
// Respond to button presses
|
|
//
|
|
|
|
public void actionPerformed(ActionEvent evt) {
|
|
if (evt.getSource() == browseButton) {
|
|
if (browseFile() && recording)
|
|
startRecording();
|
|
|
|
} else if (evt.getSource() == recordButton) {
|
|
if (!recording) {
|
|
startRecording();
|
|
} else {
|
|
stopRecording();
|
|
fnameField.setText(nextNewFilename(fnameField.getText()));
|
|
}
|
|
|
|
} else if (evt.getSource() == nextButton) {
|
|
fnameField.setText(nextNewFilename(fnameField.getText()));
|
|
if (recording)
|
|
startRecording();
|
|
|
|
} else if (evt.getSource() == closeButton) {
|
|
setVisible(false);
|
|
|
|
}
|
|
}
|
|
}
|
|
|