/*
* @(#)ScreenRecorderMain.java
*
* Copyright (c) 2011 Werner Randelshofer, Goldau, Switzerland.
* All rights reserved.
*
* You may not use, copy or modify this file, except in compliance with the
* license agreement you entered into with Werner Randelshofer.
* For details see accompanying license terms.
*/
package org.monte.screenrecorder;
import javax.swing.plaf.ButtonUI;
import java.awt.Insets;
import javax.swing.MenuElement;
import java.awt.LinearGradientPaint;
import java.awt.Graphics2D;
import java.awt.Graphics;
import javax.swing.Timer;
import javax.swing.ImageIcon;
import java.awt.Image;
import java.awt.image.BufferedImage;
import javax.swing.AbstractButton;
import java.awt.Color;
import javax.swing.ButtonGroup;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import org.monte.media.gui.datatransfer.DropFileTransferHandler;
import org.monte.media.gui.JLabelHyperlinkHandler;
import java.net.URISyntaxException;
import java.net.URI;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Enumeration;
import java.awt.Point;
import java.io.File;
import java.awt.Dimension;
import java.awt.GraphicsConfiguration;
import java.awt.Rectangle;
import javax.swing.UIManager;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.JComponent;
import org.monte.media.Format;
import org.monte.media.gui.Worker;
import org.monte.media.math.Rational;
import java.awt.AWTException;
import java.awt.Desktop;
import java.awt.Frame;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.prefs.Preferences;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.ToolTipManager;
import javax.swing.border.EmptyBorder;
import javax.swing.plaf.basic.BasicButtonUI;
import org.monte.media.image.Images;
import static org.monte.media.AudioFormatKeys.*;
import static org.monte.media.VideoFormatKeys.*;
import static java.lang.Math.*;
import java.util.Vector;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.Mixer;
import javax.sound.sampled.TargetDataLine;
import javax.swing.JMenuItem;
import javax.swing.JRadioButtonMenuItem;
/**
* ScreenRecorderMain.
*
* @author Werner Randelshofer
* @version $Id: ScreenRecorderCompactMain.java 285 2012-11-21 21:04:07Z werner
* $
*/
public class ScreenRecorderCompactMain extends javax.swing.JFrame {
private void setSelectedIndex(ButtonGroup group, int index) {
Enumeration<AbstractButton> e = group.getElements();
AbstractButton b = null;
for (int i = 0; i <= index; i++) {
if (e.hasMoreElements()) {
b = e.nextElement();
}
}
group.setSelected(b.getModel(), true);
}
private int getSelectedIndex(ButtonGroup group) {
int index = 0;
for (Enumeration<AbstractButton> e = group.getElements(); e.hasMoreElements();) {
AbstractButton b = e.nextElement();
if (b.isSelected()) {
break;
}
index++;
}
return index;
}
private AbstractButton getSelectedItem(ButtonGroup group) {
for (Enumeration<AbstractButton> e = group.getElements(); e.hasMoreElements();) {
AbstractButton b = e.nextElement();
if (b.isSelected()) {
return b;
}
}
return null;
}
private void buildAudioSourceMenu() {
Preferences prefs = Preferences.userNodeForPackage(ScreenRecorderCompactMain.class);
audioSource = prefs.getInt("ScreenRecording.audioSource", 0);
Vector<AudioSourceItem> items = getAudioSources();
audioSource = max(0, min(items.size() - 1, audioSource));
System.out.println("audioSource:" + audioSource);
int i = 0;
for (AudioSourceItem item : items) {
JRadioButtonMenuItem mi = new JRadioButtonMenuItem(item.title);
mi.putClientProperty("AudioSourceItem", item);
audioSourceGroup.add(mi);
if (i == audioSource) {
mi.setSelected(true);
}
audioMenu.insert(mi, i);
i++;
}
}
private class Handler implements ChangeListener {
@Override
public void stateChanged(ChangeEvent e) {
ScreenRecorder r = screenRecorder;
if (r != null && r.getState() == ScreenRecorder.State.FAILED) {
recordingFailed(r.getStateMessage());
}
}
}
private Handler handler = new Handler();
private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd 'at' HH.mm.ss");
private volatile Worker recorder;
private ScreenRecorder screenRecorder;
private int depth;
private int format;
//private int encoding;
private int cursor;
private int audioRate;
private int channels;
private int area;
private int fps;
private int audioSource;
private File movieFolder;
private Rectangle customAreaRect;
private Timer timer;
private String infoLabelText;
private static class AudioItem {
private String title;
private int sampleRate;
private int bitsPerSample;
public AudioItem(String title, int sampleRate, int bitsPerSample) {
this.title = title;
this.sampleRate = sampleRate;
this.bitsPerSample = bitsPerSample;
}
@Override
public String toString() {
return title;
}
}
private static class AreaItem {
private String title;
/**
* Area or null for entire screen.
*/
private Dimension inputDimension;
/**
* null if same value as input dimension.
*/
private Dimension outputDimension;
/**
* SwingConstants.CENTER, .NORTH_WEST, SOUTH_WEST.
*/
private int alignment;
private Point location;
public AreaItem(String title, Dimension dim, int alignment) {
this(title, dim, null, alignment, new Point(0, 0));
}
public AreaItem(String title, Dimension inputDim, Dimension outputDim, int alignment, Point location) {
this.title = title;
this.inputDimension = inputDim;
this.outputDimension = outputDim;
this.alignment = alignment;
this.location = location;
}
@Override
public String toString() {
return title;
}
public Rectangle getBounds(GraphicsConfiguration cfg) {
Rectangle areaRect = null;
if (inputDimension != null) {
areaRect = new Rectangle(0, 0, inputDimension.width, inputDimension.height);
}
outputDimension = outputDimension;
Rectangle screenBounds = cfg.getBounds();
if (areaRect == null) {
areaRect = (Rectangle) screenBounds.clone();
}
switch (alignment) {
case SwingConstants.CENTER:
areaRect.x = screenBounds.x + (screenBounds.width - areaRect.width) / 2;
areaRect.y = screenBounds.y + (screenBounds.height - areaRect.height) / 2;
break;
case SwingConstants.NORTH_WEST:
areaRect.x = screenBounds.x;
areaRect.y = screenBounds.y;
break;
case SwingConstants.SOUTH_WEST:
areaRect.x = screenBounds.x;
areaRect.y = screenBounds.y + screenBounds.height - areaRect.height;
break;
default:
break;
}
areaRect.translate(location.x, location.y);
areaRect = areaRect.intersection(screenBounds);
return areaRect;
}
}
private static class AudioSourceItem {
private String title;
private Mixer.Info mixerInfo;
private boolean isEnabled;
public AudioSourceItem(String title, Mixer.Info mixerInfo) {
this(title, mixerInfo, true);
}
public AudioSourceItem(String title, Mixer.Info mixerInfo, boolean isEnabled) {
this.title = title;
this.mixerInfo = mixerInfo;
this.isEnabled = isEnabled;
}
@Override
public String toString() {
return title;
}
}
/**
* Creates new form ScreenRecorderMain
*/
public ScreenRecorderCompactMain() {
setContentPane(new JPanel() {
@Override
public void paintComponent(Graphics gr) {
Graphics2D g = (Graphics2D) gr;
g.setPaint(new LinearGradientPaint(0, 0, 0, getHeight(),
new float[]{0, 0.499f, 0.5f, 1.0f},
new Color[]{new Color(0x404040),
new Color(0x2f2f2f),
new Color(0x1e1e1e),
new Color(0x151515)}));
g.fillRect(0, 0, getWidth(), getHeight());
}
});
((JPanel) getContentPane()).setBorder(new EmptyBorder(1, 2, 2, 2));
setMinimumSize(new Dimension(Math.max(240, getPreferredSize().width), getPreferredSize().height));
initComponents();
String version = ScreenRecorderCompactMain.class.getPackage().getImplementationVersion();
if (version != null) {
int p = version.indexOf(' ');
setTitle(getTitle() + " " + version.substring(0, p == -1 ? version.length() : p));
}
final Preferences prefs = Preferences.userNodeForPackage(ScreenRecorderCompactMain.class);
if (System.getProperty("os.name").toLowerCase().startsWith("windows")) {
movieFolder = new File(System.getProperty("user.home") + File.separator + "Videos");
} else {
movieFolder = new File(System.getProperty("user.home") + File.separator + "Movies");
}
movieFolder = new File(prefs.get("ScreenRecorder.movieFolder", movieFolder.toString()));
Image img = Images.createImage(ScreenRecorderCompactMain.class, "images/Recorder.StartStop.png");
BufferedImage[] imgs = Images.split(img, 4, true);
startStopButton.setUI((ButtonUI) BasicButtonUI.createUI(startStopButton));
startStopButton.setIcon(new ImageIcon(imgs[0]));
startStopButton.setDisabledIcon(new ImageIcon(imgs[1]));
startStopButton.setSelectedIcon(new ImageIcon(imgs[2]));
startStopButton.setPressedIcon(new ImageIcon(imgs[3]));
startStopButton.setText(null);
startStopButton.setBorderPainted(false);
startStopButton.setOpaque(false);
startStopButton.setMargin(new Insets(0, 0, 0, 0));
startStopButton.setBorder(new EmptyBorder(2, 2, 2, 2));
img = Images.createImage(ScreenRecorderCompactMain.class, "images/Recorder.Options.png");
imgs = Images.split(img, 2, true);
optionsButton.setUI((ButtonUI) BasicButtonUI.createUI(startStopButton));
optionsButton.setIcon(new ImageIcon(imgs[0]));
optionsButton.setDisabledIcon(new ImageIcon(imgs[1]));
optionsButton.setText(null);
optionsButton.setBorderPainted(false);
optionsButton.setOpaque(false);
optionsButton.setMargin(new Insets(0, 0, 0, 0));
optionsButton.setBorder(new EmptyBorder(2, 2, 2, 2));
infoLabelText = infoLabel.getText();
updateInfoLabel();
/*
infoLabel.setMinimumSize(new Dimension(Math.max(200,infoLabel.getPreferredSize().width),infoLabel.getPreferredSize().height));
timeLabel.setMinimumSize(new Dimension(Math.max(200,timeLabel.getPreferredSize().width),timeLabel.getPreferredSize().height));
*/
new JLabelHyperlinkHandler(infoLabel, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
File f = new File(new URI(e.getActionCommand()));
if (!f.exists()) {
f.mkdirs();
}
Desktop.getDesktop().open(f);
} catch (URISyntaxException ex) {
System.err.println("ScreenRecorderMain bad href " + e.getActionCommand() + ", " + ex);
} catch (IOException ex) {
System.err.println("ScreenRecorderMain io exception: " + ex);
}
}
});
infoLabel.setTransferHandler(new DropFileTransferHandler(JFileChooser.DIRECTORIES_ONLY, null, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
movieFolder = new File(e.getActionCommand());
prefs.put("ScreenRecorder.movieFolder", movieFolder.toString());
updateInfoLabel();
}
}));
depth = min(max(0, prefs.getInt("ScreenRecording.colorDepth", 3)), colorGroup.getButtonCount() - 1);
setSelectedIndex(colorGroup, depth);
format = min(max(0, prefs.getInt("ScreenRecording.format", 1)), formatGroup.getButtonCount() - 1);
setSelectedIndex(formatGroup, format);
//encoding = min(max(0, prefs.getInt("ScreenRecording.encoding", 0)), encodingChoice.getItemCount() - 1);
//encodingChoice.setSelectedIndex(encoding);
cursor = min(max(0, prefs.getInt("ScreenRecording.cursor", 1)), cursorGroup.getButtonCount() - 1);
setSelectedIndex(cursorGroup, cursor);
fps = min(max(0, prefs.getInt("ScreenRecording.fps", 1)), fpsGroup.getButtonCount() - 1);
setSelectedIndex(fpsGroup, fps);
audioRate = min(max(0, prefs.getInt("ScreenRecording.audioRate", 1)), audioRateGroup.getButtonCount() - 1);
setSelectedIndex(audioRateGroup, audioRate);
channels = min(max(0, prefs.getInt("ScreenRecording.channels", 0)), channelsGroup.getButtonCount() - 1);
setSelectedIndex(channelsGroup, channels);
Dimension customDim = new Dimension(prefs.getInt("ScreenRecording.customAreaWidth", 1024),
prefs.getInt("ScreenRecording.customAreaHeight", 768));
Point customLoc = new Point(
prefs.getInt("ScreenRecording.customAreaX", 100),
prefs.getInt("ScreenRecording.customAreaY", 100));
customAreaRect = new Rectangle(customLoc.x, customLoc.y, customDim.width, customDim.height);
area = min(max(0, prefs.getInt("ScreenRecording.area", 0)), areaGroup.getButtonCount() - 1);
setSelectedIndex(areaGroup, area);
buildAudioSourceMenu();
//getRootPane().setDefaultButton(startStopButton);
pack();
}
private void updateInfoLabel() {
String name = movieFolder.getName();
if (name.length() > 16) {
name = name.substring(0, 14) + "...";
}
infoLabel.setText(infoLabelText.replaceAll("\"Movies\"", "<a href=\"" + movieFolder.toURI() + "\">" + name + "</a>"));
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
java.awt.GridBagConstraints gridBagConstraints;
optionsMenu = new javax.swing.JPopupMenu();
formatAviItem = new javax.swing.JRadioButtonMenuItem();
formatQuicktimeItem = new javax.swing.JRadioButtonMenuItem();
jSeparator4 = new javax.swing.JPopupMenu.Separator();
areaScreenItem = new javax.swing.JRadioButtonMenuItem();
areaCustomItem = new javax.swing.JRadioButtonMenuItem();
jSeparator1 = new javax.swing.JPopupMenu.Separator();
videoMenu = new javax.swing.JMenu();
colorMillionsItem = new javax.swing.JRadioButtonMenuItem();
colorThousandsItem = new javax.swing.JRadioButtonMenuItem();
jSeparator5 = new javax.swing.JPopupMenu.Separator();
fps20Item = new javax.swing.JRadioButtonMenuItem();
fps10Item = new javax.swing.JRadioButtonMenuItem();
jSeparator3 = new javax.swing.JPopupMenu.Separator();
cursorBlackItem = new javax.swing.JRadioButtonMenuItem();
cursorWhiteItem = new javax.swing.JRadioButtonMenuItem();
cursoYellowItem = new javax.swing.JRadioButtonMenuItem();
cursorNoneItem = new javax.swing.JRadioButtonMenuItem();
audioMenu = new javax.swing.JMenu();
jSeparator2 = new javax.swing.JPopupMenu.Separator();
audio44kHzItem = new javax.swing.JRadioButtonMenuItem();
audio22kHzItem = new javax.swing.JRadioButtonMenuItem();
jSeparator6 = new javax.swing.JPopupMenu.Separator();
monoItem = new javax.swing.JRadioButtonMenuItem();
stereoItem = new javax.swing.JRadioButtonMenuItem();
formatGroup = new javax.swing.ButtonGroup();
areaGroup = new javax.swing.ButtonGroup();
colorGroup = new javax.swing.ButtonGroup();
audioRateGroup = new javax.swing.ButtonGroup();
cursorGroup = new javax.swing.ButtonGroup();
fpsGroup = new javax.swing.ButtonGroup();
channelsGroup = new javax.swing.ButtonGroup();
audioSourceGroup = new javax.swing.ButtonGroup();
startStopButton = new javax.swing.JToggleButton();
timeLabel = new javax.swing.JLabel();
audioMonitor = new org.monte.screenrecorder.JAudioMonitor();
infoLabel = new javax.swing.JLabel();
optionsButton = new javax.swing.JButton();
FormListener formListener = new FormListener();
formatGroup.add(formatAviItem);
formatAviItem.setText("AVI");
optionsMenu.add(formatAviItem);
formatGroup.add(formatQuicktimeItem);
formatQuicktimeItem.setSelected(true);
formatQuicktimeItem.setText("QuickTime");
optionsMenu.add(formatQuicktimeItem);
optionsMenu.add(jSeparator4);
areaGroup.add(areaScreenItem);
areaScreenItem.setSelected(true);
areaScreenItem.setText("Entire Screen");
areaScreenItem.setActionCommand("Screen");
optionsMenu.add(areaScreenItem);
areaGroup.add(areaCustomItem);
areaCustomItem.setText("Custom Area...");
areaCustomItem.setActionCommand("Custom");
areaCustomItem.addActionListener(formListener);
optionsMenu.add(areaCustomItem);
optionsMenu.add(jSeparator1);
videoMenu.setText("Video");
colorGroup.add(colorMillionsItem);
colorMillionsItem.setSelected(true);
colorMillionsItem.setText("Millions of Colors");
colorMillionsItem.setActionCommand("Millions");
videoMenu.add(colorMillionsItem);
colorGroup.add(colorThousandsItem);
colorThousandsItem.setText("Thousands of Colors");
colorThousandsItem.setActionCommand("Thousands");
videoMenu.add(colorThousandsItem);
videoMenu.add(jSeparator5);
fpsGroup.add(fps20Item);
fps20Item.setSelected(true);
fps20Item.setText("20 FPS");
fps20Item.setActionCommand("20");
videoMenu.add(fps20Item);
fpsGroup.add(fps10Item);
fps10Item.setText("10 FPS");
fps10Item.setActionCommand("10");
videoMenu.add(fps10Item);
videoMenu.add(jSeparator3);
cursorGroup.add(cursorBlackItem);
cursorBlackItem.setSelected(true);
cursorBlackItem.setText("Black Cursor");
cursorBlackItem.setActionCommand("Black");
videoMenu.add(cursorBlackItem);
cursorGroup.add(cursorWhiteItem);
cursorWhiteItem.setText("White Cursor");
cursorWhiteItem.setActionCommand("White");
videoMenu.add(cursorWhiteItem);
cursorGroup.add(cursoYellowItem);
cursoYellowItem.setText("Yellow Cursor");
cursoYellowItem.setActionCommand("White");
videoMenu.add(cursoYellowItem);
cursorGroup.add(cursorNoneItem);
cursorNoneItem.setText("No Cursor");
cursorNoneItem.setActionCommand("None");
videoMenu.add(cursorNoneItem);
optionsMenu.add(videoMenu);
audioMenu.setText("Audio");
audioMenu.add(jSeparator2);
audioRateGroup.add(audio44kHzItem);
audio44kHzItem.setSelected(true);
audio44kHzItem.setText("44.100 Hz Audio");
audio44kHzItem.setActionCommand("44100");
audioMenu.add(audio44kHzItem);
audioRateGroup.add(audio22kHzItem);
audio22kHzItem.setText("22.050 Hz Audio");
audio22kHzItem.setActionCommand("22050");
audioMenu.add(audio22kHzItem);
audioMenu.add(jSeparator6);
channelsGroup.add(monoItem);
monoItem.setSelected(true);
monoItem.setText("Mono");
monoItem.setActionCommand("44100");
audioMenu.add(monoItem);
channelsGroup.add(stereoItem);
stereoItem.setText("Stereo");
stereoItem.setActionCommand("22050");
audioMenu.add(stereoItem);
optionsMenu.add(audioMenu);
setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE);
setTitle("MonteMedia");
setResizable(false);
addWindowListener(formListener);
getContentPane().setLayout(new java.awt.GridBagLayout());
startStopButton.setText("Start");
startStopButton.setToolTipText("<html><font size=\"9px\">Starts/Stops a screen recording.<br>\nThis window will be minimized before the recording starts.<br>\nTo stop the recording, restore this window, and press this button again.");
startStopButton.addActionListener(formListener);
getContentPane().add(startStopButton, new java.awt.GridBagConstraints());
timeLabel.setFont(new java.awt.Font("Dialog", 0, 11)); // NOI18N
timeLabel.setForeground(new java.awt.Color(255, 255, 255));
timeLabel.setText("<html>--:--");
timeLabel.setToolTipText("<html><font size=\"9px\">Recording time.<br>\nShows recorded minutes and seconds when the recorder is running.");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
gridBagConstraints.insets = new java.awt.Insets(0, 6, 0, 0);
getContentPane().add(timeLabel, gridBagConstraints);
audioMonitor.setForeground(new java.awt.Color(255, 255, 255));
audioMonitor.setFont(new java.awt.Font("Dialog", 0, 11)); // NOI18N
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.insets = new java.awt.Insets(0, 10, 0, 0);
getContentPane().add(audioMonitor, gridBagConstraints);
infoLabel.setFont(new java.awt.Font("Dialog", 0, 11)); // NOI18N
infoLabel.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
infoLabel.setText("<html><font color=\"ffffff\">Into \"Movies\"</font>");
infoLabel.setToolTipText("<html><font size=\"9px\">Storage location of the screen recordings.<br>\nTo view the recorded files, click on the link.<br>\nTo change the storage location, drop a folder on the link.\n");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.insets = new java.awt.Insets(0, 10, 0, 0);
getContentPane().add(infoLabel, gridBagConstraints);
optionsButton.setText("Options");
optionsButton.addActionListener(formListener);
getContentPane().add(optionsButton, new java.awt.GridBagConstraints());
pack();
}
// Code for dispatching events from components to event handlers.
private class FormListener implements java.awt.event.ActionListener, java.awt.event.WindowListener {
FormListener() {}
public void actionPerformed(java.awt.event.ActionEvent evt) {
if (evt.getSource() == startStopButton) {
ScreenRecorderCompactMain.this.startStopPerformed(evt);
}
else if (evt.getSource() == optionsButton) {
ScreenRecorderCompactMain.this.optionsPerformed(evt);
}
else if (evt.getSource() == areaCustomItem) {
ScreenRecorderCompactMain.this.selectAreaPerformed(evt);
}
}
public void windowActivated(java.awt.event.WindowEvent evt) {
}
public void windowClosed(java.awt.event.WindowEvent evt) {
}
public void windowClosing(java.awt.event.WindowEvent evt) {
if (evt.getSource() == ScreenRecorderCompactMain.this) {
ScreenRecorderCompactMain.this.formWindowClosing(evt);
}
}
public void windowDeactivated(java.awt.event.WindowEvent evt) {
}
public void windowDeiconified(java.awt.event.WindowEvent evt) {
if (evt.getSource() == ScreenRecorderCompactMain.this) {
ScreenRecorderCompactMain.this.formWindowDeiconified(evt);
}
}
public void windowIconified(java.awt.event.WindowEvent evt) {
}
public void windowOpened(java.awt.event.WindowEvent evt) {
}
}// </editor-fold>//GEN-END:initComponents
private void updateValues() {
Preferences prefs = Preferences.userNodeForPackage(ScreenRecorderCompactMain.class);
format = getSelectedIndex(formatGroup);
prefs.putInt("ScreenRecording.format", format);
//encoding = encodingChoice.getSelectedIndex();
//prefs.putInt("ScreenRecording.encoding", encoding);
depth = getSelectedIndex(colorGroup);
prefs.putInt("ScreenRecording.colorDepth", depth);
cursor = getSelectedIndex(cursorGroup);
prefs.putInt("ScreenRecording.cursor", cursor);
audioRate = getSelectedIndex(audioRateGroup);
prefs.putInt("ScreenRecording.audioRate", audioRate);
audioSource = getSelectedIndex(audioSourceGroup);
prefs.putInt("ScreenRecording.audioSource", audioSource);
channels = getSelectedIndex(channelsGroup);
prefs.putInt("ScreenRecording.channels", channels);
area = getSelectedIndex(areaGroup);
prefs.putInt("ScreenRecording.area", area);
fps = getSelectedIndex(fpsGroup);
prefs.putInt("ScreenRecording.fps", fps);
prefs.putInt("ScreenRecording.customAreaX", customAreaRect.x);
prefs.putInt("ScreenRecording.customAreaY", customAreaRect.y);
prefs.putInt("ScreenRecording.customAreaWidth", customAreaRect.width);
prefs.putInt("ScreenRecording.customAreaHeight", customAreaRect.height);
}
private void start() throws IOException, AWTException {
updateValues();
if (screenRecorder == null) {
setSettingsEnabled(false);
//timeLabel.setForeground(Color.RED);
//timeLabel.setText("Recording...");
String mimeType;
String videoFormatName, compressorName;
float quality = 1.0f;
int bitDepth;
switch (depth) {
default:
case 0:
bitDepth = 24;
break;
case 1:
bitDepth = 16;
break;
case 2:
bitDepth = 24;
break;
}
switch (format) {
default:
case 0:
mimeType = MIME_AVI;
videoFormatName = ENCODING_AVI_TECHSMITH_SCREEN_CAPTURE;
compressorName = COMPRESSOR_NAME_AVI_TECHSMITH_SCREEN_CAPTURE;
break;
case 1:
mimeType = MIME_QUICKTIME;
videoFormatName = ENCODING_AVI_TECHSMITH_SCREEN_CAPTURE;
compressorName = COMPRESSOR_NAME_AVI_TECHSMITH_SCREEN_CAPTURE;
break;
}
int audioRate;
int audioBitsPerSample;
int audioChannels;
AudioSourceItem asi = (AudioSourceItem) getSelectedItem(audioSourceGroup).getClientProperty("AudioSourceItem");
switch (this.audioRate) {
default:
case 0:
audioRate = 44100;
audioBitsPerSample = 16;
break;
case 1:
audioRate = 22050;
audioBitsPerSample = 8;
break;
case 2:
audioRate = 0;
audioBitsPerSample = 0;
break;
}
switch (channels) {
default:
case 0:
audioChannels = 1;
break;
case 1:
audioChannels = 2;
break;
}
String crsr;
int mouseRate;
switch (cursor) {
default:
case 3:
crsr = null;
mouseRate = 0;
break;
case 0:
crsr = ScreenRecorder.ENCODING_BLACK_CURSOR;
mouseRate = 30;
break;
case 1:
crsr = ScreenRecorder.ENCODING_WHITE_CURSOR;
mouseRate = 30;
break;
case 2:
crsr = ScreenRecorder.ENCODING_YELLOW_CURSOR;
mouseRate = 30;
break;
}
GraphicsConfiguration cfg = getGraphicsConfiguration();
Rectangle areaRect = null;
Dimension outputDimension = null;
switch (area) {
default:
case 0:
areaRect = cfg.getBounds();
break;
case 1:
areaRect = customAreaRect.getBounds();
break;
}
outputDimension = areaRect.getSize();
int screenRate;
switch (fps) {
default:
case 0:
screenRate = 20;
break;
case 1:
screenRate = 10;
break;
}
screenRecorder = new ScreenRecorder(cfg, areaRect,
// the file format:
new Format(MediaTypeKey, MediaType.FILE, MimeTypeKey, mimeType),
//
// the output format for screen capture:
new Format(MediaTypeKey, MediaType.VIDEO, EncodingKey, videoFormatName,
CompressorNameKey, compressorName,
WidthKey, outputDimension.width,
HeightKey, outputDimension.height,
DepthKey, bitDepth, FrameRateKey, Rational.valueOf(screenRate),
QualityKey, quality,
KeyFrameIntervalKey, (int) (screenRate * 60) // one keyframe per minute is enough
),
//
// the output format for mouse capture:
crsr == null ? null : new Format(MediaTypeKey, MediaType.VIDEO, EncodingKey, crsr,
FrameRateKey, Rational.valueOf(mouseRate)),
//
// the output format for audio capture:
!asi.isEnabled ? null : new Format(MediaTypeKey, MediaType.AUDIO,
//EncodingKey, audioFormatName,
SampleRateKey, Rational.valueOf(audioRate),
SampleSizeInBitsKey, audioBitsPerSample,
ChannelsKey, audioChannels),
//
// the storage location of the movie
movieFolder);
screenRecorder.setAudioMixer(asi.mixerInfo == null ? null : AudioSystem.getMixer(asi.mixerInfo));
System.out.println("mxier:" + asi);
System.out.println("screenRecoder.mixer=" + screenRecorder.getAudioMixer());
if (timer == null) {
timer = new Timer(500, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
updateTimeLabel();
}
});
timer.setRepeats(true);
timer.start();
}
//startStopButton.setText("Stop");
screenRecorder.addChangeListener(handler);
screenRecorder.start();
audioMonitor.setScreenRecorder(screenRecorder);
audioMonitor.start();
}
}
private void updateTimeLabel() {
if (screenRecorder != null) {
long t = System.currentTimeMillis() - screenRecorder.getStartTime();
long h = t / (1000 * 3600);
long m = t / (1000 * 60) - (h * 60);
long s = t / (1000) - (h * 3600 + m * 60);
timeLabel.setText((h == 0 ? "" : (h < 10 ? "0" + h : h) + ":") + (m < 10 ? "0" + m : m) + ":" + ((s < 10 ? "0" + s : s)));
}
}
public void setSettingsEnabled(boolean b) {
for (MenuElement c : optionsMenu.getSubElements()) {
if (c instanceof JComponent) {
((JComponent) c).setEnabled(b);
}
}
}
private void stop() {
if (screenRecorder != null) {
audioMonitor.setScreenRecorder(null);
audioMonitor.stop();
final ScreenRecorder r = screenRecorder;
startStopButton.setEnabled(false);
if (timer != null) {
timer.stop();
timer = null;
}
timeLabel.setText("Stopping...");
screenRecorder = null;
new Worker() {
@Override
protected Object construct() throws Exception {
r.stop();
return null;
}
@Override
protected void finished() {
ScreenRecorder.State state = r.getState();
setSettingsEnabled(true);
startStopButton.setEnabled(true);
//startStopButton.setText("Start");
timeLabel.setText("--:--");
}
}.start();
}
}
private void recordingFailed(String msg) {
if (screenRecorder != null) {
screenRecorder = null;
startStopButton.setEnabled(true);
//startStopButton.setText("Start");
timeLabel.setText("Failed");
setExtendedState(Frame.NORMAL);
JOptionPane.showMessageDialog(ScreenRecorderCompactMain.this,
"<html><b>Sorry. Screen Recording failed.</b><br>"+msg.replace("\n","<br>"),
"Screen Recorder", JOptionPane.ERROR_MESSAGE);
}
}
private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing
stop();
setVisible(false);
System.exit(0);
}//GEN-LAST:event_formWindowClosing
private void formWindowDeiconified(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowDeiconified
// stop();
}//GEN-LAST:event_formWindowDeiconified
private void selectAreaPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_selectAreaPerformed
final JRecordingAreaFrame f = new JRecordingAreaFrame();
Rectangle r = customAreaRect;
f.setBounds(r);
f.updateLabel();
f.addWindowListener(new WindowAdapter() {
@Override
public void windowClosed(WindowEvent e) {
customAreaRect = f.getBounds();
f.setVisible(false);
f.dispose();
setVisible(true);
f.removeWindowListener(this);
final Preferences prefs = Preferences.userNodeForPackage(ScreenRecorderMain.class);
prefs.putInt("ScreenRecorder.customAreaX", customAreaRect.x);
prefs.putInt("ScreenRecorder.customAreaY", customAreaRect.y);
prefs.putInt("ScreenRecorder.customAreaWidth", customAreaRect.width);
prefs.putInt("ScreenRecorder.customAreaHeight", customAreaRect.height);
((JComponent) getContentPane()).invalidate();
((JComponent) getContentPane()).revalidate();
}
});
setVisible(false);
f.setVisible(true);
}//GEN-LAST:event_selectAreaPerformed
private void optionsPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_optionsPerformed
optionsMenu.show(optionsButton, 0, optionsButton.getHeight());
}//GEN-LAST:event_optionsPerformed
private void startStopPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_startStopPerformed
if (screenRecorder == null) {
setExtendedState(Frame.ICONIFIED);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
start();
} catch (Throwable t) {
t.printStackTrace();
setExtendedState(Frame.NORMAL);
JOptionPane.showMessageDialog(ScreenRecorderCompactMain.this,
"<html><b>Sorry. Screen Recording failed.</b><br>" + t.getMessage(),
"Screen Recorder", JOptionPane.ERROR_MESSAGE);
stop();
}
}
});
} else {
stop();
}
}//GEN-LAST:event_startStopPerformed
private static Vector<AudioSourceItem> getAudioSources() {
Vector<AudioSourceItem> l = new Vector<AudioSourceItem>();
l.add(new AudioSourceItem("None", null, false));
l.add(new AudioSourceItem("Default Input", null, true));
Mixer.Info[] mixers = AudioSystem.getMixerInfo();
DataLine.Info lineInfo = new DataLine.Info(
TargetDataLine.class,
new javax.sound.sampled.AudioFormat(
44100.0f,
16,
2,
true,
true));
for (Mixer.Info info : mixers) {
Mixer mixer = AudioSystem.getMixer(info);
if (mixer.isLineSupported(lineInfo)) {
l.add(new AudioSourceItem(info.getName(), info));
}
}
return l;
}
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
//UIManager.put(area, area);
ToolTipManager.sharedInstance().setDismissDelay(20000);
} catch (Exception e) {
//ignore
}
new ScreenRecorderCompactMain().setVisible(true);
}
});
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JRadioButtonMenuItem areaCustomItem;
private javax.swing.ButtonGroup areaGroup;
private javax.swing.JRadioButtonMenuItem areaScreenItem;
private javax.swing.JRadioButtonMenuItem audio22kHzItem;
private javax.swing.JRadioButtonMenuItem audio44kHzItem;
private javax.swing.JMenu audioMenu;
private org.monte.screenrecorder.JAudioMonitor audioMonitor;
private javax.swing.ButtonGroup audioRateGroup;
private javax.swing.ButtonGroup audioSourceGroup;
private javax.swing.ButtonGroup channelsGroup;
private javax.swing.ButtonGroup colorGroup;
private javax.swing.JRadioButtonMenuItem colorMillionsItem;
private javax.swing.JRadioButtonMenuItem colorThousandsItem;
private javax.swing.JRadioButtonMenuItem cursoYellowItem;
private javax.swing.JRadioButtonMenuItem cursorBlackItem;
private javax.swing.ButtonGroup cursorGroup;
private javax.swing.JRadioButtonMenuItem cursorNoneItem;
private javax.swing.JRadioButtonMenuItem cursorWhiteItem;
private javax.swing.JRadioButtonMenuItem formatAviItem;
private javax.swing.ButtonGroup formatGroup;
private javax.swing.JRadioButtonMenuItem formatQuicktimeItem;
private javax.swing.JRadioButtonMenuItem fps10Item;
private javax.swing.JRadioButtonMenuItem fps20Item;
private javax.swing.ButtonGroup fpsGroup;
private javax.swing.JLabel infoLabel;
private javax.swing.JPopupMenu.Separator jSeparator1;
private javax.swing.JPopupMenu.Separator jSeparator2;
private javax.swing.JPopupMenu.Separator jSeparator3;
private javax.swing.JPopupMenu.Separator jSeparator4;
private javax.swing.JPopupMenu.Separator jSeparator5;
private javax.swing.JPopupMenu.Separator jSeparator6;
private javax.swing.JRadioButtonMenuItem monoItem;
private javax.swing.JButton optionsButton;
private javax.swing.JPopupMenu optionsMenu;
private javax.swing.JToggleButton startStopButton;
private javax.swing.JRadioButtonMenuItem stereoItem;
private javax.swing.JLabel timeLabel;
private javax.swing.JMenu videoMenu;
// End of variables declaration//GEN-END:variables
}