Package music.ui

Source Code of music.ui.MusicalSkillCoach

/*
*    Musical Skill Coach - An interactive midi device friendly program to help music students improve their skills
*    Copyright (C) 2011  Paul-Emile Gaudet
*
*    This program is free software: you can redistribute it and/or modify
*    it under the terms of the GNU General Public License as published by
*    the Free Software Foundation, either version 3 of the License, or
*    (at your option) any later version.
*
*    This program is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU General Public License for more details.
*
*    You should have received a copy of the GNU General Public License
*    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

package music.ui;

import java.awt.*;
import java.awt.event.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;

import javax.sound.midi.MidiDevice;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.MidiUnavailableException;
import javax.sound.midi.Sequencer;
import javax.sound.midi.Synthesizer;
import javax.swing.*;
import javax.swing.event.*;

import music.lib.LabeledInteger;
import music.lib.MusicScore;
import music.lib.instruments.Piano;
import music.midi.MidiReceiver;
import music.midi.MidiTransmitter;
import music.modules.NoteTiming;
import music.modules.SightRead;
import music.ui.instruments.BasicInstrumentCanvas;
import music.ui.instruments.PianoKeyCanvas;
import music.ui.lib.MetronomeCanvas; // import music.ui.instruments.RecorderKeyCanvas;
import music.ui.panels.AccuracyPanel;
import music.ui.panels.NoteSelectionPanel;
import music.ui.panels.OctaveSelectionPanel;
import music.ui.panels.Timing;
import music.ui.panels.TrebleBassStaff;

public class MusicalSkillCoach extends JFrame implements KeyListener
{
  /**
   *
   */
  private static final long serialVersionUID = 1L;

  protected static final int PIANO_TYPE = 0;

  protected JMenuBar menuBar;
  protected JMenu file;
  protected JMenuItem filePlay;
  protected JMenuItem fileExit;

  protected JMenu exercises;
  protected JMenu exercisePractice;
  protected JMenu exerciseSightRead;
  protected JMenu exerciseTiming;

  protected JMenu keys;
  protected JMenu chords;
  protected JMenu scales;

  protected JMenu instruments;
  protected JMenu instrumentPiano;
  protected JMenuItem keysEightyEight;
  protected JMenuItem keysSixtyOne;
  protected JMenuItem keysFortyOne;

  protected JTabbedPane tabbedPane;
  protected MetronomeCanvas metronome;
  protected BasicInstrumentCanvas pianoKeys;
  protected JComboBox midiSelector;
  protected JLabel statusBar;

  protected ActionListener actionPerformed;
  protected ListSelectionListener selectionPerformed;
  protected FocusListener focusChange;
  protected ChangeListener changePerformed;

  protected JPanel srPanel;
  protected Timing timing;
  protected TrebleBassStaff practicePanel;
  protected TrebleBassStaff sightReadPanel;
  protected AccuracyPanel accuracyPanel;
  protected NoteSelectionPanel noteSelectionPanel;
  protected OctaveSelectionPanel octaveSelectionPanel;

  protected boolean processEvent;

  protected MidiDevice midiInDevice;
  protected MidiDevice midiOutDevice;
  protected MidiTransmitter mt;
  protected MidiReceiver mr;

  protected SightRead sightReader;
  protected NoteTiming noteTiming;

  protected MusicScore musicScore;

  protected Piano piano;

  protected HashMap<JRadioButtonMenuItem, LabeledInteger> keyMenuToItemLut;
  protected HashMap<JRadioButtonMenuItem, LabeledInteger> chordMenuToItemLut;
  protected HashMap<JRadioButtonMenuItem, LabeledInteger> scaleMenuToItemLut;

  protected HashMap<String, ArrayList<MidiDevice>> midiDeviceLookup;

  public MusicalSkillCoach()
  {
    super("Musical Skill Coach");

    keyMenuToItemLut = new HashMap<JRadioButtonMenuItem, LabeledInteger>();
    chordMenuToItemLut = new HashMap<JRadioButtonMenuItem, LabeledInteger>();
    scaleMenuToItemLut = new HashMap<JRadioButtonMenuItem, LabeledInteger>();

    piano = new Piano();

    actionPerformed = new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        actionEvents(e);
      }
    };
    selectionPerformed = new ListSelectionListener()
    {
      public void valueChanged(ListSelectionEvent e)
      {
        selectionEvents(e);
      }
    };
    focusChange = new FocusListener()
    {
      public void focusGained(FocusEvent e)
      {
        gotFocus(e);
      }

      public void focusLost(FocusEvent e)
      {
        lostFocus(e);
      }
    };
    changePerformed = new ChangeListener()
    {
      public void stateChanged(ChangeEvent e)
      {
        changeEvents(e);
      }
    };

    menuBar = new JMenuBar();

    file = new JMenu("File");

    file.add(filePlay = new JMenuItem("Play"));
    file.add(fileExit = new JMenuItem("Exit"));

    exercises = new JMenu("Exercises");

    exercises.add(exercisePractice = new JMenu("Practice"));
    exercises.add(exerciseSightRead = new JMenu("Sight Read"));
    exercises.add(exerciseTiming = new JMenu("Timing"));

    keys = new JMenu("Keys");
    chords = new JMenu("Chords");
    scales = new JMenu("Scales");

    instruments = new JMenu("Instrument");

    instruments.add(instrumentPiano = new JMenu("Piano"));

    instrumentPiano.add(keysEightyEight = new JMenuItem("88 Keys"));
    instrumentPiano.add(keysSixtyOne = new JMenuItem("61 Keys"));
    instrumentPiano.add(keysFortyOne = new JMenuItem("41 Keys"));

    menuBar.add(file);
    menuBar.add(exercises);
    menuBar.add(keys);
    menuBar.add(chords);
    menuBar.add(scales);
    menuBar.add(instruments);

    filePlay.addActionListener(actionPerformed);
    fileExit.addActionListener(actionPerformed);

    keysEightyEight.addActionListener(actionPerformed);
    keysSixtyOne.addActionListener(actionPerformed);
    keysFortyOne.addActionListener(actionPerformed);

    setJMenuBar(menuBar);

    JPanel mainPane = new JPanel();

    mainPane.setLayout(new BoxLayout(mainPane, BoxLayout.Y_AXIS));

    mainPane.add(tabbedPane = new JTabbedPane());

    mainPane.add(metronome = new MetronomeCanvas());
    mainPane.add(pianoKeys = new PianoKeyCanvas());

    mainPane.add(midiSelector = new JComboBox());

    JPanel panel = new JPanel();

    panel.setLayout(new GridLayout(0, 1));

    panel.add(statusBar = new JLabel("Status messages go here"));

    mainPane.add(panel);

    practicePanel = new TrebleBassStaff();
    sightReadPanel = new TrebleBassStaff();
    accuracyPanel = new AccuracyPanel();
    noteSelectionPanel = new NoteSelectionPanel();
    octaveSelectionPanel = new OctaveSelectionPanel();

    srPanel = new JPanel();
    srPanel.setLayout(new BoxLayout(srPanel, BoxLayout.X_AXIS));

    srPanel.add(sightReadPanel);

    panel = new JPanel();
    panel.setLayout(new GridLayout(3, 1));

    panel.add(accuracyPanel);
    panel.add(noteSelectionPanel);
    panel.add(octaveSelectionPanel);

    srPanel.add(panel);

    tabbedPane.addTab("Practice", practicePanel);
    tabbedPane.addTab("Sight Reading", srPanel);
    tabbedPane.addTab("Timing", timing = new Timing());

    setContentPane(mainPane);

    pack();

    statusBar.setAlignmentX(LEFT_ALIGNMENT);

    processEvent = true;

    midiSelector.addItem(new String("No MIDI device Selected"));

    MidiDevice device = null;
    MidiDevice.Info[] midiDevices = MidiSystem.getMidiDeviceInfo();

    midiInDevice = midiOutDevice = null;

    midiDeviceLookup = new HashMap<String, ArrayList<MidiDevice>>();

    ArrayList<MidiDevice> devices;

    for (int i = 0; i < midiDevices.length; i++)
    {
      try
      {
        device = MidiSystem.getMidiDevice(midiDevices[i]);

        if ((!(device instanceof Sequencer) && !(device instanceof Synthesizer)))
        {
          devices = midiDeviceLookup.get(midiDevices[i].getName());

          if (devices == null)
          {
            devices = new ArrayList<MidiDevice>();
          }

          devices.add(device);

          midiDeviceLookup.put(midiDevices[i].getName(), devices);
        }
      }
      catch (MidiUnavailableException e)
      {
      }
    }

    Set<String> s = midiDeviceLookup.keySet();
    Iterator<String> iterator = s.iterator();

    while (iterator.hasNext())
    {
      midiSelector.addItem(iterator.next());
    }

    mt = new MidiTransmitter();
    mr = new MidiReceiver();

    pianoKeys.setMidiReceiver(mr);
    pianoKeys.setMidiTransmitter(mt);

    sightReader = new SightRead();

    sightReader.setmRec(mr);
    sightReader.setmTrans(mt);
    sightReader.setTbStaff(sightReadPanel);
    sightReader.setAccuracyPanel(accuracyPanel);
    sightReader.setStatusBar(statusBar);

    sightReader.start();

    noteTiming = new NoteTiming(metronome);
    noteTiming.setmRec(mr);
    noteTiming.setPanel(timing);
    noteTiming.start();
    noteTiming.setStatusBar(statusBar);

    midiSelector.addActionListener(actionPerformed);

    JOptionPane
        .showMessageDialog(
            this,
            "This application is very early in development (version 0.7)\n(and now contains the first 8 bars of Beethoven's \"Moonlight Sonata\")\nPlease be patient as I continue to develop it when my time permits.\nFor now, please review this sourceforge project's readme.txt file for more information in 'view all files'");

    metronome.setMidiTransmitter(mt);

    noteSelectionPanel.setSightReader(sightReader);
    octaveSelectionPanel.setSightReader(sightReader);

    noteTiming.stop();

    getJarFileData("/data/moonlightsonata.txt");
    practicePanel.loadNotesFromMusicScore(musicScore);

    setInstrumentType(PIANO_TYPE);

    scales.setEnabled(false);
    chords.setEnabled(false);

    tabbedPane.setSelectedComponent(srPanel);
    verifyObject(srPanel);

    tabbedPane.addKeyListener(this);
    tabbedPane.addChangeListener(changePerformed);
  }

  protected void setInstrumentType(int instrumentType)
  {
    JRadioButtonMenuItem menuItem;
    Iterator<JRadioButtonMenuItem> iterator;

    iterator = keyMenuToItemLut.keySet().iterator();
    while (iterator.hasNext())
    {
      menuItem = iterator.next();

      menuItem.removeActionListener(actionPerformed);
      keys.remove(menuItem);
    }

    iterator = chordMenuToItemLut.keySet().iterator();
    while (iterator.hasNext())
    {
      menuItem = iterator.next();

      menuItem.removeActionListener(actionPerformed);
      chords.remove(menuItem);
    }

    iterator = scaleMenuToItemLut.keySet().iterator();
    while (iterator.hasNext())
    {
      menuItem = iterator.next();

      menuItem.removeActionListener(actionPerformed);
      scales.remove(menuItem);
    }

    keyMenuToItemLut.clear();
    chordMenuToItemLut.clear();
    scaleMenuToItemLut.clear();

    ArrayList<LabeledInteger> labels;
    Iterator<LabeledInteger> labelIterator;
    LabeledInteger labeledInteger;

    if (instrumentType == PIANO_TYPE)
    {
      labels = piano.getKeyLabels();

      JRadioButtonMenuItem firstMenuItem;

      labelIterator = labels.iterator();
      firstMenuItem = null;
      while (labelIterator.hasNext())
      {
        labeledInteger = labelIterator.next();
        menuItem = new JRadioButtonMenuItem(labeledInteger.getLabel());
        menuItem.addActionListener(actionPerformed);
        keys.add(menuItem);
        keyMenuToItemLut.put(menuItem, labeledInteger);

        if (firstMenuItem == null)
          firstMenuItem = menuItem;
      }

      labels = piano.getChordLabels();

      labelIterator = labels.iterator();
      firstMenuItem = null;
      while (labelIterator.hasNext())
      {
        labeledInteger = labelIterator.next();
        menuItem = new JRadioButtonMenuItem(labeledInteger.getLabel());
        menuItem.addActionListener(actionPerformed);
        chords.add(menuItem);
        chordMenuToItemLut.put(menuItem, labeledInteger);

        if (firstMenuItem == null)
          firstMenuItem = menuItem;
      }

      labels = piano.getScaleLabels();

      labelIterator = labels.iterator();
      firstMenuItem = null;
      while (labelIterator.hasNext())
      {
        labeledInteger = labelIterator.next();
        menuItem = new JRadioButtonMenuItem(labeledInteger.getLabel());
        menuItem.addActionListener(actionPerformed);
        scales.add(menuItem);
        scaleMenuToItemLut.put(menuItem, labeledInteger);

        if (firstMenuItem == null)
          firstMenuItem = menuItem;
      }
    }
  }

  public void getJarFileData(String filename)
  {
    MusicScore ms = new MusicScore();

    InputStream jarStream = null;
    BufferedReader bufferedReader = null;

    try
    {
      jarStream = MusicalSkillCoach.class.getResourceAsStream(filename);
      if (jarStream == null)
        return;
      bufferedReader = new BufferedReader(new InputStreamReader(jarStream));
      String line;

      while ((line = bufferedReader.readLine()) != null)
        ms.parseLine(line);
    }
    catch (Exception e)
    {
      return;
    }
    finally
    {
      try
      {
        if (bufferedReader != null)
          bufferedReader.close();
        if (jarStream != null)
          jarStream.close();
      }
      catch (IOException e)
      {
        return;
      }
    }

    this.musicScore = ms;
  }

  protected void actionEvents(ActionEvent e)
  {
    Object obj = e.getSource();

    if (processEvent == false)
      return;

    verifyObject(obj);
  }

  protected void selectionEvents(ListSelectionEvent e)
  {
    Object obj = e.getSource();

    verifyObject(obj);
  }

  protected void changeEvents(ChangeEvent e)
  {
    Object obj = e.getSource();

    verifyObject(obj);
  }

  protected void gotFocus(FocusEvent e)
  {
    Object obj = e.getSource();

    if (obj instanceof JTextField)
    {
      JTextField tf = (JTextField) obj;

      tf.setCaretPosition(0);
      tf.moveCaretPosition(tf.getText().length());
    }
  }

  protected void lostFocus(FocusEvent e)
  {
    Object obj = e.getSource();

    verifyObject(obj);
  }

  protected void verifyObject(Object obj)
  {
    if (processEvent == false)
      return;

    processEvent = false;

    if (obj instanceof JButton)
    {
    }
    else if (obj == midiSelector)
    {
      selectMidiDevice();
    }
    else if (obj instanceof JMenuItem)
    {
      if (obj == filePlay)
      {
        if (musicScore != null)
        {
          musicScore.playScore(mt);
        }
      }
      else if (obj == fileExit)
      {
        if (midiOutDevice != null)
          midiOutDevice.close();
        System.exit(0);
      }
      else if (obj == keysEightyEight)
      {
        pianoKeys.setInstrumentType(PianoKeyCanvas.KEYBOARD_LAYOUT_88KEYS);
        pianoKeys.invalidate();
        pianoKeys.repaint();
      }
      else if (obj == keysSixtyOne)
      {
        pianoKeys.setInstrumentType(PianoKeyCanvas.KEYBOARD_LAYOUT_61KEYS);
        pianoKeys.invalidate();
        pianoKeys.repaint();
      }
      else if (obj == keysFortyOne)
      {
        pianoKeys.setInstrumentType(PianoKeyCanvas.KEYBOARD_LAYOUT_41KEYS);
        pianoKeys.invalidate();
        pianoKeys.repaint();
      }
      else
      {
        JRadioButtonMenuItem jRadio = (JRadioButtonMenuItem) obj;
        LabeledInteger li;

        if ((li = keyMenuToItemLut.get(jRadio)) != null)
        {
          piano.setKey(li);

          // no time yet to do the jradio button thingie right at the moment, so doing this instead
          Iterator<JRadioButtonMenuItem> iterator = keyMenuToItemLut.keySet().iterator();
          while (iterator.hasNext())
          {
            jRadio = iterator.next();
            if (jRadio != obj)
              jRadio.setSelected(false);
          }
        }
        else if ((li = chordMenuToItemLut.get(jRadio)) != null)
        {
          piano.setChord(li);
         
          // no time yet to do the jradio button thingie right at the moment, so doing this instead
          Iterator<JRadioButtonMenuItem> iterator = chordMenuToItemLut.keySet().iterator();
          while (iterator.hasNext())
          {
            jRadio = iterator.next();
            if (jRadio != obj)
              jRadio.setSelected(false);
          }
        }
        else if ((li = scaleMenuToItemLut.get(jRadio)) != null)
        {
          piano.setScale(li);
         
          // no time yet to do the jradio button thingie right at the moment, so doing this instead
          Iterator<JRadioButtonMenuItem> iterator = scaleMenuToItemLut.keySet().iterator();
          while (iterator.hasNext())
          {
            jRadio = iterator.next();
            if (jRadio != obj)
              jRadio.setSelected(false);
          }
        }

        if (tabbedPane.getSelectedComponent() == srPanel)
        {
          // NOT YET...
        }
        else if (tabbedPane.getSelectedComponent() == timing)
        {
          noteTiming.stop();
          noteTiming.setFixedScale(piano.getScales(5));
          noteTiming.start();
         
          timing.invalidate();
          timing.repaint();
        }
      }
    }
    else if (obj == tabbedPane)
    {
      sightReader.stop();
      noteTiming.stop();

      if (tabbedPane.getSelectedComponent() == srPanel)
      {
        sightReader.start();
        chords.setEnabled(false);
        scales.setEnabled(false);
      }
      else if (tabbedPane.getSelectedComponent() == timing)
      {
        noteTiming.start();
        chords.setEnabled(false);
        scales.setEnabled(true);
      }
      else
      {
        chords.setEnabled(false);
        scales.setEnabled(false);
      }
    }

    processEvent = true;
  }

  protected void selectMidiDevice()
  {
    if (midiInDevice != null)
    {
      mt.clearMidiDevice();
      midiInDevice.close();
      midiInDevice = null;
    }

    if (midiOutDevice != null)
    {
      midiOutDevice.close();
      midiOutDevice = null;
    }

    MidiDevice device;

    String selectedDevice = (String) midiSelector.getSelectedItem();

    ArrayList<MidiDevice> al = midiDeviceLookup.get(selectedDevice);

    if (al == null)
    {
      return;
    }

    Iterator<MidiDevice> iterator = al.iterator();

    while (iterator.hasNext())
    {
      device = iterator.next();
      if (device.getMaxReceivers() != 0)
        midiInDevice = device;
      if (device.getMaxTransmitters() != 0)
        midiOutDevice = device;
    }

    if ((midiInDevice != null) && (midiOutDevice != null))
    {
      try
      {
        midiInDevice.open();
        mt.setDevice(midiInDevice);
      }
      catch (Exception e)
      {
        e.printStackTrace();
        midiInDevice = midiOutDevice = null;
      }

      try
      {
        midiOutDevice.open();
        midiOutDevice.getTransmitter().setReceiver(mr);
      }
      catch (Exception e)
      {
        e.printStackTrace();
        midiInDevice = midiOutDevice = null;
      }
    }

    if ((midiInDevice != null) && (midiOutDevice != null))
    {
      mt.setProgramChange(0, 0);
      mt.setProgramChange(1, 0);
      mt.setProgramChange(15, 0x73);
    }

    // midiSelector.setEnabled(false);

  }

  @Override
  public void keyPressed(KeyEvent e)
  {
    // System.out.println("PRESS: " + e.getKeyChar());
  }

  @Override
  public void keyReleased(KeyEvent e)
  {
    // System.out.println("RELEASE: " + e.getKeyChar());
  }

  @Override
  public void keyTyped(KeyEvent e)
  {
    // System.out.println("TYPED: " + e.getKeyChar());
    practicePanel.removeFirstObject();
    practicePanel.invalidate();
    practicePanel.repaint();
  }

  public static void main(String args[])
  {
    final MusicalSkillCoach mscMainWindow = new MusicalSkillCoach();

    mscMainWindow.addWindowListener(new WindowAdapter()
    {
      public void windowClosing(WindowEvent e)
      {
        System.exit(0);
      }
    });

    mscMainWindow.setLocation(10, 25);
    mscMainWindow.setSize(new Dimension(mscMainWindow.getPreferredSize().width, mscMainWindow.getPreferredSize().height));
    mscMainWindow.setVisible(true);
  }
}
TOP

Related Classes of music.ui.MusicalSkillCoach

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.