2
* Copyright (C) 2016 patrick
4
* This program 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 3 of the License, or
7
* (at your option) any later version.
9
* This program 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.
14
* You should have received a copy of the GNU General Public License
15
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17
package screenstudio.gui;
19
import java.awt.AWTException;
20
import java.awt.BorderLayout;
21
import java.awt.Rectangle;
22
import java.awt.SystemTray;
23
import java.awt.TrayIcon;
24
import java.awt.event.ActionEvent;
26
import java.io.IOException;
27
import java.util.List;
28
import java.util.logging.Level;
29
import java.util.logging.Logger;
30
import java.util.prefs.BackingStoreException;
31
import javax.swing.DefaultComboBoxModel;
32
import javax.swing.ImageIcon;
33
import javax.swing.JFileChooser;
34
import javax.swing.JFrame;
35
import javax.swing.JMenuItem;
36
import javax.swing.ToolTipManager;
37
import javax.swing.filechooser.FileFilter;
38
import javax.swing.table.DefaultTableModel;
39
import javax.xml.parsers.ParserConfigurationException;
40
import org.xml.sax.SAXException;
41
import screenstudio.Version;
42
import screenstudio.encoder.FFMpeg;
43
import screenstudio.panel.editor.Editor;
44
import screenstudio.sources.Compositor;
45
import screenstudio.sources.Microphone;
46
import screenstudio.sources.Screen;
47
import screenstudio.sources.Source;
48
import screenstudio.sources.Webcam;
49
import screenstudio.targets.Layout;
50
import screenstudio.targets.Layout.SourceType;
56
public class ScreenStudio extends javax.swing.JFrame {
58
private final SourceLayoutPreview mLayoutPreview;
59
private FFMpeg mFFMpeg = null;
60
private File mVideoOutputFolder = new File(System.getProperty("user.home"));
61
private long mRecordingTimestamp = 0;
62
private java.awt.TrayIcon trayIcon;
65
* Creates new form MainVersion3
67
public ScreenStudio() {
69
this.setIconImage(new ImageIcon(ScreenStudio.class.getResource("/screenstudio/gui/images/icon.png")).getImage());
71
mLayoutPreview = new SourceLayoutPreview(tableSources);
72
mLayoutPreview.setOutputWidth((Integer) spinWidth.getValue());
73
mLayoutPreview.setOutputHeight((Integer) spinHeight.getValue());
74
panPreviewLayout.add(mLayoutPreview, BorderLayout.CENTER);
75
this.setTitle("ScreenStudio " + screenstudio.Version.MAIN);
76
this.setSize(700, 400);
77
ToolTipManager.sharedInstance().setDismissDelay(8000);
78
ToolTipManager.sharedInstance().setInitialDelay(2000);
80
if (Version.hasNewVersion()) {
81
lblMessages.setText("A new version is available...");
86
private void initControls() {
87
DefaultTableModel model = (DefaultTableModel) tableSources.getModel();
88
while (model.getRowCount() > 0) {
91
cboTarget.setModel(new DefaultComboBoxModel<>(FFMpeg.FORMATS.values()));
92
cboTarget.setSelectedIndex(0);
93
cboVideoPresets.setModel(new DefaultComboBoxModel<>(FFMpeg.Presets.values()));
94
cboAudioBitrate.setModel(new DefaultComboBoxModel<>(FFMpeg.AudioRate.values()));
95
cboRTMPServers.setModel(new DefaultComboBoxModel<>());
96
txtRTMPKey.setText((""));
98
cboAudioMicrophones.setModel(new DefaultComboBoxModel());
99
cboAudioSystems.setModel(new DefaultComboBoxModel());
100
cboAudioMicrophones.addItem(new Microphone());
101
cboAudioSystems.addItem(new Microphone());
102
for (Microphone o : Microphone.getSources()) {
103
if (o.getDescription().toLowerCase().contains("monitor")) {
104
cboAudioSystems.addItem(o);
106
cboAudioMicrophones.addItem(o);
109
} catch (IOException | InterruptedException ex) {
112
setRTMPControls((FFMpeg.FORMATS) cboTarget.getSelectedItem());
113
int defaultWidth = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDisplayMode().getWidth();
114
int defaultHeight = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDisplayMode().getHeight();
115
spinWidth.setValue(defaultWidth);
116
spinHeight.setValue(defaultHeight);
117
lblVideoFolder.setText(mVideoOutputFolder.getAbsolutePath());
118
lblVideoFolder.setToolTipText(mVideoOutputFolder.getAbsolutePath());
120
updateMenuDesktops();
122
java.util.prefs.Preferences p = java.util.prefs.Preferences.userRoot().node("screenstudio");
123
spinAudioDelay.setValue(p.getFloat("audiodelay", 0));
125
if (SystemTray.isSupported()) {
126
trayIcon = new TrayIcon(this.getIconImage(), "ScreenStudio: Double-click to activate recording...");
127
if (Screen.isOSX()) {
128
trayIcon.setToolTip("ScreenStudio: CTRL-Click to activate recording...");
130
trayIcon.setImageAutoSize(true);
131
trayIcon.addActionListener((ActionEvent e) -> {
132
mnuCapture.doClick();
135
SystemTray.getSystemTray().add(trayIcon);
136
} catch (AWTException ex) {
137
Logger.getLogger(ScreenStudio.class.getName()).log(Level.SEVERE, null, ex);
146
private void updateControls(boolean enabled) {
148
cboTarget.setEnabled(enabled);
149
cboVideoPresets.setEnabled(enabled);
150
cboAudioBitrate.setEnabled(enabled);
151
cboRTMPServers.setEnabled(enabled);
152
txtRTMPKey.setEnabled(enabled);
153
cboAudioMicrophones.setEnabled(enabled);
154
cboAudioSystems.setEnabled(enabled);
155
cboAudioMicrophones.setEnabled(enabled);
156
cboAudioSystems.setEnabled(enabled);
157
txtRTMPKey.setEnabled(enabled);
158
cboRTMPServers.setEnabled(enabled);
159
spinWidth.setEnabled(enabled);
160
spinHeight.setEnabled(enabled);
161
numVideoBitrate.setEnabled(enabled);
162
spinFPS.setEnabled(enabled);
163
btnSetVideoFolder.setEnabled(enabled);
164
mnuFileLoad.setEnabled(enabled);
165
mnuFileSave.setEnabled(enabled);
168
private void loadLayout(File file) {
169
Layout layout = new Layout();
172
cboAudioBitrate.setSelectedItem(layout.getAudioBitrate());
173
for (int i = 0; i < cboAudioMicrophones.getItemCount(); i++) {
174
if (cboAudioMicrophones.getItemAt(i).getDescription().equals(layout.getAudioMicrophone())) {
175
cboAudioMicrophones.setSelectedIndex(i);
179
for (int i = 0; i < cboAudioSystems.getItemCount(); i++) {
180
if (cboAudioSystems.getItemAt(i).getDescription().equals(layout.getAudioSystem())) {
181
cboAudioSystems.setSelectedIndex(i);
185
spinFPS.setValue(layout.getOutputFramerate());
186
spinHeight.setValue(layout.getOutputHeight());
187
cboVideoPresets.setSelectedItem(layout.getOutputPreset());
188
cboTarget.setSelectedItem(layout.getOutputTarget());
189
txtRTMPKey.setText(layout.getOutputRTMPKey());
190
cboRTMPServers.setSelectedItem(layout.getOutputRTMPServer());
191
mVideoOutputFolder = layout.getOutputVideoFolder();
192
lblVideoFolder.setText(mVideoOutputFolder.getAbsolutePath());
193
lblVideoFolder.setToolTipText(mVideoOutputFolder.getAbsolutePath());
194
spinWidth.setValue(layout.getOutputWidth());
195
numVideoBitrate.setValue(layout.getVideoBitrate());
198
DefaultTableModel model = (DefaultTableModel) tableSources.getModel();
199
while (model.getRowCount() > 0) {
202
Screen[] screens = Screen.getSources();
203
Webcam[] webcams = Webcam.getSources();
204
for (screenstudio.targets.Source s : layout.getSources()) {
205
Object[] row = new Object[model.getColumnCount()];
208
row[2] = "Not found!";
217
for (Screen screen : screens) {
218
if (screen.getLabel().equals(s.ID)) {
226
row[2] = new File(s.ID);
227
row[0] = new File(s.ID).exists();
230
row[2] = new File(s.ID);
231
row[0] = new File(s.ID).exists();
234
LabelText t = new LabelText(s.ID);
235
t.setForegroundColor(s.foregroundColor);
236
t.setBackgroundColor(s.backgroundColor);
237
t.setFontName(s.fontName);
238
System.out.println("Font: " + s.fontName);
245
row[2] = new File(s.ID);
246
row[0] = new File(s.ID).exists();
250
for (Webcam webcam : webcams) {
251
if (webcam.getDevice().equals(s.ID)) {
261
} catch (IOException | ParserConfigurationException | SAXException | InterruptedException ex) {
262
Logger.getLogger(ScreenStudio.class.getName()).log(Level.SEVERE, null, ex);
265
panPreviewLayout.repaint();
268
private void saveLayout(File file) {
269
Layout layout = new Layout();
270
layout.setAudioBitrate(cboAudioBitrate.getItemAt(cboAudioBitrate.getSelectedIndex()));
271
layout.setAudioMicrophone(cboAudioMicrophones.getItemAt(cboAudioMicrophones.getSelectedIndex()).getDescription());
272
layout.setAudioSystem(cboAudioSystems.getItemAt(cboAudioSystems.getSelectedIndex()).getDescription());
273
layout.setOutputFramerate((Integer) spinFPS.getValue());
274
layout.setOutputHeight((Integer) spinHeight.getValue());
275
layout.setOutputPreset(cboVideoPresets.getItemAt(cboVideoPresets.getSelectedIndex()));
276
layout.setOutputRTMPKey(txtRTMPKey.getText());
277
if (cboRTMPServers.getSelectedIndex() != -1) {
278
layout.setOutputRTMPServer(cboRTMPServers.getSelectedItem().toString());
280
layout.setOutputRTMPServer("");
282
layout.setOutputTarget(cboTarget.getItemAt(cboTarget.getSelectedIndex()));
283
layout.setOutputVideoFolder(mVideoOutputFolder);
284
layout.setOutputWith((Integer) spinWidth.getValue());
285
layout.setVideoBitrate((Integer) numVideoBitrate.getValue());
287
List<Source> sources = Compositor.getSources(tableSources, (Integer) spinFPS.getValue());
288
for (Source s : sources) {
289
layout.addSource(s.getType(), s.getID(), s.getBounds().x, s.getBounds().y, s.getBounds().width, s.getBounds().height, s.getAlpha().getAlpha(), s.getZOrder(), s.getForeground(), s.getBackground(),s.getFontName());
293
} catch (Exception ex) {
294
Logger.getLogger(ScreenStudio.class.getName()).log(Level.SEVERE, null, ex);
298
private void setRTMPControls(FFMpeg.FORMATS value) {
306
cboRTMPServers.setModel(new DefaultComboBoxModel());
307
txtRTMPKey.setText((""));
308
cboRTMPServers.setVisible(false);
309
txtRTMPKey.setVisible(false);
310
lblRTMPKey.setVisible(false);
311
lblRTMPServer.setVisible(false);
319
cboRTMPServers.setModel(new DefaultComboBoxModel(FFMpeg.getServerList(value)));
320
txtRTMPKey.setText((""));
321
cboRTMPServers.setVisible(true);
322
txtRTMPKey.setVisible(true);
323
lblRTMPKey.setVisible(true);
324
lblRTMPServer.setVisible(true);
330
private void updateMenuWebcams() {
332
mnuMainWebcams.removeAll();
334
for (Webcam w : Webcam.getSources()) {
335
JMenuItem menu = new JMenuItem(w.getDescription());
336
menu.setActionCommand(w.getDevice());
337
menu.setToolTipText("Device: " + w.getDevice());
338
menu.addActionListener((ActionEvent e) -> {
339
DefaultTableModel model = (DefaultTableModel) tableSources.getModel();
340
Object[] row = new Object[model.getColumnCount()];
342
for (Webcam webcam : Webcam.getSources()) {
343
if (webcam.getDevice().equals(e.getActionCommand())) {
345
row[1] = SourceType.Webcam;
349
row[5] = webcam.getWidth();
350
row[6] = webcam.getHeight();
353
mLayoutPreview.repaint();
354
tabs.setSelectedComponent(panSources);
359
} catch (IOException | InterruptedException ex) {
360
Logger.getLogger(ScreenStudio.class.getName()).log(Level.SEVERE, null, ex);
364
mnuMainWebcams.add(menu);
366
} catch (IOException | InterruptedException ex) {
367
Logger.getLogger(ScreenStudio.class.getName()).log(Level.SEVERE, null, ex);
371
private void updateMenuDesktops() {
373
mnuMainDestops.removeAll();
375
for (Screen s : Screen.getSources()) {
376
JMenuItem menu = new JMenuItem(s.getDetailledLabel());
377
menu.setActionCommand(s.getLabel());
378
menu.setToolTipText("Size: " + s.getDetailledLabel());
379
menu.addActionListener((ActionEvent e) -> {
380
DefaultTableModel model = (DefaultTableModel) tableSources.getModel();
381
Object[] row = new Object[model.getColumnCount()];
383
for (Screen screen : Screen.getSources()) {
384
if (screen.getLabel().equals(e.getActionCommand())) {
386
row[1] = SourceType.Desktop;
390
row[5] = screen.getWidth();
391
row[6] = screen.getHeight();
394
mLayoutPreview.repaint();
395
tabs.setSelectedComponent(panSources);
400
} catch (IOException | InterruptedException ex) {
401
Logger.getLogger(ScreenStudio.class.getName()).log(Level.SEVERE, null, ex);
405
mnuMainDestops.add(menu);
407
} catch (IOException | InterruptedException ex) {
408
Logger.getLogger(ScreenStudio.class.getName()).log(Level.SEVERE, null, ex);
413
* This method is called from within the constructor to initialize the form.
414
* WARNING: Do NOT modify this code. The content of this method is always
415
* regenerated by the Form Editor.
417
@SuppressWarnings("unchecked")
418
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
419
private void initComponents() {
421
tabs = new javax.swing.JTabbedPane();
422
panOutput = new javax.swing.JPanel();
423
jLabel1 = new javax.swing.JLabel();
424
spinWidth = new javax.swing.JSpinner();
425
spinHeight = new javax.swing.JSpinner();
426
jLabel2 = new javax.swing.JLabel();
427
jLabel3 = new javax.swing.JLabel();
428
spinFPS = new javax.swing.JSpinner();
429
jLabel4 = new javax.swing.JLabel();
430
cboTarget = new javax.swing.JComboBox<>();
431
panTargetSettings = new javax.swing.JPanel();
432
jLabel5 = new javax.swing.JLabel();
433
jLabel6 = new javax.swing.JLabel();
434
jLabel7 = new javax.swing.JLabel();
435
lblRTMPServer = new javax.swing.JLabel();
436
lblRTMPKey = new javax.swing.JLabel();
437
numVideoBitrate = new javax.swing.JSpinner();
438
cboVideoPresets = new javax.swing.JComboBox<>();
439
cboAudioBitrate = new javax.swing.JComboBox<>();
440
cboRTMPServers = new javax.swing.JComboBox<>();
441
txtRTMPKey = new javax.swing.JTextField();
442
panSources = new javax.swing.JPanel();
443
jSplitPane1 = new javax.swing.JSplitPane();
444
panPreviewLayout = new javax.swing.JPanel();
445
scrollSources = new javax.swing.JScrollPane();
446
tableSources = new javax.swing.JTable();
447
panOptions = new javax.swing.JPanel();
448
panSettingsAudios = new javax.swing.JPanel();
449
jLabel8 = new javax.swing.JLabel();
450
jLabel9 = new javax.swing.JLabel();
451
cboAudioMicrophones = new javax.swing.JComboBox<>();
452
cboAudioSystems = new javax.swing.JComboBox<>();
453
jLabel10 = new javax.swing.JLabel();
454
spinAudioDelay = new javax.swing.JSpinner();
455
panSettingsVideos = new javax.swing.JPanel();
456
lblVideoFolder = new javax.swing.JLabel();
457
btnSetVideoFolder = new javax.swing.JButton();
458
panSettingsMisc = new javax.swing.JPanel();
459
chkStayVisible = new javax.swing.JCheckBox();
460
panStatus = new javax.swing.JPanel();
461
lblMessages = new javax.swing.JLabel();
462
menuBar = new javax.swing.JMenuBar();
463
mnuFile = new javax.swing.JMenu();
464
mnuCapture = new javax.swing.JMenuItem();
465
jSeparator1 = new javax.swing.JPopupMenu.Separator();
466
mnuFileLoad = new javax.swing.JMenuItem();
467
mnuFileSave = new javax.swing.JMenuItem();
468
mnuEdit = new javax.swing.JMenu();
469
mnuMainWebcams = new javax.swing.JMenu();
470
mnuMainDestops = new javax.swing.JMenu();
471
mnuMainAddImage = new javax.swing.JMenuItem();
472
mnuMainAddLabel = new javax.swing.JMenuItem();
473
jSeparator3 = new javax.swing.JPopupMenu.Separator();
474
mnuMainMoveUp = new javax.swing.JMenuItem();
475
mnuMainMoveDown = new javax.swing.JMenuItem();
476
jSeparator2 = new javax.swing.JPopupMenu.Separator();
477
mnuMainRemove = new javax.swing.JMenuItem();
479
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
480
setTitle("ScreenStudio");
481
addWindowStateListener(new java.awt.event.WindowStateListener() {
482
public void windowStateChanged(java.awt.event.WindowEvent evt) {
483
formWindowStateChanged(evt);
486
addWindowListener(new java.awt.event.WindowAdapter() {
487
public void windowClosing(java.awt.event.WindowEvent evt) {
488
formWindowClosing(evt);
492
jLabel1.setText("Output Format");
494
spinWidth.setModel(new javax.swing.SpinnerNumberModel(720, 640, 1920, 1));
495
spinWidth.addChangeListener(new javax.swing.event.ChangeListener() {
496
public void stateChanged(javax.swing.event.ChangeEvent evt) {
497
spinWidthStateChanged(evt);
501
spinHeight.setModel(new javax.swing.SpinnerNumberModel(480, 240, 1080, 1));
502
spinHeight.addChangeListener(new javax.swing.event.ChangeListener() {
503
public void stateChanged(javax.swing.event.ChangeEvent evt) {
504
spinHeightStateChanged(evt);
508
jLabel2.setText("X");
510
jLabel3.setText("Framerate");
512
spinFPS.setModel(new javax.swing.SpinnerNumberModel(10, 5, 30, 1));
514
jLabel4.setText("Target");
516
cboTarget.addActionListener(new java.awt.event.ActionListener() {
517
public void actionPerformed(java.awt.event.ActionEvent evt) {
518
cboTargetActionPerformed(evt);
522
panTargetSettings.setBorder(javax.swing.BorderFactory.createTitledBorder("Settings"));
524
jLabel5.setText("Video Bitrate");
526
jLabel6.setText("Video Preset");
528
jLabel7.setText("Audio Bitrate");
530
lblRTMPServer.setText("RTMP Server");
532
lblRTMPKey.setText("RTMP Secret Key");
534
numVideoBitrate.setModel(new javax.swing.SpinnerNumberModel(1000, 300, 9000, 100));
536
javax.swing.GroupLayout panTargetSettingsLayout = new javax.swing.GroupLayout(panTargetSettings);
537
panTargetSettings.setLayout(panTargetSettingsLayout);
538
panTargetSettingsLayout.setHorizontalGroup(
539
panTargetSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
540
.addGroup(panTargetSettingsLayout.createSequentialGroup()
542
.addGroup(panTargetSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
543
.addGroup(panTargetSettingsLayout.createSequentialGroup()
544
.addGroup(panTargetSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
545
.addComponent(jLabel7, javax.swing.GroupLayout.DEFAULT_SIZE, 128, Short.MAX_VALUE)
546
.addComponent(lblRTMPServer, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
547
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
548
.addGroup(panTargetSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
549
.addComponent(cboAudioBitrate, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
550
.addComponent(cboRTMPServers, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
551
.addGroup(panTargetSettingsLayout.createSequentialGroup()
552
.addGroup(panTargetSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
553
.addComponent(jLabel6, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
554
.addComponent(jLabel5, javax.swing.GroupLayout.DEFAULT_SIZE, 128, Short.MAX_VALUE))
555
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
556
.addGroup(panTargetSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
557
.addComponent(numVideoBitrate, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
558
.addComponent(cboVideoPresets, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
559
.addGroup(panTargetSettingsLayout.createSequentialGroup()
560
.addComponent(lblRTMPKey, javax.swing.GroupLayout.PREFERRED_SIZE, 128, javax.swing.GroupLayout.PREFERRED_SIZE)
561
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
562
.addComponent(txtRTMPKey, javax.swing.GroupLayout.PREFERRED_SIZE, 435, javax.swing.GroupLayout.PREFERRED_SIZE)))
563
.addContainerGap(53, Short.MAX_VALUE))
565
panTargetSettingsLayout.setVerticalGroup(
566
panTargetSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
567
.addGroup(panTargetSettingsLayout.createSequentialGroup()
569
.addGroup(panTargetSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
570
.addComponent(jLabel5)
571
.addComponent(numVideoBitrate, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
572
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
573
.addGroup(panTargetSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
574
.addComponent(jLabel6)
575
.addComponent(cboVideoPresets, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
576
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
577
.addGroup(panTargetSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
578
.addComponent(jLabel7)
579
.addComponent(cboAudioBitrate, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
580
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
581
.addGroup(panTargetSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
582
.addComponent(lblRTMPServer)
583
.addComponent(cboRTMPServers, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
584
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
585
.addGroup(panTargetSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
586
.addComponent(lblRTMPKey)
587
.addComponent(txtRTMPKey, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
588
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
591
javax.swing.GroupLayout panOutputLayout = new javax.swing.GroupLayout(panOutput);
592
panOutput.setLayout(panOutputLayout);
593
panOutputLayout.setHorizontalGroup(
594
panOutputLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
595
.addGroup(panOutputLayout.createSequentialGroup()
597
.addGroup(panOutputLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
598
.addComponent(panTargetSettings, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
599
.addGroup(panOutputLayout.createSequentialGroup()
600
.addGroup(panOutputLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
601
.addComponent(jLabel1)
602
.addComponent(jLabel3)
603
.addComponent(jLabel4))
604
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
605
.addGroup(panOutputLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
606
.addGroup(panOutputLayout.createSequentialGroup()
607
.addComponent(spinWidth, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
608
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
609
.addComponent(jLabel2)
610
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
611
.addComponent(spinHeight, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
612
.addComponent(spinFPS, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
613
.addComponent(cboTarget, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
614
.addGap(0, 0, Short.MAX_VALUE)))
617
panOutputLayout.setVerticalGroup(
618
panOutputLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
619
.addGroup(panOutputLayout.createSequentialGroup()
621
.addGroup(panOutputLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
622
.addComponent(jLabel1)
623
.addComponent(spinWidth, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
624
.addComponent(spinHeight, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
625
.addComponent(jLabel2))
626
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
627
.addGroup(panOutputLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
628
.addComponent(jLabel3)
629
.addComponent(spinFPS, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
630
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
631
.addGroup(panOutputLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
632
.addComponent(jLabel4)
633
.addComponent(cboTarget, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
634
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
635
.addComponent(panTargetSettings, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
639
tabs.addTab("Output", panOutput);
641
panSources.setLayout(new java.awt.BorderLayout());
643
jSplitPane1.setDividerLocation(150);
644
jSplitPane1.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
646
panPreviewLayout.setBackground(new java.awt.Color(51, 51, 51));
647
panPreviewLayout.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Layout", javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Lucida Grande", 0, 13), new java.awt.Color(255, 255, 255))); // NOI18N
648
panPreviewLayout.setLayout(new java.awt.BorderLayout());
649
jSplitPane1.setRightComponent(panPreviewLayout);
651
scrollSources.setBorder(javax.swing.BorderFactory.createTitledBorder("Video Sources"));
653
tableSources.setModel(new javax.swing.table.DefaultTableModel(
655
{null, null, null, null, null, null, null, null},
656
{null, null, null, null, null, null, null, null},
657
{null, null, null, null, null, null, null, null},
658
{null, null, null, null, null, null, null, null}
661
" ", "Source", "Description", "X", "Y", "Width", "Height", "Alpha"
664
Class[] types = new Class [] {
665
java.lang.Boolean.class, java.lang.String.class, java.lang.String.class, java.lang.Integer.class, java.lang.Integer.class, java.lang.Integer.class, java.lang.Integer.class, java.lang.Float.class
667
boolean[] canEdit = new boolean [] {
668
true, false, false, true, true, true, true, true
671
public Class getColumnClass(int columnIndex) {
672
return types [columnIndex];
675
public boolean isCellEditable(int rowIndex, int columnIndex) {
676
return canEdit [columnIndex];
679
tableSources.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_LAST_COLUMN);
680
tableSources.setColumnSelectionAllowed(true);
681
tableSources.setFillsViewportHeight(true);
682
tableSources.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
683
tableSources.getTableHeader().setResizingAllowed(false);
684
tableSources.getTableHeader().setReorderingAllowed(false);
685
tableSources.addMouseListener(new java.awt.event.MouseAdapter() {
686
public void mouseClicked(java.awt.event.MouseEvent evt) {
687
tableSourcesMouseClicked(evt);
690
tableSources.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
691
public void propertyChange(java.beans.PropertyChangeEvent evt) {
692
tableSourcesPropertyChange(evt);
695
tableSources.addKeyListener(new java.awt.event.KeyAdapter() {
696
public void keyPressed(java.awt.event.KeyEvent evt) {
697
tableSourcesKeyPressed(evt);
700
scrollSources.setViewportView(tableSources);
701
tableSources.getColumnModel().getSelectionModel().setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
702
if (tableSources.getColumnModel().getColumnCount() > 0) {
703
tableSources.getColumnModel().getColumn(0).setMinWidth(25);
704
tableSources.getColumnModel().getColumn(0).setPreferredWidth(25);
705
tableSources.getColumnModel().getColumn(0).setMaxWidth(25);
706
tableSources.getColumnModel().getColumn(1).setMinWidth(100);
707
tableSources.getColumnModel().getColumn(1).setPreferredWidth(100);
708
tableSources.getColumnModel().getColumn(1).setMaxWidth(100);
709
tableSources.getColumnModel().getColumn(2).setMinWidth(150);
710
tableSources.getColumnModel().getColumn(2).setPreferredWidth(150);
711
tableSources.getColumnModel().getColumn(2).setMaxWidth(2000);
712
tableSources.getColumnModel().getColumn(3).setMinWidth(60);
713
tableSources.getColumnModel().getColumn(3).setPreferredWidth(60);
714
tableSources.getColumnModel().getColumn(3).setMaxWidth(60);
715
tableSources.getColumnModel().getColumn(4).setMinWidth(60);
716
tableSources.getColumnModel().getColumn(4).setPreferredWidth(60);
717
tableSources.getColumnModel().getColumn(4).setMaxWidth(60);
718
tableSources.getColumnModel().getColumn(5).setMinWidth(60);
719
tableSources.getColumnModel().getColumn(5).setPreferredWidth(60);
720
tableSources.getColumnModel().getColumn(5).setMaxWidth(60);
721
tableSources.getColumnModel().getColumn(6).setMinWidth(60);
722
tableSources.getColumnModel().getColumn(6).setPreferredWidth(60);
723
tableSources.getColumnModel().getColumn(6).setMaxWidth(60);
724
tableSources.getColumnModel().getColumn(7).setMinWidth(60);
725
tableSources.getColumnModel().getColumn(7).setPreferredWidth(60);
726
tableSources.getColumnModel().getColumn(7).setMaxWidth(60);
729
jSplitPane1.setLeftComponent(scrollSources);
731
panSources.add(jSplitPane1, java.awt.BorderLayout.CENTER);
733
tabs.addTab("Sources", panSources);
735
panSettingsAudios.setBorder(javax.swing.BorderFactory.createTitledBorder("Audio"));
737
jLabel8.setText("Microphone Input");
739
jLabel9.setText("Audio System Input");
741
jLabel10.setText("Audio Delay");
743
spinAudioDelay.setModel(new javax.swing.SpinnerNumberModel(Float.valueOf(0.0f), Float.valueOf(-5.0f), Float.valueOf(5.0f), Float.valueOf(0.1f)));
744
spinAudioDelay.setToolTipText("<HTML><BODY>\nApply a delay (in seconds) to the audio.\n<BR><I>If video is late, apply a positive value...</I>\n</BODY></HTML>");
745
spinAudioDelay.setEditor(new javax.swing.JSpinner.NumberEditor(spinAudioDelay, "#.#"));
746
spinAudioDelay.addChangeListener(new javax.swing.event.ChangeListener() {
747
public void stateChanged(javax.swing.event.ChangeEvent evt) {
748
spinAudioDelayStateChanged(evt);
752
javax.swing.GroupLayout panSettingsAudiosLayout = new javax.swing.GroupLayout(panSettingsAudios);
753
panSettingsAudios.setLayout(panSettingsAudiosLayout);
754
panSettingsAudiosLayout.setHorizontalGroup(
755
panSettingsAudiosLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
756
.addGroup(panSettingsAudiosLayout.createSequentialGroup()
758
.addGroup(panSettingsAudiosLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
759
.addComponent(jLabel8)
760
.addComponent(jLabel9)
761
.addComponent(jLabel10))
762
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
763
.addGroup(panSettingsAudiosLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
764
.addComponent(cboAudioMicrophones, 0, 461, Short.MAX_VALUE)
765
.addComponent(cboAudioSystems, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
766
.addGroup(panSettingsAudiosLayout.createSequentialGroup()
767
.addComponent(spinAudioDelay, javax.swing.GroupLayout.PREFERRED_SIZE, 97, javax.swing.GroupLayout.PREFERRED_SIZE)
768
.addGap(0, 390, Short.MAX_VALUE)))
771
panSettingsAudiosLayout.setVerticalGroup(
772
panSettingsAudiosLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
773
.addGroup(panSettingsAudiosLayout.createSequentialGroup()
774
.addGroup(panSettingsAudiosLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
775
.addComponent(jLabel8)
776
.addComponent(cboAudioMicrophones, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
777
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
778
.addGroup(panSettingsAudiosLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
779
.addComponent(jLabel9)
780
.addComponent(cboAudioSystems, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
781
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
782
.addGroup(panSettingsAudiosLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
783
.addComponent(jLabel10)
784
.addComponent(spinAudioDelay, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
785
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
788
panSettingsVideos.setBorder(javax.swing.BorderFactory.createTitledBorder("Video Folders"));
790
lblVideoFolder.setText(" ");
792
btnSetVideoFolder.setText("Browse");
793
btnSetVideoFolder.addActionListener(new java.awt.event.ActionListener() {
794
public void actionPerformed(java.awt.event.ActionEvent evt) {
795
btnSetVideoFolderActionPerformed(evt);
799
javax.swing.GroupLayout panSettingsVideosLayout = new javax.swing.GroupLayout(panSettingsVideos);
800
panSettingsVideos.setLayout(panSettingsVideosLayout);
801
panSettingsVideosLayout.setHorizontalGroup(
802
panSettingsVideosLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
803
.addGroup(panSettingsVideosLayout.createSequentialGroup()
804
.addComponent(lblVideoFolder, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
805
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
806
.addComponent(btnSetVideoFolder)
809
panSettingsVideosLayout.setVerticalGroup(
810
panSettingsVideosLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
811
.addGroup(panSettingsVideosLayout.createSequentialGroup()
812
.addGroup(panSettingsVideosLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
813
.addComponent(lblVideoFolder)
814
.addComponent(btnSetVideoFolder))
815
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
818
panSettingsMisc.setBorder(javax.swing.BorderFactory.createTitledBorder("Misc"));
820
chkStayVisible.setText("Stay Visible");
822
javax.swing.GroupLayout panSettingsMiscLayout = new javax.swing.GroupLayout(panSettingsMisc);
823
panSettingsMisc.setLayout(panSettingsMiscLayout);
824
panSettingsMiscLayout.setHorizontalGroup(
825
panSettingsMiscLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
826
.addGroup(panSettingsMiscLayout.createSequentialGroup()
828
.addComponent(chkStayVisible)
829
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
831
panSettingsMiscLayout.setVerticalGroup(
832
panSettingsMiscLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
833
.addComponent(chkStayVisible)
836
javax.swing.GroupLayout panOptionsLayout = new javax.swing.GroupLayout(panOptions);
837
panOptions.setLayout(panOptionsLayout);
838
panOptionsLayout.setHorizontalGroup(
839
panOptionsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
840
.addGroup(panOptionsLayout.createSequentialGroup()
842
.addGroup(panOptionsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
843
.addComponent(panSettingsAudios, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
844
.addComponent(panSettingsVideos, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
845
.addComponent(panSettingsMisc, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
848
panOptionsLayout.setVerticalGroup(
849
panOptionsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
850
.addGroup(panOptionsLayout.createSequentialGroup()
852
.addComponent(panSettingsAudios, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
853
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
854
.addComponent(panSettingsVideos, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
855
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
856
.addComponent(panSettingsMisc, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
857
.addContainerGap(99, Short.MAX_VALUE))
860
tabs.addTab("Options", panOptions);
862
getContentPane().add(tabs, java.awt.BorderLayout.CENTER);
864
panStatus.setBorder(new javax.swing.border.SoftBevelBorder(javax.swing.border.BevelBorder.LOWERED));
865
panStatus.setPreferredSize(new java.awt.Dimension(767, 20));
866
panStatus.setLayout(new javax.swing.BoxLayout(panStatus, javax.swing.BoxLayout.LINE_AXIS));
868
lblMessages.setText("Welcome to ScreenStudio");
869
panStatus.add(lblMessages);
871
getContentPane().add(panStatus, java.awt.BorderLayout.SOUTH);
873
mnuFile.setText("Layout");
875
mnuCapture.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_R, java.awt.event.InputEvent.CTRL_MASK));
876
mnuCapture.setText("Record");
877
mnuCapture.setToolTipText("<html><body>\nStart recording/streaming using CTRL-R. \n<BR><B>ScreenStudio</B> will automatically hide in the taskbar of your system. \n<BR>To stop the recording, simply restore the <B>ScreenStudio</B> window.\n</body></html>");
878
mnuCapture.addActionListener(new java.awt.event.ActionListener() {
879
public void actionPerformed(java.awt.event.ActionEvent evt) {
880
mnuCaptureActionPerformed(evt);
883
mnuFile.add(mnuCapture);
884
mnuFile.add(jSeparator1);
886
mnuFileLoad.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_O, java.awt.event.InputEvent.CTRL_MASK));
887
mnuFileLoad.setText("Open");
888
mnuFileLoad.setToolTipText("<HTML><BODY>\nOpen a <B>ScreenStudio</B> XML layout file\n</BODY></HTML>");
889
mnuFileLoad.addActionListener(new java.awt.event.ActionListener() {
890
public void actionPerformed(java.awt.event.ActionEvent evt) {
891
mnuFileLoadActionPerformed(evt);
894
mnuFile.add(mnuFileLoad);
896
mnuFileSave.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_S, java.awt.event.InputEvent.CTRL_MASK));
897
mnuFileSave.setText("Save");
898
mnuFileSave.setToolTipText("<HTML><BODY>\nSave the current layour to a <B>ScreenStudio</B> XML layout file\n</BODY></HTML>");
899
mnuFileSave.addActionListener(new java.awt.event.ActionListener() {
900
public void actionPerformed(java.awt.event.ActionEvent evt) {
901
mnuFileSaveActionPerformed(evt);
904
mnuFile.add(mnuFileSave);
906
menuBar.add(mnuFile);
908
mnuEdit.setText("Sources");
910
mnuMainWebcams.setText("Webcams");
911
mnuEdit.add(mnuMainWebcams);
913
mnuMainDestops.setText("Desktops");
914
mnuEdit.add(mnuMainDestops);
916
mnuMainAddImage.setText("Add Image...");
917
mnuMainAddImage.setToolTipText("Browse your hard disk to add a source image file");
918
mnuMainAddImage.addActionListener(new java.awt.event.ActionListener() {
919
public void actionPerformed(java.awt.event.ActionEvent evt) {
920
mnuMainAddImageActionPerformed(evt);
923
mnuEdit.add(mnuMainAddImage);
925
mnuMainAddLabel.setText("Add Label");
926
mnuMainAddLabel.setToolTipText("<HTML><BODY>\nAdd a new text label. \n<BR>Double-click on the source to edit the content.\n</BODY></HTML>");
927
mnuMainAddLabel.addActionListener(new java.awt.event.ActionListener() {
928
public void actionPerformed(java.awt.event.ActionEvent evt) {
929
mnuMainAddLabelActionPerformed(evt);
932
mnuEdit.add(mnuMainAddLabel);
933
mnuEdit.add(jSeparator3);
935
mnuMainMoveUp.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_UP, java.awt.event.InputEvent.ALT_MASK));
936
mnuMainMoveUp.setText("Move Up");
937
mnuMainMoveUp.setToolTipText("Move the currently selected source to a higher layer");
938
mnuMainMoveUp.addActionListener(new java.awt.event.ActionListener() {
939
public void actionPerformed(java.awt.event.ActionEvent evt) {
940
mnuMainMoveUpActionPerformed(evt);
943
mnuEdit.add(mnuMainMoveUp);
945
mnuMainMoveDown.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_DOWN, java.awt.event.InputEvent.ALT_MASK));
946
mnuMainMoveDown.setText("Move Down");
947
mnuMainMoveDown.setToolTipText("Move the currently selected source to a lower layer");
948
mnuMainMoveDown.addActionListener(new java.awt.event.ActionListener() {
949
public void actionPerformed(java.awt.event.ActionEvent evt) {
950
mnuMainMoveDownActionPerformed(evt);
953
mnuEdit.add(mnuMainMoveDown);
954
mnuEdit.add(jSeparator2);
956
mnuMainRemove.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_DELETE, 0));
957
mnuMainRemove.setText("Remove Source");
958
mnuMainRemove.setToolTipText("Remove the currently selected source");
959
mnuMainRemove.addActionListener(new java.awt.event.ActionListener() {
960
public void actionPerformed(java.awt.event.ActionEvent evt) {
961
mnuMainRemoveActionPerformed(evt);
964
mnuEdit.add(mnuMainRemove);
966
menuBar.add(mnuEdit);
968
setJMenuBar(menuBar);
971
}// </editor-fold>//GEN-END:initComponents
973
private void tableSourcesPropertyChange(java.beans.PropertyChangeEvent evt) {//GEN-FIRST:event_tableSourcesPropertyChange
974
if (mLayoutPreview != null) {
975
mLayoutPreview.repaint();
977
}//GEN-LAST:event_tableSourcesPropertyChange
979
private void tableSourcesKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_tableSourcesKeyPressed
980
mLayoutPreview.repaint();
981
}//GEN-LAST:event_tableSourcesKeyPressed
983
private void tableSourcesMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_tableSourcesMouseClicked
984
if (evt.getClickCount() == 2) {
985
int rowIndex = tableSources.getSelectedRow();
986
if (tableSources.getValueAt(rowIndex, 1) == SourceType.LabelText) {
987
Editor ed = new Editor(((LabelText) tableSources.getValueAt(rowIndex, 2)), this);
990
tableSources.setValueAt(ed.getLabelText(), rowIndex, 2);
991
tableSources.repaint();
994
mLayoutPreview.repaint();
995
}//GEN-LAST:event_tableSourcesMouseClicked
997
private void spinWidthStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_spinWidthStateChanged
998
if (mLayoutPreview != null) {
999
mLayoutPreview.setOutputWidth((Integer) spinWidth.getValue());
1001
}//GEN-LAST:event_spinWidthStateChanged
1003
private void spinHeightStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_spinHeightStateChanged
1004
if (mLayoutPreview != null) {
1005
mLayoutPreview.setOutputHeight((Integer) spinHeight.getValue());
1007
}//GEN-LAST:event_spinHeightStateChanged
1009
private void cboTargetActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cboTargetActionPerformed
1010
setRTMPControls((FFMpeg.FORMATS) cboTarget.getSelectedItem());
1011
}//GEN-LAST:event_cboTargetActionPerformed
1014
private void mnuCaptureActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mnuCaptureActionPerformed
1015
if (mFFMpeg != null) {
1016
if (mFFMpeg.getState() == FFMpeg.RunningState.Error) {
1017
lblMessages.setText(mFFMpeg.getLastErrorMessage());
1019
lblMessages.setText("Stopped...");
1023
Microphone.getVirtualAudio(null, null);
1024
} catch (IOException | InterruptedException ex) {
1025
Logger.getLogger(ScreenStudio.class.getName()).log(Level.SEVERE, null, ex);
1028
mnuCapture.setText("Record");
1029
if (!chkStayVisible.isSelected()) {
1030
if (trayIcon != null) {
1031
trayIcon.setImage(this.getIconImage());
1032
this.setVisible(true);
1035
updateControls(true);
1036
if (FFMpeg.isRTMP((FFMpeg.FORMATS) cboTarget.getSelectedItem())) {
1037
txtRTMPKey.setVisible(true);
1040
if (txtRTMPKey.isVisible()) {
1041
txtRTMPKey.setVisible(false);
1043
boolean abort = false;
1044
if (tableSources.getRowCount() == 0) {
1045
lblMessages.setText("No video source to display...");
1048
if (cboAudioMicrophones.getSelectedIndex() == 0 && cboAudioSystems.getSelectedIndex() == 0) {
1049
lblMessages.setText("No audio source selected...");
1053
List<Source> sources = Compositor.getSources(tableSources, (Integer) spinFPS.getValue());
1054
Compositor compositor = new Compositor(sources, new Rectangle(0, 0, (Integer) spinWidth.getValue(), (Integer) spinHeight.getValue()), (Integer) spinFPS.getValue());
1055
mFFMpeg = new FFMpeg(compositor);
1056
String audio = "default";
1057
Microphone mic = null;
1058
Microphone sys = null;
1059
if (cboAudioMicrophones.getSelectedIndex() > 0) {
1060
mic = (Microphone) cboAudioMicrophones.getSelectedItem();
1062
if (cboAudioSystems.getSelectedIndex() > 0) {
1063
sys = (Microphone) cboAudioSystems.getSelectedItem();
1066
audio = Microphone.getVirtualAudio(mic, sys);
1067
} catch (IOException ex) {
1068
Logger.getLogger(ScreenStudio.class.getName()).log(Level.SEVERE, null, ex);
1069
} catch (InterruptedException ex) {
1070
Logger.getLogger(ScreenStudio.class.getName()).log(Level.SEVERE, null, ex);
1072
mFFMpeg.setAudio((FFMpeg.AudioRate) cboAudioBitrate.getSelectedItem(), audio, (Float) spinAudioDelay.getValue());
1074
if (cboRTMPServers.getSelectedItem() != null) {
1075
server = cboRTMPServers.getSelectedItem().toString();
1076
server = server.split(";")[1];
1078
mFFMpeg.setOutputFormat((FFMpeg.FORMATS) cboTarget.getSelectedItem(), (FFMpeg.Presets) cboVideoPresets.getSelectedItem(), (Integer) numVideoBitrate.getValue(), server, txtRTMPKey.getText(), mVideoOutputFolder);
1079
new Thread(mFFMpeg).start();
1080
lblMessages.setText("Recording...");
1081
mnuCapture.setText("Stop");
1082
if (trayIcon != null) {
1083
trayIcon.setImage(new ImageIcon(ScreenStudio.class.getResource("/screenstudio/gui/images/iconRunning.png")).getImage());
1086
updateControls(false);
1087
if (!chkStayVisible.isSelected()) {
1088
if (trayIcon != null) {
1089
this.setVisible(false);
1091
this.setExtendedState(JFrame.ICONIFIED);
1094
mRecordingTimestamp = System.currentTimeMillis();
1098
long seconds = (System.currentTimeMillis() - mRecordingTimestamp) / 1000;
1100
setTitle("Recording! (" + seconds + " sec)");
1102
setTitle("Recording! (" + (seconds / 60) + " min " + (seconds % 60) + " sec)");
1104
if (f.getState() == FFMpeg.RunningState.Error) {
1105
System.err.println("Encoder error detected...");
1106
mnuCapture.doClick();
1111
} catch (InterruptedException ex) {
1112
Logger.getLogger(ScreenStudio.class.getName()).log(Level.SEVERE, null, ex);
1116
setTitle("ScreenStudio " + screenstudio.Version.MAIN);
1121
}//GEN-LAST:event_mnuCaptureActionPerformed
1123
private void mnuFileSaveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mnuFileSaveActionPerformed
1124
java.util.prefs.Preferences p = java.util.prefs.Preferences.userRoot().node("screenstudio");
1125
String lastFolder = p.get("lastfolder", ".");
1126
JFileChooser chooser = new JFileChooser(new File(lastFolder));
1127
chooser.setAcceptAllFileFilterUsed(false);
1128
chooser.setFileFilter(new FileFilter() {
1130
public boolean accept(File f) {
1131
return f.isDirectory() || f.getName().toUpperCase().endsWith(".XML");
1135
public String getDescription() {
1136
return "ScreenStudio XML Layout";
1139
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
1140
if (chooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) {
1141
if (chooser.getSelectedFile() != null) {
1142
saveLayout(chooser.getSelectedFile());
1143
p.put("lastfolder", chooser.getSelectedFile().getParent());
1146
} catch (BackingStoreException ex) {
1147
Logger.getLogger(ScreenStudio.class.getName()).log(Level.SEVERE, null, ex);
1152
}//GEN-LAST:event_mnuFileSaveActionPerformed
1154
private void mnuFileLoadActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mnuFileLoadActionPerformed
1155
// load last folder...
1156
java.util.prefs.Preferences p = java.util.prefs.Preferences.userRoot().node("screenstudio");
1157
String lastFolder = p.get("lastfolder", ".");
1158
JFileChooser chooser = new JFileChooser(new File(lastFolder));
1159
chooser.setAcceptAllFileFilterUsed(false);
1160
chooser.setFileFilter(new FileFilter() {
1162
public boolean accept(File f) {
1163
return f.isDirectory() || f.getName().toUpperCase().endsWith(".XML");
1167
public String getDescription() {
1168
return "ScreenStudio XML Layout";
1171
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
1172
if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
1173
if (chooser.getSelectedFile() != null) {
1174
loadLayout(chooser.getSelectedFile());
1175
p.put("lastfolder", chooser.getSelectedFile().getParent());
1178
} catch (BackingStoreException ex) {
1179
Logger.getLogger(ScreenStudio.class.getName()).log(Level.SEVERE, null, ex);
1184
}//GEN-LAST:event_mnuFileLoadActionPerformed
1186
private void btnSetVideoFolderActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnSetVideoFolderActionPerformed
1187
JFileChooser chooser = new JFileChooser(mVideoOutputFolder);
1188
chooser.setAcceptAllFileFilterUsed(false);
1189
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
1190
chooser.showOpenDialog(this);
1191
if (chooser.getSelectedFile() != null) {
1192
mVideoOutputFolder = chooser.getSelectedFile();
1193
lblVideoFolder.setText(mVideoOutputFolder.getAbsolutePath());
1194
lblVideoFolder.setToolTipText(mVideoOutputFolder.getAbsolutePath());
1196
}//GEN-LAST:event_btnSetVideoFolderActionPerformed
1198
private void mnuMainAddImageActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mnuMainAddImageActionPerformed
1199
JFileChooser chooser = new JFileChooser(mVideoOutputFolder);
1200
chooser.setAcceptAllFileFilterUsed(false);
1201
chooser.setFileFilter(new FileFilter() {
1203
public boolean accept(File f) {
1204
return f.isDirectory() || f.getName().toUpperCase().endsWith(".PNG") || f.getName().toUpperCase().endsWith(".JPG") || f.getName().toUpperCase().endsWith(".GIF") || f.getName().toUpperCase().endsWith(".BMP");
1208
public String getDescription() {
1209
return "Image Files";
1212
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
1213
chooser.showOpenDialog(this);
1214
if (chooser.getSelectedFile() != null) {
1215
File image = chooser.getSelectedFile();
1217
DefaultTableModel model = (DefaultTableModel) tableSources.getModel();
1218
Object[] row = new Object[model.getColumnCount()];
1220
row[1] = SourceType.Image;
1229
mLayoutPreview.repaint();
1230
tabs.setSelectedComponent(panSources);
1231
}//GEN-LAST:event_mnuMainAddImageActionPerformed
1233
private void mnuMainAddLabelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mnuMainAddLabelActionPerformed
1234
DefaultTableModel model = (DefaultTableModel) tableSources.getModel();
1235
Object[] row = new Object[model.getColumnCount()];
1237
row[1] = SourceType.LabelText;
1238
row[2] = new LabelText("<HTML><BODY>New Label...</BODY><HTML>");
1245
mLayoutPreview.repaint();
1246
tabs.setSelectedComponent(panSources);
1247
}//GEN-LAST:event_mnuMainAddLabelActionPerformed
1249
private void mnuMainMoveUpActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mnuMainMoveUpActionPerformed
1250
if (tableSources.getSelectedRow() != -1 && tableSources.getSelectedRow() > 0) {
1251
Object[] row = new Object[tableSources.getColumnCount()];
1252
for (int i = 0; i < row.length; i++) {
1253
row[i] = tableSources.getValueAt(tableSources.getSelectedRow(), i);
1254
tableSources.setValueAt(tableSources.getValueAt(tableSources.getSelectedRow() - 1, i), tableSources.getSelectedRow(), i);
1255
tableSources.setValueAt(row[i], tableSources.getSelectedRow() - 1, i);
1257
int index = tableSources.getSelectedRow() - 1;
1258
tableSources.setRowSelectionInterval(index, index);
1259
mLayoutPreview.repaint();
1260
tabs.setSelectedComponent(panSources);
1262
}//GEN-LAST:event_mnuMainMoveUpActionPerformed
1264
private void mnuMainMoveDownActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mnuMainMoveDownActionPerformed
1265
if (tableSources.getSelectedRow() != -1 && tableSources.getSelectedRow() < tableSources.getRowCount() - 1) {
1266
Object[] row = new Object[tableSources.getColumnCount()];
1267
for (int i = 0; i < row.length; i++) {
1268
row[i] = tableSources.getValueAt(tableSources.getSelectedRow(), i);
1269
tableSources.setValueAt(tableSources.getValueAt(tableSources.getSelectedRow() + 1, i), tableSources.getSelectedRow(), i);
1270
tableSources.setValueAt(row[i], tableSources.getSelectedRow() + 1, i);
1272
int index = tableSources.getSelectedRow() + 1;
1273
tableSources.setRowSelectionInterval(index, index);
1274
mLayoutPreview.repaint();
1275
tabs.setSelectedComponent(panSources);
1277
}//GEN-LAST:event_mnuMainMoveDownActionPerformed
1279
private void formWindowStateChanged(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowStateChanged
1280
if (mFFMpeg != null && evt.getOldState() == JFrame.ICONIFIED && trayIcon == null) {
1281
mnuCapture.doClick();
1283
}//GEN-LAST:event_formWindowStateChanged
1285
private void mnuMainRemoveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mnuMainRemoveActionPerformed
1286
if (tableSources.getSelectedRow() != -1) {
1287
int index = tableSources.getSelectedRow();
1288
DefaultTableModel model = (DefaultTableModel) tableSources.getModel();
1289
model.removeRow(index);
1290
mLayoutPreview.repaint();
1292
}//GEN-LAST:event_mnuMainRemoveActionPerformed
1294
private void spinAudioDelayStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_spinAudioDelayStateChanged
1295
java.util.prefs.Preferences p = java.util.prefs.Preferences.userRoot().node("screenstudio");
1296
p.putFloat("audiodelay", (Float) spinAudioDelay.getValue());
1299
} catch (BackingStoreException ex) {
1300
Logger.getLogger(ScreenStudio.class.getName()).log(Level.SEVERE, null, ex);
1302
}//GEN-LAST:event_spinAudioDelayStateChanged
1304
private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing
1305
if (trayIcon != null) {
1306
SystemTray.getSystemTray().remove(trayIcon);
1308
}//GEN-LAST:event_formWindowClosing
1311
* @param args the command line arguments
1313
public static void main(String args[]) {
1314
/* Set the Nimbus look and feel */
1315
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
1316
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
1317
* For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
1320
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
1321
if ("Nimbus".equals(info.getName())) {
1322
javax.swing.UIManager.setLookAndFeel(info.getClassName());
1326
} catch (ClassNotFoundException ex) {
1327
java.util.logging.Logger.getLogger(ScreenStudio.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
1328
} catch (InstantiationException ex) {
1329
java.util.logging.Logger.getLogger(ScreenStudio.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
1330
} catch (IllegalAccessException ex) {
1331
java.util.logging.Logger.getLogger(ScreenStudio.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
1332
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
1333
java.util.logging.Logger.getLogger(ScreenStudio.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
1338
/* Create and display the form */
1339
java.awt.EventQueue.invokeLater(new Runnable() {
1341
new ScreenStudio().setVisible(true);
1346
// Variables declaration - do not modify//GEN-BEGIN:variables
1347
private javax.swing.JButton btnSetVideoFolder;
1348
private javax.swing.JComboBox<FFMpeg.AudioRate> cboAudioBitrate;
1349
private javax.swing.JComboBox<Microphone> cboAudioMicrophones;
1350
private javax.swing.JComboBox<Microphone> cboAudioSystems;
1351
private javax.swing.JComboBox<String> cboRTMPServers;
1352
private javax.swing.JComboBox<FFMpeg.FORMATS> cboTarget;
1353
private javax.swing.JComboBox<FFMpeg.Presets> cboVideoPresets;
1354
private javax.swing.JCheckBox chkStayVisible;
1355
private javax.swing.JLabel jLabel1;
1356
private javax.swing.JLabel jLabel10;
1357
private javax.swing.JLabel jLabel2;
1358
private javax.swing.JLabel jLabel3;
1359
private javax.swing.JLabel jLabel4;
1360
private javax.swing.JLabel jLabel5;
1361
private javax.swing.JLabel jLabel6;
1362
private javax.swing.JLabel jLabel7;
1363
private javax.swing.JLabel jLabel8;
1364
private javax.swing.JLabel jLabel9;
1365
private javax.swing.JPopupMenu.Separator jSeparator1;
1366
private javax.swing.JPopupMenu.Separator jSeparator2;
1367
private javax.swing.JPopupMenu.Separator jSeparator3;
1368
private javax.swing.JSplitPane jSplitPane1;
1369
private javax.swing.JLabel lblMessages;
1370
private javax.swing.JLabel lblRTMPKey;
1371
private javax.swing.JLabel lblRTMPServer;
1372
private javax.swing.JLabel lblVideoFolder;
1373
private javax.swing.JMenuBar menuBar;
1374
private javax.swing.JMenuItem mnuCapture;
1375
private javax.swing.JMenu mnuEdit;
1376
private javax.swing.JMenu mnuFile;
1377
private javax.swing.JMenuItem mnuFileLoad;
1378
private javax.swing.JMenuItem mnuFileSave;
1379
private javax.swing.JMenuItem mnuMainAddImage;
1380
private javax.swing.JMenuItem mnuMainAddLabel;
1381
private javax.swing.JMenu mnuMainDestops;
1382
private javax.swing.JMenuItem mnuMainMoveDown;
1383
private javax.swing.JMenuItem mnuMainMoveUp;
1384
private javax.swing.JMenuItem mnuMainRemove;
1385
private javax.swing.JMenu mnuMainWebcams;
1386
private javax.swing.JSpinner numVideoBitrate;
1387
private javax.swing.JPanel panOptions;
1388
private javax.swing.JPanel panOutput;
1389
private javax.swing.JPanel panPreviewLayout;
1390
private javax.swing.JPanel panSettingsAudios;
1391
private javax.swing.JPanel panSettingsMisc;
1392
private javax.swing.JPanel panSettingsVideos;
1393
private javax.swing.JPanel panSources;
1394
private javax.swing.JPanel panStatus;
1395
private javax.swing.JPanel panTargetSettings;
1396
private javax.swing.JScrollPane scrollSources;
1397
private javax.swing.JSpinner spinAudioDelay;
1398
private javax.swing.JSpinner spinFPS;
1399
private javax.swing.JSpinner spinHeight;
1400
private javax.swing.JSpinner spinWidth;
1401
private javax.swing.JTable tableSources;
1402
private javax.swing.JTabbedPane tabs;
1403
private javax.swing.JTextField txtRTMPKey;
1404
// End of variables declaration//GEN-END:variables