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

/* Nabízí řadu objektů typu AudioClip v roletovém menu, 
   které lze přehrát jednou, cyklicky nebo zastavit.

   Je možné, aby v jednom okamžiku hrálo více klipů současně.

   Metoda stop() ukončí všechny aktuálně hrající objekty typu
   AudioClip.

   Založeno na tutoriálu o zvuku v Javě s názvem SoundApplication
*/

import javax.swing.*;
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;


public class SoundPlayer extends JFrame implements ActionListener
{
  private final static String SOUND_DIR = "Sounds/";

  private final static String[] soundFNms = 
           {"spacemusic.au", "tiger.aiff", "mcdonald.mid", "dog.wav"};

  private HashMap soundsMap;         // uchovává dvojice <fnm,AudioClip>
  private ArrayList playingClips;    // seznam hrajících objektů typu AudioClip
        
  private JComboBox playListJcb;
  private JButton playButton, loopButton, stopButton;
  private JLabel statusLabel;
        


  public SoundPlayer() 
  {
    super( "Zvuková aplikace" );

    playingClips = new ArrayList();
    initGUI();
    loadSounds();

    setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
    setSize( new Dimension(500,100) );
    setResizable(false);    // rozměry okna jsou pevně dány
    setVisible(true);
  } // konec metody: SoundPlayer()


  private void initGUI()
  /* Vytvoří roletové menu obsahující objekty typu AudioClip a 
     tlačítka pro manipulaci s nimi. */
  {
    Container c = getContentPane();
    c.setLayout( new BorderLayout() );   


    playListJcb = new JComboBox(soundFNms);

    playButton = new JButton("Hrát jednou");
    playButton.addActionListener(this);

    loopButton = new JButton("Hrát dokola");
    loopButton.addActionListener(this);

    stopButton = new JButton("Stop");
    stopButton.addActionListener(this);
        
    statusLabel = new JLabel("Pro přehrání zvoleného souboru stiskněte tlačítko \"Hrát jednou\" nebo \"Hrát dokola\".");
                
    JPanel controlPanel = new JPanel();
    controlPanel.add(playListJcb);
    controlPanel.add(playButton);
    controlPanel.add(loopButton);
    controlPanel.add(stopButton);           
                
    JPanel statusPanel = new JPanel();
    statusPanel.add(statusLabel);
                
    c.add(controlPanel, BorderLayout.CENTER);
    c.add(statusPanel, BorderLayout.SOUTH);
  }  // konec metody: initGUI()



  private void loadSounds()
  /* Načte objekty typu AudioClip a uloží je do hašovací 
     tabulky soundsMap, jejíž klíče tvoří jména souborů klipů. */
  {
    soundsMap = new HashMap();
    for (int i=0; i < soundFNms.length; i++) {
      AudioClip clip = Applet.newAudioClip( 
                getClass().getResource(SOUND_DIR + soundFNms[i]) );
      if (clip == null)
        System.out.println("Problém při načítání " +  SOUND_DIR + soundFNms[i]);
      else 
        soundsMap.put(soundFNms[i], clip);
    }
  } // konec metody: loadSounds()


  public void actionPerformed(ActionEvent event) 
  // reakce na stisky tlačítek
  {
    Object source = event.getSource();
    if (source == playButton)
      playMusic(false);    // false znamená nepřehrávej cyklicky
    else if (source == loopButton)
      playMusic(true);     // zahaj cyklické přehrávání
    else if (source == stopButton)
      stopMusic();
  } // konec metody: actionPerformed()


  private void playMusic(boolean toLoop)
  /* Získá relevantní objekt typu AudioClip a spustí jej.
     Uloží odkaz na klip do seznamu playingClips. */
  {
    String chosenFile = (String) playListJcb.getSelectedItem();

    // pokus se získat objekt typu AudioClip
    AudioClip audioClip = (AudioClip) soundsMap.get(chosenFile);
    if (audioClip == null) {
      statusLabel.setText("Zvukový soubor " + chosenFile + " nebyl načten");
      return;
    }

    if (toLoop)
      audioClip.loop();
    else
      audioClip.play();     // přehraj pouze jednou

    playingClips.add(audioClip);   // ulož odkaz na přehrávaný klip
    String times = (toLoop) ? " opakovaně" : " jedenkrát";
    statusLabel.setText("Přehrávám zvukový soubor " + chosenFile + times);
  }  // konec metody: playMusic()



  private void stopMusic()
  /* Zastaví všechny klipy voláním metody stop() na všech odkazech
     v seznamu playingClips. Problém je, že některé klipy 
     již mohly dohrát, neexistuje však žádný způsob, jak toto
     s pomocí třídy AudioClip detekovat. */
  {
    if (playingClips.isEmpty())
      statusLabel.setText("Není co zastavit");
    else {
      AudioClip audioClip;
      for(int i=0; i < playingClips.size(); i++) {
        audioClip = (AudioClip) playingClips.get(i);
        audioClip.stop();   // již mohou být zastaveny, ale volání metody
                            // stop() znovu jim neublíží
      }
      playingClips.clear();
      statusLabel.setText("Všechna hudba zastavena");
    }
  }  // konec metody: stopMusic()


  // -----------------------------------------

  public static void main(String args[]) 
  {  new SoundPlayer();  }

} // konec třídy: SoundPlayer
