/** Delete the current selection */
 public void performDelete() {
   Selection sel = waveDisplay.getSelection();
   int pos = sel.getLeft();
   cutList.addElement(new DeleteElement(sel.getLeft(), sel.getRight() - sel.getLeft()));
   waveDisplay.setSelection(new Selection(0));
   waveDisplay.setPosition(pos);
 }
 /** Create a clone of the current CutList to be used as clipboard source */
 private void prepareClipboard() {
   Selection sel = waveDisplay.getSelection();
   int left = sel.getLeft();
   int right = sel.getRight();
   CutListSource cl = cutList.duplicate();
   if (left == 0 && right == cl.getLength()) copySource = cl;
   else copySource = new SubSource(cl, left, right - left);
 }
 /**
  * Get the AudioInputStream for the current selection
  *
  * @see com.groovemanager.sampled.AudioPlayerProvider#getAudioInputStream()
  */
 public AudioInputStream getAudioInputStream() throws NotReadyException {
   Selection sel = waveDisplay.getSelection();
   lastStart = sel.getLeft();
   if (lastStart >= cutList.getLength()) lastStart = 0;
   int right = sel.getRight();
   if (right > cutList.getLength()) right = cutList.getLength();
   if (lastStart == right)
     return cutList.getAudioInputStream(lastStart, cutList.getLength() - right);
   else return cutList.getAudioInputStream(lastStart, right - lastStart);
 }
  /**
   * Perform an EditAction of the given type
   *
   * @param type The type of the EditAction to apply
   */
  public void editAction(int type) {
    Selection sel = waveDisplay.getSelection();
    switch (type) {
      case EditAction.DELETE:
        if (sel.getRight() <= sel.getLeft()) return;
        performDelete();
        undoOperations.add(new Integer(type));
        redoOperations.clear();
        redoElements.clear();
        break;
      case EditAction.UNDO:
        if (!canUndo()) return;
        performUndo();
        break;

      case EditAction.REDO:
        if (!canRedo()) return;
        performRedo();
        break;

      case EditAction.COPY:
        if (sel.getRight() <= sel.getLeft()) return;
        performCopy();
        break;

      case EditAction.CUT:
        if (sel.getRight() <= sel.getLeft()) return;
        performCut();
        undoOperations.add(new Integer(type));
        redoOperations.clear();
        redoElements.clear();
        break;

      case EditAction.PASTE:
        try {
          performPaste();
          undoOperations.add(new Integer(type));
          redoOperations.clear();
          redoElements.clear();
        } catch (DifferentChannelException e) {
          e.printStackTrace();
          editor.errorMessage(
              "Could not perform paste operation because the data in the clipboard has different number of channels.");
        }
        break;

      case EditAction.TRIM:
        if (sel.getRight() <= sel.getLeft()) return;
        performTrim();
        undoOperations.add(new Integer(type));
        redoOperations.clear();
        redoElements.clear();
        break;
      default:
        break;
    }
  }
 /** Trim this WaveTab´s data to the current selection */
 public void performTrim() {
   Selection sel = waveDisplay.getSelection();
   int pos = sel.getLeft();
   cutList.addElement(new DeleteElement(0, sel.getLeft()));
   cutList.addElement(
       new DeleteElement(
           sel.getRight() - sel.getLeft(), cutList.getLength() - sel.getRight() + sel.getLeft()));
   waveDisplay.setSelection(new Selection(0, cutList.getLength()));
   waveDisplay.setPosition(0);
 }
  /**
   * Apply the given effect to this WaveTab´s audio data
   *
   * @param effect The effect to apply
   */
  public void applyEffect(Effect effect) {
    Selection sel = waveDisplay.getSelection();
    if (sel.getLeft() == sel.getRight())
      waveDisplay.setSelection(new Selection(0, getTotalLength()));
    Thread thread = null;
    try {
      AudioInputStream stream = getAudioInputStream();
      int sourceChannels = stream.getFormat().getChannels();
      stream = AudioManager.getStereoInputStream(stream);
      final FXUnit unit = new FXUnit(effect);
      if (effect.needsAnalysis()) {
        Analyzer a = new Analyzer(unit, stream);
        ProgressMonitor monitor =
            new ProgressMonitor(getShell(), a, "Analyzing...", "Analyzing audio data");
        monitor.start();
        stream = AudioManager.getStereoInputStream(getAudioInputStream());
      }

      final SourceDataLine sourceLine = unit.getEffectSourceLine();
      sourceLine.open();
      sourceLine.start();
      final TargetDataLine targetLine = unit.getEffectTargetLine();
      targetLine.open();
      targetLine.start();
      if (!stream.getFormat().equals(sourceLine.getFormat())) {
        if (AudioSystem.isConversionSupported(sourceLine.getFormat(), stream.getFormat()))
          stream = AudioSystem.getAudioInputStream(sourceLine.getFormat(), stream);
        else {
          editor.errorMessage(
              "Unable to apply effect:\nFormat conversion from "
                  + stream.getFormat()
                  + " to "
                  + sourceLine.getFormat()
                  + " not supported.");
          return;
        }
      }

      final AudioInputStream inStream = stream;
      thread =
          new Thread() {
            public void run() {
              int numBytesRead = 0;
              byte[] buffer = new byte[sourceLine.getBufferSize()];
              while (numBytesRead != -1 && !getItem().isDisposed()) {
                try {
                  numBytesRead = inStream.read(buffer, 0, buffer.length);
                } catch (IOException e1) {
                  e1.printStackTrace();
                  numBytesRead = -1;
                }
                if (numBytesRead > 0) {
                  sourceLine.write(buffer, 0, numBytesRead);
                }
                try {
                  Thread.sleep(0, 1);
                } catch (InterruptedException e) {
                }
              }
            }
          };
      thread.start();

      AudioInputStream in = new AudioInputStream(targetLine);
      if (sourceChannels == 1) in = AudioManager.getMonoInputStream(in);
      File tempFile = File.createTempFile("gmtmp_", ".wav");
      AudioFormat tempFormat =
          new AudioFormat(
              fileFormat.getFormat().getSampleRate(),
              16,
              fileFormat.getFormat().getChannels(),
              true,
              false);
      AudioFileOutputStream out =
          AudioManager.getDefault()
              .getAudioFileOutputStream(
                  tempFile, tempFormat, AudioFileFormat.Type.WAVE, null, null, null);
      if (!in.getFormat().equals(out.getFormat()))
        in = AudioSystem.getAudioInputStream(out.getFormat(), in);
      SaveFileThread saver =
          new SaveFileThread(
              in, out, (int) inStream.getFrameLength(), in.getFormat().getFrameSize(), true);
      ProgressMonitor monitor =
          new ProgressMonitor(
              getShell(), saver, "Apply Effect", "Applying " + effect.getName() + " to Selection");
      monitor.start();

      File tempPeak = File.createTempFile("gmtmp_", ".gmpk");
      CreatePeakFileThread peak =
          new CreatePeakFileThread(AudioSystem.getAudioInputStream(tempFile), tempPeak);
      monitor =
          new ProgressMonitor(
              getShell(), peak, "Creating peak file", "Creating peak file for applied effect.");
      monitor.start();

      PeakWaveForm pwf = new PeakWaveForm(tempPeak);
      AudioFileWaveForm awf = new AudioFileWaveForm(tempFile, pwf, 32 * 1024, 25);
      CutListSource newSource = new AudioFileSource(tempFile, awf);

      sel = waveDisplay.getSelection();
      int left = sel.getLeft();
      int right = sel.getRight();

      ReplaceElement el =
          new ReplaceElement(
              effect.getName(), newSource, left, right - left, fileFormat.getFormat());
      cutList.addElement(el);
      undoOperations.add(el);
      redoOperations.clear();
      thread.stop();
    } catch (NotReadyException e) {
      e.printStackTrace();
      editor.errorMessage(e.getMessage());
      if (thread != null) thread.stop();
    } catch (NotFinishedException e) {
      e.printStackTrace();
      editor.errorMessage(e.getMessage());
      if (thread != null) thread.stop();
    } catch (LineUnavailableException e) {
      e.printStackTrace();
      editor.errorMessage(e.getMessage());
      if (thread != null) thread.stop();
    } catch (IOException e) {
      e.printStackTrace();
      editor.errorMessage(e.getMessage());
      if (thread != null) thread.stop();
    } catch (UnsupportedAudioFileException e) {
      e.printStackTrace();
      editor.errorMessage(e.getMessage());
      if (thread != null) thread.stop();
    }
  }