/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.hadeslee.yoyoplayer.player.ui;
import com.hadeslee.yoyoplayer.equalizer.EqualizerUI;
import com.hadeslee.yoyoplayer.playlist.PlayListUI;
import com.hadeslee.yoyoplayer.lyric.Lyric;
import com.hadeslee.yoyoplayer.lyric.LyricUI;
import com.hadeslee.yoyoplayer.player.BasicController;
import com.hadeslee.yoyoplayer.player.BasicPlayerEvent;
import com.hadeslee.yoyoplayer.player.BasicPlayerException;
import com.hadeslee.yoyoplayer.player.BasicPlayerListener;
import com.hadeslee.yoyoplayer.util.AudioChart;
import com.hadeslee.yoyoplayer.util.Config;
import com.hadeslee.yoyoplayer.util.Loader;
import com.hadeslee.yoyoplayer.playlist.PlayList;
import com.hadeslee.yoyoplayer.playlist.PlayListItem;
import com.hadeslee.yoyoplayer.setting.AudioChartPanel;
import com.hadeslee.yoyoplayer.setting.OptionDialog;
import com.hadeslee.yoyoplayer.tag.SongInfoDialog;
import com.hadeslee.yoyoplayer.util.FileNameFilter;
import com.hadeslee.yoyoplayer.util.Playerable;
import com.hadeslee.yoyoplayer.util.SongInfo;
import com.hadeslee.yoyoplayer.util.Util;
import com.hadeslee.yoyoplayer.util.YOYOSlider;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.PopupMenu;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.io.File;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.MessageFormat;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.sound.sampled.SourceDataLine;
import javax.swing.AbstractAction;
import javax.swing.AbstractButton;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JToggleButton;
import javax.swing.SwingConstants;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
/**
*
* @author hadeslee
*/
public class PlayerUI extends JPanel implements Playerable, ActionListener, ChangeListener, BasicPlayerListener {
private static final long serialVersionUID = 20071214L;
//表示播放器的各种状态
public static final int INIT = 0;
public static final int OPEN = 1;
public static final int PLAY = 2;
public static final int PAUSE = 3;
public static final int STOP = 4;
private static Logger log = Logger.getLogger(PlayerUI.class.getName());
private JButton pre, next, play, stop;//四个播放相关按钮
private JButton close, min;//右上角的三个图标
private JLabel about;//关于信息的一个标签,添加了鼠标事件
private JLabel state, channel;//表示标题和信息的一个标签
protected JToggleButton pl, lrc, eq, speaker;//三个状态按钮,和一个音量按钮
private YOYOSlider pos, pan, volume;//三个进度条
private AudioChart audioChart;//示波器
private Lyric lyric;//一个歌词对象
private BasicController player;//基本的播放器对象
private Map audioInfo;//里面存的是所有有关的音频信息
private int playerState;//播放器的当前状态
private Config config;//一个配置对象
private long lastScrollTime;//上一次的滚动歌曲信息的时候
private boolean posValueJump;//表示现在位置条是否在拖动中
private PlayListItem currentItem;//当前正在播放的列表项
private long secondsAmount;//总共用去的秒数
private Loader loader;//一个负责总装载的接口,一般由主窗口实现
private PlayList playlist;//一个播放列表的实现,
private String currentSongName;//当前正在播放的歌曲的名字
private String currentFileOrURL;//当前正在放的歌曲的文件名或者URL路径
private boolean currentIsFile;//当前正在播放的是否是文件,因为可能是网络上的URL
private String titleText;//标题应该显示的内容
private PlayListUI playlistUI;//摠放列表的UI的引用
private EqualizerUI equalizerUI;//调音器的UI引用
private LyricUI lyricUI;//歌词显示面板UI的引用
private SongInfo songInfo;//当前正在播放的歌曲的一些信息,用于滚动显示在时间下面
private boolean posDragging;//指示当前的进度条是否在拖动中
private double posValue;//指示当前的进度条所在的位置的比例
private TimePanel timePanel;//显时间的面板
private SongInfoPanel infoPanel;//显示歌曲信息的面板
private Image[] playImgs, pauseImgs;//用于显示播放和暂停的图标数组
private String currentState;//当前的状态,比如正在播放,停止,暂停
private boolean isSeeked;//是否已经seek了
private double lastRate;//最后的比率
private final Object lock = new Object();
private volatile boolean scrollTitle;//是否滚动标题栏
private String title = Config.NAME;
private Thread thread;//显示任务栏的标题滚动线程
private long seekedTime;//拖过的时间
// private //一个监听鼠标滚轮滚动的监听器,用于调节音量
public PlayerUI() {
super(null);
setPreferredSize(new Dimension(285, 155));
}
/**
* 得到媒体当前的时间,以毫秒为单位
* @return 时间
*/
public long getTime() {
if (player == null) {
return -1;
} else {
return player.getMicrosecondPosition() / 1000 + seekedTime;
}
}
void setLastRate(double rate) {
this.lastRate = rate;
}
public void setPlayList(PlayList playlist) {
this.playlist = playlist;
}
public AudioChart getAudioChart() {
return audioChart;
}
public boolean loadPlaylist() {
boolean loaded = false;
String lastPlay = config.getCurrentFileOrUrl();
log.log(Level.INFO, "lastPlay=" + lastPlay);
if (lastPlay != null) {
for (PlayListItem item : playlist.getAllItems()) {
if (item.getLocation().equals(lastPlay)) {
log.log(Level.INFO, "找到了最后要播的匹配!!");
this.setCurrentSong(item);
break;
}
}
}
return loaded;
}
public void processJumpToFile(int modifiers) {
throw new UnsupportedOperationException("Not yet implemented");
}
public void processPreferences(int modifiers) {
throw new UnsupportedOperationException("Not yet implemented");
}
public void pressStart() {
play.doClick();
}
public void pressEq() {
eq.doClick();
}
public void pressLrc() {
lrc.doClick();
}
public void pressPl() {
pl.doClick();
}
/**
* 给此面板本身以及所有的子组件都添加上这个
* 监听器
*/
private void addMouseVolumeListener() {
MouseVolumeListener mv = new MouseVolumeListener();
this.addMouseWheelListener(mv);
int count = this.getComponentCount();
for (int i = 0; i < count; i++) {
this.getComponent(i).addMouseWheelListener(mv);
}
}
private void initUI() {