Package jrackattack.midi

Source Code of jrackattack.midi.MidiThread

/* For License see bottom */
/*
* MidiThread.java
*
* Created on 29. Juni 2007, 21:32
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/

package jrackattack.midi;

import javax.sound.midi.InvalidMidiDataException;
import javax.sound.midi.MidiDevice;
import javax.sound.midi.MidiMessage;
import javax.sound.midi.MidiUnavailableException;
import javax.sound.midi.Receiver;
import javax.sound.midi.ShortMessage;
import javax.sound.midi.SysexMessage;

import jonkoshare.util.VersionInformation;
import jrackattack.JRackAttack;
import jrackattack.event.FXParameterEvent;
import jrackattack.event.PatternParameterEvent;
import jrackattack.event.ProgramParameterEvent;
import jrackattack.event.SoundParameterEvent;
import jrackattack.gui.JRackAttackFrame;

import org.apache.log4j.Logger;

/**
* Separate Thread to send Midi messages to a configured receiver. This is
* necessary to have a time source and to avoid a lock for the GUI while
* playing.
*
* @author Alexander Methke
*/
@VersionInformation(//
lastChanged = "$LastChangedDate: 2009-09-15 13:42:26 -0500 (Tue, 15 Sep 2009) $", //
authors = { "Alexander Methke" }, //
revision = "$LastChangedRevision: 12 $", //
lastEditor = "$LastChangedBy: onkobu $", //
id = "$Id")
public class MidiThread extends Thread {
  private static final Logger log = Logger.getLogger(MidiThread.class);

  public static ShortMessage CLOCK_MESSAGE;
  public static ShortMessage SYSTEM_RESET_MESSAGE;
  public static ShortMessage ALIVE_MESSAGE;

  public static enum TestModes {
    CHORD, DRUMS, MELODY
  };

  protected MidiThread(MidiDevice dIn, MidiDevice dOut) {
    this();
    setMidiInDevice(dIn);
    setMidiOutDevice(dOut);
  }

  protected MidiThread() {
    if (CLOCK_MESSAGE == null) {
      CLOCK_MESSAGE = new ShortMessage();
      SYSTEM_RESET_MESSAGE = new ShortMessage();
      ALIVE_MESSAGE = new ShortMessage();
      try {
        CLOCK_MESSAGE.setMessage(ShortMessage.TIMING_CLOCK);
        SYSTEM_RESET_MESSAGE.setMessage(ShortMessage.SYSTEM_RESET);
        ALIVE_MESSAGE.setMessage(ShortMessage.ACTIVE_SENSING);
      } catch (Exception ex) {
      }
    }
  }

  public static MidiThread getInstance() {
    if (instance == null) {
      instance = new MidiThread();
      instance.start();
      readerInstance = new MidiReader();
      readerInstance.start();
    }
    return instance;
  }

  public static MidiThread getTestInstance(MidiDevice dev, int channel,
      TestModes tm, int progNo) {
    MidiThread t = new MidiThread();
    t.setMidiOutDevice(dev);
    t.setChannel(channel);
    t.setTestMode(tm);
    t.setProgramNumber(progNo);
    t.initTestMessages();
    return t;
  }

  @Override
  public void run() {
    while (runFlag) {
      try {
        sleep(100);
      } catch (Exception ex) {
      }
      if (runOnce) {
        break;
      }
      /*
       * aliveCounter++; if (aliveCounter>40) { aliveCounter=0; try {
       * enqueueEvent(ALIVE_MESSAGE); } catch (Exception ex) {
       * ex.printStackTrace(); } }
       */
    }
    cleanUp();
  }

  public void receivedData() {
    receivedData = true;
  }

  public void setRunFlag(boolean state) {
    runFlag = state;
  }

  public boolean isRunning() {
    return runFlag;
  }

  protected void cleanUp() {
    if (getMidiOutDevice() == null) {
      return;
    }
    getMidiOutDevice().close();
  }

  public void setChannel(int ch) {
    channel = ch;
  }

  public int getChannel() {
    return channel;
  }

  public boolean initTestMessages() {
    ShortMessage sm = new ShortMessage();
    try {
      sm.setMessage(ShortMessage.SYSTEM_RESET, 0, 0);
      enqueueEvent(sm);
      if (programNumber != -1) {
        sm = new ShortMessage();
        sm.setMessage(ShortMessage.PROGRAM_CHANGE, programNumber, 0);
        enqueueEvent(sm);
      }
      switch (testMode) {
      case DRUMS: {
        addDrumEvents(channel);
      }
        break;
      case CHORD: {
        addChordEvents(channel);
      }
        break;
      case MELODY: {
        addMelodyEvents(channel);
      }
        break;
      }
    } catch (InvalidMidiDataException e) {
      log.error("error", e);
      return false;
    } catch (MidiUnavailableException e) {
      log.error("error", e);
      return false;
    }
    return true;
  }

  public boolean init(MidiDevice inDev, MidiDevice outDev) {
    setMidiInDevice(inDev);
    setMidiOutDevice(outDev);
    return true;
  }

  public boolean init(MidiDevice inDev, MidiDevice outDev, MidiDevice keyDev) {
    setMidiInDevice(inDev);
    setMidiOutDevice(outDev);
    setKeyInDevice(keyDev);
    return true;
  }

  public void emitVolumeChange(Object src, int sndNo, int vol) {
    emitParamChange(src, sndNo, RackAttack.VOLUME, vol);
  }

