package com.Series40Book;

import javax.microedition.lcdui.*;
import javax.microedition.media.control.*;
import javax.microedition.media.*;
import javax.microedition.midlet.*;
import java.io.InputStream;

public class MidiPlayer extends MIDlet
            implements CommandListener {

  private Display display;
  private Command exit;
  private Command play;
  private Command back;

  private TempoControl tempoControl;
  private MIDIControl midiControl;
  private RateControl rateControl;
  private PitchControl pitchControl;
  private VolumeControl volumeControl;
  private StopTimeControl stopControl;

  private TextField tempoField;
  private TextField pitchField;
  private TextField rateField;
  private Gauge volumeGauge;
  private Gauge stopGauge;
  private ChoiceGroup config;

  private Form playerOptions = null;
  private Form playerStates = null;

  // media file location
  public static String mediaMidi;
  public static String remotePrefix;
  public static String localPrefix;

  public MidiPlayer () {
    display = Display.getDisplay(this);
    mediaMidi = getAppProperty ("MediaMidi");
    remotePrefix = getAppProperty ("RemotePrefix");
    localPrefix = getAppProperty ("LocalPrefix");

    exit = new Command ("Done", Command.EXIT, 1);
    play = new Command ("Play", Command.OK, 1);
    back = new Command ("Back", Command.BACK, 1);
  }

  protected void startApp () {
    playerOptions = new Form ("Midi player");
    playerOptions.addCommand (exit);
    playerOptions.addCommand (play);
    playerOptions.setCommandListener (this);

    tempoField = new TextField (
        "Tempo", "100000", 7, TextField.NUMERIC);
    pitchField = new TextField (
        "Pitch", "0", 7, TextField.NUMERIC);
    rateField = new TextField (
        "Rate", "100000", 7, TextField.NUMERIC);

    volumeGauge = new Gauge ("Vol", true, 10, 5);
    stopGauge = new Gauge ("Stop time", true, 20, 20);

    config = new ChoiceGroup ("", Choice.MULTIPLE);
    config.append ("Play local file?", null);
    config.append ("Play backwards?", null);

    playerOptions.append (tempoField);
    playerOptions.append (pitchField);
    playerOptions.append (rateField);
    playerOptions.append (stopGauge);
    playerOptions.append (volumeGauge);
    playerOptions.append (config);

    display.setCurrent (playerOptions);
  }

  protected void pauseApp () {
    // Do nothing
  }

  protected void destroyApp (boolean unconditional) {
    // Do nothing
  }

  public void commandAction (Command c, Displayable d) {
    if (c == exit) {
      destroyApp (true);
      notifyDestroyed ();

    } else if (c == play) {
      try {
        playMidi ();
        showStates ();
      } catch (Exception e) {
        e.printStackTrace ();
      }

    } else if (c == back) {
      display.setCurrent (playerOptions);
    }
  }


  public void playMidi () throws Exception {
    Player player;

    if (config.isSelected(0)) {
      InputStream is =
          this.getClass().getResourceAsStream (
              localPrefix + mediaMidi);
      player = Manager.createPlayer(is, "audio/midi");
    } else {
      player = Manager.createPlayer(
          remotePrefix + mediaMidi);
    }
    player.addPlayerListener(new StopListener ());
    player.realize();

    volumeControl = (VolumeControl) player.getControl(
        "VolumeControl");
    // The volume is from 0 to 100
    volumeControl.setLevel (
        volumeGauge.getValue() * 10);

    stopControl = (StopTimeControl) player.getControl(
        "StopTimeControl");
    // The argument microsecond NOT millisecond!
    stopControl.setStopTime (
        stopGauge.getValue() * 1000000);

    tempoControl = (TempoControl) player.getControl (
        "TempoControl");
    int t = Integer.parseInt (tempoField.getString());
    tempoControl.setTempo(t);

    pitchControl = (PitchControl) player.getControl (
        "PitchControl");
    int p = Integer.parseInt (pitchField.getString());
    pitchControl.setPitch(p);

    rateControl = (RateControl) player.getControl (
        "RateControl");
    int r = Integer.parseInt (rateField.getString());
    if (config.isSelected(1)) {
      r = -1 * r;
    }
    rateControl.setRate(r);

    midiControl = (MIDIControl) player.getControl (
        "MIDIControl");

    player.start ();
  }

  public void showStates () {
    playerStates = new Form ("Channel Vols");
    playerStates.addCommand (back);
    playerStates.setCommandListener (this);

    for (int i = 0; i <= 15; i++) {
      playerStates.append ("\n " + i + ": " +
          Integer.toString(
              midiControl.getChannelVolume(i)));
    }

    display.setCurrent(playerStates);
  }

}