/* License see bottom*/
package jpianotrain.gui;
import static jpianotrain.util.ConfigurationKeys.KEYBOARD_IN_DEVICE;
import static jpianotrain.util.ConfigurationKeys.SYNTHESIZER_ENABLED;
import static jpianotrain.util.ConfigurationKeys.SYNTHESIZER_BANK;
import static jpianotrain.util.ConfigurationKeys.SYNTHESIZER_INSTRUMENT;
import static jpianotrain.util.ResourceKeys.INFO_PAGE_SYNTHESIZER;
import static jpianotrain.util.ResourceKeys.LABEL_BANK;
import static jpianotrain.util.ResourceKeys.LABEL_DEVICE_KEYBOARD;
import static jpianotrain.util.ResourceKeys.LABEL_INSTRUMENT;
import static jpianotrain.util.ResourceKeys.LABEL_SYNTHESIZER;
import static jpianotrain.util.ResourceKeys.MESSAGE_MIDI_INIT_FAILED;
import static jpianotrain.util.ResourceKeys.MESSAGE_NO_TRANSMITTER;
import static jpianotrain.util.ResourceKeys.TITLE_DESCRIPTION;
import static jpianotrain.util.ResourceKeys.TITLE_MIDI_INIT_FAILED;
import static jpianotrain.util.ResourceKeys.TITLE_SYNTHESIZER;
import static jpianotrain.util.ResourceKeys.TITLE_TEST;
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.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.sound.midi.Instrument;
import javax.sound.midi.MidiDevice;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.Patch;
import javax.sound.midi.Synthesizer;
import javax.sound.midi.MidiDevice.Info;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import jpianotrain.ApplicationContext;
import jpianotrain.event.SynthesizerPanelListener;
import jpianotrain.midi.MidiThread;
import jpianotrain.util.ResourceFactory;
import jpianotrain.util.UserConfiguration;
import org.apache.log4j.Logger;
/**
* Configuration panel for builtin Java Synthesizer.
*
* @author methke01
* @since 0.0.2
*/
public class SynthesizerPanel extends ConfigurationPanel
implements ChangeListener,
MidiChooser {
private static final Logger log=Logger.getLogger(SynthesizerPanel.class);
public SynthesizerPanel() {
super();
createUI();
listeners=new ArrayList<SynthesizerPanelListener>();
}
protected void createUI() {
setLayout(new GridBagLayout());
GridBagConstraints gbc=new GridBagConstraints();
InfoPanel ip=new InfoPanel(INFO_PAGE_SYNTHESIZER, true);
ip.setPreferredSize(new Dimension(260, 100));
ip.setMaximumSize(ip.getPreferredSize());
gbc.gridx=0;
gbc.gridy=0;
gbc.gridheight=GridBagConstraints.REMAINDER;
gbc.fill=GridBagConstraints.BOTH;
add(ip, gbc);
gbc.gridx=1;
JPanel jp=createSynthesizerPanel();
jp.setBorder(createBorder(TITLE_SYNTHESIZER));
gbc.gridheight=1;
gbc.weightx=0.3;
gbc.weighty=0.6;
add(jp, gbc);
testSettings=new TestSettings();
testSettings.setMidiChooser(this);
testSettings.setBorder(createBorder(TITLE_TEST));
gbc.gridy++;
gbc.weightx=0.3;
gbc.weighty=0.4;
add(testSettings, gbc);
descriptionPanel=new DeviceDescription();
gbc.gridy=0;
gbc.gridx=2;
gbc.weightx=0.7;
gbc.fill=GridBagConstraints.BOTH;
gbc.gridwidth=GridBagConstraints.REMAINDER;
gbc.gridheight=GridBagConstraints.REMAINDER;
descriptionPanel.setBorder(createBorder(TITLE_DESCRIPTION));
add(descriptionPanel, gbc);
}
private JPanel createSynthesizerPanel() {
JPanel jp=new JPanel();
instrumentList=new JComboBox();
instrumentList.setMaximumSize(new Dimension(150, 20));
instrumentList.setPreferredSize(instrumentList.getPreferredSize());
activateCheck=new JCheckBox();
activateCheck.addActionListener(this);
bankSpinner=new JSpinner();
bankSpinner.addChangeListener(this);
GridBagConstraints gbc=new GridBagConstraints();
jp.setLayout(new GridBagLayout());
gbc.insets=new Insets(2,2,2,2);
gbc.gridx=0;
gbc.gridy=0;
gbc.anchor=GridBagConstraints.EAST;
jp.add(createLabel(LABEL_SYNTHESIZER), gbc);
gbc.gridy++;
jp.add(createLabel(LABEL_DEVICE_KEYBOARD), gbc);
gbc.gridy++;
jp.add(createLabel(LABEL_BANK), gbc);
gbc.gridy++;
jp.add(createLabel(LABEL_INSTRUMENT), gbc);
gbc.gridx++;
gbc.gridy=0;
jp.add(activateCheck, gbc);
keyboardInBox = new JComboBox();
keyboardInBox.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent evt) {
keyboardInBoxItemStateChanged(evt);
}
});
gbc.gridy++;
jp.add(keyboardInBox, gbc);
gbc.gridy++;
jp.add(bankSpinner, gbc);
gbc.gridy++;
gbc.fill=GridBagConstraints.HORIZONTAL;
jp.add(instrumentList, gbc);
return jp;
}
public void initData() {
instrumentMap=new HashMap<Integer, List<Instrument>>();
int maxBank=Integer.MIN_VALUE;
int minBank=Integer.MAX_VALUE;
try {
synth =
MidiSystem.getSynthesizer();
synth.open();
Instrument[] instruments =
synth.getAvailableInstruments();
for(Instrument i:instruments) {
Patch p=i.getPatch();
int bank=p.getBank();
if (bank>maxBank) {
maxBank=bank;
}
if (bank<minBank) {
minBank=bank;
}
List<Instrument> l=instrumentMap.get(bank);
if (l==null) {
l=new ArrayList<Instrument>();
instrumentMap.put(bank, l);
}
l.add(i);
if (instrumentMap.size()==1) {
instrumentList.addItem(i);
}
}
} catch (Exception ex) {
log.error("failed to show some midi information", ex);
}
((SpinnerNumberModel)bankSpinner.getModel()).setMinimum(minBank);
((SpinnerNumberModel)bankSpinner.getModel()).setMaximum(maxBank);
keyboardInBox.removeAllItems();
UserConfiguration uc=UserConfiguration.getInstance();
if (uc.getBooleanProperty(SYNTHESIZER_ENABLED, false)) {
activateCheck.setSelected(true);
enableSynthesizer(true);
} else {
activateCheck.setSelected(false);
enableSynthesizer(false);
}
int bank=uc.getIntProperty(SYNTHESIZER_BANK, -1);
if (bank!=-1) {
bankSpinner.setValue(bank);
}
int instrument=uc.getIntProperty(SYNTHESIZER_INSTRUMENT, -1);
if (instrument!=-1) {
instrumentList.setSelectedIndex(instrument);
}
if (keyInIndex==-1) {
keyInIndex=uc.getIntProperty(KEYBOARD_IN_DEVICE, -1);
}
try {
MidiDevice dev;
MidiDevice.Info[] info=MidiSystem.getMidiDeviceInfo();
int c=info.length;
for (int i=0;i<c;i++) {
dev=MidiSystem.getMidiDevice(info[i]);
int max=dev.getMaxTransmitters();
if (max>0 || max==-1) {
keyboardInBox.addItem(info[i]);
}
}
if (keyInIndex!=-1) {
keyboardInBox.setSelectedIndex(keyInIndex);
}
} catch (Exception ex) {
log.error("failure while filling midi in list", ex);
}
}
public void rejectData() {
if (synth.isOpen()) {
synth.close();
}
}
public void saveData() {
UserConfiguration uc=UserConfiguration.getInstance();
uc.putProperty(SYNTHESIZER_ENABLED, activateCheck.isSelected());
uc.putProperty(SYNTHESIZER_BANK,
((SpinnerNumberModel)bankSpinner.getModel()).getNumber().intValue());
uc.putProperty(SYNTHESIZER_INSTRUMENT, instrumentList.getSelectedIndex());
ApplicationContext ctx=ApplicationContext.getInstance();
if (synth.isOpen()) {
synth.close();
}
boolean flag=false;
try {
this.keyInIndex=keyboardInBox.getSelectedIndex();
uc.putProperty(KEYBOARD_IN_DEVICE, keyInIndex);
MidiDevice.Info keyInfo=(MidiDevice.Info)keyboardInBox.getSelectedItem();
MidiDevice keyDev=MidiSystem.getMidiDevice(keyInfo);
if (keyDev.getMaxTransmitters()==0) {
JOptionPane.showMessageDialog(ctx.getDefaultDialogOwner(),
ResourceFactory.getString(MESSAGE_NO_TRANSMITTER),
ResourceFactory.getString(TITLE_MIDI_INIT_FAILED),
JOptionPane.ERROR_MESSAGE);
}
flag=MidiThread.getInstance().init(keyDev,
synth,
(Instrument)instrumentList.getSelectedItem());
} catch (Exception ex) {
log.error("failed to init midi thread", ex);
}
if (flag) {
ctx.setMidiStatus(ApplicationContext.MidiStatus.ON);
} else {
ctx.setMidiStatus(ApplicationContext.MidiStatus.OFF);
JOptionPane.showMessageDialog(ctx.getDefaultDialogOwner(),
ResourceFactory.getString(MESSAGE_MIDI_INIT_FAILED),
ResourceFactory.getString(TITLE_MIDI_INIT_FAILED),
JOptionPane.ERROR_MESSAGE);
}
}
// ItemListener
private void keyboardInBoxItemStateChanged(ItemEvent evt) {
descriptionPanel.setDeviceInfo((MidiDevice.Info)keyboardInBox.getSelectedItem());
}
// ChangeListener
public void stateChanged(ChangeEvent e) {
if (e.getSource()!=bankSpinner) {
return;
}
Number n=((SpinnerNumberModel)bankSpinner.getModel()).getNumber();
List<Instrument> il=instrumentMap.get(n.intValue());
if (il==null) {
return;
}
instrumentList.removeAllItems();
for (Instrument i:il) {
instrumentList.addItem(i);
}
}
// MidiChooser
@Override
public int getSelectedChannel() {
return -1;
}
@Override
public Instrument getSelectedInstrument() {
return (Instrument)instrumentList.getSelectedItem();
}
@Override
public Info getSelectedOutputDevice() {
return null;
}
@Override
public Synthesizer getSelectedSynthesizer() {
return synth;
}
// ActionListener
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource()==activateCheck) {
enableSynthesizer(activateCheck.isSelected());
}
}
public void addListener(SynthesizerPanelListener l) {
if (listeners.contains(l)) {
return;
}
listeners.add(l);
}
public void removeListener(SynthesizerPanelListener l) {
listeners.remove(l);
}
private void enableSynthesizer(boolean state) {
testSettings.setEnabled(state);
bankSpinner.setEnabled(state);
instrumentList.setEnabled(state);
descriptionPanel.setEnabled(state);
keyboardInBox.setEnabled(state);
for(SynthesizerPanelListener spl:listeners) {
spl.synthesizerPanelEnabled(state);
}
}
private int keyInIndex;
private List<SynthesizerPanelListener> listeners;
private Synthesizer synth;
private Map<Integer, List<Instrument>> instrumentMap;
private JCheckBox activateCheck;
private JSpinner bankSpinner;
private JComboBox instrumentList;
private JComboBox keyboardInBox;
private TestSettings testSettings;
private DeviceDescription descriptionPanel;
}
/*
Copyright (C) 2008 Alexander Methke
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program 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 for more details.
You should have received a copy of the GNU General Public License
along with this program (gplv3.txt).
*/