  public void emitPanChange(Object src, int sndNo, int pan) {
    emitParamChange(src, sndNo, RackAttack.PAN, pan);
  }

  public void emitNoteOn(int note) {
    assertValidMidiValue(note, "note pitch");
    ShortMessage sm = new ShortMessage();
    try {
      sm.setMessage(ShortMessage.NOTE_ON, note, 100);
      enqueueEvent(sm);
    } catch (InvalidMidiDataException e) {
      log.error("error", e);
    } catch (MidiUnavailableException e) {
      log.error("error", e);
    }
  }

  public void emitNoteOff(int note) {
    assertValidMidiValue(note, "note pitch");
    ShortMessage sm = new ShortMessage();
    try {
      sm.setMessage(ShortMessage.NOTE_OFF, note, 100);
      enqueueEvent(sm);
    } catch (InvalidMidiDataException e) {
      log.error("error", e);
    } catch (MidiUnavailableException e) {
      log.error("error", e);
    }
  }

  public void emitFxChange(Object src, int fx, byte[] ah_al, int value) {
    assertValidFXNumber(fx);
    assertValidMidiValue(value, "sys ex value");
    SysexMessage sms = new SysexMessage();
    byte[] bytes = new byte[14];
    bytes[0] = (byte) SysexMessage.SYSTEM_EXCLUSIVE; // SysEx (SOX)
    bytes[1] = RackAttack.WALDORF_MANUFACTURER_BYTE; // Waldorf (IDW)
    bytes[2] = RackAttack.RACK_ATTACK_MODEL_BYTE; // RackAttack (IDM)
    bytes[3] = 0x00; // Default ID (IDD)
    // OS Version 1.05 seems to transmit SNDP twice
    // works only this way (captured from RackAttack output)
    bytes[4] = RackAttack.FX_CHANGE; // CMD (SNDP)
    bytes[5] = RackAttack.EDIT_BUFFER; // CMD (SNDP)
    bytes[6] = (byte) (fx & 0xFF); // SNDN
    bytes[7] = ah_al[0]; // PAH
    bytes[8] = ah_al[1]; // PAL
    bytes[9] = (byte) (value & 0x7F); // SNDV
    bytes[10] = (byte) (bytes[4] + bytes[5] + bytes[6] + bytes[7]
        + bytes[8] + bytes[9] & 0x7F); // CKSUM
    // bytes[10]=(byte)RackAttack.TRUE_CKSUM; //CKSUM
    bytes[11] = (byte) SysexMessage.SPECIAL_SYSTEM_EXCLUSIVE; // EOX
    // a bit tricky but flushes SysEx-Buffers (in any sort of device)
    bytes[12] = (byte) SysexMessage.SYSTEM_EXCLUSIVE; // SysEx (SOX)
    bytes[13] = (byte) SysexMessage.SPECIAL_SYSTEM_EXCLUSIVE; // EOX

    try {
      sms.setMessage(bytes, bytes.length);
      enqueueEvent(sms);
      JRackAttackFrame.getInstance().internalFxChange(
          new FXParameterEvent(src, fx, ah_al, value));
    } catch (InvalidMidiDataException e) {
      log.error("error", e);
    } catch (MidiUnavailableException e) {
      log.error("error", e);
    }
  }

  public void emitGlobalChange(Object src, byte[] ah_al, int value) {
    assertValidMidiValue(value, "sys ex value");
    SysexMessage sms = new SysexMessage();
    byte[] bytes = new byte[12];
    bytes[0] = (byte) SysexMessage.SYSTEM_EXCLUSIVE; // SysEx (SOX)
    bytes[1] = RackAttack.WALDORF_MANUFACTURER_BYTE; // Waldorf (IDW)
    bytes[2] = RackAttack.RACK_ATTACK_MODEL_BYTE; // RackAttack (IDM)
    bytes[3] = 0x00; // Default ID (IDD)
    bytes[4] = RackAttack.GLOBAL_CHANGE; // CMD (GLBP)
    bytes[5] = ah_al[0]; // PAH
    bytes[6] = ah_al[1]; // PAL
    bytes[7] = (byte) (value & 0xFF); // SNDV
    bytes[8] = (byte) (bytes[4] + bytes[5] + bytes[6] + bytes[7] & 0x7F); // CKSUM
    bytes[9] = (byte) SysexMessage.SPECIAL_SYSTEM_EXCLUSIVE; // EOX
    // a bit tricky but flushes SysEx-Buffers (in any sort of device)
    bytes[10] = (byte) SysexMessage.SYSTEM_EXCLUSIVE; // SysEx (SOX)
    bytes[11] = (byte) SysexMessage.SPECIAL_SYSTEM_EXCLUSIVE; // EOX

    try {
      sms.setMessage(bytes, bytes.length);
      enqueueEvent(sms);
      // JRackAttackFrame.getInstance().internalParamChange(new
      // SoundParameterEvent(src, snd, ah_al, value));
    } catch (InvalidMidiDataException e) {
      log.error("error", e);
    } catch (MidiUnavailableException e) {
      log.error("error", e);
    }
  }

