package ac.essex.ooechs.music.util.midi;

import javax.sound.midi.*;

/**
 * Plays a sequence of notes using the default Midi Player on your system.
 */
public class MIDIPlayer {

    int channel;

    Receiver receiver = null;

    public static void main(String[] args) {
        MIDIPlayer p = new MIDIPlayer();
        p.play(new Note(52, Note.CROTCHET));
        p.pause();
        p.play(new Note(50, Note.CROTCHET));
        p.pause();
        p.play(new Note(48, Note.CROTCHET));
        p.pause();
        p.play(new Note(50, Note.CROTCHET));
        p.pause();
        p.play(new Note(52, Note.CROTCHET));
        p.pause();
        p.play(new Note(52, Note.CROTCHET));
        p.pause();
        p.play(new Note(52, Note.CROTCHET));
        p.pause();

    }

    public MIDIPlayer() {

        channel = 0;

        // We retrieve a Receiver for the default MidiDevice.
        try {
            receiver = MidiSystem.getReceiver();
        } catch (MidiUnavailableException e) {
            System.err.println(e);
            System.exit(1);
        }

    }

    public void play(Note n) {
        new MIDIPlayer.NotePlayer(n).start();
    }

    public void pause() {
        try {
        Thread.sleep(Tempo.getDuration(Note.QUAVER));
        } catch (Exception e) {}
    }

    class NotePlayer extends Thread {

        Note n;

        public NotePlayer(Note n) {
            this.n = n;
        }

        public void run() {

            ShortMessage onMessage = null;
            ShortMessage offMessage = null;

            try {
                onMessage = new ShortMessage();
                offMessage = new ShortMessage();
                onMessage.setMessage(ShortMessage.NOTE_ON, channel, n.key, n.volume);
                offMessage.setMessage(ShortMessage.NOTE_OFF, channel, n.key, 0);
            } catch (InvalidMidiDataException e) {
                System.err.println(e);
            }

            // Turn the note on
            receiver.send(onMessage, -1);

            // Wait, then turn the note off
            try {
                Thread.sleep(n.duration);
            } catch (InterruptedException e) {
                // Should not happen
            }

            // Turn the note off
            receiver.send(offMessage, -1);
        }

    }

    public void stop() {

        // Clean up
        receiver.close();

    }

}
