package chatty.gui.components.settings;
import chatty.Chatty;
import chatty.Helper;
import chatty.util.MiscUtil;
import chatty.util.Sound;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FilenameFilter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileNameExtensionFilter;
/**
*
* @author tduva
*/
public class SoundSettings extends SettingsPanel {
private static final Insets SMALL_BUTTON_INSETS = new Insets(-1,15,-1,15);
private final static String FILE_PATH = Chatty.getSoundDirectory();
private final static int VOLUME_MIN = 0;
private static final int VOLUME_MAX = 100;
private static final FileFilter FILE_FILTER = new FileNameExtensionFilter("Wav sounds", "wav");
private final SettingsDialog d;
private final Map<ComboStringSetting, String> fileSettings = new LinkedHashMap<>();
private final JLabel filesResult = new JLabel();
public SoundSettings(final SettingsDialog d) {
this.d = d;
JPanel general = addTitledPanel("General Sound Settings", 0);
GridBagConstraints gbc;
gbc = d.makeGbc(0, 0, 3, 1);
gbc.anchor = GridBagConstraints.WEST;
general.add(d.addSimpleBooleanSetting("sounds", "Enable sounds",
"Use this to enable/disable all sounds."), gbc);
gbc = d.makeGbc(0, 1, 3, 1, GridBagConstraints.WEST);
gbc.insets = new Insets(5,20,2,5);
general.add(new JLabel("Chatty looks for sound files (.wav) in this "
+ "folder:"), gbc);
gbc = d.makeGbc(0, 2, 3, 1);
gbc.insets = new Insets(3,20,3,5);
JTextField path = new JTextField(FILE_PATH);
path.setPreferredSize(new Dimension(0, path.getPreferredSize().height));
path.setEditable(false);
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1;
general.add(path, gbc);
ActionListener buttonListener = new MyButtonListener();
gbc = d.makeGbc(1, 3, 1, 1, GridBagConstraints.EAST);
JButton rescanButton = new JButton("Rescan folder");
rescanButton.setMargin(SMALL_BUTTON_INSETS);
rescanButton.addActionListener(buttonListener);
rescanButton.setActionCommand("scanFolder");
general.add(rescanButton, gbc);
gbc = d.makeGbc(0, 3, 1, 1, GridBagConstraints.EAST);
gbc.weightx = 1;
general.add(filesResult, gbc);
gbc = d.makeGbc(2, 3, 1, 1, GridBagConstraints.EAST);
JButton openFolderButton = new JButton("Open folder");
openFolderButton.setMargin(SMALL_BUTTON_INSETS);
openFolderButton.addActionListener(buttonListener);
openFolderButton.setActionCommand("openFolder");
general.add(openFolderButton, gbc);
// Output Device
JPanel devicePanel = new JPanel();
devicePanel.add(new JLabel("Output Device: "));
Map<String, String> devicePresets = new HashMap<>();
devicePresets.put("", "<default>");
for (String dev : Sound.getDeviceNames()) {
devicePresets.put(dev, dev);
}
final ComboStringSetting device = new ComboStringSetting(devicePresets);
device.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Sound.setDeviceName(device.getSettingValue());
}
});
d.addStringSetting("soundDevice", device);
devicePanel.add(device);
general.add(devicePanel, d.makeGbc(0, 4, 3, 1, GridBagConstraints.WEST));
// Tabs
JTabbedPane tabs = new JTabbedPane();
gbc = d.makeGbc(0, 1, 3, 1);
gbc.insets = new Insets(0,0,0,0);
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1;
addPanel(tabs, getGbc(1));
addSoundOptions(tabs, "highlight", "Highlight");
addSoundOptions(tabs, "status", "Stream Status");
addSoundOptions(tabs, "message", "Message");
addSoundOptions(tabs, "joinPart", "Join/Part");
addSoundOptions(tabs, "follower", "Follower");
// Delay
// gbc = d.makeGbc(0, 2, 1, 1);
// general.add(new JLabel("Sound delay (seconds): "), gbc);
//
// JTextField delay = d.addSimpleLongSetting("soundDelay", 3, true);
// gbc = d.makeGbc(1, 2, 1, 1);
// gbc.anchor = GridBagConstraints.WEST;
// general.add(delay, gbc);
addPanel(general, getGbc(0));
scanFiles(false);
}
private void addSoundOptions(JTabbedPane tabs, final String id, final String label) {
tabs.add(makeSoundOptions(id, label), label);
}
/**
* Creates a set of sound options using the given setting names, that must
* be valid.
*
* @param statusSetting The setting that contains whether this sound is
* on/off/..
* @param fileSetting The name of the sound file
* @param volumeSetting The volume adjustment of this sound
* @return A JPanel containing the components
*/
private JPanel makeSoundOptions(final String id, final String label) {
final String statusSetting = id+"Sound";
final String fileSetting = id+"SoundFile";
final String volumeSetting = id+"SoundVolume";
final String delaySetting = id+"SoundDelay";
GridBagConstraints gbc;
JPanel panel = new JPanel(new GridBagLayout());
panel.setBorder(new EmptyBorder(10,5,5,5));
// Status (on/off/..)
gbc = d.makeGbc(0, 0, 2, 1);
ComboStringSetting hlSetting = new ComboStringSetting(SettingConstants.requirementOptions);
d.addStringSetting(statusSetting, hlSetting);
panel.add(hlSetting, gbc);
// File
gbc = d.makeGbc(2, 0, 1, 1);
final ComboStringSetting file = d.addComboStringSetting(fileSetting, 20,
false, new String[]{});
//file.addCommand("choose", "Choose file..");
file.setPreferredSize(new Dimension(120,file.getPreferredSize().height));
fileSettings.put(file, label);
// file.setActionListener(new ActionListener() {
//
// @Override
// public void actionPerformed(ActionEvent e) {
// JFileChooser fileChooser = new JFileChooser("sounds");
// fileChooser.setFileFilter(FILE_FILTER);
// int result = fileChooser.showOpenDialog(d);
// if (result == JFileChooser.APPROVE_OPTION) {
// File selectedFile = fileChooser.getSelectedFile();
// String label = selectedFile.getName();
// String value = selectedFile.toString();
// file.add(value);
// }
// }
// });
panel.add(file, gbc);
// Play button
JButton play = new JButton("Play");
play.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String file = d.getStringSetting(fileSetting);
long volume = d.getLongSetting(volumeSetting);
Sound.play(file, volume, "test", -1);
}
});
gbc = d.makeGbc(3, 0, 1, 1);
panel.add(play, gbc);
JPanel secondPanel = new JPanel(new GridBagLayout());
// Volume
gbc = d.makeGbc(0, 0, 1, 1);
gbc.anchor = GridBagConstraints.WEST;
secondPanel.add(new JLabel("Volume:"), gbc);
SliderLongSetting volumeSlider = new SliderLongSetting(JSlider.HORIZONTAL, VOLUME_MIN, VOLUME_MAX, 0);
volumeSlider.setMajorTickSpacing(10);
volumeSlider.setMinorTickSpacing(5);
volumeSlider.setPaintTicks(true);
d.addLongSetting(volumeSetting, volumeSlider);
gbc = d.makeGbc(1, 0, 1, 1);
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1;
secondPanel.add(volumeSlider, gbc);
gbc = d.makeGbc(2, 0, 1, 1);
gbc.anchor = GridBagConstraints.EAST;
secondPanel.add(new JLabel("Delay:"), gbc);
JTextField delay = d.addSimpleLongSetting(delaySetting, 3, true);
gbc = d.makeGbc(3, 0, 1, 1);
gbc.insets = new Insets(5,5,5,2);
gbc.anchor = GridBagConstraints.EAST;
secondPanel.add(delay, gbc);
gbc = d.makeGbc(0, 1, 4, 1);
gbc.anchor = GridBagConstraints.WEST;
panel.add(secondPanel, gbc);
return panel;
}
private void scanFiles(boolean showMessage) {
File file = new File(FILE_PATH);
File[] files = file.listFiles(new WavFilenameFilter());
String resultText = "";
String warningText = "";
if (files == null) {
resultText = "Error scanning folder.";
} else {
if (files.length == 0) {
resultText = "No sound files found.";
} else {
resultText = files.length+" sound files found.";
}
String[] fileNames = new String[files.length];
for (int i=0;i<files.length;i++) {
fileNames[i] = files[i].getName();
}
Arrays.sort(fileNames);
for (ComboStringSetting s : fileSettings.keySet()) {
Object selected = s.getSelectedItem();
s.removeAllItems();
boolean currentOneStillThere = false;
for (String item : fileNames) {
if (item.equals(selected)) {
currentOneStillThere = true;
}
s.add(item);
}
if (!currentOneStillThere && selected != null) {
warningText += "\n'"+selected+"' (used as "+fileSettings.get(s)+" sound) wasn't found.";
} else {
s.setSelectedItem(selected);
}
}
}
if (showMessage) {
JOptionPane.showMessageDialog(this, resultText+warningText);
}
filesResult.setText(resultText);
}
private class MyButtonListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("openFolder")) {
MiscUtil.openFolder(new File(FILE_PATH), d);
} else if (e.getActionCommand().equals("scanFolder")) {
scanFiles(true);
}
}
}
private static class WavFilenameFilter implements FilenameFilter {
@Override
public boolean accept(File dir, String name) {
if (name.endsWith(".wav")) {
return true;
}
return false;
}
}
}