  public void emitProgramChange(Object src, int prg, byte[] ah_al, int value) {
    assertValidProgramNumber(prg);
    assertValidMidiValue(value, "sys ex value");
    SysexMessage sms = new SysexMessage();
    byte[] bytes = new byte[14];
    bytes[0] = (byte) SysexMessage.SYSTEM_EXCLUSIVE; // SysEx (SOX)
    bytes[1] = RackAttack.WALDORF_MANUFACTURER_BYTE; // Waldorf (IDW)
    bytes[2] = RackAttack.RACK_ATTACK_MODEL_BYTE; // RackAttack (IDM)
    bytes[3] = 0x00; // Default ID (IDD)
    bytes[4] = RackAttack.PROGRAM_CHANGE; // CMD (SNDP)
    bytes[5] = RackAttack.EDIT_BUFFER; // CMD (SNDP)
    bytes[6] = (byte) (prg & 0xFF); // SNDN
    bytes[7] = ah_al[0]; // PAH
    bytes[8] = ah_al[1]; // PAL
    bytes[9] = (byte) (value & 0xFF); // SNDV
    bytes[10] = (byte) (bytes[4] + bytes[5] + bytes[6] + bytes[7]
        + bytes[8] + bytes[9] & 0x7F); // CKSUM
    // bytes[10]=(byte)RackAttack.TRUE_CKSUM; //CKSUM
    bytes[11] = (byte) SysexMessage.SPECIAL_SYSTEM_EXCLUSIVE; // EOX
    // a bit tricky but flushes SysEx-Buffers (in any sort of device)
    bytes[12] = (byte) SysexMessage.SYSTEM_EXCLUSIVE; // SysEx (SOX)
    bytes[13] = (byte) SysexMessage.SPECIAL_SYSTEM_EXCLUSIVE; // EOX

    try {
      sms.setMessage(bytes, bytes.length);
      enqueueEvent(sms);
      JRackAttackFrame.getInstance().internalProgramChange(
          new ProgramParameterEvent(src, prg, ah_al, value));
    } catch (InvalidMidiDataException e) {
      log.error("error", e);
    } catch (MidiUnavailableException e) {
      log.error("error", e);
    }
  }

  public void emitPatternChange(Object src, int snd, byte[] ah_al, int value) {
    assertValidPatternNumber(snd);
    assertValidMidiValue(value, "sys ex value");
    SysexMessage sms = new SysexMessage();
    byte[] bytes = new byte[14];
    bytes[0] = (byte) SysexMessage.SYSTEM_EXCLUSIVE; // SysEx (SOX)
    bytes[1] = RackAttack.WALDORF_MANUFACTURER_BYTE; // Waldorf (IDW)
    bytes[2] = RackAttack.RACK_ATTACK_MODEL_BYTE; // RackAttack (IDM)
    bytes[3] = 0x00; // Default ID (IDD)
    bytes[4] = RackAttack.PATTERN_CHANGE; // CMD (SNDP)
    bytes[5] = RackAttack.EDIT_BUFFER;
    bytes[6] = (byte) (snd & 0xFF); // SNDN
    bytes[7] = ah_al[0]; // PAH
    bytes[8] = ah_al[1]; // PAL
    bytes[9] = (byte) (value & 0xFF); // SNDV
    bytes[10] = (byte) (bytes[4] + bytes[5] + bytes[6] + bytes[7]
        + bytes[8] + bytes[9] & 0x7F); // CKSUM
    // bytes[10]=(byte)RackAttack.TRUE_CKSUM; //CKSUM
    bytes[11] = (byte) SysexMessage.SPECIAL_SYSTEM_EXCLUSIVE; // EOX
    // a bit tricky but flushes SysEx-Buffers (in any sort of device)
    bytes[12] = (byte) SysexMessage.SYSTEM_EXCLUSIVE; // SysEx (SOX)
    bytes[13] = (byte) SysexMessage.SPECIAL_SYSTEM_EXCLUSIVE; // EOX

    try {
      sms.setMessage(bytes, bytes.length);
      enqueueEvent(sms);
      JRackAttackFrame.getInstance().internalPatternChange(
          new PatternParameterEvent(src, snd, ah_al, value));
    } catch (InvalidMidiDataException e) {
      log.error("error", e);
    } catch (MidiUnavailableException e) {
      log.error("error", e);
    }
  }

  public void emitParamChange(Object src, int snd, byte[] ah_al, int value) {
    /*
     * log("<<<tracer>>>"); for(StackTraceElement
     * ste:Thread.currentThread().getStackTrace()) { log(ste.toString()); }
     */
    assertValidSoundNumber(snd);
    assertValidMidiValue(value, "sys ex value");
    SysexMessage sms = new SysexMessage();
    byte[] bytes = new byte[14];
    bytes[0] = (byte) SysexMessage.SYSTEM_EXCLUSIVE; // SysEx (SOX)
    bytes[1] = RackAttack.WALDORF_MANUFACTURER_BYTE; // Waldorf (IDW)
    bytes[2] = RackAttack.RACK_ATTACK_MODEL_BYTE; // RackAttack (IDM)
    bytes[3] = 0x00; // Default ID (IDD)
    bytes[4] = RackAttack.SOUND_CHANGE; // CMD (SNDP)
    bytes[5] = RackAttack.EDIT_BUFFER; // CMD (SNDP)
    bytes[6] = (byte) (snd & 0xFF); // SNDN
    bytes[7] = ah_al[0]; // PAH
    bytes[8] = ah_al[1]; // PAL
    bytes[9] = (byte) (value & 0xFF); // SNDV
    bytes[10] = (byte) (bytes[4] + bytes[5] + bytes[6] + bytes[7]
        + bytes[8] + bytes[9] & 0x7F); // CKSUM
    // bytes[10]=(byte)RackAttack.TRUE_CKSUM; //CKSUM
    bytes[11] = (byte) SysexMessage.SPECIAL_SYSTEM_EXCLUSIVE; // EOX
    // a bit tricky but flushes SysEx-Buffers (in any sort of device)
    bytes[12] = (byte) SysexMessage.SYSTEM_EXCLUSIVE; // SysEx (SOX)
    bytes[13] = (byte) SysexMessage.SPECIAL_SYSTEM_EXCLUSIVE; // EOX

    try {
      sms.setMessage(bytes, bytes.length);
      enqueueEvent(sms);
      JRackAttackFrame.getInstance().internalParamChange(
          new SoundParameterEvent(src, snd, ah_al, value));
    } catch (InvalidMidiDataException e) {
      log.error("error", e);
    } catch (MidiUnavailableException e) {
      log.error("error", e);
    }
  }

