/* UD Music Theory Test JApplet */ import java.applet.Applet; import javax.swing.*; import java.awt.*; import java.awt.event.*; import javax.sound.midi.*; import java.io.*; import java.util.*; import java.net.*; public class UdmtMidiSetup extends JApplet implements ActionListener, MetaEventListener, Runnable { private JButton playButton, recordButton, queueButton; private JComboBox midiInComboBox, midiOutComboBox; private JLabel midiInComboLabel, midiOutComboLabel; private String[] midiInDevices, midiOutDevices; private int[] midiInDeviceNums, midiOutDeviceNums; private int currentMidiInDeviceNum, currentMidiOutDeviceNum; private int prevMidiInDeviceNum, prevMidiOutDeviceNum; private MidiDevice.Info[] myMidiDeviceInfo; private MidiDevice myMidiInDevice, myMidiOutDevice; private Sequencer mySequencer; private Synthesizer mySynth ; private Receiver myReceiver; private UdmtMidiInQueue myMidiInReceiver; private Transmitter myTransmitter, myMidiInTransmitter; private boolean midiInActive, midiOutActive; private int prevQptr = -1; private Rectangle rect; private Thread looper; private boolean running; private String banner = ""; private int[][] noteVels; private UdmtMidiDisplay myMidiDisplay; private int numEventsRecorded = 0; final String upperCaseSharps ="cCdDefFgGaAb"; final String lowerCaseFlats ="CdDeEFgGaAbB"; //--------------------------------------------------------------------------------------------- public void init() { //the following line is suggested in the Java Tutorial p.459 for JDK 1.1 getRootPane().putClientProperty("defeatSystemEventQueueCheck",Boolean.TRUE); Container content = getContentPane(); content.setLayout(new BorderLayout()); currentMidiInDeviceNum = 0; currentMidiOutDeviceNum = 0; midiInActive = false; midiOutActive = false; getMidiDevices(); initializeMidi(); JPanel devicePanel = new JPanel(); devicePanel.setLayout( new GridLayout(4,2) ); midiInComboLabel = new JLabel("MIDI IN Device:"); devicePanel.add(midiInComboLabel); midiOutComboLabel = new JLabel("MIDI OUT Device:"); devicePanel.add(midiOutComboLabel); midiInComboBox = new JComboBox ( midiInDevices ); midiInComboBox.addActionListener(this); devicePanel.add(midiInComboBox); midiOutComboBox = new JComboBox ( midiOutDevices ); midiOutComboBox.addActionListener(this); devicePanel.add(midiOutComboBox); midiInComboLabel = new JLabel(""); devicePanel.add(midiInComboLabel); midiOutComboLabel = new JLabel(""); devicePanel.add(midiOutComboLabel); recordButton = new JButton("Test MIDI IN"); recordButton.addActionListener(this); recordButton.setEnabled(true); devicePanel.add(recordButton); playButton = new JButton("Test MIDI OUT"); playButton.addActionListener(this); playButton.setEnabled(true); devicePanel.add(playButton); content.add("South",devicePanel); //JPanel testPanel = new JPanel(); //testPanel.setLayout( new FlowLayout() ); //queueButton = new JButton("View MIDI IN queue"); //queueButton.addActionListener(this); //queueButton.setEnabled(true); //testPanel.add(queueButton); //content.add("South",testPanel); JPanel displayPanel = new JPanel(new BorderLayout()); displayPanel.add(myMidiDisplay = new UdmtMidiDisplay()); content.add("North",displayPanel); // Initialize array of note velocities. noteVels = new int[16][128]; for (int c=0; c<16; c++) { for (int n=0; n<128; n++) { noteVels[c][n] = 0; } } } //--------------------------------------------------------------------------------------------- public void actionPerformed(ActionEvent event) { if(event.getActionCommand().equals("View MIDI IN queue")) { viewMidiInQueue(); } if(event.getActionCommand().equals("Test MIDI OUT")) { testMidiOut(); midiInComboBox.setEnabled(false); midiOutComboBox.setEnabled(false); } else if(event.getActionCommand().equals("STOP Playback")) { mySequencer.stop(); playButton.setText("Test MIDI OUT"); if (recordButton.getText().equals("Test MIDI IN")) { midiInComboBox.setEnabled(true); midiOutComboBox.setEnabled(true); } } else if(event.getActionCommand().equals("STOP Recording")) { myMidiInReceiver.stopRecording(); recordButton.setText("Test MIDI IN"); if (playButton.getText().equals("Test MIDI OUT")) { midiInComboBox.setEnabled(true); midiOutComboBox.setEnabled(true); } } else if(event.getActionCommand().equals("Test MIDI IN")) { testMidiIn(); midiInComboBox.setEnabled(false); midiOutComboBox.setEnabled(false); } else if (event.getActionCommand().equals("comboBoxChanged")) { currentMidiInDeviceNum = midiInDeviceNums[midiInComboBox.getSelectedIndex()]; currentMidiOutDeviceNum = midiOutDeviceNums[midiOutComboBox.getSelectedIndex()]; System.out.println("Combo box changed"); System.out.println("Current Midi Out Device#=" + currentMidiOutDeviceNum); System.out.println("Current Midi IN Device#=" + currentMidiInDeviceNum); initializeMidi(); //System.out.println("Midi Out device index: " + midiOutComboBox.getSelectedIndex()); //System.out.println("Item=" + midiOutComboBox.getItemAt(midiOutComboBox.getSelectedIndex())); //System.out.println("Midi IN device index: " + midiInComboBox.getSelectedIndex()); //System.out.println("Item=" + midiInComboBox.getItemAt(midiInComboBox.getSelectedIndex())); } } //--------------------------------------------------------------------------------------------- // Determine all installed midi devices and populate the arrays that contain the descriptions // and device numbers of the MIDI input and output devices. Also, take a guess at what the // user's preferred MIDI in and out devices are. //--------------------------------------------------------------------------------------------- private void getMidiDevices() { int ixIn, ixOut, numIn, numOut, numDevs; String[] allDevices; boolean[] allDevInput, allDevOutput; myMidiDeviceInfo = MidiSystem.getMidiDeviceInfo(); numDevs = myMidiDeviceInfo.length; allDevices = new String[numDevs]; allDevInput = new boolean[numDevs]; allDevOutput = new boolean[numDevs]; numIn = 0; numOut = 0; for (int i = 0; i < numDevs; i++) { try { MidiDevice device = MidiSystem.getMidiDevice(myMidiDeviceInfo[i]); allDevices[i] = myMidiDeviceInfo[i].getName(); if (device.getMaxTransmitters() != 0) { allDevInput[i] = true; numIn++; } if (device.getMaxReceivers() != 0) { allDevOutput[i] = true; numOut++; } } catch (MidiUnavailableException e) { e.printStackTrace(); numDevs = 0; } } midiInDevices = new String[numIn]; midiOutDevices = new String[numOut]; midiInDeviceNums = new int[numIn]; midiOutDeviceNums = new int[numOut]; ixIn = 0; ixOut = 0; for (int j = 0; j < numDevs; j++) { if (allDevInput[j]) { midiInDevices[ixIn] = allDevices[j]; midiInDeviceNums[ixIn] = j; ixIn++; } if (allDevOutput[j]) { midiOutDevices[ixOut] = allDevices[j]; midiOutDeviceNums[ixOut] = j; ixOut++; } } // for } // method getMidiDevices //--------------------------------------------------------------------------------------------- // Use selected device numbers to initialize MIDI In and Out. // Midi Out Device # = midiOutDeviceNums[midiOutComboBox.getSelectedIndex()]) // Midi IN Device # = midiInDeviceNums[midiInComboBox.getSelectedIndex()]) //--------------------------------------------------------------------------------------------- private void initializeMidi() { System.out.println("initializeMidi:"); try { if ((currentMidiOutDeviceNum >= 0) && (midiOutActive)) { System.out.println("Closing myMidiOutDevice: "+prevMidiOutDeviceNum); mySequencer.close(); myMidiOutDevice.close(); } myMidiOutDevice = MidiSystem.getMidiDevice( myMidiDeviceInfo[currentMidiOutDeviceNum] ); myMidiOutDevice.open(); mySequencer = MidiSystem.getSequencer(); myTransmitter = mySequencer.getTransmitter(); mySequencer.open(); mySequencer.addMetaEventListener(this); myTransmitter.setReceiver(myMidiOutDevice.getReceiver()); System.out.println("Opened myMidiOutDevice: "+currentMidiOutDeviceNum); midiOutActive = true; prevMidiOutDeviceNum = currentMidiOutDeviceNum; if ((currentMidiInDeviceNum >= 0) && (midiInActive)) { System.out.println("Closing myMidiInDevice: "+prevMidiInDeviceNum); myMidiInDevice.close(); } myMidiInDevice = MidiSystem.getMidiDevice( myMidiDeviceInfo[currentMidiInDeviceNum] ); myMidiInDevice.open(); myMidiInTransmitter = myMidiInDevice.getTransmitter(); myMidiInReceiver = new UdmtMidiInQueue(); myMidiInTransmitter.setReceiver(myMidiInReceiver); System.out.println("Opened myMidiInDevice: "+currentMidiInDeviceNum); midiInActive = true; prevMidiInDeviceNum = currentMidiInDeviceNum; } catch (MidiUnavailableException e) { System.out.println("MidiUnavailableException encountered"); } } //--------------------------------------------------------------------------------------------- private void testMidiOut() { Sequence mySequence; Track[] myTracks; byte blankbytes[] = { 0 }; System.out.println("testMidiOut"); try { mySequence = new Sequence(Sequence.PPQ, 24, 1); myTracks = mySequence.getTracks(); mySequencer.setTempoInBPM(120); ShortMessage mymsg = new ShortMessage(); mymsg.setMessage(0x90, 0x3c, 0x40); MidiEvent myevent = new MidiEvent(mymsg, 0); myTracks[0].add(myevent); ShortMessage mymsg2 = new ShortMessage(); mymsg2.setMessage(0x90, 0x40, 0x40); MidiEvent myevent2 = new MidiEvent(mymsg2, 24); myTracks[0].add(myevent2); ShortMessage mymsg3 = new ShortMessage(); mymsg3.setMessage(0x90, 0x3c, 0x00); MidiEvent myevent3 = new MidiEvent(mymsg3, 48); myTracks[0].add(myevent3); ShortMessage mymsg4 = new ShortMessage(); mymsg4.setMessage(0x90, 0x40, 0x00); MidiEvent myevent4 = new MidiEvent(mymsg4, 72); myTracks[0].add(myevent4); ShortMessage drummsg = new ShortMessage(); drummsg.setMessage (0x99, 42, 0x7F); // metronome click on channel 10 for (int t = 96; t <= 9600; t+=24) { myTracks[0].add(new MidiEvent(drummsg, t)); } MetaMessage mymsg5 = new MetaMessage(); mymsg5.setMessage(0x2f, blankbytes, 0); MidiEvent myevent5 = new MidiEvent(mymsg5,96); myTracks[0].add(myevent5); mySequencer.setSequence(mySequence); mySequencer.start(); playButton.setText("STOP Playback"); } catch (InvalidMidiDataException e) { System.out.println("Invalid MIDI Data Exception"); e.printStackTrace(); } //catch (InterruptedException e) //{ System.out.println("Interrupted Exception"); // e.printStackTrace(); //} } //--------------------------------------------------------------------------------------------- // The following method is called whenever a Meta event is processed by the sequencer. // We are checking for meta event type 47 to determine if the end of the sequence has been reached. //--------------------------------------------------------------------------------------------- public void meta(MetaMessage msg) { if (msg.getType() == 47) { System.out.println("End of Track - Stopping Sequence"); if (mySequencer.isRunning()) { mySequencer.stop(); } playButton.setText("Test MIDI OUT"); } } //--------------------------------------------------------------------------------------------- private void testMidiIn() { System.out.println("testMidiIn"); myMidiInReceiver.startRecording(); recordButton.setText("STOP Recording"); } //--------------------------------------------------------------------------------------------- private void viewMidiInQueue() { int currQptr, maxQptr; long t; int c,n,v; //System.out.println("viewMidiInQueue"); maxQptr = myMidiInReceiver.getMidiInQueueSize(); //System.out.println("Queue Size="+maxQptr); currQptr = myMidiInReceiver.getMidiInQueuePtr(); //System.out.println("Prev Qptr ="+prevQptr+" Curr Qptr="+currQptr); if (currQptr == prevQptr) { //System.out.println("No new events recorded since you last checked"); } else { while (prevQptr != currQptr) { prevQptr++; if (prevQptr >= maxQptr) { prevQptr = 0; } t = myMidiInReceiver.getMidiInQueueTime(prevQptr); c = myMidiInReceiver.getMidiInQueueChnl(prevQptr); n = myMidiInReceiver.getMidiInQueueNote(prevQptr); v = myMidiInReceiver.getMidiInQueueVel(prevQptr); //System.out.println("T="+t+" C="+c+" N="+n+" V="+v); numEventsRecorded++; banner = "Number of Events Recorded from MIDI IN: "+numEventsRecorded; //keep track of all notes that are down now noteVels[c][n] = v; } } } //--------------------------------------------------------------------------------------------- // Animation routines: //--------------------------------------------------------------------------------------------- public void start() { if(!running) { running = true; looper = new Thread(this); looper.start(); } } public void stop() { running = false; } public void run() { try { while(running) { repaint(); looper.sleep(50); frameNext(); } } catch(InterruptedException e) { running = false; } } public void update(Graphics g) { if(running) { if(rect == null) { rect = getBounds(); frameFirst(); } myMidiDisplay.paint(g); } } private void frameFirst() { banner = ""; } private void frameNext() { viewMidiInQueue(); } //--------------------------------------------------------------------------------------------- class UdmtMidiDisplay extends JPanel { public UdmtMidiDisplay() { setLayout (new BorderLayout()); setPreferredSize (new Dimension(800,50)); } public void paint(Graphics g) { g.setColor(Color.green); g.fillRect(0,0,800,30); g.setColor(Color.black); g.drawString(banner,0,20); for (int c=0; c<16; c++) { for (int n=21; n<=108; n++) { if (noteVels[c][n] == 0) { g.setColor(Color.white); } else { g.setColor(Color.red); } g.fillRect( (n-21)*8+40, (c*8)+50, 7, 7 ); } } } } // END OF CLASS UdmtMidiDisplay } // END OF CLASS UdmtMidiSetup