/*
* Created on Dec 15, 2004
*
* Copyright (c) 2005 Peter Johan Salomonsen (http://www.petersalomonsen.com)
*
* http://www.frinika.com
*
* This file is part of Frinika.
*
* Frinika 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 2 of the License, or
* (at your option) any later version.
*
* Frinika 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 Frinika; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package com.frinika.synth.synths.sampler;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.sound.sampled.TargetDataLine;
import javax.swing.ButtonGroup;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JSlider;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
import com.frinika.voiceserver.JavaSoundVoiceServer;
import com.frinika.sequencer.gui.AudioDeviceHandle;
import com.frinika.synth.InstrumentNameListener;
import com.frinika.synth.Synth;
import com.frinika.synth.importers.wav.WavImporter;
import com.frinika.synth.synths.MySampler;
import com.frinika.synth.synths.sampler.settings.SampledSoundSettings;
import com.frinika.tools.MyFileFilter;
import static com.frinika.localization.CurrentLocale.getMessage;
/**
* @author Peter Johan Salomonsen
*
*/
public class SamplerGUI extends JFrame implements InstrumentNameListener {
private static final long serialVersionUID = 1L;
TableModel sampleMapTableModel;
JTable sampleMapTable;
RecorderGUI recorderGUI;
SampleMapTableRenderer sampleMapTableRenderer = new SampleMapTableRenderer();
MySampler sampler;
static boolean stereo = false;
static TargetDataLine lineIn = null;
static AudioDeviceHandle audioInDevice = null;
public SamplerGUI(final MySampler sampler)
{
this.sampler = sampler;
setLayout(new BorderLayout());
JPanel layersPanel = new JPanel();
final JComboBox layerComboBox = new JComboBox();
for(int n=1;n<=6;n++)
{
layerComboBox.addItem(new Integer(n));
}
layerComboBox.setSelectedIndex(sampler.getSamplerSettings().getLayers()-1);
layerComboBox.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
sampler.getSamplerSettings().setLayers(layerComboBox.getSelectedIndex()+1);
}});
layersPanel.add(new JLabel("Layers: "));
layersPanel.add(layerComboBox);
final JSlider freqSpreadSlider = new JSlider(JSlider.HORIZONTAL,0,1000,
(int)(sampler.getSamplerSettings().getFreqSpread()*80f));
freqSpreadSlider.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
sampler.getSamplerSettings().setFreqSpread((freqSpreadSlider.getValue() / 80f));
}});
layersPanel.add(new JLabel("Frequency spread:"));
layersPanel.add(freqSpreadSlider);
JPanel midPanel = new JPanel();
midPanel.setLayout(new BorderLayout());
midPanel.add(layersPanel,BorderLayout.NORTH);
sampleMapTableModel = new SampleMapTableModel(sampler);
sampleMapTable = new JTable(sampleMapTableModel) {
private static final long serialVersionUID = 1L;
public Component prepareRenderer(TableCellRenderer renderer,
int row, int column) {
Component c = super.prepareRenderer(renderer, row, column);
if(column == 0)
{
switch(row%12)
{
case 0:
// C
c.setBackground(Color.WHITE);
c.setForeground(Color.BLACK);
break;
case 1:
// B
c.setBackground(Color.WHITE);
c.setForeground(Color.BLACK);
break;
case 2:
// A#
c.setBackground(Color.BLACK);
c.setForeground(Color.WHITE);
break;
case 3:
// A
c.setBackground(Color.WHITE);
c.setForeground(Color.BLACK);
break;
case 4:
// G#
c.setBackground(Color.BLACK);
c.setForeground(Color.WHITE);
break;
case 5:
// G
c.setBackground(Color.WHITE);
c.setForeground(Color.BLACK);
break;
case 6:
// F#
c.setBackground(Color.BLACK);
c.setForeground(Color.WHITE);
break;
case 7:
// F
c.setBackground(Color.WHITE);
c.setForeground(Color.BLACK);
break;
case 8:
// E
c.setBackground(Color.WHITE);
c.setForeground(Color.BLACK);
break;
case 9:
// D#
c.setBackground(Color.BLACK);
c.setForeground(Color.WHITE);
break;
case 10:
// D
c.setBackground(Color.WHITE);
c.setForeground(Color.BLACK);
break;
case 11:
// C#
c.setBackground(Color.BLACK);
c.setForeground(Color.WHITE);
break;
}
}
else
{
if(!sampleMapTable.isCellSelected(row,column))
{
c.setBackground(null);
c.setForeground(null);
}
}
return c;
}
};
sampleMapTable.getColumnModel().getColumn(0).setHeaderValue("Note/Vel");
sampleMapTable.setIntercellSpacing(new Dimension(0,0));
sampleMapTable.setShowGrid(false);
sampleMapTable.setFont(new Font(sampleMapTable.getFont().getFontName(),
sampleMapTable.getFont().getStyle(), 9));
for(int n = 1;n<sampleMapTable.getColumnCount();n++)
{
TableColumn col = sampleMapTable.getColumnModel().getColumn(n);
col.setHeaderValue(128-n);
col.setCellRenderer(sampleMapTableRenderer );
col.setMinWidth(5);
col.setPreferredWidth(5);
//col.setHeaderRenderer(new SampleMapTableRenderer());
}
sampleMapTable.getTableHeader().setReorderingAllowed(false);
sampleMapTable.getTableHeader().setResizingAllowed(false);
sampleMapTable.setColumnSelectionAllowed(true);
sampleMapTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
JScrollPane sampleMapPane = new JScrollPane(sampleMapTable);
midPanel.add(sampleMapPane,BorderLayout.CENTER);
add(midPanel,BorderLayout.CENTER);
sampleMapTable.addMouseListener(new MouseAdapter() {
/* (non-Javadoc)
* @see java.awt.event.MouseAdapter#mouseClicked(java.awt.event.MouseEvent)
*/
public void mouseClicked(MouseEvent e) {
if(e.getClickCount()==2)
new SampleEditor((SampledSoundSettings)sampleMapTableModel.getValueAt(sampleMapTable.getSelectedRow(),sampleMapTable.getSelectedColumn()));
}
});
JMenuBar menuBar = new JMenuBar();
add(menuBar,BorderLayout.NORTH);
JMenu fileMenu = new JMenu("File");
menuBar.add(fileMenu);
final JMenuItem renameMenuItem = new JMenuItem("Rename");
renameMenuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
sampler.setInstrumentName(
JOptionPane.showInputDialog("Enter new name",
sampler.getInstrumentName()));
}});
fileMenu.add(renameMenuItem);
final JMenuItem importSFMenuItem = new JMenuItem("Import SoundFont V2");
importSFMenuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
sampler.sfi.showGUI();
}});
fileMenu.add(importSFMenuItem);
final JMenuItem importWavMenuItem = new JMenuItem("Import Wav");
importWavMenuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try
{
JFileChooser chooser = new JFileChooser();
chooser.setDialogTitle("Import wav");
chooser.setFileFilter(new MyFileFilter(".wav","Wav files"));
if(chooser.showOpenDialog(SamplerGUI.this)==
JFileChooser.APPROVE_OPTION) {
SampledSoundSettings sampledSound = new WavImporter().importWav(chooser.getSelectedFile());
sampledSound.setRootKey(getLowestNotenumberInSelection());
insertSampleToSelection(sampledSound);
};
} catch(Exception ex) { ex.printStackTrace(); }
}});
fileMenu.add(importWavMenuItem);
JMenu recordMenu = new JMenu("Record");
menuBar.add(recordMenu);
if(sampler.getAudioOutput() instanceof JavaSoundVoiceServer)
{
JMenu audioInputMenu = new JMenu(getMessage("sampler.menu.audio_inputs"));
recordMenu.add(audioInputMenu);
try {
throw new Exception("FIXME");
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
// if(audioInDevice==null)
// {
// audioInDevice = AudioHub.getAudioInHandles().get(0);
// lineIn = audioInDevice.getLine();
// stereo = audioInDevice.getFormat().getChannels() == 2 ? true : false;
// }
//
// ButtonGroup audioInGroup = new ButtonGroup();
// for(final AudioDeviceHandle device : AudioHub.getAudioInHandles())
// {
// JRadioButtonMenuItem audioInItem = new JRadioButtonMenuItem(device.toString());
//
// if(audioInItem.getText().equals(audioInDevice.toString()))
// audioInItem.setSelected(true);
//
// audioInputMenu.add(audioInItem);
// audioInGroup.add(audioInItem);
// audioInItem.addActionListener(new ActionListener() {
//
// public void actionPerformed(ActionEvent event) {
// audioInDevice = device;
// }});
// }
}
else
{
JMenu audioInputMenu = new JMenu(getMessage("sampler.menu.audio_inputs"));
recordMenu.add(audioInputMenu);
ButtonGroup audioInGroup = new ButtonGroup();
JMenuItem item = new JRadioButtonMenuItem("Mono (left)");
item.setSelected(!stereo);
audioInGroup.add(item);
audioInputMenu.add(item);
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
stereo = false;
}});
item = new JRadioButtonMenuItem("Stereo");
item.setSelected(stereo);
audioInGroup.add(item);
audioInputMenu.add(item);
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
stereo = true;
}});
}
final JMenuItem recordMenuItem = new JMenuItem("Record to key");
recordMenuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
sampler.recordMode = MySampler.RECORDMODE_SINGLE_KEY;
startSampler();
}});
recordMenu.add(recordMenuItem);
final JMenuItem recordAllKeysMenuItem = new JMenuItem("Record to all keys");
recordAllKeysMenuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
sampler.recordMode = MySampler.RECORDMODE_ALL_KEYS;
startSampler();
}});
recordMenu.add(recordAllKeysMenuItem);
final JMenuItem recordToSelectionMenuItem = new JMenuItem("Record to selection");
recordToSelectionMenuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
sampler.recordMode = MySampler.RECORDMODE_SELECTION;
startSampler();
}});
recordMenu.add(recordToSelectionMenuItem);
setSize(700,500);
setVisible(true);
setTitle(sampler.getInstrumentName());
sampler.addInstrumentNameListener(this);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
addWindowListener(new WindowAdapter() {
/* (non-Javadoc)
* @see java.awt.event.WindowAdapter#windowClosed(java.awt.event.WindowEvent)
*/
public void windowClosed(WindowEvent e) {
sampler.removeInstrumentNameListener(SamplerGUI.this);
}
});
}
void startSampler()
{
try {
sampler.samplerOscillator.startMonitor(lineIn,stereo);
openRecorderGUI();
JOptionPane.showMessageDialog(SamplerGUI.this,"Your input is now being monitored. Recording will start on MIDI Note ON and stop on MIDI Note OFF.");
} catch (Exception e) {
e.printStackTrace();
JOptionPane.showMessageDialog(SamplerGUI.this,getMessage("sampler.menu.audio_input_error"));
}
}
void openRecorderGUI()
{
if(recorderGUI!=null)
recorderGUI.dispose();
recorderGUI = new RecorderGUI(sampler.samplerOscillator);
}
public void insertSampleToSelection(SampledSoundSettings sampledSound)
{
for(int x : sampleMapTable.getSelectedColumns())
for(int y : sampleMapTable.getSelectedRows())
sampleMapTable.setValueAt(sampledSound,y,x);
}
public static void main(String[] args)
{
new SamplerGUI(null);
}
public int getLowestNotenumberInSelection()
{
int row = 0;
for(int n : sampleMapTable.getSelectedRows())
if(n>row)
row = n;
return 96-row;
}
/**
* Check if the given note with the specified velocity is selected
* @param noteNumber
* @param velocity
* @return
*/
public boolean isNoteInSelection(int noteNumber, int velocity) {
return sampleMapTable.isCellSelected(96-noteNumber,128-velocity);
}
/* (non-Javadoc)
* @see com.petersalomonsen.mystudio.mysynth.InstrumentNameListener#instrumentNameChange(java.lang.String)
*/
public void instrumentNameChange(Synth synth, String instrumentName) {
setTitle(instrumentName);
}
}