  public SoundParameter[] loadAllSoundParameter() {
    return null;
  }

  public void storeSoundParameter(SoundParameter sp, boolean buffer) {
    try {
      enqueueEvent(sp.createMessage(buffer));
    } catch (MidiUnavailableException ex) {
      log.error("error", ex);
    }
  }

  public void loadFXParameter(int fx, boolean buffer) {
    assertValidFXNumber(fx);
    SysexMessage sms = new SysexMessage();
    byte[] bytes = null;
    bytes = new byte[11];
    bytes[0] = (byte) SysexMessage.SYSTEM_EXCLUSIVE; // SysEx (SOX)
    bytes[1] = RackAttack.WALDORF_MANUFACTURER_BYTE; // Waldorf (IDW)
    bytes[2] = RackAttack.RACK_ATTACK_MODEL_BYTE; // RackAttack (IDM)
    bytes[3] = 0x00; // Default ID (IDD)
    bytes[4] = RackAttack.FX_REQUEST; // CMD (SNDP)
    if (buffer) {
      bytes[5] = RackAttack.EDIT_BUFFER;
    } else {
      bytes[5] = RackAttack.ASSEMBLY_BUFFER;
    }
    bytes[6] = (byte) (fx & 0xFF); // SNDN
    bytes[7] = (byte) (bytes[4] + bytes[5] + bytes[6] & 0x7F); // CKSUM
    bytes[8] = (byte) SysexMessage.SPECIAL_SYSTEM_EXCLUSIVE; // EOX
    // a bit tricky but flushes SysEx-Buffers (in any sort of device)
    bytes[9] = (byte) SysexMessage.SYSTEM_EXCLUSIVE; // SysEx (SOX)
    bytes[10] = (byte) SysexMessage.SPECIAL_SYSTEM_EXCLUSIVE; // EOX

    try {
      sms.setMessage(bytes, bytes.length);
      enqueueEvent(sms);
    } catch (InvalidMidiDataException e) {
      log.error("error", e);
    } catch (MidiUnavailableException e) {
      log.error("error", e);
    }
    log(" Waiting for midi in events");
    for (int i = 0; i < 5; i++) {
      if (receivedData) {
        break;
      }
      try {
        sleep(500);
      } catch (InterruptedException e) {
      }
    }
    if (!receivedData) {
      JRackAttackFrame.getInstance().handleError("msg.no_data_received");
    } else {
      receivedData = false;
    }
  }

  public void loadGlobalParameter() {
    SysexMessage sms = new SysexMessage();
    byte[] bytes = null;
    bytes = new byte[10];
    bytes[0] = (byte) SysexMessage.SYSTEM_EXCLUSIVE; // SysEx (SOX)
    bytes[1] = RackAttack.WALDORF_MANUFACTURER_BYTE; // Waldorf (IDW)
    bytes[2] = RackAttack.RACK_ATTACK_MODEL_BYTE; // RackAttack (IDM)
    bytes[3] = 0x00; // Default ID (IDD)
    bytes[4] = RackAttack.GLOBAL_REQUEST; // CMD (SNDP)
    bytes[5] = 0x00;
    bytes[6] = (byte) (bytes[4] + bytes[5] & 0x7F); // CKSUM
    bytes[7] = (byte) SysexMessage.SPECIAL_SYSTEM_EXCLUSIVE; // EOX
    // a bit tricky but flushes SysEx-Buffers (in any sort of device)
    bytes[8] = (byte) SysexMessage.SYSTEM_EXCLUSIVE; // SysEx (SOX)
    bytes[9] = (byte) SysexMessage.SPECIAL_SYSTEM_EXCLUSIVE; // EOX

    try {
      sms.setMessage(bytes, bytes.length);
      enqueueEvent(sms);
    } catch (InvalidMidiDataException e) {
      log.error("error", e);
    } catch (MidiUnavailableException e) {
      log.error("error", e);
    }
    log(" Waiting for midi in events");
    for (int i = 0; i < 5; i++) {
      if (receivedData) {
        break;
      }
      try {
        sleep(500);
      } catch (InterruptedException e) {
      }
    }
    if (!receivedData) {
      JRackAttackFrame.getInstance().handleError("msg.no_data_received");
    } else {
      receivedData = false;
    }
  }

