/** * Music editor * * @author pquiring * * Created : Jan 14, 2014 */ import java.util.*; import java.io.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.table.*; import javax.swing.filechooser.*; import javax.sound.midi.*; import javaforce.*; import javaforce.media.*; import javaforce.jni.*; public class SongPanel extends javax.swing.JPanel implements Music.Listener, Receiver, MediaIO { /** * Creates new form MainPanel */ public SongPanel() { initComponents(); tableView.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); tableView.setTableHeader(null); tableView.setRowHeight(20); colModel = (DefaultTableColumnModel)tableView.getColumnModel(); samples = new Samples(this); samplesPane.setViewportView(samples); loadLibrary(); reset(); } /** * 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() { noteTypes = new javax.swing.ButtonGroup(); tabs = new javax.swing.JTabbedPane(); generalTab = new javax.swing.JPanel(); jLabel1 = new javax.swing.JLabel(); name = new javax.swing.JTextField(); jLabel8 = new javax.swing.JLabel(); jScrollPane3 = new javax.swing.JScrollPane(); comment = new javax.swing.JTextArea(); patternsTab = new javax.swing.JPanel(); jToolBar2 = new javax.swing.JToolBar(); jLabel11 = new javax.swing.JLabel(); pattern = new javax.swing.JComboBox(); addPattern = new javax.swing.JButton(); removePattern = new javax.swing.JButton(); jButton10 = new javax.swing.JButton(); filler2 = new javax.swing.Box.Filler(new java.awt.Dimension(10, 0), new java.awt.Dimension(10, 0), new java.awt.Dimension(10, 32767)); jButton11 = new javax.swing.JButton(); jButton12 = new javax.swing.JButton(); filler5 = new javax.swing.Box.Filler(new java.awt.Dimension(10, 0), new java.awt.Dimension(10, 0), new java.awt.Dimension(10, 32767)); jButton2 = new javax.swing.JButton(); jButton3 = new javax.swing.JButton(); jButton1 = new javax.swing.JButton(); jToolBar4 = new javax.swing.JToolBar(); jLabel2 = new javax.swing.JLabel(); bpm = new javax.swing.JSpinner(); filler3 = new javax.swing.Box.Filler(new java.awt.Dimension(10, 0), new java.awt.Dimension(10, 0), new java.awt.Dimension(10, 32767)); jLabel3 = new javax.swing.JLabel(); jButton7 = new javax.swing.JButton(); jButton8 = new javax.swing.JButton(); filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(10, 0), new java.awt.Dimension(10, 0), new java.awt.Dimension(10, 32767)); jScrollPane1 = new javax.swing.JScrollPane(); tableView = new javax.swing.JTable() { public TableCellEditor getCellEditor(int row, int column) { if (row == 0) return _getCellEditor(row, column); return super.getCellEditor(row, column); } }; seqTab = new javax.swing.JPanel(); jScrollPane4 = new javax.swing.JScrollPane(); sequence = new javax.swing.JList(); seqUp = new javax.swing.JButton(); seqDown = new javax.swing.JButton(); jToolBar1 = new javax.swing.JToolBar(); jLabel13 = new javax.swing.JLabel(); seqPattern = new javax.swing.JComboBox(); seqAdd = new javax.swing.JButton(); seqRemove = new javax.swing.JButton(); instrTab = new javax.swing.JPanel(); jToolBar5 = new javax.swing.JToolBar(); jLabel14 = new javax.swing.JLabel(); instrument = new javax.swing.JComboBox(); iRemove = new javax.swing.JButton(); jButton9 = new javax.swing.JButton(); filler9 = new javax.swing.Box.Filler(new java.awt.Dimension(10, 0), new java.awt.Dimension(10, 0), new java.awt.Dimension(10, 32767)); jLabel5 = new javax.swing.JLabel(); library = new javax.swing.JComboBox(); iAddLibrary = new javax.swing.JButton(); filler10 = new javax.swing.Box.Filler(new java.awt.Dimension(10, 0), new java.awt.Dimension(10, 0), new java.awt.Dimension(10, 32767)); jLabel7 = new javax.swing.JLabel(); iAddFile = new javax.swing.JButton(); filler6 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(32767, 0)); jToolBar7 = new javax.swing.JToolBar(); jLabel6 = new javax.swing.JLabel(); regions = new javax.swing.JComboBox(); jButton14 = new javax.swing.JButton(); jButton15 = new javax.swing.JButton(); jButton13 = new javax.swing.JButton(); filler11 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(32767, 0)); samplesTab = new javax.swing.JPanel(); jToolBar3 = new javax.swing.JToolBar(); jLabel9 = new javax.swing.JLabel(); sample = new javax.swing.JComboBox(); jButton17 = new javax.swing.JButton(); jButton18 = new javax.swing.JButton(); jButton16 = new javax.swing.JButton(); filler8 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(32767, 0)); jToolBar6 = new javax.swing.JToolBar(); sustain = new javax.swing.JCheckBox(); loop = new javax.swing.JCheckBox(); attenuation = new javax.swing.JCheckBox(); filler4 = new javax.swing.Box.Filler(new java.awt.Dimension(10, 0), new java.awt.Dimension(10, 0), new java.awt.Dimension(10, 32767)); jLabel4 = new javax.swing.JLabel(); zoom = new javax.swing.JComboBox(); jButton4 = new javax.swing.JButton(); jButton5 = new javax.swing.JButton(); jButton6 = new javax.swing.JButton(); filler7 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(32767, 0)); samplesPane = new javax.swing.JScrollPane(); tabs.setPreferredSize(new java.awt.Dimension(418, 580)); generalTab.setPreferredSize(new java.awt.Dimension(418, 580)); jLabel1.setText("Name:"); jLabel8.setText("Comments:"); comment.setColumns(20); comment.setRows(5); jScrollPane3.setViewportView(comment); javax.swing.GroupLayout generalTabLayout = new javax.swing.GroupLayout(generalTab); generalTab.setLayout(generalTabLayout); generalTabLayout.setHorizontalGroup( generalTabLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(generalTabLayout.createSequentialGroup() .addContainerGap() .addGroup(generalTabLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(generalTabLayout.createSequentialGroup() .addComponent(jLabel1) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(name)) .addGroup(generalTabLayout.createSequentialGroup() .addComponent(jLabel8) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 550, Short.MAX_VALUE))) .addContainerGap()) ); generalTabLayout.setVerticalGroup( generalTabLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(generalTabLayout.createSequentialGroup() .addContainerGap() .addGroup(generalTabLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel1) .addComponent(name, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addGroup(generalTabLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jLabel8) .addComponent(jScrollPane3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addContainerGap(449, Short.MAX_VALUE)) ); tabs.addTab("General", generalTab); patternsTab.setPreferredSize(new java.awt.Dimension(418, 580)); jToolBar2.setFloatable(false); jToolBar2.setRollover(true); jLabel11.setText("Pattern:"); jToolBar2.add(jLabel11); pattern.setMaximumSize(new java.awt.Dimension(128, 20)); pattern.setMinimumSize(new java.awt.Dimension(128, 20)); pattern.addItemListener(new java.awt.event.ItemListener() { public void itemStateChanged(java.awt.event.ItemEvent evt) { patternItemStateChanged(evt); } }); jToolBar2.add(pattern); addPattern.setIcon(new javax.swing.ImageIcon(getClass().getResource("/plus.png"))); // NOI18N addPattern.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { addPatternActionPerformed(evt); } }); jToolBar2.add(addPattern); removePattern.setIcon(new javax.swing.ImageIcon(getClass().getResource("/minus.png"))); // NOI18N removePattern.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { removePatternActionPerformed(evt); } }); jToolBar2.add(removePattern); jButton10.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edit.png"))); // NOI18N jButton10.setFocusable(false); jButton10.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); jButton10.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); jButton10.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButton10ActionPerformed(evt); } }); jToolBar2.add(jButton10); jToolBar2.add(filler2); jButton11.setIcon(new javax.swing.ImageIcon(getClass().getResource("/up.png"))); // NOI18N jButton11.setFocusable(false); jButton11.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); jButton11.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); jButton11.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButton11ActionPerformed(evt); } }); jToolBar2.add(jButton11); jButton12.setIcon(new javax.swing.ImageIcon(getClass().getResource("/down.png"))); // NOI18N jButton12.setFocusable(false); jButton12.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); jButton12.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); jButton12.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButton12ActionPerformed(evt); } }); jToolBar2.add(jButton12); jToolBar2.add(filler5); jButton2.setIcon(new javax.swing.ImageIcon(getClass().getResource("/play.png"))); // NOI18N jButton2.setFocusable(false); jButton2.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); jButton2.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); jButton2.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButton2ActionPerformed(evt); } }); jToolBar2.add(jButton2); jButton3.setIcon(new javax.swing.ImageIcon(getClass().getResource("/stop.png"))); // NOI18N jButton3.setFocusable(false); jButton3.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); jButton3.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); jButton3.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButton3ActionPerformed(evt); } }); jToolBar2.add(jButton3); jButton1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/record.png"))); // NOI18N jButton1.setFocusable(false); jButton1.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); jButton1.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); jButton1.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButton1ActionPerformed(evt); } }); jToolBar2.add(jButton1); jToolBar4.setFloatable(false); jLabel2.setText("BPM:"); jToolBar4.add(jLabel2); bpm.setModel(new javax.swing.SpinnerNumberModel(80, 1, 65536, 1)); bpm.setMaximumSize(new java.awt.Dimension(60, 20)); bpm.setMinimumSize(new java.awt.Dimension(20, 20)); bpm.setPreferredSize(new java.awt.Dimension(20, 20)); bpm.addChangeListener(new javax.swing.event.ChangeListener() { public void stateChanged(javax.swing.event.ChangeEvent evt) { bpmStateChanged(evt); } }); bpm.addKeyListener(new java.awt.event.KeyAdapter() { public void keyTyped(java.awt.event.KeyEvent evt) { bpmKeyTyped(evt); } }); jToolBar4.add(bpm); jToolBar4.add(filler3); jLabel3.setText("Track:"); jToolBar4.add(jLabel3); jButton7.setIcon(new javax.swing.ImageIcon(getClass().getResource("/plus.png"))); // NOI18N jButton7.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButton7ActionPerformed(evt); } }); jToolBar4.add(jButton7); jButton8.setIcon(new javax.swing.ImageIcon(getClass().getResource("/minus.png"))); // NOI18N jButton8.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButton8ActionPerformed(evt); } }); jToolBar4.add(jButton8); jToolBar4.add(filler1); tableView.setFont(JF.getMonospacedFont(0, 12)); tableView.setModel(tableModel); tableView.setCellSelectionEnabled(true); tableView.getTableHeader().setReorderingAllowed(false); tableView.addMouseListener(new java.awt.event.MouseAdapter() { public void mouseClicked(java.awt.event.MouseEvent evt) { tableViewMouseClicked(evt); } }); tableView.addKeyListener(new java.awt.event.KeyAdapter() { public void keyPressed(java.awt.event.KeyEvent evt) { tableViewKeyPressed(evt); } public void keyReleased(java.awt.event.KeyEvent evt) { tableViewKeyReleased(evt); } public void keyTyped(java.awt.event.KeyEvent evt) { tableViewKeyTyped(evt); } }); jScrollPane1.setViewportView(tableView); tableView.getColumnModel().getSelectionModel().setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); javax.swing.GroupLayout patternsTabLayout = new javax.swing.GroupLayout(patternsTab); patternsTab.setLayout(patternsTabLayout); patternsTabLayout.setHorizontalGroup( patternsTabLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jToolBar2, javax.swing.GroupLayout.DEFAULT_SIZE, 628, Short.MAX_VALUE) .addComponent(jToolBar4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 628, Short.MAX_VALUE) ); patternsTabLayout.setVerticalGroup( patternsTabLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(patternsTabLayout.createSequentialGroup() .addComponent(jToolBar2, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jToolBar4, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 520, Short.MAX_VALUE)) ); tabs.addTab("Patterns", patternsTab); seqTab.setPreferredSize(new java.awt.Dimension(418, 580)); sequence.addListSelectionListener(new javax.swing.event.ListSelectionListener() { public void valueChanged(javax.swing.event.ListSelectionEvent evt) { sequenceValueChanged(evt); } }); jScrollPane4.setViewportView(sequence); seqUp.setIcon(new javax.swing.ImageIcon(getClass().getResource("/up.png"))); // NOI18N seqUp.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { seqUpActionPerformed(evt); } }); seqDown.setIcon(new javax.swing.ImageIcon(getClass().getResource("/down.png"))); // NOI18N seqDown.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { seqDownActionPerformed(evt); } }); jToolBar1.setFloatable(false); jToolBar1.setRollover(true); jLabel13.setText("Pattern:"); jToolBar1.add(jLabel13); seqPattern.setMaximumSize(new java.awt.Dimension(128, 20)); seqPattern.setMinimumSize(new java.awt.Dimension(128, 20)); jToolBar1.add(seqPattern); seqAdd.setIcon(new javax.swing.ImageIcon(getClass().getResource("/plus.png"))); // NOI18N seqAdd.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { seqAddActionPerformed(evt); } }); jToolBar1.add(seqAdd); seqRemove.setIcon(new javax.swing.ImageIcon(getClass().getResource("/minus.png"))); // NOI18N seqRemove.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { seqRemoveActionPerformed(evt); } }); javax.swing.GroupLayout seqTabLayout = new javax.swing.GroupLayout(seqTab); seqTab.setLayout(seqTabLayout); seqTabLayout.setHorizontalGroup( seqTabLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(seqTabLayout.createSequentialGroup() .addContainerGap() .addComponent(jScrollPane4, javax.swing.GroupLayout.PREFERRED_SIZE, 172, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(seqTabLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(seqUp) .addComponent(seqDown) .addComponent(seqRemove)) .addContainerGap(391, Short.MAX_VALUE)) .addComponent(jToolBar1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) ); seqTabLayout.setVerticalGroup( seqTabLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(seqTabLayout.createSequentialGroup() .addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(seqTabLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(seqTabLayout.createSequentialGroup() .addComponent(seqUp) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(seqDown) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(seqRemove) .addGap(0, 0, Short.MAX_VALUE)) .addComponent(jScrollPane4, javax.swing.GroupLayout.DEFAULT_SIZE, 556, Short.MAX_VALUE))) ); tabs.addTab("Sequence", seqTab); instrTab.setPreferredSize(new java.awt.Dimension(418, 580)); jToolBar5.setFloatable(false); jToolBar5.setRollover(true); jToolBar5.setMinimumSize(new java.awt.Dimension(1, 1)); jToolBar5.setPreferredSize(new java.awt.Dimension(1, 25)); jLabel14.setText("Instrument:"); jToolBar5.add(jLabel14); instrument.setMaximumSize(new java.awt.Dimension(256, 32767)); instrument.setMinimumSize(new java.awt.Dimension(256, 20)); instrument.addItemListener(new java.awt.event.ItemListener() { public void itemStateChanged(java.awt.event.ItemEvent evt) { instrumentItemStateChanged(evt); } }); jToolBar5.add(instrument); iRemove.setIcon(new javax.swing.ImageIcon(getClass().getResource("/minus.png"))); // NOI18N iRemove.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { iRemoveActionPerformed(evt); } }); jToolBar5.add(iRemove); jButton9.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edit.png"))); // NOI18N jButton9.setFocusable(false); jButton9.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); jButton9.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); jButton9.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButton9ActionPerformed(evt); } }); jToolBar5.add(jButton9); jToolBar5.add(filler9); jLabel5.setText("Library:"); jToolBar5.add(jLabel5); library.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Piano", "etc" })); library.setMaximumSize(new java.awt.Dimension(256, 32767)); library.setMinimumSize(new java.awt.Dimension(256, 20)); jToolBar5.add(library); iAddLibrary.setIcon(new javax.swing.ImageIcon(getClass().getResource("/plus.png"))); // NOI18N iAddLibrary.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { iAddLibraryActionPerformed(evt); } }); jToolBar5.add(iAddLibrary); jToolBar5.add(filler10); jLabel7.setText("Import:"); jToolBar5.add(jLabel7); iAddFile.setIcon(new javax.swing.ImageIcon(getClass().getResource("/plus.png"))); // NOI18N iAddFile.setToolTipText(""); iAddFile.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { iAddFileActionPerformed(evt); } }); jToolBar5.add(iAddFile); jToolBar5.add(filler6); jToolBar7.setFloatable(false); jToolBar7.setRollover(true); jLabel6.setText("Regions:"); jToolBar7.add(jLabel6); regions.setMaximumSize(new java.awt.Dimension(256, 32767)); regions.setMinimumSize(new java.awt.Dimension(256, 20)); regions.addItemListener(new java.awt.event.ItemListener() { public void itemStateChanged(java.awt.event.ItemEvent evt) { regionsItemStateChanged(evt); } }); jToolBar7.add(regions); jButton14.setIcon(new javax.swing.ImageIcon(getClass().getResource("/plus.png"))); // NOI18N jButton14.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButton14ActionPerformed(evt); } }); jToolBar7.add(jButton14); jButton15.setIcon(new javax.swing.ImageIcon(getClass().getResource("/minus.png"))); // NOI18N jButton15.setToolTipText(""); jButton15.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButton15ActionPerformed(evt); } }); jToolBar7.add(jButton15); jButton13.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edit.png"))); // NOI18N jButton13.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButton13ActionPerformed(evt); } }); jToolBar7.add(jButton13); jToolBar7.add(filler11); javax.swing.GroupLayout instrTabLayout = new javax.swing.GroupLayout(instrTab); instrTab.setLayout(instrTabLayout); instrTabLayout.setHorizontalGroup( instrTabLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jToolBar5, javax.swing.GroupLayout.DEFAULT_SIZE, 628, Short.MAX_VALUE) .addComponent(jToolBar7, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) ); instrTabLayout.setVerticalGroup( instrTabLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(instrTabLayout.createSequentialGroup() .addComponent(jToolBar5, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jToolBar7, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE) .addContainerGap(531, Short.MAX_VALUE)) ); tabs.addTab("Instruments", instrTab); jToolBar3.setFloatable(false); jToolBar3.setRollover(true); jLabel9.setText("Sample:"); jToolBar3.add(jLabel9); sample.setMaximumSize(new java.awt.Dimension(256, 32767)); sample.setMinimumSize(new java.awt.Dimension(256, 20)); sample.addItemListener(new java.awt.event.ItemListener() { public void itemStateChanged(java.awt.event.ItemEvent evt) { sampleItemStateChanged(evt); } }); jToolBar3.add(sample); jButton17.setIcon(new javax.swing.ImageIcon(getClass().getResource("/plus.png"))); // NOI18N jButton17.setToolTipText(""); jButton17.setFocusable(false); jButton17.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); jButton17.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); jButton17.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButton17ActionPerformed(evt); } }); jToolBar3.add(jButton17); jButton18.setIcon(new javax.swing.ImageIcon(getClass().getResource("/minus.png"))); // NOI18N jButton18.setFocusable(false); jButton18.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); jButton18.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); jButton18.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButton18ActionPerformed(evt); } }); jToolBar3.add(jButton18); jButton16.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edit.png"))); // NOI18N jButton16.setFocusable(false); jButton16.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); jButton16.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); jButton16.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButton16ActionPerformed(evt); } }); jToolBar3.add(jButton16); jToolBar3.add(filler8); jToolBar6.setFloatable(false); jToolBar6.setRollover(true); jToolBar6.setMinimumSize(new java.awt.Dimension(1, 1)); jToolBar6.setPreferredSize(new java.awt.Dimension(1, 25)); sustain.setText("Sustain"); sustain.addItemListener(new java.awt.event.ItemListener() { public void itemStateChanged(java.awt.event.ItemEvent evt) { sustainItemStateChanged(evt); } }); jToolBar6.add(sustain); loop.setText("Loop"); loop.addItemListener(new java.awt.event.ItemListener() { public void itemStateChanged(java.awt.event.ItemEvent evt) { loopItemStateChanged(evt); } }); jToolBar6.add(loop); attenuation.setText("Attenuation"); attenuation.addItemListener(new java.awt.event.ItemListener() { public void itemStateChanged(java.awt.event.ItemEvent evt) { attenuationItemStateChanged(evt); } }); jToolBar6.add(attenuation); jToolBar6.add(filler4); jLabel4.setText("Zoom:"); jToolBar6.add(jLabel4); zoom.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "1:1", "1:2", "1:4", "1:8", "1:16", "1:32", "1:64", "1:128" })); zoom.setMaximumSize(new java.awt.Dimension(128, 32767)); zoom.setMinimumSize(new java.awt.Dimension(128, 20)); zoom.addItemListener(new java.awt.event.ItemListener() { public void itemStateChanged(java.awt.event.ItemEvent evt) { zoomItemStateChanged(evt); } }); jToolBar6.add(zoom); jButton4.setIcon(new javax.swing.ImageIcon(getClass().getResource("/play.png"))); // NOI18N jButton4.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButton4ActionPerformed(evt); } }); jToolBar6.add(jButton4); jButton5.setIcon(new javax.swing.ImageIcon(getClass().getResource("/stop.png"))); // NOI18N jButton5.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButton5ActionPerformed(evt); } }); jToolBar6.add(jButton5); jButton6.setIcon(new javax.swing.ImageIcon(getClass().getResource("/keyup.png"))); // NOI18N jButton6.setToolTipText("Key up"); jButton6.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButton6ActionPerformed(evt); } }); jToolBar6.add(jButton6); jToolBar6.add(filler7); javax.swing.GroupLayout samplesTabLayout = new javax.swing.GroupLayout(samplesTab); samplesTab.setLayout(samplesTabLayout); samplesTabLayout.setHorizontalGroup( samplesTabLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jToolBar3, javax.swing.GroupLayout.DEFAULT_SIZE, 628, Short.MAX_VALUE) .addComponent(jToolBar6, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, samplesTabLayout.createSequentialGroup() .addContainerGap() .addComponent(samplesPane) .addContainerGap()) ); samplesTabLayout.setVerticalGroup( samplesTabLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(samplesTabLayout.createSequentialGroup() .addComponent(jToolBar3, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jToolBar6, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(samplesPane, javax.swing.GroupLayout.DEFAULT_SIZE, 514, Short.MAX_VALUE) .addContainerGap()) ); tabs.addTab("Samples", samplesTab); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(tabs, javax.swing.GroupLayout.DEFAULT_SIZE, 633, Short.MAX_VALUE) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(tabs, javax.swing.GroupLayout.DEFAULT_SIZE, 615, Short.MAX_VALUE) ); }// </editor-fold>//GEN-END:initComponents private void addPatternActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addPatternActionPerformed music.addPattern(4); int size = music.song.patterns.size(); String name = "Verse " + size; int idx = size - 1; music.song.patterns.get(idx).name = name; pattern.addItem(name); pattern.setSelectedIndex(idx); updatePattern(); }//GEN-LAST:event_addPatternActionPerformed private void patternItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_patternItemStateChanged currentPatternIdx = pattern.getSelectedIndex(); updatePattern(); }//GEN-LAST:event_patternItemStateChanged private void tableViewMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_tableViewMouseClicked evt.consume(); if (evt.getClickCount() == 2) { editNote(); } }//GEN-LAST:event_tableViewMouseClicked private void tableViewKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_tableViewKeyTyped evt.consume(); enterNote(evt.getKeyChar()); }//GEN-LAST:event_tableViewKeyTyped private void removePatternActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removePatternActionPerformed if (!JF.showConfirm("Delete Pattern?", "Are you sure?")) return; music.removePattern(currentPatternIdx); if (music.song.patterns.size() == 0) { music.addPattern(4); } updatePattern(); }//GEN-LAST:event_removePatternActionPerformed private void jButton7ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton7ActionPerformed music.addTrack(currentPatternIdx); updatePattern(); }//GEN-LAST:event_jButton7ActionPerformed private void jButton8ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton8ActionPerformed int col = tableView.getSelectedColumn(); if (col == -1) { JF.showError("Notice", "Select a track to delete"); return; } if (col == 0) return; if (!JF.showConfirm("Delete Track?", "Are you sure?")) return; music.removeTrack(currentPatternIdx, col - 1); updatePattern(); }//GEN-LAST:event_jButton8ActionPerformed private void seqAddActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_seqAddActionPerformed int idx = seqPattern.getSelectedIndex(); if (idx == -1) return; music.song.sequence.add(idx); updateSequenceList(); }//GEN-LAST:event_seqAddActionPerformed private void seqRemoveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_seqRemoveActionPerformed int idx = sequence.getSelectedIndex(); if (idx == -1) { JF.showError("Notice", "Select a sequence to delete"); return; } // if (!JF.showConfirm("Delete Sequence?", "Are you sure?")) return; music.song.sequence.remove(idx); updateSequenceList(); }//GEN-LAST:event_seqRemoveActionPerformed private void seqUpActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_seqUpActionPerformed int idx = sequence.getSelectedIndex(); if (idx <= 0) return; Integer top = music.song.sequence.get(idx-1); Integer bot = music.song.sequence.get(idx); music.song.sequence.set(idx-1, bot); music.song.sequence.set(idx, top); updateSequenceList(); sequence.setSelectedIndex(idx-1); }//GEN-LAST:event_seqUpActionPerformed private void seqDownActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_seqDownActionPerformed int idx = sequence.getSelectedIndex(); if (idx == -1) return; if (idx == music.song.sequence.size() - 1) return; Integer top = music.song.sequence.get(idx); Integer bot = music.song.sequence.get(idx+1); music.song.sequence.set(idx, bot); music.song.sequence.set(idx+1, top); updateSequenceList(); sequence.setSelectedIndex(idx+1); }//GEN-LAST:event_seqDownActionPerformed private void tableViewKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_tableViewKeyPressed evt.consume(); int row = tableView.getSelectedRow(); int col = tableView.getSelectedColumn(); if (row == -1 || col == -1) return; if (row == 0) return; TableCell cell = null; if (col > 0) cell = (TableCell)tableView.getValueAt(row, col); int cnt = -1, sel = -1; if (evt.getModifiers() == 0) { switch(evt.getKeyCode()) { case KeyEvent.VK_ESCAPE: if (recording) recordStop(); break; case KeyEvent.VK_DELETE: enterNote(' '); break; case KeyEvent.VK_ENTER: editNote(); break; case KeyEvent.VK_UP: if (row == 1) break; if (col > 0) sel = cell.getSelection(); row--; if (col > 0) ((TableCell)tableView.getValueAt(row, col)).setSelection(sel); break; case KeyEvent.VK_DOWN: if (row == tableView.getRowCount() - 1) break; if (col > 0) sel = cell.getSelection(); row++; if (col > 0) ((TableCell)tableView.getValueAt(row, col)).setSelection(sel); break; case KeyEvent.VK_LEFT: if (col == 0) break; if (cell == null) break; //should not happen sel = cell.getSelection(); if (sel == 0) { col--; if (col > 0) { cell = (TableCell)tableView.getValueAt(row, col); cell.setSelection(2); } } else { cell.setSelection(sel-1); } break; case KeyEvent.VK_RIGHT: cnt = tableView.getColumnCount(); if (cell == null) { if (col == cnt-1) break; col++; break; } sel = cell.getSelection(); if (sel == 2) { if (col == cnt-1) break; col++; cell = (TableCell)tableView.getValueAt(row, col); cell.setSelection(0); } else { cell.setSelection(sel+1); } break; } } if (col > 1 && evt.getModifiers() == KeyEvent.CTRL_MASK) { Music.Track track = music.song.patterns.get(currentPatternIdx).tracks.get(col-1); switch(evt.getKeyCode()) { case KeyEvent.VK_C: //copy note/vol/fx cbNote = track.notes[row-1]; cbVolCmd = track.volcmds[row-1]; cbVolParam = track.volparams[row-1]; cbFXCmd = track.fxcmds[row-1]; cbFXParam = track.fxparams[row-1]; break; case KeyEvent.VK_V: //paste note/vol/fx track.notes[row-1] = cbNote; track.volcmds[row-1] = cbVolCmd; track.volparams[row-1] = cbVolParam; track.fxcmds[row-1] = cbFXCmd; track.fxparams[row-1] = cbFXParam; updatePattern(); break; } } tableView.changeSelection(row, col, false, false); // tableView.scrollRectToVisible(tableView.getCellRect(row, col, true)); tableView.repaint(); }//GEN-LAST:event_tableViewKeyPressed private void tableViewKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_tableViewKeyReleased evt.consume(); }//GEN-LAST:event_tableViewKeyReleased private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed musicStart(); music.playPattern(currentPatternIdx); }//GEN-LAST:event_jButton2ActionPerformed private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton3ActionPerformed if (recording) recordStop(); else music.stopMusic(); if (exporting) { musicEnded(); } }//GEN-LAST:event_jButton3ActionPerformed private void bpmStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_bpmStateChanged if (currentPatternIdx == -1) return; music.song.patterns.get(currentPatternIdx).bpm = (Integer)bpm.getValue(); }//GEN-LAST:event_bpmStateChanged private void jButton6ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton6ActionPerformed if (soundIdx != -1) { music.channelKeyUp(soundIdx); // soundIdx = -1; //may still have a loop } }//GEN-LAST:event_jButton6ActionPerformed private void jButton5ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton5ActionPerformed if (soundIdx != -1) { music.channelStop(soundIdx); soundIdx = -1; } }//GEN-LAST:event_jButton5ActionPerformed private void jButton4ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton4ActionPerformed if (currentSampleIdx == -1) return; musicStart(); if (soundIdx != -1) { music.channelStop(soundIdx); soundIdx = -1; } soundIdx = music.samplePlay(currentSampleIdx, 1.0f, 1.0f); }//GEN-LAST:event_jButton4ActionPerformed private void zoomItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_zoomItemStateChanged samples.revalidate(); samples.repaint(); }//GEN-LAST:event_zoomItemStateChanged private void iAddFileActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_iAddFileActionPerformed JFileChooser chooser = new JFileChooser(); chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); chooser.addChoosableFileFilter(new FileNameExtensionFilter("WAV", "wav")); chooser.setFileFilter(chooser.getChoosableFileFilters()[1]); //use first added filefilter added chooser.setMultiSelectionEnabled(false); chooser.setCurrentDirectory(new File(MainPanel.currentPath)); if (chooser.showOpenDialog(this) != JFileChooser.APPROVE_OPTION) return; int iidx = music.song.instruments.size(); int sidx = music.song.samples.size(); String name = "Instrument " + (iidx+1); music.addInstrument(name); music.addRegion(iidx, 0, 0x7f, 0x3c, sidx); if (!music.addSamples(name + "_" + 0, chooser.getSelectedFile().getAbsolutePath(), -1, -1, -1, -1, 0.0f)) { JF.showError("Error", "Failed to load wav file"); return; } updateSamples(); sample.setSelectedIndex(sidx); updateSample(); updateInstruments(); instrument.setSelectedIndex(iidx); updateInstrument(); }//GEN-LAST:event_iAddFileActionPerformed private void iAddLibraryActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_iAddLibraryActionPerformed String name = (String)library.getSelectedItem(); if (name == null) return; int libidx = library.getSelectedIndex(); if (libidx == -1) return; Library.Entry entry = Library.get(libidx); int iidx = music.song.instruments.size(); int sidx = music.song.samples.size(); switch (entry.type) { case WAV: music.addInstrument(name); music.addRegion(iidx, 0, 0x7f, 0x3c, sidx); if (!music.addSamples(name + "_" + 0, entry.fullPath, -1, -1, -1, -1, 0.0f)) { JF.showError("Error", "Failed to load wav file"); break; } break; case DLS: DLS dls = Library.getDLS(entry.dls_idx); music.addInstrument(name); int cnt = dls.getRegionsCount(name); for(int a=0;a<cnt;a++) { DLS.Instrument i = dls.getInstrument(name, a); if (i == null) return; int susStart = -1, susEnd = -1; if (i.loopStart != -1) { susStart = i.loopStart; susEnd = i.loopStart + i.loopLength; } DLS.Region region = dls.getRegion(name, a); music.addRegion(iidx, region.keyMin, region.keyMax, region.unityNote, sidx + a); float attenuation = 0.0f; //region.attenuation; //TODO??? if (!music.addSamples(name + " " + (sidx+a), i.samples, -1, -1, susStart, susEnd, attenuation)) { JF.showError("Error", "Failed to load wav file"); break; } } break; } updateSamples(); sample.setSelectedIndex(sidx); updateSample(); updateInstruments(); instrument.setSelectedIndex(iidx); updatePattern(); }//GEN-LAST:event_iAddLibraryActionPerformed private void iRemoveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_iRemoveActionPerformed if (currentInstrumentIdx == -1) return; if (!JF.showConfirm("Delete Instrument?", "Are you sure?")) return; music.removeInstrument(currentInstrumentIdx); currentInstrumentIdx = -1; updateInstruments(); updatePattern(); }//GEN-LAST:event_iRemoveActionPerformed private void instrumentItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_instrumentItemStateChanged if (currentInstrumentIdx != -1) { saveInstrument(); } currentInstrumentIdx = instrument.getSelectedIndex(); updateInstrument(); }//GEN-LAST:event_instrumentItemStateChanged private void loopItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_loopItemStateChanged if (loop.isSelected()) { if (samples.sample == null) { loop.setSelected(false); return; } if (samples.loopStart == -1) { int length = samples.sample.samples.length-1; samples.loopStart = (int)(length * 0.10f); samples.loopEnd = (int)(length * 0.90f); } } else { if (samples.sample == null) return; // samples.loopStart = -1; // samples.loopEnd = -1; } samples.showLoop = loop.isSelected(); samples.repaint(); }//GEN-LAST:event_loopItemStateChanged private void sustainItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_sustainItemStateChanged if (sustain.isSelected()) { if (samples.sample == null) { sustain.setSelected(false); return; } if (samples.sustainStart == -1) { int length = samples.sample.samples.length-1; samples.sustainStart = (int)(length * 0.05f); samples.sustainEnd = (int)(length * 0.95f); } } else { if (samples.sample == null) return; // samples.sustainStart = -1; // samples.sustainEnd = -1; } samples.showSustain = sustain.isSelected(); samples.repaint(); }//GEN-LAST:event_sustainItemStateChanged private void attenuationItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_attenuationItemStateChanged samples.showAttenuation = attenuation.isSelected(); samples.repaint(); }//GEN-LAST:event_attenuationItemStateChanged private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed if (recording) recordStop(); else recordStart(); }//GEN-LAST:event_jButton1ActionPerformed private void bpmKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_bpmKeyTyped if (currentPatternIdx == -1) return; music.song.patterns.get(currentPatternIdx).bpm = (Integer)bpm.getValue(); }//GEN-LAST:event_bpmKeyTyped private void jButton10ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton10ActionPerformed if (currentPatternIdx == -1) return; String newName = JF.getString("Edit Name", (String)pattern.getSelectedItem()); if (newName == null) return; music.song.patterns.get(currentPatternIdx).name = newName; int idx = currentPatternIdx; updatePatterns(); pattern.setSelectedIndex(idx); updateSequence(); updateSequenceList(); }//GEN-LAST:event_jButton10ActionPerformed private void jButton9ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton9ActionPerformed if (currentInstrumentIdx == -1) return; String newName = JF.getString("Edit Name", (String)instrument.getSelectedItem()); if (newName == null) return; music.song.instruments.get(currentInstrumentIdx).name = newName; int idx = currentInstrumentIdx; updateInstruments(); instrument.setSelectedIndex(idx); updatePattern(); }//GEN-LAST:event_jButton9ActionPerformed private void sequenceValueChanged(javax.swing.event.ListSelectionEvent evt) {//GEN-FIRST:event_sequenceValueChanged currentSequenceIdx = sequence.getSelectedIndex(); }//GEN-LAST:event_sequenceValueChanged private void jButton11ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton11ActionPerformed //move pattern up if (currentPatternIdx <= 0) return; if (music.song.patterns.size() < 2) return; Music.Pattern pat = music.song.patterns.remove(currentPatternIdx); music.song.patterns.add(currentPatternIdx - 1, pat); //update sequence for(int a=0;a<music.song.sequence.size();a++) { int idx = music.song.sequence.get(a); if (idx == currentPatternIdx) { music.song.sequence.set(a, idx - 1); } else if (idx == currentPatternIdx - 1) { music.song.sequence.set(a, idx + 1); } } int idx = currentPatternIdx - 1; updatePatterns(); pattern.setSelectedIndex(idx); updatePattern(); updateSequenceList(); updateSequence(); }//GEN-LAST:event_jButton11ActionPerformed private void jButton12ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton12ActionPerformed //move pattern down if (currentPatternIdx == -1) return; int patSize = music.song.patterns.size(); if (patSize < 2) return; if (currentPatternIdx == patSize-1) return; Music.Pattern pat = music.song.patterns.remove(currentPatternIdx); music.song.patterns.add(currentPatternIdx + 1, pat); //update sequence for(int a=0;a<music.song.sequence.size();a++) { int idx = music.song.sequence.get(a); if (idx == currentPatternIdx) { music.song.sequence.set(a, idx + 1); } else if (idx == currentPatternIdx + 1) { music.song.sequence.set(a, idx - 1); } } int idx = currentPatternIdx + 1; updatePatterns(); pattern.setSelectedIndex(idx); updatePattern(); updateSequenceList(); updateSequence(); }//GEN-LAST:event_jButton12ActionPerformed private void sampleItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_sampleItemStateChanged if (currentSampleIdx != -1) { saveSample(); } currentSampleIdx = sample.getSelectedIndex(); updateSample(); }//GEN-LAST:event_sampleItemStateChanged private void jButton13ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton13ActionPerformed if (currentInstrumentIdx == -1) return; EditRegion dialog = new EditRegion(null, true, music.song.instruments.get(currentInstrumentIdx).regions.get(currentRegionIdx), music, true); dialog.setVisible(true); updateInstrument(); }//GEN-LAST:event_jButton13ActionPerformed private void regionsItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_regionsItemStateChanged currentRegionIdx = regions.getSelectedIndex(); }//GEN-LAST:event_regionsItemStateChanged private void jButton14ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton14ActionPerformed if (currentInstrumentIdx == -1) return; Music.Region region = new Music.Region(); EditRegion dialog = new EditRegion(null, true, region, music, false); dialog.setVisible(true); if (!dialog.accepted) return; music.song.instruments.get(currentInstrumentIdx).regions.add(region); updateInstrument(); }//GEN-LAST:event_jButton14ActionPerformed private void jButton15ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton15ActionPerformed if (currentInstrumentIdx == -1) return; if (currentRegionIdx == -1) return; if (!JF.showConfirm("Delete Region?", "Are you sure?")) return; music.song.instruments.get(currentInstrumentIdx).regions.remove(currentRegionIdx); updateInstrument(); }//GEN-LAST:event_jButton15ActionPerformed private void jButton16ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton16ActionPerformed if (currentSampleIdx == -1) return; String newName = JF.getString("Edit Name", music.song.samples.get(currentSampleIdx).name); if (newName == null) return; music.song.samples.get(currentSampleIdx).name = newName; updateSamples(); updateSample(); }//GEN-LAST:event_jButton16ActionPerformed private void jButton18ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton18ActionPerformed if (currentSampleIdx == -1) return; if (!JF.showConfirm("Delete Sample?", "Are you sure?")) return; music.removeSamples(currentSampleIdx); updateSamples(); updateSample(); }//GEN-LAST:event_jButton18ActionPerformed private void jButton17ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton17ActionPerformed JFileChooser chooser = new JFileChooser(); chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); chooser.addChoosableFileFilter(new FileNameExtensionFilter("WAV", "wav")); chooser.setFileFilter(chooser.getChoosableFileFilters()[1]); //use first added filefilter added chooser.setMultiSelectionEnabled(false); chooser.setCurrentDirectory(new File(MainPanel.currentPath)); if (chooser.showOpenDialog(this) != JFileChooser.APPROVE_OPTION) return; int sidx = music.song.samples.size(); File file = chooser.getSelectedFile(); String name = file.getName(); if (name.toLowerCase().endsWith(".wav")) { name = name.substring(0, name.length() - 4); } if (!music.addSamples(name, file.getAbsolutePath(), -1, -1, -1, -1, 0.0f)) { JF.showError("Error", "Failed to load wav file"); return; } updateSamples(); sample.setSelectedIndex(sidx); updateSample(); }//GEN-LAST:event_jButton17ActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton addPattern; private javax.swing.JCheckBox attenuation; private javax.swing.JSpinner bpm; private javax.swing.JTextArea comment; private javax.swing.Box.Filler filler1; private javax.swing.Box.Filler filler10; private javax.swing.Box.Filler filler11; private javax.swing.Box.Filler filler2; private javax.swing.Box.Filler filler3; private javax.swing.Box.Filler filler4; private javax.swing.Box.Filler filler5; private javax.swing.Box.Filler filler6; private javax.swing.Box.Filler filler7; private javax.swing.Box.Filler filler8; private javax.swing.Box.Filler filler9; private javax.swing.JPanel generalTab; private javax.swing.JButton iAddFile; private javax.swing.JButton iAddLibrary; private javax.swing.JButton iRemove; private javax.swing.JPanel instrTab; private javax.swing.JComboBox instrument; private javax.swing.JButton jButton1; private javax.swing.JButton jButton10; private javax.swing.JButton jButton11; private javax.swing.JButton jButton12; private javax.swing.JButton jButton13; private javax.swing.JButton jButton14; private javax.swing.JButton jButton15; private javax.swing.JButton jButton16; private javax.swing.JButton jButton17; private javax.swing.JButton jButton18; private javax.swing.JButton jButton2; private javax.swing.JButton jButton3; private javax.swing.JButton jButton4; private javax.swing.JButton jButton5; private javax.swing.JButton jButton6; private javax.swing.JButton jButton7; private javax.swing.JButton jButton8; private javax.swing.JButton jButton9; private javax.swing.JLabel jLabel1; private javax.swing.JLabel jLabel11; private javax.swing.JLabel jLabel13; private javax.swing.JLabel jLabel14; private javax.swing.JLabel jLabel2; private javax.swing.JLabel jLabel3; private javax.swing.JLabel jLabel4; private javax.swing.JLabel jLabel5; private javax.swing.JLabel jLabel6; private javax.swing.JLabel jLabel7; private javax.swing.JLabel jLabel8; private javax.swing.JLabel jLabel9; private javax.swing.JScrollPane jScrollPane1; private javax.swing.JScrollPane jScrollPane3; private javax.swing.JScrollPane jScrollPane4; private javax.swing.JToolBar jToolBar1; private javax.swing.JToolBar jToolBar2; private javax.swing.JToolBar jToolBar3; private javax.swing.JToolBar jToolBar4; private javax.swing.JToolBar jToolBar5; private javax.swing.JToolBar jToolBar6; private javax.swing.JToolBar jToolBar7; private javax.swing.JComboBox library; private javax.swing.JCheckBox loop; private javax.swing.JTextField name; private javax.swing.ButtonGroup noteTypes; private javax.swing.JComboBox pattern; private javax.swing.JPanel patternsTab; private javax.swing.JComboBox regions; private javax.swing.JButton removePattern; private javax.swing.JComboBox sample; private javax.swing.JScrollPane samplesPane; private javax.swing.JPanel samplesTab; private javax.swing.JButton seqAdd; private javax.swing.JButton seqDown; private javax.swing.JComboBox seqPattern; private javax.swing.JButton seqRemove; private javax.swing.JPanel seqTab; private javax.swing.JButton seqUp; private javax.swing.JList sequence; private javax.swing.JCheckBox sustain; private javax.swing.JTable tableView; private javax.swing.JTabbedPane tabs; private javax.swing.JComboBox zoom; // End of variables declaration//GEN-END:variables private DefaultTableModel tableModel = new DefaultTableModel() { public boolean isCellEditable(int row,int col) { if (row == 0 && col > 0) return true; return false; } public void setValueAt(Object value,int row,int col) { if (value == null) return; if (row == 0) { //DefaultCellEditor assumes entry was a string, so instead of a combobox JComboBox cb = (JComboBox)tableView.getValueAt(row, col); String str = (String)value; int idx = JF.atox(str.substring(0, 2)); cb.setSelectedIndex(idx); music.song.patterns.get(currentPatternIdx).tracks.get(col-1).startInstrument = (byte)idx; } else { super.setValueAt(value, row, col); } } }; private DefaultTableColumnModel colModel; // = new DefaultTableColumnModel(); private Music music; private int currentPatternIdx = -1; private int currentSequenceIdx = -1; private int currentInstrumentIdx = -1; private int currentRegionIdx = -1; private int currentSampleIdx = -1; private Samples samples; private String filename; private int soundIdx = -1; private byte cbNote = -1, cbVolCmd, cbFXCmd; private int cbVolParam, cbFXParam; private MidiDevice midi; private Transmitter trans; private java.util.Timer timer; private boolean recording; private boolean recordingStarted; private boolean exporting; private MediaEncoder ffmpeg; private RandomAccessFile exportFile; private void reset() { music = new Music(); music.reset(); repaint(); updatePatterns(); updatePattern(); } private void updatePatterns() { currentPatternIdx = -1; pattern.removeAllItems(); int size = music.song.patterns.size(); for(int a=0;a<size;a++) { pattern.addItem(music.song.patterns.get(a).name); } } private void updateSequence() { int idx = seqPattern.getSelectedIndex(); seqPattern.removeAllItems(); int cnt = pattern.getItemCount(); if (idx >= cnt) idx = cnt - 1; for(int a=0;a<cnt;a++) { seqPattern.addItem(music.song.patterns.get(a).name); } seqPattern.setSelectedIndex(idx); } private void updatePattern() { updateSequence(); tableModel.setRowCount(0); tableModel.setColumnCount(0); tableView.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); if (currentPatternIdx >= music.song.patterns.size()) { currentPatternIdx = music.song.patterns.size() - 1; pattern.setSelectedIndex(currentPatternIdx); } if (currentPatternIdx == -1) { bpm.setValue(80); return; } Music.Pattern pattern = music.song.patterns.get(currentPatternIdx); bpm.setValue(pattern.bpm); int cnt = pattern.tracks.size(); tableModel.setColumnCount(1 + cnt); ArrayList<Object> row = new ArrayList<Object>(); row.clear(); TableColumn col; col = colModel.getColumn(0); // col.setCellRenderer(new SimpleTableCellRenderer()); // col.setHeaderRenderer(new SimpleTableCellRenderer()); // col.setHeaderValue(null); row.add(""); for(int t=0;t<cnt;t++) { Music.Track track = pattern.tracks.get(t); col = colModel.getColumn(t+1); col.setCellRenderer(new SimpleTableCellRenderer()); // col.setHeaderRenderer(new SimpleTableCellRenderer()); // col.setHeaderValue(new JComboBox()); row.add(getTrackInstruments(track)); } tableModel.addRow(row.toArray()); for(int r=0;r<64;r++) { row.clear(); row.add(String.format("%02d", r)); for(int t=0;t<cnt;t++) { Music.Track track = pattern.tracks.get(t); row.add(new TableCell(getNoteVolFX(track, r))); } tableModel.addRow(row.toArray()); } setTableWidths(); tableView.repaint(); } private void updateCell() { int col = tableView.getSelectedColumn(); int row = tableView.getSelectedRow(); if (col <= 0) return; if (row <= 0) return; if (currentPatternIdx == -1) return; Music.Track track = music.song.patterns.get(currentPatternIdx).tracks.get(col-1); Object obj = new TableCell(getNoteVolFX(track, row-1)); tableView.setValueAt(obj, row, col); tableView.repaint(); } private String getNoteVolFX(Music.Track track, int row) { return getNote(track.notes[row]) + " " + getVolCmd(track.volcmds[row]) //+ getHexParam(track.volparams[r]) + " " + getFXCmd(track.fxcmds[row]); //+ getHexParam(track.fxparams[r]) } private String keys[] = {"C-", "C#", "D-", "D#", "E-", "F-", "F#", "G-", "G#", "A-", "A#", "B-"}; private String getNote(byte note) { if (note == -1) { return "..."; } int octave = note / 12; int key = note % 12; return keys[key] + octave; } private String getVolCmd(int value) { switch (value) { case Music.VOLCMD_NONE: return ".."; case Music.VOLCMD_SET_VOLUME: return "sv"; case Music.VOLCMD_SET_VOL_VIBRATE_SPEED: return "vv"; case Music.VOLCMD_SET_PAN_VIBRATE_SPEED: return "vp"; case Music.VOLCMD_TREMOLO: return "tr"; case Music.VOLCMD_PANBRELLO: return "pa"; case Music.VOLCMD_SET_PANNING: return "sp"; case Music.VOLCMD_SLIDE: return "vs"; case Music.VOLCMD_PAN_SLIDE: return "ps"; } return "??"; } private String getFXCmd(int value) { switch (value) { case Music.FXCMD_NONE: return ".."; case Music.FXCMD_PORTAMENTO_TO_NOTE: return "pn"; case Music.FXCMD_SET_VIBRATE_SPEED: return "vs"; case Music.FXCMD_VIBRATO: return "vb"; case Music.FXCMD_PORTAMENTO: return "po"; case Music.FXCMD_TREMOR: return "tr"; case Music.FXCMD_SET_INSTRUMENT: return "si"; case Music.FXCMD_DELAY_START: return "ds"; case Music.FXCMD_SAMPLE_OFFSET: return "so"; case Music.FXCMD_SET_BPM: return "sm"; case Music.FXCMD_KEY_OFF: return "ko"; case Music.FXCMD_PATTERN_BREAK: return "pb"; } return "??"; } private String getHexParam(int value) { //or float ??? if (value == 0) return "........"; return String.format("%08x", value); } private void setTableWidths() { int cnt = colModel.getColumnCount(); for(int a=0;a<cnt;a++) { TableColumn col = colModel.getColumn(a); int width = 25; if (a > 0) width = 100; col.setResizable(false); col.setMinWidth(width); col.setMaxWidth(width); col.setPreferredWidth(width); } } private void editNote() { int col = tableView.getSelectedColumn(); if (col <= 0) return; int row = tableView.getSelectedRow(); if (row <= 0) return; row--; col--; if (currentPatternIdx == -1) return; Music.Pattern pattern = music.song.patterns.get(currentPatternIdx); Music.Track track = pattern.tracks.get(col); EditNote dialog = new EditNote(null, true, track.notes[row] ,track.volcmds[row], track.volparams[row] ,track.fxcmds[row], track.fxparams[row], music); dialog.setVisible(true); if (dialog.accepted) { track.notes[row] = dialog.note; track.volcmds[row] = dialog.volcmd; track.volparams[row] = dialog.volparam; track.fxcmds[row] = dialog.fxcmd; track.fxparams[row] = dialog.fxparam; updatePattern(); tableView.repaint(); } } private void updateSequenceList() { ArrayList<String> list = new ArrayList<String>(); int cnt = music.song.sequence.size(); for(int a=0;a<cnt;a++) { int idx = music.song.sequence.get(a); list.add("" + a + music.song.patterns.get(idx).name); } sequence.setListData(list.toArray(new String[0])); } private void updateInstruments() { saveInstrument(); int idx = currentInstrumentIdx; currentInstrumentIdx = -1; instrument.removeAllItems(); int cnt = music.song.instruments.size(); if (cnt == 0) { return; } for(int a=0;a<cnt;a++) { instrument.addItem(music.song.instruments.get(a).name); } if (idx != -1) instrument.setSelectedIndex(idx); } private char row1[] = {'q' ,'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']'}; private char row2[] = {'a' ,'s', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '\r'}; private char row3[] = {'z' ,'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', '?', '?'}; private void enterNote(char ch) { int row = tableView.getSelectedRow(); int col = tableView.getSelectedColumn(); if (row <= 0) return; if (col <= 0) return; if (currentPatternIdx == -1) return; TableCell cell = (TableCell)tableView.getValueAt(row, col); int sel = cell.getSelection(); Music.Track track = music.song.patterns.get(currentPatternIdx).tracks.get(col-1); switch (sel) { case 0: //note byte newnote = -2; if (ch == ' ') { newnote = -1; } else if (ch >= '0' && ch <= '9') { //change octave (if there is a note) if (track.notes[row-1] == -1) break; int octave = (ch - '0') * 12; int key = track.notes[row-1] % 12; track.notes[row-1] = (byte)(octave + key); } else { for(int a=0;a<12;a++) { if (row1[a] == ch) { newnote = (byte)((3 * 12) + a); break; } else if (row2[a] == ch) { newnote = (byte)((4 * 12) + a); break; } else if (row3[a] == ch) { newnote = (byte)((5 * 12) + a); break; } } } if (newnote != -2) track.notes[row-1] = newnote; break; case 1: //volcmd if (ch == ' ') { track.volcmds[row-1] = 0; track.volparams[row-1] = 0; } /* if (ch >= '0' && ch <= '9') { track.volcmds[row-1] <<= 4; track.volcmds[row-1] |= (ch - '0'); } else if (ch >= 'a' && ch <= 'f') { track.volcmds[row-1] <<= 4; track.volcmds[row-1] |= (ch - 'a' + 10); } */ break; /* case 2: //volparam if (ch >= '0' && ch <= '9') { track.volparams[row-1] <<= 4; track.volparams[row-1] |= (ch - '0'); } else if (ch >= 'a' && ch <= 'f') { track.volparams[row-1] <<= 4; track.volparams[row-1] |= (ch - 'a' + 10); } break; */ case 2: //fxcmd if (ch == ' ') { track.fxcmds[row-1] = 0; track.fxparams[row-1] = 0; } /* if (ch >= '0' && ch <= '9') { track.fxcmds[row-1] <<= 4; track.fxcmds[row-1] |= (ch - '0'); } else if (ch >= 'a' && ch <= 'f') { track.fxcmds[row-1] <<= 4; track.fxcmds[row-1] |= (ch - 'a' + 10); } */ break; /* case 4: //fxparam if (ch >= '0' && ch <= '9') { track.fxparams[row-1] <<= 4; track.fxparams[row-1] |= (ch - '0'); } else if (ch >= 'a' && ch <= 'f') { track.fxparams[row-1] <<= 4; track.fxparams[row-1] |= (ch - 'a' + 10); } break; */ } updateCell(); cell = (TableCell)tableView.getValueAt(row, col); cell.setSelection(sel); } public void selectTab(int idx) { tabs.setSelectedIndex(idx); } private void updateInstrument() { updateRegions(); } private void saveInstrument() { } private void updateRegions() { regions.removeAllItems(); if (currentInstrumentIdx == -1) return; Music.Instrument i = music.song.instruments.get(currentInstrumentIdx); if (i.regions == null) return; //beta file for(int a=0;a<i.regions.size();a++) { Music.Region r = i.regions.get(a); regions.addItem("" + DLS.getKeyName(r.low) + " thru " + DLS.getKeyName(r.high)); } } private void updateSample() { if (currentSampleIdx == -1) { loop.setSelected(false); sustain.setSelected(false); attenuation.setSelected(false); samples.setSample(null); samplesPane.repaint(); return; } Music.Sample i = music.song.samples.get(currentSampleIdx); samples.setSample(i); samples.loopStart = i.loopStart; samples.loopEnd = i.loopEnd; loop.setSelected(i.loopStart != -1); samples.sustainStart = i.sustainStart; samples.sustainEnd = i.sustainEnd; sustain.setSelected(i.sustainStart != -1); samples.attenuation = i.attenuation; attenuation.setSelected(i.attenuation > 0.0f); samples.revalidate(); samples.repaint(); } public void saveSample() { if (currentSampleIdx == -1) return; Music.Sample s = music.song.samples.get(currentSampleIdx); if (loop.isSelected()) { s.loopStart = samples.loopStart; s.loopEnd = samples.loopEnd; } else { s.loopStart = -1; s.loopEnd = -1; } if (sustain.isSelected()) { s.sustainStart = samples.sustainStart; s.sustainEnd = samples.sustainEnd; } else { s.sustainStart = -1; s.sustainEnd = -1; } if (attenuation.isSelected()) s.attenuation = samples.attenuation; else s.attenuation = 0.0f; } public void updateSamples() { saveSample(); int idx = currentSampleIdx; currentSampleIdx = -1; sample.removeAllItems(); int cnt = music.song.samples.size(); if (cnt == 0) { return; } for(int a=0;a<cnt;a++) { sample.addItem(music.song.samples.get(a).name); } if (idx != -1) sample.setSelectedIndex(idx); } public int getZoom() { int idx = zoom.getSelectedIndex(); switch (idx) { case 0: return 1; case 1: return 2; case 2: return 4; case 3: return 8; case 4: return 16; case 5: return 32; case 6: return 64; case 7: return 128; } return -1; } public JComboBox getTrackInstruments(final Music.Track track) { final JComboBox cb = new JComboBox(); int cnt = music.song.instruments.size(); if (cnt == 0) return cb; for(int a=0;a<cnt;a++) { cb.addItem(String.format("%02x", a) + ":" + music.song.instruments.get(a).name); } cb.setSelectedIndex(track.startInstrument); cb.addItemListener(new ItemListener(){ public void itemStateChanged(ItemEvent e) { track.startInstrument = (byte)cb.getSelectedIndex(); } }); return cb; } private void loadLibrary() { library.removeAllItems(); ArrayList<Library.Entry> list = Library.getList(); for(int a=0;a<list.size();a++) { library.addItem(list.get(a).name); } } public void playSong() { musicStart(); music.playSong(false); } public void playPattern() { musicStart(); music.setListener(this); music.playSong(false); } public void stopSong() { music.stopMusic(); if (exporting) { musicEnded(); } } public void musicEnded() { JFLog.log("musicEnded"); music.stop(); if (exporting) { ffmpeg.stop(); try { exportFile.close(); } catch (Exception e) { JFLog.log(e); } exporting = false; } } public void musicSamples(short samples[]) { if (exporting) { ffmpeg.addAudio(samples); } } public void musicRow(int seq,int pat,int row) { final int _seq = seq; final int _pat = pat; final int _row = row; java.awt.EventQueue.invokeLater(new Runnable() { public void run() { if (_seq != -1) { if (currentSequenceIdx != _seq) { sequence.setSelectedIndex(_seq); } } if (_pat != -1) { if (currentPatternIdx != _pat) { pattern.setSelectedIndex(_pat); } } tableView.changeSelection(_row+1, 0, false, false); } }); } private DefaultCellEditor editor; public TableCellEditor _getCellEditor(int row, int column) { int col = tableView.convertColumnIndexToModel(column); //order of cols can change (not in this app though) JComboBox cb = (JComboBox)tableView.getValueAt(row, col); editor = new DefaultCellEditor(cb); editor.setClickCountToStart(1); return editor; } public Dimension getSamplesPaneSize() { return new Dimension(samplesPane.getWidth(), samplesPane.getHeight()); } public void updateGeneral() { name.setText(music.song.name); comment.setText(music.song.comment); } public boolean load(String fn) { music = new Music(); filename = fn; if (!music.load(fn)) return false; updatePatterns(); updatePattern(); updateSequence(); updateSequenceList(); updateInstruments(); updateInstrument(); updateSamples(); updateSample(); updateGeneral(); return true; } public boolean save() { if (filename == null) { JFileChooser chooser = new JFileChooser(); chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); chooser.addChoosableFileFilter(new FileNameExtensionFilter("Music Projects (*.mproj)", "mproj")); chooser.setFileFilter(chooser.getChoosableFileFilters()[1]); //use first added filefilter added chooser.setMultiSelectionEnabled(false); chooser.setCurrentDirectory(new File(MainPanel.currentPath)); if (chooser.showSaveDialog(this) != JFileChooser.APPROVE_OPTION) return false; File file = chooser.getSelectedFile(); MainPanel.currentPath = file.getParent(); if (MainPanel.currentPath == null) MainPanel.currentPath = JF.getUserPath() + "/Music"; filename = file.getAbsolutePath(); if (!filename.toLowerCase().endsWith(".mproj")) filename += ".mproj"; } String title; title = filename; int idx = title.indexOf(".mproj"); if (idx != -1) title = title.substring(0, idx); idx = title.lastIndexOf("/"); if (idx != -1) title = title.substring(idx+1); idx = title.lastIndexOf("\\"); if (idx != -1) title = title.substring(idx+1); music.song.name = name.getText(); music.song.comment = comment.getText(); MainPanel.This.setTitle(this, title); return music.save(filename); } public void closeSong() { music.close(); } private void musicStart() { if (music.isRunning()) return; music.start(20, 1); music.setListener(this); } private void recordStart() { notes.clear(); if (currentPatternIdx == -1) return; pattern.setEnabled(false); recordingStarted = false; recording = true; if (Settings.current.midiDevice.length() > 0) { //open midi device for recording loadMIDI(Settings.current.midiDevice); } int delay = (1000 * 60) / (Integer)bpm.getValue(); timer = new java.util.Timer(); timer.scheduleAtFixedRate(new TimerTask() { public void run() { java.awt.EventQueue.invokeLater(new Runnable() { public void run() { recordBeat(); } }); } }, delay, delay); } private void recordStop() { pattern.setEnabled(true); recording = false; if (timer != null) { timer.cancel(); timer = null; } if (midi != null) { midi.close(); midi = null; } } private class Note { int note; boolean down; int velocity; } private ArrayList<Note> notes = new ArrayList<Note>(); private Object notesLock = new Object(); private int noteTrack[] = new int[128]; //keep track of which track(col) note was played on private void recordBeat() { if (!recordingStarted) return; int col = tableView.getSelectedColumn(); int row = tableView.getSelectedRow(); int colMax = tableModel.getColumnCount(); Note note; int rcol = col; while (!notes.isEmpty()) { synchronized(notesLock) { note = notes.remove(0); } if (note.down) { Music.Track track = music.song.patterns.get(currentPatternIdx).tracks.get(rcol-1); track.notes[row-1] = (byte)note.note; track.fxcmds[row-1] = 0; //remove key off if set noteTrack[note.note] = rcol; } else { Music.Track track = music.song.patterns.get(currentPatternIdx).tracks.get(noteTrack[note.note]-1); track.fxcmds[row-1] = Music.FXCMD_KEY_OFF; } tableView.changeSelection(row, rcol, false, false); updateCell(); if (note.down) rcol++; if (rcol == colMax) break; } row++; if (row == 64) { //end recording recordStop(); return; } tableView.changeSelection(row, col, false, false); } private void loadMIDI(String midiName) { if (midi != null) { midi.close(); midi = null; } MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo(); try { if (infos == null) throw new Exception("no devices found"); for(int a=0;a<infos.length;a++) { MidiDevice midiDevice = MidiSystem.getMidiDevice(infos[a]); if (midiDevice.getMaxTransmitters() == 0) continue; String name = infos[a].getName(); if (name.equals(midiName)) { midi = midiDevice; trans = midi.getTransmitter(); trans.setReceiver(this); midi.open(); JFLog.log("selected device:" + midi + "," + trans); return; } } if (midi == null) return; } catch (Exception e) { JFLog.log(e); return; } } //Receiver.close() - do nothing public void close() {} //Receiver.send() - receive MIDI message public void send(MidiMessage message, long timeStamp) { if (!(message instanceof ShortMessage)) return; //decode message ShortMessage sm = (ShortMessage)message; int cmd = sm.getCommand() & 0xff; int d1 = sm.getData1() & 0x7f; int d2 = sm.getData2() & 0x7f; String cmdstr = null; Note note = new Note(); switch (cmd) { case 0x80: //note off // note / velocity (zero) cmdstr = "keyUp"; //d1 = key note.note = d1; note.down = false; synchronized(notesLock) { notes.add(note); } break; case 0x90: //note on // note / velocity (0-127) cmdstr = "keyDn"; //d1 = note //d2 = velocity note.note = d1; note.velocity = d2; note.down = true; synchronized(notesLock) { notes.add(note); } if (!recordingStarted) recordingStarted = true; // if (!velocity.isSelected()) d2 = 0x7f; break; case 0xb0: //control change // control / value (0-127) // controls : 1 = modulation : 7 = volume : 4a = ch1 : 47 = ch2 : 49 = ch3 : 48 = ch4 cmdstr = " ctrl"; break; case 0xe0: //pitch wheel cmdstr = "pitch"; // zero / value (0-127) break; } JFLog.log(String.format("%s:%02x:%02x:%02x", cmdstr, cmd, d1, d2)); } public void insertRow() { int row = tableView.getSelectedRow(); int col = tableView.getSelectedColumn(); if (row <= 0) return; if (col <= 0) return; if (currentPatternIdx == -1) return; row--; col--; Music.Pattern pat = music.song.patterns.get(currentPatternIdx); int nTracks = pat.tracks.size(); for(int t=0;t<nTracks;t++) { Music.Track track = pat.tracks.get(t); for(int r=63;r>row;r--) { track.notes[r] = track.notes[r-1]; track.volcmds[r] = track.volcmds[r-1]; track.volparams[r] = track.volparams[r-1]; track.fxcmds[r] = track.fxcmds[r-1]; track.fxparams[r] = track.fxparams[r-1]; } track.notes[row] = -1; track.volcmds[row] = 0; track.volparams[row] = 0; track.fxcmds[row] = 0; track.fxparams[row] = 0; } updatePattern(); } public void deleteRow() { int row = tableView.getSelectedRow(); int col = tableView.getSelectedColumn(); if (row <= 0) return; if (col <= 0) return; row--; col--; if (currentPatternIdx == -1) return; Music.Pattern pat = music.song.patterns.get(currentPatternIdx); int nTracks = pat.tracks.size(); for(int t=0;t<nTracks;t++) { Music.Track track = pat.tracks.get(t); for(int r=row;r<64;r++) { track.notes[r] = track.notes[r+1]; track.volcmds[r] = track.volcmds[r+1]; track.volparams[r] = track.volparams[r+1]; track.fxcmds[r] = track.fxcmds[r+1]; track.fxparams[r] = track.fxparams[r+1]; } track.notes[63] = -1; track.volcmds[63] = 0; track.volparams[63] = 0; track.fxcmds[63] = 0; track.fxparams[63] = 0; } updatePattern(); } public void dupPattern() { if (currentPatternIdx == -1) return; Music.Pattern oldpat = music.song.patterns.get(currentPatternIdx); music.addPattern(oldpat.tracks.size()); int size = music.song.patterns.size(); String name = "Verse " + size; int idx = size - 1; Music.Pattern newpat = music.song.patterns.get(idx); newpat.name = name; newpat.bpm = oldpat.bpm; int nTracks = oldpat.tracks.size(); for(int t=0;t<nTracks;t++) { Music.Track oldtrack = oldpat.tracks.get(t); Music.Track newtrack = newpat.tracks.get(t); for(int r=0;r<64;r++) { newtrack.notes[r] = oldtrack.notes[r]; newtrack.volcmds[r] = oldtrack.volcmds[r]; newtrack.volparams[r] = oldtrack.volparams[r]; newtrack.fxcmds[r] = oldtrack.fxcmds[r]; newtrack.fxparams[r] = oldtrack.fxparams[r]; } } pattern.addItem(name); pattern.setSelectedIndex(idx); updatePattern(); } public void export() { JFileChooser chooser = new JFileChooser(); chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); FileNameExtensionFilter wav = new FileNameExtensionFilter("WAV (*.wav)", "wav"); JFLog.log("wav=" + wav); chooser.addChoosableFileFilter(wav); FileNameExtensionFilter mp3 = new FileNameExtensionFilter("MP3 (*.mp3)", "mp3"); JFLog.log("mp3=" + mp3); chooser.addChoosableFileFilter(mp3); chooser.setFileFilter(chooser.getChoosableFileFilters()[1]); //use first added filefilter added chooser.setMultiSelectionEnabled(false); chooser.setCurrentDirectory(new File(MainPanel.currentPath)); if (chooser.showSaveDialog(this) != JFileChooser.APPROVE_OPTION) return; String file = chooser.getSelectedFile().getAbsolutePath(); String ext; int idx = file.lastIndexOf('.'); if (idx == -1) { JFLog.log("fileFilter=" + chooser.getFileFilter()); if (chooser.getFileFilter() == wav) { file += ".wav"; ext = "wav"; } else if (chooser.getFileFilter() == mp3) { ext = "mp3"; file += ".mp3"; } else { //assume wav file += ".wav"; ext = "wav"; } } else { ext = file.substring(idx+1).toLowerCase(); if (!ext.equals("wav") && !ext.equals("mp3")) { //add ext JFLog.log("fileFilter=" + chooser.getFileFilter()); if (chooser.getFileFilter() == wav) { ext = "wav"; file += ".wav"; } else if (chooser.getFileFilter() == mp3) { ext = "mp3"; file += ".mp3"; } else { //assume wav file += ".wav"; ext = "wav"; } } } try { exportFile = new RandomAccessFile(file, "rw"); } catch (Exception e) { JFLog.log(e); JF.showError("Error", "Failed to create export file"); return; } exporting = true; ffmpeg = new MediaEncoder(); if (ext.equals("mp3")) { String bitRate = JF.getString("Enter bitrate (32-512)", "128"); if (bitRate == null) bitRate = "128"; int bits = JF.atoi(bitRate); if (bits < 32) bits = 32; if (bits > 512) bits = 512; ffmpeg.setAudioBitRate(bits * 1024); } ffmpeg.start(this, -1, -1, -1, 2, 44100, ext, false, true); playSong(); } //MediaCoderIO interface public int read(MediaCoder coder, byte[] bytes) { return 0; } public int write(MediaCoder coder, byte[] bytes) { try { exportFile.write(bytes); } catch (Exception e) { JFLog.log(e); } return bytes.length; } public long seek(MediaCoder coder, long pos, int how) { try { switch (how) { case MediaCoder.SEEK_SET: exportFile.seek(pos); break; case MediaCoder.SEEK_CUR: exportFile.seek(exportFile.getFilePointer() + pos); break; case MediaCoder.SEEK_END: exportFile.seek(exportFile.length() + pos); break; } } catch (Exception e) { JFLog.log(e); } return pos; } }