/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2014 Neil C Smith.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 3 for more details.
*
* You should have received a copy of the GNU General Public License version 3
* along with this work; if not, see http://www.gnu.org/licenses/
*
*
* Please visit http://neilcsmith.net if you need additional information or
* have any questions.
*/
package net.neilcsmith.praxis.live.audio.options;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import net.neilcsmith.praxis.audio.AudioSettings;
import org.jaudiolibs.audioservers.AudioServerProvider;
import org.jaudiolibs.audioservers.ext.Device;
import org.openide.util.Lookup;
final class GeneralAudioPanel extends javax.swing.JPanel {
private final static String JAVASOUND = "JavaSound";
private final static String JACK = "JACK";
private final static DeviceInfo DEFAULT_DEVICE_INFO = new DeviceInfo(null);
// private final static String[] libraries = new String[]{
// "JavaSound", "JACK"
// };
// private final static String[] libraryDisplay = new String[]{
// "JavaSound", "Jack Audio Connection Kit"
// };
private final static int[] buffersizes = new int[]{
32, 64, 128, 256, 512, 1024, 2048, 4096
};
// private final static String[] buffersizeDisplay = new String[]{
// "32", "64", "128", "256", "512", "1024", "2048", "4096"
// };
private final GeneralAudioOptionsPanelController controller;
private final List<Library> libraries;
GeneralAudioPanel(GeneralAudioOptionsPanelController controller) {
this.controller = controller;
this.libraries = initLibraries();
initComponents();
initChoosers();
}
private List<Library> initLibraries() {
List<Library> libs = new ArrayList<>();
for (AudioServerProvider prov
: Lookup.getDefault().lookupAll(AudioServerProvider.class)) {
libs.add(new Library(prov));
}
Collections.sort(libs, new Comparator<Library>() {
@Override
public int compare(Library lib1, Library lib2) {
String n1 = lib1.provider.getLibraryName();
String n2 = lib2.provider.getLibraryName();
if (JAVASOUND.equals(n1)) {
return -1;
} else if (JAVASOUND.equals(n2)) {
return 1;
} else {
return n1.compareTo(n2);
}
}
});
return libs;
}
/**
* 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.
*/
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
defaultConfigPanel = new javax.swing.JPanel();
defaultConfigDescription = new javax.swing.JLabel();
libraryLbl = new javax.swing.JLabel();
libraryChooser = new javax.swing.JComboBox();
deviceLbl = new javax.swing.JLabel();
deviceChooser = new javax.swing.JComboBox();
buffersizeLbl = new javax.swing.JLabel();
buffersizeChooser = new javax.swing.JComboBox();
inputDeviceLbl = new javax.swing.JLabel();
inputDeviceChooser = new javax.swing.JComboBox();
slaveWarning = new javax.swing.JLabel();
defaultConfigPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(GeneralAudioPanel.class, "GeneralAudioPanel.defaultConfigPanel.border.title"))); // NOI18N
defaultConfigDescription.setForeground(javax.swing.UIManager.getDefaults().getColor("textInactiveText"));
defaultConfigDescription.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
org.openide.awt.Mnemonics.setLocalizedText(defaultConfigDescription, org.openide.util.NbBundle.getMessage(GeneralAudioPanel.class, "GeneralAudioPanel.defaultConfigDescription.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(libraryLbl, org.openide.util.NbBundle.getMessage(GeneralAudioPanel.class, "GeneralAudioPanel.libraryLbl.text")); // NOI18N
libraryChooser.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
libraryChooserActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(deviceLbl, org.openide.util.NbBundle.getMessage(GeneralAudioPanel.class, "GeneralAudioPanel.deviceLbl.text")); // NOI18N
deviceChooser.setEnabled(false);
deviceChooser.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
deviceChooserActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(buffersizeLbl, org.openide.util.NbBundle.getMessage(GeneralAudioPanel.class, "GeneralAudioPanel.buffersizeLbl.text")); // NOI18N
buffersizeChooser.setEnabled(false);
org.openide.awt.Mnemonics.setLocalizedText(inputDeviceLbl, org.openide.util.NbBundle.getMessage(GeneralAudioPanel.class, "GeneralAudioPanel.inputDeviceLbl.text")); // NOI18N
inputDeviceChooser.setEnabled(false);
slaveWarning.setFont(slaveWarning.getFont().deriveFont(slaveWarning.getFont().getStyle() | java.awt.Font.BOLD));
slaveWarning.setForeground(javax.swing.UIManager.getDefaults().getColor("textInactiveText"));
slaveWarning.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
org.openide.awt.Mnemonics.setLocalizedText(slaveWarning, org.openide.util.NbBundle.getMessage(GeneralAudioPanel.class, "GeneralAudioPanel.slaveWarning.text")); // NOI18N
javax.swing.GroupLayout defaultConfigPanelLayout = new javax.swing.GroupLayout(defaultConfigPanel);
defaultConfigPanel.setLayout(defaultConfigPanelLayout);
defaultConfigPanelLayout.setHorizontalGroup(
defaultConfigPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(defaultConfigPanelLayout.createSequentialGroup()
.addGroup(defaultConfigPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(defaultConfigPanelLayout.createSequentialGroup()
.addGap(42, 42, 42)
.addComponent(defaultConfigDescription, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGroup(defaultConfigPanelLayout.createSequentialGroup()
.addContainerGap()
.addGroup(defaultConfigPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(buffersizeLbl)
.addComponent(libraryLbl)
.addComponent(deviceLbl)
.addComponent(inputDeviceLbl))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(defaultConfigPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(inputDeviceChooser, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(buffersizeChooser, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(libraryChooser, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(deviceChooser, javax.swing.GroupLayout.Alignment.TRAILING, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
.addComponent(slaveWarning, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addContainerGap())
);
defaultConfigPanelLayout.setVerticalGroup(
defaultConfigPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(defaultConfigPanelLayout.createSequentialGroup()
.addContainerGap()
.addGroup(defaultConfigPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(libraryChooser, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(libraryLbl))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(defaultConfigPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(deviceChooser, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(deviceLbl))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(defaultConfigPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(inputDeviceChooser, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(inputDeviceLbl))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(defaultConfigPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(buffersizeLbl)
.addComponent(buffersizeChooser, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 181, Short.MAX_VALUE)
.addComponent(defaultConfigDescription)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(slaveWarning)
.addContainerGap())
);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(defaultConfigPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(defaultConfigPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addContainerGap())
);
}// </editor-fold>//GEN-END:initComponents
private void libraryChooserActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_libraryChooserActionPerformed
Object o = libraryChooser.getSelectedItem();
if (o instanceof Library) {
initLibrary((Library) o);
}
}//GEN-LAST:event_libraryChooserActionPerformed
private void deviceChooserActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deviceChooserActionPerformed
Object o = deviceChooser.getSelectedItem();
if (o instanceof DeviceInfo) {
DeviceInfo info = (DeviceInfo) o;
if (info.device != null && info.device.getMaxInputChannels() > 0) {
inputDeviceChooser.setSelectedItem(DEFAULT_DEVICE_INFO);
inputDeviceChooser.setEnabled(false);
} else {
inputDeviceChooser.setEnabled(inputDeviceChooser.getItemCount() > 1);
}
}
}//GEN-LAST:event_deviceChooserActionPerformed
private void initChoosers() {
for (Library lib : libraries) {
libraryChooser.addItem(lib);
}
for (int bsize : buffersizes) {
buffersizeChooser.addItem(bsize);
}
}
void load() {
String libName = AudioSettings.getLibrary();
Library active = libraries.get(0);
for (Library lib : libraries) {
if (lib.provider.getLibraryName().equals(libName)) {
active = lib;
break;
}
}
libraryChooser.setSelectedItem(active);
}
void store() {
Object o = libraryChooser.getSelectedItem();
if (o instanceof Library) {
AudioSettings.setLibrary(((Library)o).provider.getLibraryName());
}
o = deviceChooser.getSelectedItem();
if (o instanceof DeviceInfo) {
DeviceInfo info = (DeviceInfo) o;
if (info.device != null) {
AudioSettings.setDeviceName(info.device.getName());
} else {
AudioSettings.setDeviceName(null);
}
}
o = inputDeviceChooser.getSelectedItem();
if (o instanceof DeviceInfo) {
DeviceInfo info = (DeviceInfo) o;
if (info.device != null) {
AudioSettings.setInputDeviceName(info.device.getName());
} else {
AudioSettings.setInputDeviceName(null);
}
}
if (buffersizeChooser.isEnabled()) {
o = buffersizeChooser.getSelectedItem();
if (o instanceof Integer) {
AudioSettings.setBuffersize((int)o);
}
}
}
private void initLibrary(Library lib) {
deviceChooser.removeAllItems();
inputDeviceChooser.removeAllItems();
String devName = AudioSettings.getDeviceName();
String inDevName = AudioSettings.getInputDeviceName();
DeviceInfo dev = DEFAULT_DEVICE_INFO;
DeviceInfo inDev = DEFAULT_DEVICE_INFO;
for (DeviceInfo devInfo : lib.devices) {
deviceChooser.addItem(devInfo);
if (devInfo.device != null && devInfo.device.getName().equals(devName)) {
dev = devInfo;
}
}
for (DeviceInfo devInfo : lib.inputDevices) {
inputDeviceChooser.addItem(devInfo);
if (devInfo.device != null && devInfo.device.getName().equals(inDevName)) {
inDev = devInfo;
}
}
inputDeviceChooser.setSelectedItem(inDev);
deviceChooser.setSelectedItem(dev);
int bsize = AudioSettings.getBuffersize();
buffersizeChooser.setSelectedItem(bsize);
inputDeviceChooser.setEnabled(inputDeviceChooser.getItemCount() > 1);
deviceChooser.setEnabled(deviceChooser.getItemCount() > 1);
buffersizeChooser.setEnabled(!JACK.equals(lib.provider.getLibraryName()));
}
boolean valid() {
// check whether form is consistent and complete
return true;
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JComboBox buffersizeChooser;
private javax.swing.JLabel buffersizeLbl;
private javax.swing.JLabel defaultConfigDescription;
private javax.swing.JPanel defaultConfigPanel;
private javax.swing.JComboBox deviceChooser;
private javax.swing.JLabel deviceLbl;
private javax.swing.JComboBox inputDeviceChooser;
private javax.swing.JLabel inputDeviceLbl;
private javax.swing.JComboBox libraryChooser;
private javax.swing.JLabel libraryLbl;
private javax.swing.JLabel slaveWarning;
// End of variables declaration//GEN-END:variables
private static class Library {
private final AudioServerProvider provider;
private final String desc;
private final DeviceInfo[] devices;
private final DeviceInfo[] inputDevices;
private Library(AudioServerProvider provider) {
this.provider = provider;
String str = provider.getLibraryDescription();
if (!str.isEmpty()) {
desc = provider.getLibraryName() + " : " + str;
} else {
desc = provider.getLibraryName();
}
List<DeviceInfo> outs = new ArrayList<>();
List<DeviceInfo> ins = new ArrayList<>();
outs.add(DEFAULT_DEVICE_INFO);
ins.add(DEFAULT_DEVICE_INFO);
for (Device device : provider.findAll(Device.class)) {
if (device.getMaxOutputChannels() > 0) {
outs.add(new DeviceInfo(device));
} else if (device.getMaxInputChannels() > 0) {
ins.add(new DeviceInfo(device));
}
}
devices = outs.toArray(new DeviceInfo[outs.size()]);
inputDevices = ins.toArray(new DeviceInfo[ins.size()]);
}
@Override
public String toString() {
return desc;
}
@Override
public int hashCode() {
int hash = 7;
hash = 97 * hash + Objects.hashCode(this.provider);
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Library other = (Library) obj;
if (!Objects.equals(this.provider, other.provider)) {
return false;
}
return true;
}
}
private static class DeviceInfo {
private final Device device;
private DeviceInfo(Device device) {
this.device = device;
}
@Override
public String toString() {
return device == null ? "Default Device" : device.getName();
}
@Override
public int hashCode() {
int hash = 7;
hash = 79 * hash + Objects.hashCode(this.device);
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final DeviceInfo other = (DeviceInfo) obj;
if (!Objects.equals(this.device, other.device)) {
return false;
}
return true;
}
}
}