  public void resetEditBuffer() {
    SysexMessage sms = new SysexMessage();
    byte[] bytes = null;
    bytes = new byte[12];
    bytes[0] = (byte) SysexMessage.SYSTEM_EXCLUSIVE; // SysEx (SOX)
    bytes[1] = RackAttack.WALDORF_MANUFACTURER_BYTE; // Waldorf (IDW)
    bytes[2] = RackAttack.RACK_ATTACK_MODEL_BYTE; // RackAttack (IDM)
    bytes[3] = 0x00; // Default ID (IDD)
    bytes[4] = RackAttack.MOV_COMMAND; // CMD (MODR)
    bytes[5] = RackAttack.MCMD_INIT_BUFFER;
    bytes[6] = RackAttack.EDIT_BUFFER;
    bytes[7] = 0; // not recognized
    bytes[8] = (byte) (bytes[4] + bytes[5] + bytes[6] + bytes[7] & 0x7F); // CKSUM
    bytes[9] = (byte) SysexMessage.SPECIAL_SYSTEM_EXCLUSIVE; // EOX
    // a bit tricky but flushes SysEx-Buffers (in any sort of device)
    bytes[10] = (byte) SysexMessage.SYSTEM_EXCLUSIVE; // SysEx (SOX)
    bytes[11] = (byte) SysexMessage.SPECIAL_SYSTEM_EXCLUSIVE; // EOX

    try {
      sms.setMessage(bytes, bytes.length);
      enqueueEvent(sms);
    } catch (InvalidMidiDataException e) {
      log.error("error", e);
    } catch (MidiUnavailableException e) {
      log.error("error", e);
    }
  }

  /**
   * Copies the current program from memory into edit buffer.
   */
  public void recallProgramToEdit() {
    SysexMessage sms = new SysexMessage();
    byte[] bytes = null;
    bytes = new byte[12];
    bytes[0] = (byte) SysexMessage.SYSTEM_EXCLUSIVE; // SysEx (SOX)
    bytes[1] = RackAttack.WALDORF_MANUFACTURER_BYTE; // Waldorf (IDW)
    bytes[2] = RackAttack.RACK_ATTACK_MODEL_BYTE; // RackAttack (IDM)
    bytes[3] = 0x00; // Default ID (IDD)
    bytes[4] = RackAttack.MOV_COMMAND; // CMD (MODR)
    bytes[5] = RackAttack.MCMD_RECALL_CURRENT_PROGRAM;
    bytes[6] = RackAttack.MCMD_MOV1_RECALL_CURRENT_PROGRAM;
    bytes[7] = 0; // not recognized
    bytes[8] = (byte) (bytes[4] + bytes[5] + bytes[6] + bytes[7] & 0x7F); // CKSUM
    bytes[9] = (byte) SysexMessage.SPECIAL_SYSTEM_EXCLUSIVE; // EOX
    // a bit tricky but flushes SysEx-Buffers (in any sort of device)
    bytes[10] = (byte) SysexMessage.SYSTEM_EXCLUSIVE; // SysEx (SOX)
    bytes[11] = (byte) SysexMessage.SPECIAL_SYSTEM_EXCLUSIVE; // EOX

    try {
      sms.setMessage(bytes, bytes.length);
      enqueueEvent(sms);
    } catch (InvalidMidiDataException e) {
      log.error("error", e);
    } catch (MidiUnavailableException e) {
      log.error("error", e);
    }
  }

  /**
   * Copies the current program from memory into edit buffer.
   */
  public void loadProgramToEdit(int pNumber) {
    SysexMessage sms = new SysexMessage();
    byte[] bytes = null;
    bytes = new byte[12];
    bytes[0] = (byte) SysexMessage.SYSTEM_EXCLUSIVE; // SysEx (SOX)
    bytes[1] = RackAttack.WALDORF_MANUFACTURER_BYTE; // Waldorf (IDW)
    bytes[2] = RackAttack.RACK_ATTACK_MODEL_BYTE; // RackAttack (IDM)
    bytes[3] = 0x00; // Default ID (IDD)
    bytes[4] = RackAttack.MOV_COMMAND; // CMD (MODR)
    bytes[5] = RackAttack.MCMD_COPY_PROGRAM_TO_EDIT;
    bytes[6] = RackAttack.EDIT_BUFFER;
    bytes[7] = (byte) (pNumber & 0x7f); // not recognized
    bytes[8] = (byte) (bytes[4] + bytes[5] + bytes[6] + bytes[7] & 0x7F); // CKSUM
    bytes[9] = (byte) SysexMessage.SPECIAL_SYSTEM_EXCLUSIVE; // EOX
    // a bit tricky but flushes SysEx-Buffers (in any sort of device)
    bytes[10] = (byte) SysexMessage.SYSTEM_EXCLUSIVE; // SysEx (SOX)
    bytes[11] = (byte) SysexMessage.SPECIAL_SYSTEM_EXCLUSIVE; // EOX

    try {
      sms.setMessage(bytes, bytes.length);
      enqueueEvent(sms);
    } catch (InvalidMidiDataException e) {
      log.error("error", e);
    } catch (MidiUnavailableException e) {
      log.error("error", e);
    }
  }

