/*******************************************************************************
* Rhythos Editor is a game editor and project management tool for making RPGs on top of the Rhythos Game system.
*
* Copyright (C) 2013 David Maletz
*
* 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. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package mrpg.media;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.HierarchyEvent;
import java.awt.event.HierarchyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.plaf.metal.MetalSliderUI;
public class MediaPlayer extends JPanel implements ActionListener, ChangeListener, FrameListener, MouseListener, MouseMotionListener, HierarchyListener {
private static final long serialVersionUID = -2645984272456152640L;
private static final Icon PLAY_ICON = new PlayIcon(), PAUSE_ICON = new PauseIcon(), STOP_ICON = new StopIcon();
private final Audio.Player player = new Audio.Player(); private Audio.Clip clip;
private final JButton play, stop; private final JSlider pos; private final JProgressBar vol; private long len = 1; private int posVal = 0;
private FrameListener listener;
public MediaPlayer(){
player.setFrameListener(this);
play = new JButton(PLAY_ICON); play.addActionListener(this); play.setEnabled(false); add(play);
stop = new JButton(STOP_ICON); stop.addActionListener(this); stop.setEnabled(false); add(stop);
vol = new JProgressBar(JProgressBar.VERTICAL, 0, 1000); vol.addChangeListener(this); vol.setEnabled(false); vol.setFont(vol.getFont().deriveFont(8.f));
vol.setPreferredSize(new Dimension(vol.getPreferredSize().width, 20)); vol.setValue(1000); add(vol);
vol.addMouseListener(this); vol.addMouseMotionListener(this); SliderUI posui = new SliderUI();
pos = new JSlider(0, 1000, 0); pos.addChangeListener(this); pos.addMouseListener(posui); pos.setEnabled(false);
pos.setPreferredSize(new Dimension(150, pos.getPreferredSize().height)); pos.setUI(posui); add(pos);
}
public void setFrameListener(FrameListener l){synchronized(player){listener = l;}}
public Audio.Clip getClip(){return clip;}
public void setClip(Audio.Clip c){
stop(); boolean b = c != null; clip = c;
if(b){player.setClip(c); player.setVolume(vol.getValue()*0.001f); len = c.length();}
play.setEnabled(b); stop.setEnabled(b); vol.setEnabled(b); pos.setEnabled(b);
}
public void play(){player.play(); play.setIcon(PAUSE_ICON);}
public void setFrame(long f){player.setFrame(f);}
public void pause(){player.pause(); play.setIcon(PLAY_ICON);}
public boolean isRunning(){return player.isRunning();}
public void stop(){player.stop(); play.setIcon(PLAY_ICON);}
public void addNotify(){super.addNotify(); addHierarchyListener(this);}
public void removeNotify(){removeHierarchyListener(this); super.removeNotify();}
public void hierarchyChanged(HierarchyEvent e){
if((e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) != 0) if(!isShowing()) stop();
}
public void actionPerformed(ActionEvent e){
if(e.getSource() == play){if(player.isRunning()) pause(); else play();}
else stop();
}
public void playFrame(long f) {posVal = (int)((f%len)*1000.f/len); pos.setValue(posVal); if(listener != null) listener.playFrame(f);}
public void stateChanged(ChangeEvent e) {
if(e.getSource() == pos){
synchronized(player){
if(pos.getValue() != posVal){posVal = pos.getValue(); player.setFrame((long)(posVal*0.001f*len));}
}
} else {if(vol.isEnabled()) player.setVolume(vol.getValue()*0.001f);}
}
public void mouseClicked(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) { }
public void mousePressed(MouseEvent e) {vol.setValue((18-e.getY())*56);}
public void mouseReleased(MouseEvent e) {}
public void mouseDragged(MouseEvent e) {mousePressed(e);}
public void mouseMoved(MouseEvent e) {}
private static class SliderUI extends MetalSliderUI implements MouseListener {
private int x = 0;
protected void scrollDueToClickInTrack(int dir){slider.setValue(valueForXPosition(x));}
public void mouseClicked(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) { }
public void mousePressed(MouseEvent e) {x = e.getX();}
public void mouseReleased(MouseEvent e) {}
}
private static class PlayIcon implements Icon {
public int getIconHeight() {return 12;}
public int getIconWidth() {return 12;}
public void paintIcon(Component c, Graphics g, int x, int y) {g.setColor(c.getForeground()); g.fillPolygon(new int[]{x, x+12, x}, new int[]{y, y+6, y+12}, 3);}
}
private static class PauseIcon implements Icon {
public int getIconHeight() {return 12;}
public int getIconWidth() {return 12;}
public void paintIcon(Component c, Graphics g, int x, int y) {g.setColor(c.getForeground()); g.fillRect(x, y, 3, 12); g.fillRect(x+9, y, 3, 12);}
}
private static class StopIcon implements Icon {
public int getIconHeight() {return 12;}
public int getIconWidth() {return 12;}
public void paintIcon(Component c, Graphics g, int x, int y) {g.setColor(c.getForeground()); g.fillRect(x, y, 12, 12);}
}
}