
// MidiInfo.java
// Andrew Davison, April 2005, ad@fivedots.coe.psu.ac.th

/* Uchovává jedinou midi-sekvenci a umožňuje ji spustit,
   zastavit, pozastavit, opětovně spustit a nechat ji hrát dokola.

   Cyklické přehrávání lze ovládat pomocí třídy MidisLoader voláním metody
   tryLooping().

   Třída MidisLoader předává odkaz na svůj sekvencer každému objektu typu MidiInfo,
   které tak mohou sami přehrávat své patry.
*/

import java.io.*;
import javax.sound.midi.*;


public class MidiInfo
{
  private final static String SOUND_DIR = "Sounds/";

  private String name, filename;
  private Sequence seq = null;
  private Sequencer sequencer;   // získáno od objektu typu MidisLoader
  private boolean isLooping = false;


  public MidiInfo(String nm, String fnm, Sequencer sqr)
  {
    name = nm;
    filename = SOUND_DIR + fnm;
    sequencer = sqr;
    loadMidi();
  } // konec metody: MidiInfo()


  private void loadMidi()
  // načti midi-sekvenci
  { 
    try {
      seq = MidiSystem.getSequence( getClass().getResource(filename) );
    }
    catch (InvalidMidiDataException e) {
      System.out.println("nečitelný/nepodporovaný midi-soubor: " + filename);
    }
    catch (IOException e) {
      System.out.println("Nemohu přečíst soubor: " + filename);
    }
    catch (Exception e) {
      System.out.println("Problém s " + filename);
    }
  } // konec metody: loadMidi()



  public void play(boolean toLoop)
  { if ((sequencer != null) && (seq != null)) {
      try {
        sequencer.setSequence(seq);   // načti MIDI-sekvenci do sekvenceru
        sequencer.setTickPosition(0); // vynuluj pozici na začátek sekvence
        isLooping = toLoop;
        sequencer.start();            // přehrej sekvenci
      }
      catch (InvalidMidiDataException e) {
        System.out.println("Poškozený/neplatný soubor midi: " + filename);
      }
    }
  } // konec metody: play()



  public void stop()
  /* Zastaví sekvenci. Chceme, aby se spustila meta-zpráva 'end-of-track',
     takže ji zastavíme přetočením na její konec. Tato meta-zpráva se pošle
     do metody meta() objektu typu MidisLoader, od něhož pochází používaný sekvencer.
  */
  { if ((sequencer != null) && (seq != null)) {
      isLooping = false;
      if (!sequencer.isRunning())   // sekvence může být pozastavena
        sequencer.start();
      sequencer.setTickPosition( sequencer.getTickLength() );  
         // pro aktivaci zprávy end-of-track se přesuň na konec sekvence
    }
  } // konec metody: stop()



  public void pause()
  // pozastav sekvenci zastavením sekvenceru
  { if ((sequencer != null) && (seq != null)) {
      if (sequencer.isRunning())
        sequencer.stop();
    }
  }


  public void resume()
  { if ((sequencer != null) && (seq != null))
      sequencer.start();
  }


  public boolean tryLooping()
  /* Přehrej hudbu cyklicky, pokud je to možné, a hlas
     kdykoliv dojde k přesunu na začátek.
     Tato metoda se volá z metody meta() třídy MidisLoader obdrží-li
     meta-zprávu 'end-of-track'.

     Jinými slovy, sekvence není nastavena do 'režimu cyklení'
     (který je možný až s novými metodami v J2SE 1.5), ale místo toho
     ji objekt typu MidisLoader přehrává stále dokola.
  */
  { if ((sequencer != null) && (seq != null)) {
      if (sequencer.isRunning())
        sequencer.stop();
      sequencer.setTickPosition(0);
      if (isLooping) {    // opět přehrej sekvenci
        sequencer.start();
        return true;
      }
    }
    return false;
  } // konec metody: tryLooping()


  // -------------- metody pro přístup k atributům -------------------

  public String getName()
  {  return name;  }

}  // konec třídy: MidiInfo