  public void dumpProgramFromEdit(int pNumber) {
    readerInstance.setNextProgramNumber(pNumber);
    SysexMessage sms = new SysexMessage();
    byte[] bytes = null;
    bytes = new byte[12];
    bytes[0] = (byte) SysexMessage.SYSTEM_EXCLUSIVE; // SysEx (SOX)
    bytes[1] = RackAttack.WALDORF_MANUFACTURER_BYTE; // Waldorf (IDW)
    bytes[2] = RackAttack.RACK_ATTACK_MODEL_BYTE; // RackAttack (IDM)
    bytes[3] = 0x00; // Default ID (IDD)
    bytes[4] = RackAttack.MOV_COMMAND; // CMD (MODR)
    bytes[5] = RackAttack.MCMD_DUMP_PROGRAM_FROM_EDIT;
    bytes[6] = RackAttack.EDIT_BUFFER;
    bytes[7] = 0; // not recognized
    bytes[8] = (byte) (bytes[4] + bytes[5] + bytes[6] + bytes[7] & 0x7F); // CKSUM
    bytes[9] = (byte) SysexMessage.SPECIAL_SYSTEM_EXCLUSIVE; // EOX
    // a bit tricky but flushes SysEx-Buffers (in any sort of device)
    bytes[10] = (byte) SysexMessage.SYSTEM_EXCLUSIVE; // SysEx (SOX)
    bytes[11] = (byte) SysexMessage.SPECIAL_SYSTEM_EXCLUSIVE; // EOX
    try {
      sms.setMessage(bytes, bytes.length);
      enqueueEvent(sms);
    } catch (InvalidMidiDataException e) {
      log.error("error", e);
    } catch (MidiUnavailableException e) {
      log.error("error", e);
    }
  }

  public void storeProgramFromEdit(int pNumber) {
    SysexMessage sms = new SysexMessage();
    byte[] bytes = null;
    bytes = new byte[12];
    bytes[0] = (byte) SysexMessage.SYSTEM_EXCLUSIVE; // SysEx (SOX)
    bytes[1] = RackAttack.WALDORF_MANUFACTURER_BYTE; // Waldorf (IDW)
    bytes[2] = RackAttack.RACK_ATTACK_MODEL_BYTE; // RackAttack (IDM)
    bytes[3] = 0x00; // Default ID (IDD)
    bytes[4] = RackAttack.MOV_COMMAND; // CMD (MODR)
    bytes[5] = RackAttack.MCMD_COPY_PROGRAM_FROM_EDIT;
    bytes[6] = RackAttack.EDIT_BUFFER;
    bytes[7] = (byte) (pNumber & 0x7f); // not recognized
    bytes[8] = (byte) (bytes[4] + bytes[5] + bytes[6] + bytes[7] & 0x7F); // CKSUM
    bytes[9] = (byte) SysexMessage.SPECIAL_SYSTEM_EXCLUSIVE; // EOX
    // a bit tricky but flushes SysEx-Buffers (in any sort of device)
    bytes[10] = (byte) SysexMessage.SYSTEM_EXCLUSIVE; // SysEx (SOX)
    bytes[11] = (byte) SysexMessage.SPECIAL_SYSTEM_EXCLUSIVE; // EOX

    try {
      sms.setMessage(bytes, bytes.length);
      enqueueEvent(sms);
    } catch (InvalidMidiDataException e) {
      log.error("error", e);
    } catch (MidiUnavailableException e) {
      log.error("error", e);
    }
  }

  /**
   * Loads the given sound from it's program memory to the edit buffer. This
   * is a sort of reset.
   */
  public void loadSoundFromProgramToEdit(int snd) {
    assertValidSoundNumber(snd);
    SysexMessage sms = new SysexMessage();
    byte[] bytes = null;
    bytes = new byte[12];
    bytes[0] = (byte) SysexMessage.SYSTEM_EXCLUSIVE; // SysEx (SOX)
    bytes[1] = RackAttack.WALDORF_MANUFACTURER_BYTE; // Waldorf (IDW)
    bytes[2] = RackAttack.RACK_ATTACK_MODEL_BYTE; // RackAttack (IDM)
    bytes[3] = 0x00; // Default ID (IDD)
    bytes[4] = RackAttack.MOV_COMMAND; // CMD (SNDP)
    bytes[5] = RackAttack.MCMD_RECALL_SOUND;
    bytes[6] = RackAttack.MCMD_MOV1_RECALL_SOUND;
    bytes[7] = (byte) (snd & 0xFF); // SNDN
    bytes[8] = (byte) (bytes[4] + bytes[5] + bytes[6] + bytes[7] & 0x7F); // CKSUM
    bytes[9] = (byte) SysexMessage.SPECIAL_SYSTEM_EXCLUSIVE; // EOX
    // a bit tricky but flushes SysEx-Buffers (in any sort of device)
    bytes[10] = (byte) SysexMessage.SYSTEM_EXCLUSIVE; // SysEx (SOX)
    bytes[11] = (byte) SysexMessage.SPECIAL_SYSTEM_EXCLUSIVE; // EOX

    try {
      sms.setMessage(bytes, bytes.length);
      enqueueEvent(sms);
    } catch (InvalidMidiDataException e) {
      log.error("error", e);
    } catch (MidiUnavailableException e) {
      log.error("error", e);
    }
  }

