diff --git a/Java/MoppyDesk/src/moppydesk/MoppyMainWindow.form b/Java/MoppyDesk/src/moppydesk/MoppyMainWindow.form new file mode 100644 index 0000000..821a7e7 --- /dev/null +++ b/Java/MoppyDesk/src/moppydesk/MoppyMainWindow.form @@ -0,0 +1,172 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Java/MoppyDesk/src/moppydesk/MoppyMainWindow.java b/Java/MoppyDesk/src/moppydesk/MoppyMainWindow.java new file mode 100644 index 0000000..29c119e --- /dev/null +++ b/Java/MoppyDesk/src/moppydesk/MoppyMainWindow.java @@ -0,0 +1,296 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * MoppyMainWindow.java + * + * Created on Oct 8, 2011, 8:34:57 PM + */ +package moppydesk; + +import gnu.io.CommPortIdentifier; +import java.io.File; +import java.util.Enumeration; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.prefs.Preferences; +import javax.swing.JComboBox; +import javax.swing.JFileChooser; +import javax.swing.JOptionPane; +import javax.swing.JSlider; + +/** + * + * @author Sam + */ +public class MoppyMainWindow extends javax.swing.JFrame implements MoppyStatusConsumer{ + + static String PREF_COM_PORT = "comPort"; + static String PREF_LOADED_SEQ = "loadedSequencePath"; + + MoppyUI app; + Preferences prefs = Preferences.userNodeForPackage(MoppyUI.class); + final JFileChooser sequenceChooser = new JFileChooser(); + boolean comboBoxReady = false; + + /** Creates new form MoppyMainWindow */ + public MoppyMainWindow(MoppyUI app) { + this.app = app; + initComponents(); + + updateComSelectionMenu(); + + initializeSequencer((String) comSelectionMenu.getSelectedItem()); + + String previouslyLoadedFile = prefs.get(PREF_LOADED_SEQ, null); + if (previouslyLoadedFile != null){ + loadSequenceFile(new File(previouslyLoadedFile)); + } + } + + private void updateComSelectionMenu() { + comboBoxReady = false; + comSelectionMenu.removeAllItems(); + Enumeration e = CommPortIdentifier.getPortIdentifiers(); + while (e.hasMoreElements()) { + comSelectionMenu.addItem(e.nextElement().getName()); + } + comSelectionMenu.setSelectedItem(prefs.get(PREF_COM_PORT, "")); + comboBoxReady = true; + } + + private void initializeSequencer(String comPort) { + statusLabel.setText("Initializing sequencer..."); + if (app.ms != null) { + app.ms.closeSequencer(); + } + try { + app.ms = new MoppySequencer(comPort); + app.ms.addListener(this); + } catch (Exception ex) { + Logger.getLogger(MoppyMainWindow.class.getName()).log(Level.SEVERE, null, ex); + statusLabel.setText("Sequencer initialization error!"); + JOptionPane.showMessageDialog(rootPane, ex); + } + statusLabel.setText("Sequencer connected to " + comPort); + } + + /** 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") + // //GEN-BEGIN:initComponents + private void initComponents() { + + startButton = new javax.swing.JButton(); + stopButton = new javax.swing.JButton(); + comSelectionMenu = new javax.swing.JComboBox(); + statusLabel = new javax.swing.JLabel(); + jSeparator1 = new javax.swing.JSeparator(); + loadButton = new javax.swing.JButton(); + sequenceNameLabel = new javax.swing.JLabel(); + jLabel1 = new javax.swing.JLabel(); + jSlider1 = new javax.swing.JSlider(); + bpmLabel = new javax.swing.JLabel(); + + setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); + addWindowListener(new java.awt.event.WindowAdapter() { + public void windowClosing(java.awt.event.WindowEvent evt) { + MoppyMainWindow.this.windowClosing(evt); + } + }); + + startButton.setText("Start"); + startButton.setEnabled(false); + startButton.setName("startButton"); // NOI18N + startButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + startButtonClicked(evt); + } + }); + + stopButton.setText("Stop/Reset"); + stopButton.setName("stopButton"); // NOI18N + stopButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + stopResetClicked(evt); + } + }); + + comSelectionMenu.setName("comSelectionMenu"); // NOI18N + comSelectionMenu.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + comPortSelected(evt); + } + }); + + statusLabel.setText("Loading application..."); + statusLabel.setName("statusLabel"); // NOI18N + + jSeparator1.setName("jSeparator1"); // NOI18N + + loadButton.setText("Load Sequence"); + loadButton.setName("loadButton"); // NOI18N + loadButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + loadSequence(evt); + } + }); + + sequenceNameLabel.setText(""); + sequenceNameLabel.setName("sequenceNameLabel"); // NOI18N + + jLabel1.setText("Current Sequence:"); + jLabel1.setName("jLabel1"); // NOI18N + + jSlider1.setMajorTickSpacing(10); + jSlider1.setMaximum(210); + jSlider1.setMinimum(20); + jSlider1.setPaintTicks(true); + jSlider1.setValue(120); + jSlider1.setName("jSlider1"); // NOI18N + jSlider1.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() { + public void mouseDragged(java.awt.event.MouseEvent evt) { + tempoSliderChanged(evt); + } + }); + + bpmLabel.setText(jSlider1.getValue() + " bpm"); + bpmLabel.setName("bpmLabel"); // NOI18N + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(comSelectionMenu, javax.swing.GroupLayout.PREFERRED_SIZE, 79, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(statusLabel) + .addComponent(jSeparator1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 380, Short.MAX_VALUE) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(sequenceNameLabel) + .addComponent(jSlider1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(bpmLabel, javax.swing.GroupLayout.Alignment.TRAILING)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 30, Short.MAX_VALUE) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addGroup(layout.createSequentialGroup() + .addComponent(startButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(stopButton)) + .addComponent(loadButton))) + .addComponent(jLabel1)) + .addContainerGap()) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(comSelectionMenu, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 107, Short.MAX_VALUE) + .addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(sequenceNameLabel) + .addComponent(loadButton)) + .addGap(18, 18, 18) + .addComponent(bpmLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(startButton) + .addComponent(stopButton)) + .addComponent(jSlider1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(11, 11, 11) + .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 8, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(statusLabel) + .addContainerGap()) + ); + + pack(); + }// //GEN-END:initComponents + + private void stopResetClicked(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_stopResetClicked + statusLabel.setText("Stopping..."); + app.ms.stopSequencer(); + startButton.setEnabled(true); + statusLabel.setText("Stopped"); + }//GEN-LAST:event_stopResetClicked + + private void startButtonClicked(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_startButtonClicked + startButton.setEnabled(false); + app.ms.startSequencer(); + }//GEN-LAST:event_startButtonClicked + + private void loadSequence(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_loadSequence + String previouslyLoaded = prefs.get(PREF_LOADED_SEQ, null); + if (previouslyLoaded != null){ + sequenceChooser.setCurrentDirectory(new File(previouslyLoaded)); + } + int returnVal = sequenceChooser.showOpenDialog(this); + + if (returnVal == JFileChooser.APPROVE_OPTION) { + loadSequenceFile(sequenceChooser.getSelectedFile()); + } else { + //Cancelled + } + }//GEN-LAST:event_loadSequence + + private void loadSequenceFile(File sequenceFile){ + try { + statusLabel.setText("Loading file..."); + app.ms.loadFile(sequenceFile.getPath()); + sequenceNameLabel.setText(sequenceFile.getName()); + prefs.put(PREF_LOADED_SEQ, sequenceFile.getPath()); + statusLabel.setText("Loaded " + sequenceFile.getName()); + startButton.setEnabled(true); + } catch (Exception ex) { + Logger.getLogger(MoppyMainWindow.class.getName()).log(Level.SEVERE, null, ex); + statusLabel.setText("File loading error!"); + JOptionPane.showMessageDialog(rootPane, ex); + } + } + + private void tempoSliderChanged(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_tempoSliderChanged + JSlider s = (JSlider) evt.getSource(); + app.ms.setTempo(s.getValue()); + bpmLabel.setText(s.getValue() + " bpm"); + }//GEN-LAST:event_tempoSliderChanged + + private void comPortSelected(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_comPortSelected + JComboBox cb = (JComboBox) evt.getSource(); + if (comboBoxReady) { + String comPort = (String) cb.getSelectedItem(); + initializeSequencer(comPort); + prefs.put(PREF_COM_PORT, comPort); + } + }//GEN-LAST:event_comPortSelected + + private void windowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_windowClosing + app.ms.closeSequencer(); + }//GEN-LAST:event_windowClosing + + public void tempoChanged(int newTempo) { + jSlider1.setValue(newTempo); + bpmLabel.setText(newTempo + " bpm"); + } + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel bpmLabel; + private javax.swing.JComboBox comSelectionMenu; + private javax.swing.JLabel jLabel1; + private javax.swing.JSeparator jSeparator1; + private javax.swing.JSlider jSlider1; + private javax.swing.JButton loadButton; + private javax.swing.JLabel sequenceNameLabel; + private javax.swing.JButton startButton; + private javax.swing.JLabel statusLabel; + private javax.swing.JButton stopButton; + // End of variables declaration//GEN-END:variables + +} diff --git a/Java/MoppyDesk/src/moppydesk/MoppyStatusConsumer.java b/Java/MoppyDesk/src/moppydesk/MoppyStatusConsumer.java new file mode 100644 index 0000000..98cf77f --- /dev/null +++ b/Java/MoppyDesk/src/moppydesk/MoppyStatusConsumer.java @@ -0,0 +1,13 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package moppydesk; + +/** + * + * @author Sam + */ +public interface MoppyStatusConsumer { + public void tempoChanged(int newTempo); +} diff --git a/Java/MoppyDesk/src/moppydesk/MoppyUI.java b/Java/MoppyDesk/src/moppydesk/MoppyUI.java new file mode 100644 index 0000000..e142c2d --- /dev/null +++ b/Java/MoppyDesk/src/moppydesk/MoppyUI.java @@ -0,0 +1,29 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package moppydesk; + +import org.jdesktop.application.SingleFrameApplication; + +/** + * + * @author Sam + */ +public class MoppyUI extends SingleFrameApplication{ + + MoppySequencer ms = null; + + @Override + protected void startup() { + show(new MoppyMainWindow(this)); + } + + /** + * Main method launching the application. + */ + public static void main(String[] args) { + launch(MoppyUI.class, args); + } + +}