/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
/*
* OutputPanel.java
*
* Created on 15-Apr-2012, 1:28:32 AM
*/
package webcamstudio.components;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.prefs.BackingStoreException;
import java.util.prefs.Preferences;
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import webcamstudio.WebcamStudio;
import static webcamstudio.WebcamStudio.theme;
import webcamstudio.channels.MasterChannels;
import static webcamstudio.components.ChannelPanel.lblOnAir;
import webcamstudio.exporter.vloopback.VideoDevice;
import webcamstudio.externals.FME;
import webcamstudio.media.renderer.Exporter;
import webcamstudio.mixers.MasterMixer;
import webcamstudio.streams.SinkAudio;
import webcamstudio.streams.SinkBroadcast;
import webcamstudio.streams.SinkFile;
import webcamstudio.streams.SinkLinuxDevice;
import webcamstudio.streams.SinkUDP;
import webcamstudio.streams.Stream;
import webcamstudio.util.GridLayout2;
import webcamstudio.util.Tools;
import webcamstudio.util.Tools.OS;
/**
*
* @author patrick (modified by karl)
*/
public class OutputPanel extends javax.swing.JPanel implements Stream.Listener, WebcamStudio.Listener, ChannelPanel.Listener, Exporter.Listener {
TreeMap<String, SinkFile> files = new TreeMap<>();
TreeMap<String, SinkBroadcast> broadcasts = new TreeMap<>();
ArrayList<String> broadcastsOut = new ArrayList<>();
TreeMap<String, SinkLinuxDevice> devices = new TreeMap<>();
ArrayList<String> devicesOut = new ArrayList<>();
TreeMap<String, SinkUDP> udpOut = new TreeMap<>();
TreeMap<String, SinkAudio> audioOut = new TreeMap<>();
TreeMap<String, FME> fmes = new TreeMap<>();
private final static String userHomeDir = Tools.getUserHome();
boolean skyCamMode = false;
int camCount = 0;
int fmeCount = 0;
String virtualDevice = "webcamstudio";
TreeMap<String, ResourceMonitorLabel> labels = new TreeMap<>();
JPanel wDFrame;
FME currFME;
JPopupMenu fmePopup = new JPopupMenu();
JPopupMenu sinkFilePopup = new JPopupMenu();
JPopupMenu sinkUDPPopup = new JPopupMenu();
File f;
SinkFile fileStream;
SinkUDP udpStream;
SinkAudio audioStream;
private boolean audioOutState = false;
private boolean udpOutState = false;
private boolean audioOutSwitch = false;
private boolean udpOutSwitch = false;
private boolean fmeOutState = false;
private boolean fmeOutSwitch = false;
private boolean camOutState = false;
private boolean camOutSwitch = false;
private final ArrayList<String> idWSOuts = new ArrayList<>();
private String idWSAD;
private String idDef;
private String idWSOut;
private final String[] v4l2PixelFormats = { "RGB24", "UYUV", "BGR24" };
@SuppressWarnings("unchecked")
/** Creates new form OutputPanel
* @param aFrame */
public OutputPanel(JPanel aFrame) {
initComponents();
GridLayout2 columLayout = new GridLayout2(0,1);
this.setLayout(columLayout);
panelPixelFormat.setLayout(columLayout);
panelDefaultOutputs.setLayout(columLayout);
panelVirtualAudio.setLayout(columLayout);
panelVirtualC.setLayout(columLayout);
panelVirtualA.setLayout(columLayout);
panelDefault.setLayout(columLayout);
panelFME.setLayout(columLayout);
comboPixelFormat.setModel(new javax.swing.DefaultComboBoxModel(v4l2PixelFormats));
f = new File(userHomeDir + "/.webcamstudio/Record To File");
udpStream = new SinkUDP();
fileStream = new SinkFile(f);
audioStream = new SinkAudio();
// System.out.println("SinkAudio"+audioStream);
tglRecordToFile.addMouseListener(new java.awt.event.MouseAdapter() {
@Override
public void mousePressed(java.awt.event.MouseEvent evt) {
JToggleButton button = ((JToggleButton) evt.getSource());
if (!button.isSelected()) {
sinkFileRightMousePressed(evt);
}
}
});
tglUDP.addMouseListener(new java.awt.event.MouseAdapter() {
@Override
public void mousePressed(java.awt.event.MouseEvent evt) {
JToggleButton button = ((JToggleButton) evt.getSource());
if (!button.isSelected()) {
sinkUDPRightMousePressed(evt);
}
}
});
wDFrame = aFrame;
fmeInitPopUp();
sinkFileInitPopUp();
sinkUDPInitPopUp();
final OutputPanel instanceSinkOP = this;
WebcamStudio.setListenerOP(instanceSinkOP);
ChannelPanel.setListenerCPOPanel(instanceSinkOP);
Exporter.setListenerEx(instanceSinkOP);
if (Tools.getOS() == OS.LINUX) {
paintWSCamButtons ();
}
fileStream.setWidth(MasterMixer.getInstance().getWidth());
fileStream.setHeight(MasterMixer.getInstance().getHeight());
fileStream.setRate(MasterMixer.getInstance().getRate());
udpStream.setWidth(MasterMixer.getInstance().getWidth());
udpStream.setHeight(MasterMixer.getInstance().getHeight());
udpStream.setRate(MasterMixer.getInstance().getRate());
this.setDropTarget(new DropTarget() {
@Override
public synchronized void drop(DropTargetDropEvent evt) {
try {
String fileName = "";
evt.acceptDrop(DnDConstants.ACTION_REFERENCE);
boolean success = false;
DataFlavor dataFlavor = null;
if (evt.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
dataFlavor = DataFlavor.javaFileListFlavor;
} else if (evt.isDataFlavorSupported(DataFlavor.stringFlavor)) {
dataFlavor = DataFlavor.stringFlavor;
} else {
for (DataFlavor d : evt.getTransferable().getTransferDataFlavors()) {
if (evt.getTransferable().isDataFlavorSupported(d)) {
System.out.println("Supported: " + d.getDefaultRepresentationClassAsString());
dataFlavor = d;
break;
}
}
}
Object data = evt.getTransferable().getTransferData(dataFlavor);
String files = "";
if (data instanceof Reader) {
char[] text = new char[65536];
files = new String(text).trim();
} else if (data instanceof InputStream) {
char[] text = new char[65536];
files = new String(text).trim();
} else if (data instanceof String) {
files = data.toString().trim();
} else {
List list = (List) data;
for (Object o : list) {
files += new File(o.toString()).toURI().toURL().toString() + "\n";
}
}
if (files.length() > 0) {
String[] lines = files.split("\n");
for (String line : lines) {
File file = new File(new URL(line.trim()).toURI());
fileName = file.getName();
if (file.exists() && file.getName().toLowerCase().endsWith("xml")) {
success = true;
FME fme = new FME(file);
fmes.put(fme.getName(), fme);
addButtonBroadcast(fme);
}
}
}
evt.dropComplete(success);
if (!success) {
ResourceMonitorLabel label = new ResourceMonitorLabel(System.currentTimeMillis() + 5000, "Unsupported file: " + fileName);
ResourceMonitor.getInstance().addMessage(label);
}
} catch (UnsupportedFlavorException | IOException | URISyntaxException ex) {
ex.printStackTrace();
}
}
});
}
public void loadPrefs(Preferences prefs) {
Preferences fmePrefs = prefs.node("fme");
Preferences filePrefs = prefs.node("filerec");
Preferences udpPrefs = prefs.node("udp");
try {
String[] services = fmePrefs.childrenNames();
String[] servicesF = filePrefs.childrenNames();
String[] servicesU = udpPrefs.childrenNames();
for (String s : servicesF){
Preferences serviceF = filePrefs.node(s);
fileStream.setVbitrate(serviceF.get("vbitrate", "1200"));
fileStream.setAbitrate(serviceF.get("abitrate", "128"));
}
for (String s : servicesU){
Preferences serviceU = udpPrefs.node(s);
udpStream.setVbitrate(serviceU.get("vbitrate", "1200"));
udpStream.setAbitrate(serviceU.get("abitrate", "128"));
udpStream.setStandard(serviceU.get("standard", "STD"));
}
for (String s : services) {
Preferences service = fmePrefs.node(s);
String url = service.get("url", "");
String name = service.get("name", "");
String abitrate = service.get("abitrate", "512000");
String vbitrate = service.get("vbitrate", "96000");
String vcodec = service.get("vcodec", "");
String acodec = service.get("acodec", "");
String width = service.get("width", "");
String height = service.get("height", "");
String stream = service.get("stream", "");
String mount = service.get("mount", "");
String password = service.get("password", "");
String port = service.get("port", "");
String keyInt = service.get("keyint", "");
String standard = service.get("standard", "STD");
// for compatibility before KeyInt
if ("".equals(keyInt)) {
keyInt = "125";
}
// System.out.println("Loaded KeyInt: "+keyInt+"###");
FME fme = new FME(url, stream, name, abitrate, vbitrate, vcodec, acodec, width, height, mount, password, port, keyInt);
fme.setStandard(standard);
fmes.put(fme.getName(), fme);
addButtonBroadcast(fme);
}
} catch (BackingStoreException ex) {
Logger.getLogger(OutputPanel.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void savePrefs(Preferences prefs) {
Preferences fmePrefs = prefs.node("fme");
Preferences filePrefs = prefs.node("filerec");
Preferences udpPrefs = prefs.node("udp");
try {
fmePrefs.removeNode();
fmePrefs.flush();
fmePrefs = prefs.node("fme");
filePrefs.removeNode();
filePrefs.flush();
filePrefs = prefs.node("filerec");
udpPrefs.removeNode();
udpPrefs.flush();
udpPrefs = prefs.node("udp");
} catch (BackingStoreException ex) {
Logger.getLogger(OutputPanel.class.getName()).log(Level.SEVERE, null, ex);
}
for (FME fme : fmes.values()) {
Preferences service = fmePrefs.node(fme.getName());
service.put("url", fme.getUrl());
service.put("name", fme.getName());
service.put("abitrate", fme.getAbitrate());
service.put("vbitrate", fme.getVbitrate());
service.put("vcodec", fme.getVcodec());
service.put("acodec", fme.getAcodec());
service.put("width", fme.getWidth());
service.put("height", fme.getHeight());
service.put("stream", fme.getStream());
service.put("mount", fme.getMount());
service.put("password", fme.getPassword());
service.put("port", fme.getPort());
service.put("keyint", fme.getKeyInt());
service.put("standard", fme.getStandard());
}
Preferences serviceF = filePrefs.node("frecordset");
serviceF.put("abitrate", fileStream.getAbitrate());
serviceF.put("vbitrate", fileStream.getVbitrate());
Preferences serviceU = udpPrefs.node("uoutset");
serviceU.put("abitrate", udpStream.getAbitrate());
serviceU.put("vbitrate", udpStream.getVbitrate());
serviceU.put("standard", udpStream.getStandard());
}
private String checkDoubleBroad(String s) {
String res = s;
for (String broName : broadcastsOut) {
if (s.equals(broName)){
res = "";
}
}
return res;
}
private String checkDoubleCam(String s) {
String res = s;
for (String camName : devicesOut) {
if (s.equals(camName)){
res = "";
}
}
return res;
}
private void addButtonBroadcast(final FME fme) {
final OutputPanel instanceSinkFME = this;
JToggleButton button = new JToggleButton();
// Dimension d = new Dimension(139,22);
// button.setPreferredSize(d);
button.setText(fme.getName());
button.setActionCommand(fme.getUrl()+"/"+fme.getStream());
button.setIcon(tglRecordToFile.getIcon());
button.setSelectedIcon(tglRecordToFile.getSelectedIcon());
button.setRolloverEnabled(false);
button.setToolTipText("Drag to the right to Remove... - Right Click for Settings");
button.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
JToggleButton button = ((JToggleButton) evt.getSource());
FME fme = fmes.get(button.getText());
if (button.isSelected()) {
if (fme != null){
fmeOutState = true;
String cleanBroad = checkDoubleBroad(button.getText());
if (!"".equals(cleanBroad)) {
broadcastsOut.add(cleanBroad);
// System.out.println("broadcastsOut: "+broadcastsOut);
}
fmeCount ++;
SinkBroadcast broadcast = new SinkBroadcast(fme);
broadcast.setStandard(fme.getStandard());
broadcast.setRate(MasterMixer.getInstance().getRate());
broadcast.setWidth(MasterMixer.getInstance().getWidth());
fme.setWidth(Integer.toString(MasterMixer.getInstance().getWidth()));
broadcast.setHeight(MasterMixer.getInstance().getHeight());
fme.setHeight(Integer.toString(MasterMixer.getInstance().getHeight()));
broadcast.setListener(instanceSinkFME);
broadcast.read();
broadcasts.put(button.getText(), broadcast);
ResourceMonitorLabel label = new ResourceMonitorLabel(System.currentTimeMillis()+10000, "Broadcasting to " + fme.getName());
labels.put(fme.getName(), label);
ResourceMonitor.getInstance().addMessage(label);
lblOnAir.setForeground(Color.RED);
} else {
fmeCount --;
button.setSelected(false);
}
} else {
fmeOutState = fmeCount > 0;
broadcastsOut.remove(button.getText());
SinkBroadcast broadcast = broadcasts.get(button.getText());
if (broadcast != null) {
fmeCount --;
broadcast.stop();
broadcast.destroy();
broadcasts.remove(fme.getName());
ResourceMonitorLabel label = labels.get(fme.getName());
labels.remove(fme.getName());
ResourceMonitor.getInstance().removeMessage(label);
if (fmeCount == 0 && !udpOutState) {
if (theme.equals("Dark")) {
lblOnAir.setForeground(Color.WHITE);
} else {
lblOnAir.setForeground(Color.BLACK);
}
}
}
}
}
});
button.addMouseMotionListener(new java.awt.event.MouseMotionListener() {
@Override
public void mouseDragged(MouseEvent e) {
if (e.getX() > getWidth()) {
JToggleButton button = ((JToggleButton) e.getSource());
if (!button.isSelected() && e.getX() > getWidth()) {
System.out.println(button.getText()+" removed ...");
SinkBroadcast broadcast = broadcasts.remove(button.getText());
if (broadcast != null) {
MasterChannels.getInstance().unregister(broadcast);
}
fmes.remove(button.getText());
labels.remove(fme.getName());
remove(button);
revalidate();
}
}
}
@Override
public void mouseMoved(MouseEvent e) {
}
});
button.addMouseListener(new java.awt.event.MouseAdapter() {
@Override
public void mousePressed(MouseEvent evt) {
JToggleButton button = ((JToggleButton) evt.getSource());
if (!button.isSelected()) {
fmeRightMousePressed(evt, fme);
}
}
});
this.add(button);
this.revalidate();
}
private void fmeRightMousePressed(java.awt.event.MouseEvent evt, FME fme) {
if (evt.isPopupTrigger()) {
fmePopup.show(evt.getComponent(), evt.getX(), evt.getY());
currFME = fme;
}
}
private void sinkFileRightMousePressed(java.awt.event.MouseEvent evt) { // , SinkFile sinkfile
if (evt.isPopupTrigger()) {
sinkFilePopup.show(evt.getComponent(), evt.getX(), evt.getY());
}
}
private void sinkUDPRightMousePressed(java.awt.event.MouseEvent evt) {
if (evt.isPopupTrigger()) {
sinkUDPPopup.show(evt.getComponent(), evt.getX(), evt.getY());
}
}
private void fmeInitPopUp(){
JMenuItem fmeSettings = new JMenuItem (new AbstractAction("FME Settings") {
@Override
public void actionPerformed(ActionEvent e) {
FMESettings fmeSet = new FMESettings(currFME);
fmeSet.setLocationRelativeTo(WebcamStudio.cboAnimations);
fmeSet.setAlwaysOnTop(true);
fmeSet.setVisible(true);
}
});
fmeSettings.setIcon(new ImageIcon(getClass().getResource("/webcamstudio/resources/tango/working-4.png"))); // NOI18N
fmePopup.add(fmeSettings);
}
private void sinkFileInitPopUp(){
JMenuItem sinkSettings = new JMenuItem (new AbstractAction("Record Settings") {
@Override
public void actionPerformed(ActionEvent e) {
SinkSettings sinkSet = new SinkSettings(fileStream, null);
sinkSet.setLocationRelativeTo(WebcamStudio.cboAnimations);
sinkSet.setAlwaysOnTop(true);
sinkSet.setVisible(true);
}
});
sinkSettings.setIcon(new ImageIcon(getClass().getResource("/webcamstudio/resources/tango/working-4.png"))); // NOI18N
sinkFilePopup.add(sinkSettings);
}
private void sinkUDPInitPopUp(){
JMenuItem sinkSettings = new JMenuItem (new AbstractAction("UDP Settings") {
@Override
public void actionPerformed(ActionEvent e) {
SinkSettings sinkSet = new SinkSettings(null, udpStream);
sinkSet.setLocationRelativeTo(WebcamStudio.cboAnimations);
sinkSet.setAlwaysOnTop(true);
sinkSet.setVisible(true);
}
});
sinkSettings.setIcon(new ImageIcon(getClass().getResource("/webcamstudio/resources/tango/working-4.png"))); // NOI18N
sinkUDPPopup.add(sinkSettings);
}
/** 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() {
outputTabs = new javax.swing.JTabbedPane();
panelVirtualC = new javax.swing.JPanel();
panelPixelFormat = new javax.swing.JPanel();
labelPixelFormat = new javax.swing.JLabel();
comboPixelFormat = new javax.swing.JComboBox();
panelVirtualA = new javax.swing.JPanel();
panelVirtualAudio = new javax.swing.JPanel();
tglWSAudioDev = new javax.swing.JCheckBox();
tglAudioOut = new javax.swing.JToggleButton();
panelDefault = new javax.swing.JPanel();
panelDefaultOutputs = new javax.swing.JPanel();
tglRecordToFile = new javax.swing.JToggleButton();
tglUDP = new javax.swing.JToggleButton();
panelFME = new javax.swing.JPanel();
panelSetFME = new javax.swing.JPanel();
btnAddFME = new javax.swing.JButton();
jLabel1 = new javax.swing.JLabel();
java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("webcamstudio/Languages"); // NOI18N
setBorder(javax.swing.BorderFactory.createTitledBorder(bundle.getString("OUTPUT"))); // NOI18N
setToolTipText(bundle.getString("DROP_OUTPUT")); // NOI18N
setPreferredSize(new java.awt.Dimension(237, 393));
setLayout(new org.netbeans.lib.awtextra.AbsoluteLayout());
outputTabs.setFont(new java.awt.Font("Noto Sans", 0, 11)); // NOI18N
outputTabs.setMaximumSize(new java.awt.Dimension(370, 32767));
outputTabs.setMinimumSize(new java.awt.Dimension(150, 98));
outputTabs.setName("outputTabs"); // NOI18N
// outputTabs.setFont(new java.awt.Font("Noto Sans", 0, 10));
panelVirtualC.setName("panelVirtualC"); // NOI18N
panelPixelFormat.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "WebcamStudio Virtual Cam", javax.swing.border.TitledBorder.CENTER, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Noto Sans", 0, 10))); // NOI18N
panelPixelFormat.setName("panelPixelFormat"); // NOI18N
labelPixelFormat.setFont(new java.awt.Font("Noto Sans", 0, 10)); // NOI18N
labelPixelFormat.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
labelPixelFormat.setText("Pixel Format");
labelPixelFormat.setName("labelPixelFormat"); // NOI18N
comboPixelFormat.setName("comboPixelFormat"); // NOI18N
javax.swing.GroupLayout panelPixelFormatLayout = new javax.swing.GroupLayout(panelPixelFormat);
panelPixelFormat.setLayout(panelPixelFormatLayout);
panelPixelFormatLayout.setHorizontalGroup(
panelPixelFormatLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelPixelFormatLayout.createSequentialGroup()
.addGroup(panelPixelFormatLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(labelPixelFormat)
.addComponent(comboPixelFormat, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap(84, Short.MAX_VALUE))
);
panelPixelFormatLayout.setVerticalGroup(
panelPixelFormatLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelPixelFormatLayout.createSequentialGroup()
.addGap(24, 24, 24)
.addComponent(labelPixelFormat)
.addGap(0, 0, 0)
.addComponent(comboPixelFormat, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
);
javax.swing.GroupLayout panelVirtualCLayout = new javax.swing.GroupLayout(panelVirtualC);
panelVirtualC.setLayout(panelVirtualCLayout);
panelVirtualCLayout.setHorizontalGroup(
panelVirtualCLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 178, Short.MAX_VALUE)
.addGroup(panelVirtualCLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelVirtualCLayout.createSequentialGroup()
.addContainerGap()
.addComponent(panelPixelFormat, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addContainerGap()))
);
panelVirtualCLayout.setVerticalGroup(
panelVirtualCLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 124, Short.MAX_VALUE)
.addGroup(panelVirtualCLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelVirtualCLayout.createSequentialGroup()
.addGap(0, 0, Short.MAX_VALUE)
.addComponent(panelPixelFormat, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, Short.MAX_VALUE)))
);
outputTabs.addTab("Webcam", panelVirtualC);
panelVirtualA.setName("panelVirtualA"); // NOI18N
panelVirtualAudio.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "WebcamStudio Virtual Audio", javax.swing.border.TitledBorder.CENTER, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Noto Sans", 0, 10))); // NOI18N
panelVirtualAudio.setName("panelVirtualAudio"); // NOI18N
tglWSAudioDev.setText("WSAudioDevice");
tglWSAudioDev.setToolTipText("WebcamStudio Master Audio Sink");
tglWSAudioDev.setName("tglWSAudioDev"); // NOI18N
tglWSAudioDev.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
tglWSAudioDevActionPerformed(evt);
}
});
tglAudioOut.setIcon(new javax.swing.ImageIcon(getClass().getResource("/webcamstudio/resources/tango/audio-card.png"))); // NOI18N
tglAudioOut.setText("Audio Out");
tglAudioOut.setToolTipText("WebcamStudio Master Audio Output");
tglAudioOut.setName("tglAudioOut"); // NOI18N
tglAudioOut.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
tglAudioOutActionPerformed(evt);
}
});
javax.swing.GroupLayout panelVirtualAudioLayout = new javax.swing.GroupLayout(panelVirtualAudio);
panelVirtualAudio.setLayout(panelVirtualAudioLayout);
panelVirtualAudioLayout.setHorizontalGroup(
panelVirtualAudioLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelVirtualAudioLayout.createSequentialGroup()
.addGroup(panelVirtualAudioLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(tglWSAudioDev, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(tglAudioOut, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addContainerGap(32, Short.MAX_VALUE))
);
panelVirtualAudioLayout.setVerticalGroup(
panelVirtualAudioLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelVirtualAudioLayout.createSequentialGroup()
.addComponent(tglAudioOut)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 25, Short.MAX_VALUE)
.addComponent(tglWSAudioDev))
);
javax.swing.GroupLayout panelVirtualALayout = new javax.swing.GroupLayout(panelVirtualA);
panelVirtualA.setLayout(panelVirtualALayout);
panelVirtualALayout.setHorizontalGroup(
panelVirtualALayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelVirtualALayout.createSequentialGroup()
.addContainerGap()
.addComponent(panelVirtualAudio, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addContainerGap())
);
panelVirtualALayout.setVerticalGroup(
panelVirtualALayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelVirtualALayout.createSequentialGroup()
.addContainerGap()
.addComponent(panelVirtualAudio, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addContainerGap())
);
outputTabs.addTab("Audio", panelVirtualA);
panelDefault.setName("panelDefault"); // NOI18N
panelDefaultOutputs.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "WebcamStudio Default Outputs", javax.swing.border.TitledBorder.CENTER, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Noto Sans", 0, 10))); // NOI18N
panelDefaultOutputs.setName("panelDefaultOutputs"); // NOI18N
tglRecordToFile.setIcon(new javax.swing.ImageIcon(getClass().getResource("/webcamstudio/resources/tango/media-record.png"))); // NOI18N
tglRecordToFile.setText(bundle.getString("RECORD")); // NOI18N
tglRecordToFile.setToolTipText("Save to FIle - Right Click for Settings");
tglRecordToFile.setMaximumSize(new java.awt.Dimension(32767, 32));
tglRecordToFile.setMinimumSize(new java.awt.Dimension(87, 21));
tglRecordToFile.setName("tglRecordToFile"); // NOI18N
tglRecordToFile.setPreferredSize(new java.awt.Dimension(300, 22));
tglRecordToFile.setRolloverIcon(new javax.swing.ImageIcon(getClass().getResource("/webcamstudio/resources/tango/media-record.png"))); // NOI18N
tglRecordToFile.setSelectedIcon(new javax.swing.ImageIcon(getClass().getResource("/webcamstudio/resources/tango/media-playback-stop.png"))); // NOI18N
tglRecordToFile.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
tglRecordToFileActionPerformed(evt);
}
});
tglUDP.setIcon(new javax.swing.ImageIcon(getClass().getResource("/webcamstudio/resources/tango/media-record.png"))); // NOI18N
tglUDP.setText(bundle.getString("UDP_MPEG_OUT")); // NOI18N
tglUDP.setToolTipText("Stream to udp://@127.0.0.1:7000 - Right Click for Settings");
tglUDP.setMaximumSize(new java.awt.Dimension(32767, 32));
tglUDP.setMinimumSize(new java.awt.Dimension(237, 21));
tglUDP.setName("tglUDP"); // NOI18N
tglUDP.setPreferredSize(new java.awt.Dimension(300, 22));
tglUDP.setRolloverIcon(new javax.swing.ImageIcon(getClass().getResource("/webcamstudio/resources/tango/media-record.png"))); // NOI18N
tglUDP.setSelectedIcon(new javax.swing.ImageIcon(getClass().getResource("/webcamstudio/resources/tango/media-playback-stop.png"))); // NOI18N
tglUDP.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
tglUDPActionPerformed(evt);
}
});
javax.swing.GroupLayout panelDefaultOutputsLayout = new javax.swing.GroupLayout(panelDefaultOutputs);
panelDefaultOutputs.setLayout(panelDefaultOutputsLayout);
panelDefaultOutputsLayout.setHorizontalGroup(
panelDefaultOutputsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelDefaultOutputsLayout.createSequentialGroup()
.addGroup(panelDefaultOutputsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(tglUDP, javax.swing.GroupLayout.PREFERRED_SIZE, 127, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(tglRecordToFile, javax.swing.GroupLayout.PREFERRED_SIZE, 79, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap(17, Short.MAX_VALUE))
);
panelDefaultOutputsLayout.setVerticalGroup(
panelDefaultOutputsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelDefaultOutputsLayout.createSequentialGroup()
.addComponent(tglRecordToFile, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(tglUDP, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap())
);
javax.swing.GroupLayout panelDefaultLayout = new javax.swing.GroupLayout(panelDefault);
panelDefault.setLayout(panelDefaultLayout);
panelDefaultLayout.setHorizontalGroup(
panelDefaultLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 178, Short.MAX_VALUE)
.addGroup(panelDefaultLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelDefaultLayout.createSequentialGroup()
.addContainerGap()
.addComponent(panelDefaultOutputs, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addContainerGap()))
);
panelDefaultLayout.setVerticalGroup(
panelDefaultLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 124, Short.MAX_VALUE)
.addGroup(panelDefaultLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelDefaultLayout.createSequentialGroup()
.addGap(0, 0, Short.MAX_VALUE)
.addComponent(panelDefaultOutputs, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, Short.MAX_VALUE)))
);
outputTabs.addTab("Default", panelDefault);
panelFME.setName("panelFME"); // NOI18N
panelSetFME.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "WebcamStudio FME", javax.swing.border.TitledBorder.CENTER, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Noto Sans", 0, 10))); // NOI18N
panelSetFME.setName("panelSetFME"); // NOI18N
btnAddFME.setFont(new java.awt.Font("Noto Sans", 3, 12)); // NOI18N
btnAddFME.setIcon(new javax.swing.ImageIcon(getClass().getResource("/webcamstudio/resources/tango/list-add.png"))); // NOI18N
btnAddFME.setText("Add FME");
btnAddFME.setToolTipText("Add FME");
btnAddFME.setMaximumSize(new java.awt.Dimension(32767, 34));
btnAddFME.setMinimumSize(new java.awt.Dimension(22, 22));
btnAddFME.setName("btnAddFME"); // NOI18N
btnAddFME.setPreferredSize(new java.awt.Dimension(300, 22));
btnAddFME.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnAddFMEActionPerformed(evt);
}
});
javax.swing.GroupLayout panelSetFMELayout = new javax.swing.GroupLayout(panelSetFME);
panelSetFME.setLayout(panelSetFMELayout);
panelSetFMELayout.setHorizontalGroup(
panelSetFMELayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 144, Short.MAX_VALUE)
.addGroup(panelSetFMELayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelSetFMELayout.createSequentialGroup()
.addContainerGap()
.addComponent(btnAddFME, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addContainerGap()))
);
panelSetFMELayout.setVerticalGroup(
panelSetFMELayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 79, Short.MAX_VALUE)
.addGroup(panelSetFMELayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelSetFMELayout.createSequentialGroup()
.addGap(15, 15, 15)
.addComponent(btnAddFME, javax.swing.GroupLayout.PREFERRED_SIZE, 35, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(29, Short.MAX_VALUE)))
);
javax.swing.GroupLayout panelFMELayout = new javax.swing.GroupLayout(panelFME);
panelFME.setLayout(panelFMELayout);
panelFMELayout.setHorizontalGroup(
panelFMELayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 178, Short.MAX_VALUE)
.addGroup(panelFMELayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelFMELayout.createSequentialGroup()
.addContainerGap()
.addComponent(panelSetFME, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addContainerGap()))
);
panelFMELayout.setVerticalGroup(
panelFMELayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 124, Short.MAX_VALUE)
.addGroup(panelFMELayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelFMELayout.createSequentialGroup()
.addContainerGap()
.addComponent(panelSetFME, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addContainerGap()))
);
outputTabs.addTab("FME", panelFME);
add(outputTabs, new org.netbeans.lib.awtextra.AbsoluteConstraints(17, 31, 190, -1));
jLabel1.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
jLabel1.setText("FMEs");
jLabel1.setName("jLabel1"); // NOI18N
add(jLabel1, new org.netbeans.lib.awtextra.AbsoluteConstraints(17, 203, 203, -1));
}// </editor-fold>//GEN-END:initComponents
private void tglRecordToFileActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_tglRecordToFileActionPerformed
if (tglRecordToFile.isSelected()) {
boolean overWrite = true;
JFileChooser chooser = new JFileChooser();
FileNameExtensionFilter aviFilter = new FileNameExtensionFilter("AVI files (*.avi)", "avi");
FileNameExtensionFilter mp4Filter = new FileNameExtensionFilter("MP4 files (*.mp4)", "mp4");
FileNameExtensionFilter flvFilter = new FileNameExtensionFilter("FLV files (*.flv)", "flv");
chooser.setFileFilter(aviFilter);
chooser.setFileFilter(mp4Filter);
chooser.setFileFilter(flvFilter);
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
chooser.setDialogTitle("Choose Destination File ...");
int retval = chooser.showSaveDialog(this);
f = chooser.getSelectedFile();
if (retval == JFileChooser.APPROVE_OPTION && f != null) {
if (chooser.getFileFilter().equals(aviFilter)) {
if(!chooser.getSelectedFile().getAbsolutePath().endsWith(".avi")){
f = new File(chooser.getSelectedFile() + ".avi");
}
} else if (chooser.getFileFilter().equals(mp4Filter) && !chooser.getSelectedFile().getAbsolutePath().endsWith(".mp4")) {
f = new File(chooser.getSelectedFile() + ".mp4");
} else if (chooser.getFileFilter().equals(flvFilter) && !chooser.getSelectedFile().getAbsolutePath().endsWith(".flv")) {
f = new File(chooser.getSelectedFile() + ".flv");
}
if(f.exists()){
int result = JOptionPane.showConfirmDialog(this,"File exists, overwrite?","Attention",JOptionPane.YES_NO_CANCEL_OPTION);
switch(result){
case JOptionPane.YES_OPTION:
overWrite = true;
break;
case JOptionPane.NO_OPTION:
overWrite = false;
break;
case JOptionPane.CANCEL_OPTION:
overWrite = false;
break;
case JOptionPane.CLOSED_OPTION:
overWrite = false;
break;
}
}
}
if (retval == JFileChooser.APPROVE_OPTION && overWrite) {
fileStream.setFile(f);
fileStream.setListener(instanceSink);
// Fix lost prefs
if ("".equals(fileStream.getVbitrate())) {
fileStream.setVbitrate("1200");
}
if ("".equals(fileStream.getAbitrate())) {
fileStream.setAbitrate("128");
}
fileStream.read();
// System.out.println("VBitRate: "+fileStream.getVbitrate());
files.put("RECORD", fileStream);
ResourceMonitorLabel label = new ResourceMonitorLabel(System.currentTimeMillis()+10000, "Recording to " + f.getName());
labels.put("RECORD", label);
ResourceMonitor.getInstance().addMessage(label);
} else {
tglRecordToFile.setSelected(false);
ResourceMonitorLabel label3 = new ResourceMonitorLabel(System.currentTimeMillis()+10000, "Record Cancelled!");
ResourceMonitor.getInstance().addMessage(label3);
}
} else {
SinkFile fileStream = files.get("RECORD");
if (fileStream != null) {
fileStream.stop();
fileStream = null;
files.remove("RECORD");
ResourceMonitorLabel label = labels.get("RECORD");
ResourceMonitor.getInstance().removeMessage(label);
ResourceMonitorLabel label2 = new ResourceMonitorLabel(System.currentTimeMillis()+10000, "File is saved!");
ResourceMonitor.getInstance().addMessage(label2);
}
}
}//GEN-LAST:event_tglRecordToFileActionPerformed
private void tglUDPActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_tglUDPActionPerformed
if (tglUDP.isSelected()) {
udpOutState = true;
udpStream.setListener(instanceSink);
// Fix lost prefs
if ("".equals(udpStream.getVbitrate())) {
udpStream.setVbitrate("1200");
}
if ("".equals(udpStream.getAbitrate())) {
udpStream.setAbitrate("128");
}
if ("".equals(udpStream.getStandard())) {
udpStream.setStandard("STD");
}
udpStream.read();
udpOut.put("UDPOut", udpStream);
ResourceMonitorLabel label = new ResourceMonitorLabel(System.currentTimeMillis()+10000, "Unicast mpeg2 to udp://127.0.0.1:7000");
labels.put("UDPOut", label);
ResourceMonitor.getInstance().addMessage(label);
lblOnAir.setForeground(Color.RED);
} else {
udpOutState = false;
SinkUDP udpStream = udpOut.get("UDPOut");
if (udpStream != null) {
udpStream.stop();
udpStream = null;
udpOut.remove("UDPOut");
ResourceMonitorLabel label = labels.get("UDPOut");
ResourceMonitor.getInstance().removeMessage(label);
}
if (fmeCount == 0) {
if (theme.equals("Dark")) {
lblOnAir.setForeground(Color.WHITE);
} else {
lblOnAir.setForeground(Color.BLACK);
}
}
}
}//GEN-LAST:event_tglUDPActionPerformed
private void paintWSCamButtons() {
for (final VideoDevice d : VideoDevice.getInputDevices()) {
String vdName = d.getFile().getName();
if (!vdName.endsWith("video21")) {
JToggleButton wsCamButton = new JToggleButton();
Dimension dim = new Dimension(139,22);
wsCamButton.setPreferredSize(dim);
wsCamButton.setText(d.getName());
wsCamButton.setActionCommand(d.getFile().getAbsolutePath());
wsCamButton.setIcon(tglRecordToFile.getIcon());
wsCamButton.setSelectedIcon(tglRecordToFile.getSelectedIcon());
wsCamButton.setRolloverEnabled(false);
wsCamButton.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
String device = evt.getActionCommand();
JToggleButton button = ((JToggleButton) evt.getSource());
if (button.isSelected()) {
camOutState = true;
String cleanCam = checkDoubleCam(button.getText());
if (!"".equals(cleanCam)) {
devicesOut.add(d.getName());
}
camCount ++;
SinkLinuxDevice stream = new SinkLinuxDevice(new File(device), button.getText(), (comboPixelFormat.getSelectedIndex() + 1));
stream.setRate(MasterMixer.getInstance().getRate());
stream.setWidth(MasterMixer.getInstance().getWidth());
stream.setHeight(MasterMixer.getInstance().getHeight());
stream.setListener(instanceSink);
stream.read();
devices.put(button.getText(), stream);
ResourceMonitorLabel label = new ResourceMonitorLabel(System.currentTimeMillis()+10000, "Rendering to " + button.getText() + " ("+(comboPixelFormat.getSelectedIndex() + 1)+")");
labels.put(button.getText(), label);
ResourceMonitor.getInstance().addMessage(label);
comboPixelFormat.setEnabled(false);
} else {
camOutState = camCount > 0;
devicesOut.remove(d.getName());
SinkLinuxDevice stream = devices.get(button.getText());
if (stream != null) {
camCount --;
stream.stop();
devices.remove(button.getText());
// System.out.println("WS Camera Stopped ...");
ResourceMonitorLabel label = labels.remove(button.getText());
ResourceMonitor.getInstance().removeMessage(label);
if (camCount == 0) {
comboPixelFormat.setEnabled(true);
}
}
if (camCount == 0) {
comboPixelFormat.setEnabled(true);
}
}
}
});
panelPixelFormat.add(wsCamButton);
panelPixelFormat.revalidate();
this.revalidate();
}
}
}
@Override
public void resetFMECount() {
fmeCount=0;
}
@Override
public void resetSinks(ActionEvent evt) {
fileStream.destroy();
udpStream.destroy();
audioStream.destroy();
f = new File(userHomeDir + "/.webcamstudio/Record To File");
fileStream = new SinkFile(f);
udpStream = new SinkUDP();
audioStream = new SinkAudio();
Preferences filePrefs = WebcamStudio.prefs.node("filerec");
Preferences udpPrefs = WebcamStudio.prefs.node("udp");
try {
String[] servicesF = filePrefs.childrenNames();
String[] servicesU = udpPrefs.childrenNames();
for (String s : servicesF){
Preferences serviceF = filePrefs.node(s);
fileStream.setVbitrate(serviceF.get("vbitrate", ""));
fileStream.setAbitrate(serviceF.get("abitrate", ""));
}
for (String s : servicesU){
Preferences serviceU = udpPrefs.node(s);
udpStream.setVbitrate(serviceU.get("vbitrate", ""));
udpStream.setAbitrate(serviceU.get("abitrate", ""));
udpStream.setStandard(serviceU.get("standard", ""));
}
} catch (BackingStoreException ex) {
Logger.getLogger(OutputPanel.class.getName()).log(Level.SEVERE, null, ex);
}
}
@Override
public void requestReset() {
audioOutSwitch = audioOutState;
udpOutSwitch = udpOutState;
if (fmeOutState) {
fmeOutSwitch = true;
fmeCount = 0;
} else {
fmeOutSwitch = false;
}
if (camOutState) {
camOutSwitch = true;
camCount = 0;
} else {
camOutSwitch = false;
}
}
@Override
public void requestStart() {
String[] currentBroadcasts = new String[broadcastsOut.size()];
currentBroadcasts = broadcastsOut.toArray(currentBroadcasts);
String[] currentDevices = new String[devicesOut.size()];
currentDevices = devicesOut.toArray(currentDevices);
if (audioOutSwitch){
tglAudioOut.doClick();
}
if (udpOutSwitch){
tglUDP.doClick();
}
if (fmeOutSwitch){
for (String bro : currentBroadcasts) {
for (Component c : this.getComponents()) {
if (c instanceof JToggleButton) {
JToggleButton b = (JToggleButton) c;
if (b.getText().equals(bro)) {
b.doClick();
}
}
}
}
}
if (camOutSwitch){
for (String cam : currentDevices) {
for (Component c : this.getComponents()) {
if (c instanceof JToggleButton) {
JToggleButton b = (JToggleButton) c;
if (b.getText().equals(cam)) {
b.doClick();
}
}
}
}
}
}
@Override
public void requestStop() {
audioOutSwitch = false;
udpOutSwitch = false;
fmeOutSwitch = false;
camOutSwitch = false;
}
@Override
public void resetAutoPLBtnState(ActionEvent evt) {
// Nothing Here
}
@Override
public void resetBtnStates(ActionEvent evt) {
comboPixelFormat.setEnabled(true);
tglWSAudioDev.setEnabled(true);
camCount = 0;
fmeCount = 0;
broadcastsOut.clear();
devicesOut.clear();
}
@Override
public void setRemoteOn() {
// Nothing Here
}
private void tglAudioOutActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_tglAudioOutActionPerformed
if (tglAudioOut.isSelected()) {
audioOutState = true;
tglWSAudioDev.setEnabled(false);
audioStream.setListener(instanceSink);
audioStream.read();
audioOut.put("AudioOut", audioStream);
ResourceMonitorLabel label = new ResourceMonitorLabel(System.currentTimeMillis()+10000, "Master Audio to Speakers");
labels.put("AudioOut", label);
ResourceMonitor.getInstance().addMessage(label);
if (tglWSAudioDev.isSelected()){
try {
Process p = Runtime.getRuntime().exec("pactl list short sinks");
InputStreamReader isr;
BufferedReader reader;
try (InputStream in = p.getInputStream()) {
isr = new InputStreamReader(in);
reader = new BufferedReader(isr);
String line = reader.readLine();
while (line != null) {
if (line.contains("WSAudioDevice")) {
String [] id = line.split("\t");
System.out.println("Found WSAD: <"+id[0]+">");
idWSAD = id[0];
}
line = reader.readLine();
}
}
isr.close();
reader.close();
p.destroy();
} catch (IOException ex) {
Logger.getLogger(OutputPanel.class.getName()).log(Level.SEVERE, null, ex);
}
Tools.sleep(250);
try {
Process p = Runtime.getRuntime().exec("pactl list short sink-inputs");
InputStreamReader isr;
BufferedReader reader;
try (InputStream in = p.getInputStream()) {
isr = new InputStreamReader(in);
reader = new BufferedReader(isr);
String line = reader.readLine();
while (line != null) {
String [] id = line.split("\t");
System.out.println("Found WSOut: <"+id[0]+">"+"<"+id[1]+">");
idWSOuts.add(id[0]);
idDef = id[1];
line = reader.readLine();
}
}
isr.close();
reader.close();
p.destroy();
} catch (IOException ex) {
Logger.getLogger(OutputPanel.class.getName()).log(Level.SEVERE, null, ex);
}
idWSOut = idWSOuts.get(idWSOuts.size()-1);
try {
execPACTL("pactl move-sink-input "+idWSOut+" "+idWSAD);
} catch (IOException ex) {
Logger.getLogger(OutputPanel.class.getName()).log(Level.SEVERE, null, ex);
} catch (InterruptedException ex) {
Logger.getLogger(OutputPanel.class.getName()).log(Level.SEVERE, null, ex);
}
}
} else {
audioOutState = false;
SinkAudio audioStream = audioOut.get("AudioOut");
// System.out.println("Killed SinkAudio"+audioStream);
tglWSAudioDev.setEnabled(true);
if (audioStream != null) {
audioStream.stop();
audioStream = null;
audioOut.remove("AudioOut");
ResourceMonitorLabel label = labels.get("AudioOut");
ResourceMonitor.getInstance().removeMessage(label);
}
if (tglWSAudioDev.isSelected()){
}
}
}//GEN-LAST:event_tglAudioOutActionPerformed
private void tglWSAudioDevActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_tglWSAudioDevActionPerformed
if (tglWSAudioDev.isSelected()){
try {
execPACTL("pactl load-module module-null-sink sink_name=WSAudioDevice sink_properties=device.description=\"WSAudioDevice\"");
} catch (IOException ex) {
Logger.getLogger(OutputPanel.class.getName()).log(Level.SEVERE, null, ex);
} catch (InterruptedException ex) {
Logger.getLogger(OutputPanel.class.getName()).log(Level.SEVERE, null, ex);
}
Tools.sleep(100);
} else {
try {
execPACTL("pactl unload-module module-null-sink");
} catch (IOException ex) {
Logger.getLogger(OutputPanel.class.getName()).log(Level.SEVERE, null, ex);
} catch (InterruptedException ex) {
Logger.getLogger(OutputPanel.class.getName()).log(Level.SEVERE, null, ex);
}
Tools.sleep(100);
}
}//GEN-LAST:event_tglWSAudioDevActionPerformed
private void btnAddFMEActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnAddFMEActionPerformed
final FME fme = new FME();
final FMEDialog fmeDiag = new FMEDialog(fme);
fmeDiag.setLocationRelativeTo(WebcamStudio.cboAnimations);
fmeDiag.setAlwaysOnTop(true);
fmeDiag.setVisible(true);
Thread addFME = new Thread(new Runnable() {
@Override
public void run() {
while (fmeDiag.isVisible()) {
Tools.sleep(100);
}
if (FMEDialog.add.equals("ok")) {
fmes.put(fme.getName(), fme);
addButtonBroadcast(fme);
}
}
});
addFME.setPriority(Thread.MIN_PRIORITY);
addFME.start();
}//GEN-LAST:event_btnAddFMEActionPerformed
public static void execPACTL(String command) throws IOException, InterruptedException {
// String output;
// System.out.println(command);
Process p = Runtime.getRuntime().exec(command);
try (InputStream in = p.getInputStream(); InputStreamReader isr = new InputStreamReader(in)) {
BufferedReader reader = new BufferedReader(isr);
reader.readLine();
reader.close();
}
p.waitFor();
p.destroy();
// System.out.println("Output: " + output);
// return output;
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton btnAddFME;
private javax.swing.JComboBox comboPixelFormat;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel labelPixelFormat;
private javax.swing.JTabbedPane outputTabs;
private javax.swing.JPanel panelDefault;
private javax.swing.JPanel panelDefaultOutputs;
private javax.swing.JPanel panelFME;
private javax.swing.JPanel panelPixelFormat;
private javax.swing.JPanel panelSetFME;
private javax.swing.JPanel panelVirtualA;
private javax.swing.JPanel panelVirtualAudio;
private javax.swing.JPanel panelVirtualC;
private javax.swing.JToggleButton tglAudioOut;
private javax.swing.JToggleButton tglRecordToFile;
final OutputPanel instanceSink = this;
private javax.swing.JToggleButton tglUDP;
private javax.swing.JCheckBox tglWSAudioDev;
// End of variables declaration//GEN-END:variables
@Override
public void sourceUpdated(Stream stream) {
if (stream instanceof SinkFile) {
tglRecordToFile.setSelected(stream.isPlaying());
} else if (stream instanceof SinkUDP) {
tglUDP.setSelected(stream.isPlaying());
} else if (stream instanceof SinkAudio) {
tglAudioOut.setSelected(stream.isPlaying());
} else if (stream instanceof SinkBroadcast) {
String name = stream.getName();
for (Component c : this.getComponents()) {
if (c instanceof JToggleButton) {
JToggleButton b = (JToggleButton) c;
if (b.getText().equals(name)) {
b.setSelected(stream.isPlaying());
}
}
}
} else if (stream instanceof SinkLinuxDevice) {
String name = stream.getName();
for (Component c : this.getComponents()) {
if (c instanceof JToggleButton) {
JToggleButton b = (JToggleButton) c;
if (b.getText().equals(name)) {
b.setSelected(stream.isPlaying());
}
}
}
}
}
@Override
public void updatePreview(BufferedImage image) {
// nothing here.
}
@Override
public void stopChTime(ActionEvent evt) {
// nothing here.
}
@Override
public void resetButtonsStates(ActionEvent evt) {
comboPixelFormat.setEnabled(true);
tglWSAudioDev.setEnabled(true);
camCount = 0;
fmeCount = 0;
}
@Override
public void addLoadingChannel(String name) { // used addLoadingChannel to activate Output from command line.
for (Component c : this.getComponents()) {
// At this moment this workaround. After will make the proper fix.
if (c instanceof JCheckBox) {
// Nothing here.
} else if (c instanceof JToggleButton) {
JToggleButton b = (JToggleButton) c;
if (b.getText().contains(name)) {
b.doClick();
}
}
}
}
@Override
public void removeChannels(String removeSc, int a) {
}
}