  public void loadSoundParameter(int snd, boolean buffer) {
    assertValidSoundNumber(snd);
    SysexMessage sms = new SysexMessage();
    byte[] bytes = null;
    bytes = new byte[11];
    bytes[0] = (byte) SysexMessage.SYSTEM_EXCLUSIVE; // SysEx (SOX)
    bytes[1] = RackAttack.WALDORF_MANUFACTURER_BYTE; // Waldorf (IDW)
    bytes[2] = RackAttack.RACK_ATTACK_MODEL_BYTE; // RackAttack (IDM)
    bytes[3] = 0x00; // Default ID (IDD)
    bytes[4] = RackAttack.SOUND_REQUEST; // CMD (SNDP)
    if (buffer) {
      bytes[5] = RackAttack.EDIT_BUFFER;
    } else {
      bytes[5] = RackAttack.ASSEMBLY_BUFFER;
    }
    bytes[6] = (byte) (snd & 0xFF); // SNDN
    bytes[7] = (byte) (bytes[4] + bytes[5] + bytes[6] & 0x7F); // CKSUM
    bytes[8] = (byte) SysexMessage.SPECIAL_SYSTEM_EXCLUSIVE; // EOX
    // a bit tricky but flushes SysEx-Buffers (in any sort of device)
    bytes[9] = (byte) SysexMessage.SYSTEM_EXCLUSIVE; // SysEx (SOX)
    bytes[10] = (byte) SysexMessage.SPECIAL_SYSTEM_EXCLUSIVE; // EOX

    try {
      sms.setMessage(bytes, bytes.length);
      enqueueEvent(sms);
    } catch (InvalidMidiDataException e) {
      log.error("error", e);
    } catch (MidiUnavailableException e) {
      log.error("error", e);
    }
    log(" Waiting for midi in events");
    for (int i = 0; i < 5; i++) {
      if (receivedData) {
        break;
      }
      try {
        sleep(500);
      } catch (InterruptedException e) {
      }
    }
    if (!receivedData) {
      JRackAttackFrame.getInstance().handleError("msg.no_data_received");
    } else {
      receivedData = false;
    }
  }

  protected void assertValidPatternNumber(int patNo) {
    assertValidSoundNumber(patNo);
  }

  protected void assertValidSoundNumber(int sndNo) {
    if (sndNo < 0 || sndNo > 23) {
      throw new IllegalArgumentException(
          "Sound number may range only from 1-24, " + sndNo
              + " is therefore invalid");
    }
  }

  protected void assertValidProgramNumber(int prgNo) {
    if (prgNo < 0 || prgNo > 49) {
      throw new IllegalArgumentException(
          "Program number may range only from 1-50, " + prgNo
              + " is therefore invalid");
    }
  }

  protected void assertValidFXNumber(int fxNo) {
    if (fxNo < 0 || fxNo > 3) {
      throw new IllegalArgumentException(
          "Fx number may range only from 1-4, " + fxNo
              + " is therefore invalid");
    }
  }

  protected void assertValidMidiValue(int val, String valueName) {
    if (val < 0 || val > 128) {
      throw new IllegalArgumentException("Value for " + valueName
          + " may range only from 0..127, " + val
          + " is therefore invalid");
    }
  }

  private void addDrumEvents(int channel) {
    NoteMessage sm = null;
    try {
      for (int i = 0; i < 30; i++) {
        sm = new NoteMessage();
        sm.setMessage(ShortMessage.NOTE_ON, channel, 40 + i, 100);
        sm.setDuration(250);
        enqueueEvent(sm);
        enqueueEvent(new PauseMessage(50));

        sm = new NoteMessage();
        sm.setMessage(ShortMessage.NOTE_OFF, channel, 40 + i, 100);
        enqueueEvent(sm);
      }
    } catch (InvalidMidiDataException e) {
      log.error("error", e);
    } catch (MidiUnavailableException e) {
      log.error("error", e);
    }
  }

  private void addChordEvents(int channel) {
    ChordMessage sm = null;
    try {
      sm = new ChordMessage(new int[] { 64, 67, 70 }, channel, 1000,
          ShortMessage.NOTE_ON);
      enqueueEvent(sm);

      sm = new ChordMessage(sm, ShortMessage.NOTE_OFF);
      enqueueEvent(sm);
    } catch (InvalidMidiDataException e) {
      log.error("error", e);
    } catch (MidiUnavailableException e) {
      log.error("error", e);
    }
  }

  private void addMelodyEvents(int channel) {
    try {
      NoteMessage sm = null;
      sm = new NoteMessage();
      sm.setMessage(ShortMessage.NOTE_ON, channel, 64, 100);
      sm.setDuration(750);
      enqueueEvent(sm);

      sm = new NoteMessage();
      sm.setMessage(ShortMessage.NOTE_OFF, channel, 64, 100);
      enqueueEvent(sm);

      sm = new NoteMessage();
      sm.setMessage(ShortMessage.NOTE_ON, channel, 70, 100);
      sm.setDuration(500);
      enqueueEvent(sm);

      sm = new NoteMessage();
      sm.setMessage(ShortMessage.NOTE_OFF, channel, 70, 100);
      enqueueEvent(sm);

      sm = new NoteMessage();
      sm.setMessage(ShortMessage.NOTE_ON, channel, 70, 100);
      sm.setDuration(250);
      enqueueEvent(sm);

      sm = new NoteMessage();
      sm.setMessage(ShortMessage.NOTE_OFF, channel, 70, 100);
      enqueueEvent(sm);

      sm = new NoteMessage();
      sm.setMessage(ShortMessage.NOTE_ON, channel, 67, 100);
      sm.setDuration(1000);
      enqueueEvent(sm);

      sm = new NoteMessage();
      sm.setMessage(ShortMessage.NOTE_OFF, channel, 67, 100);
      enqueueEvent(sm);
    } catch (InvalidMidiDataException e) {
      log.error("error", e);
    } catch (MidiUnavailableException e) {
      log.error("error", e);
    }
  }

  protected void setMidiInDevice(MidiDevice dev) {
    readerInstance.setMidiInDevice(dev);
  }

  public MidiDevice getMidiInDevice() {
    return readerInstance.getMidiInDevice();
  }

  public MidiDevice getMidiOutDevice() {
    return outDevice;
  }

  protected void setMidiOutDevice(MidiDevice dev) {
    if (outDevice != null && dev != outDevice && outDevice.isOpen()) {
      outDevice.close();
    }

    outDevice = dev;

    if (outDevice != null && !outDevice.isOpen()) {
      try {
        outDevice.open();
      } catch (MidiUnavailableException e) {
        log.error("error", e);
      }
    }
  }

  protected synchronized void enqueueEvent(MidiMessage msg)
      throws MidiUnavailableException {
    MidiDevice dev = getMidiOutDevice();
    if (JRackAttack.spoolMidi()) {
      log("sending " + MidiReader.formatMidiMessage(msg));
    }
    if (dev == null) {
      return;
    }
    // open device
    /*
     * if (!dev.isOpen()) { dev.open();
     * dev.getReceiver().send(SYSTEM_RESET_MESSAGE,-1); }
     */
    if (receiver == null) {
      receiver = dev.getReceiver();
    }
    if (msg instanceof ChordMessage) {
      ChordMessage cMesg = (ChordMessage) msg;
      receiver.send(cMesg.getNote1(), 0);
      receiver.send(cMesg.getNote2(), 0);
      receiver.send(cMesg.getNote3(), 0);
      if (cMesg.getNote4() != null) {
        receiver.send(cMesg.getNote1(), -1);
        log("as note message");
      }
      if ((cMesg.getNote1().getStatus() & 0xF0) == ShortMessage.NOTE_ON) {
        log("sleeping message duration (" + cMesg.getDuration()
            + " mS)");
        try {
          sleep(cMesg.getDuration());
        } catch (InterruptedException e) {
        }
      }
    } else if (msg instanceof PauseMessage) {
      log("pause message (" + ((DurationMessage) msg).getDuration()
          + " mS)");
      try {
        sleep(((DurationMessage) msg).getDuration());
      } catch (InterruptedException e) {
      }
    } else if (msg instanceof DurationMessage) {
      log("duration message (" + ((DurationMessage) msg).getDuration()
          + " mS)");
      receiver.send(msg, -1);
      if ((msg.getStatus() & 0xF0) == ShortMessage.NOTE_ON) {
        try {
          sleep(((DurationMessage) msg).getDuration());
        } catch (InterruptedException e) {
        }
      }
    } else {
      log("raw midi message");
      receiver.send(msg, -1);
    }
  }

  /**
   * Getter for property testMode.
   *
   * @return Value of property testMode.
   */
  public TestModes getTestMode() {
    return this.testMode;
  }

  /**
   * Setter for property testMode.
   *
   * @param testMode
   *            New value of property testMode.
   */
  public void setTestMode(TestModes testMode) {
    this.testMode = testMode;
  }

  /**
   * Getter for property programNumber.
   *
   * @return Value of property programNumber.
   */
  public int getProgramNumber() {
    return this.programNumber;
  }

  /**
   * Setter for property programNumber.
   *
   * @param programNumber
   *            New value of property programNumber.
   */
  public void setProgramNumber(int programNumber) {
    this.programNumber = programNumber;
  }

  /**
   * Getter for property runOnce.
   *
   * @return Value of property runOnce.
   */
  public boolean isRunOnce() {
    return this.runOnce;
  }

  /**
   * Setter for property runOnce.
   *
   * @param runOnce
   *            New value of property runOnce.
   */
  public void setRunOnce(boolean runOnce) {
    this.runOnce = runOnce;
  }

  /**
   * Getter for property keyInDevice.
   *
   * @return Value of property keyInDevice.
   */
  public MidiDevice getKeyInDevice() {
    return this.keyInDevice;
  }

  /**
   * Setter for property keyInDevice.
   *
   * @param keyInDevice
   *            New value of property keyInDevice.
   */
  public void setKeyInDevice(MidiDevice keyInDevice) {
    readerInstance.setKeyInDevice(keyInDevice);
    this.keyInDevice = keyInDevice;
  }

  protected void log(String msg) {
    log.debug(msg + " (hc:" + hashCode() + ")");
  }

  private static MidiThread instance;
  private static MidiReader readerInstance;

  private boolean runFlag = true;

  private int channel;

  private MidiDevice outDevice;

  /**
   * Holds value of property testMode.
   */
  private TestModes testMode;

  /**
   * Holds value of property programNumber.
   */
  private int programNumber;

  /**
   * Holds value of property runOnce.
   */
  private boolean runOnce = false;

  /**
   * Holds value of property keyInDevice.
   */
  private MidiDevice keyInDevice;

  private boolean receivedData;

  private Receiver receiver;
}
/*
* Copyright (C) 2008 Alexander Methke
*
* 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 (gplv3.txt).
*/
TOP

Related Classes of jrackattack.midi.MidiThread

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.