package org.lysty.ui;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JProgressBar;
import javax.swing.JSlider;
import javax.swing.JToggleButton;
import javax.swing.ListCellRenderer;
import javax.swing.SwingConstants;
import javax.swing.Timer;
import javax.swing.border.TitledBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import net.miginfocom.swing.MigLayout;
import org.apache.log4j.Logger;
import org.jaudiotagger.audio.AudioFile;
import org.jaudiotagger.audio.AudioFileIO;
import org.lysty.core.AppSettingsManager;
import org.lysty.core.PlaylistGenerator;
import org.lysty.core.StrategyFactory;
import org.lysty.dao.Song;
import org.lysty.strategies.StrategyConfiguration;
import org.lysty.util.Utils;
public class PlayerPanel extends JPanel implements StrategySettingsListener {
private static final String FEATURE_DURATION = "duration";
private static final int DEFAULT_FRAMES_PER_SECS = 38;
private JProgressBar progress;
private JToggleButton btnStartPause;
private JButton btnStop;
private JButton btnNext;
private JButton btnPrev;
private PlayPanelListener listener;
private JToggleButton btnInfin;
private JButton btnSleep;
private JToggleButton btnRandom;
private static final int MINS_TO_MILIS = 60000;
public enum PlayState {
PLAYING, PAUSED, STOPPED
}
private PlayState playState;
private Timer timer;
private int pausedOnFrame;
private JComboBox cmbStrategy;
private JButton btnFillSettings;
private PlaylistGenerator currentStrategy;
private StrategyConfiguration currentStrategySettings;
private JSlider volumeSlider;
private JLabel lblTime;
private Logger logger = Logger.getLogger(PlayerPanel.class);
/**
* @return the currentStrategy
*/
public PlaylistGenerator getCurrentStrategy() {
return currentStrategy;
}
/**
* @param currentStrategy
* the currentStrategy to set
*/
public void setCurrentStrategy(PlaylistGenerator currentStrategy) {
this.currentStrategy = currentStrategy;
}
/**
* @return the currentStrategySettings
*/
public StrategyConfiguration getCurrentStrategySettings() {
return currentStrategySettings;
}
public PlayState getState() {
return playState;
}
public void setState(PlayState state) {
if (playState == state) {
// no state changed
return;
}
playState = state;
if (state == PlayState.PLAYING) {
btnStartPause.setIcon(Utils.getIcon(ResourceConstants.PAUSE_ICON));
btnStartPause.setSelected(true);
} else if (state == PlayState.PAUSED) {
btnStartPause.setIcon(Utils.getIcon(ResourceConstants.PLAY_ICON));
btnStartPause.setSelected(false);
if (timer != null)
timer.stop();
} else if (state == PlayState.STOPPED) {
btnStartPause.setIcon(Utils.getIcon(ResourceConstants.PLAY_ICON));
btnStartPause.setSelected(false);
if (timer != null)
timer.stop();
setCurrentSongProgress(0);
}
}
public int getCurrentProgress() {
return progress.getValue();
}
public PlayerPanel(PlayPanelListener listener) {
this.listener = listener;
createUI();
layoutControls();
setState(PlayState.STOPPED);
}
public void loadLatestSettings() {
String strategyClass = AppSettingsManager
.getProperty(AppSettingsManager.LS_FILL_STRATEGY);
if (Utils.stringNotNullOrEmpty(strategyClass)) {
PlaylistGenerator strategy = StrategyFactory
.getStrategyByClassName(strategyClass);
if (strategy != null)
cmbStrategy.setSelectedItem(strategy);
}
btnInfin.setSelected(AppSettingsManager
.getPropertyAsBoolean(AppSettingsManager.LS_INFINI_PLAY));
listener.setInfinyPlay(btnInfin.isSelected());
volumeSlider.setValue(Integer.parseInt(AppSettingsManager.getProperty(
AppSettingsManager.LS_VOLUME_LEVEL, "90")));
}
private void layoutControls() {
setLayout(new MigLayout("", "[grow]", "[][grow]"));
JPanel panel = new JPanel();
panel.setBorder(new TitledBorder(null, "", TitledBorder.LEADING,
TitledBorder.TOP, null, null));
add(panel, "cell 0 0,grow");
panel.setLayout(new MigLayout("", "[][][][][][][]", "[][]"));
panel.add(progress, "flowx,spanx 6,growx");
panel.add(lblTime, "flowx,align right,span");
panel.add(btnStartPause, "flowx");
panel.add(btnStop, "flowx");
panel.add(btnPrev, "flowx");
panel.add(btnNext, "flowx");
panel.add(volumeSlider, "flowx,push,span 2,alignx right");
panel.add(btnRandom, "flowx,push,align right,split 2,gapleft 5");
panel.add(btnSleep, "flowx,push,alignx right");
JPanel panel_1 = new JPanel();
panel_1.setBorder(new TitledBorder(null, "", TitledBorder.LEADING,
TitledBorder.TOP, null, null));
add(panel_1, "cell 0 1,grow");
panel_1.setLayout(new MigLayout("", "[][grow][]", "[]"));
panel_1.add(btnInfin, "cell 0 0,aligny top");
panel_1.add(cmbStrategy, "cell 1 0,growx");
panel_1.add(btnFillSettings, "cell 2 0");
}
protected void showSettingsFrame() {
PlaylistGenerator strategy = (PlaylistGenerator) cmbStrategy
.getSelectedItem();
StrategySettingsWindow.getInstance().createUi(strategy, this);
StrategySettingsWindow.getInstance().setListener(this);
}
public void setCurrentSong(Song song, int playFrom) {
try {
int duration = 0;
if (song.getAttribute(FEATURE_DURATION) != null) {
duration = Integer
.parseInt(song.getAttribute(FEATURE_DURATION));
} else {
try {
AudioFile audioFile = AudioFileIO.read(song.getFile());
duration = audioFile.getAudioHeader().getTrackLength();
} catch (Exception e) {
logger.error("Couldn't extract audio duraion for song: "
+ song.getFile().getName(), e);
duration = 0;
}
}
final int fDuration = duration;
if (playFrom == 0) {
setCurrentSongProgress(0);
progress.setMaximum(duration);
progress.setString("");
progress.setStringPainted(true);
}
if (timer != null) {
timer.stop();
}
timer = new Timer(1000, new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
// ...Update the progress bar...
setCurrentSongProgress(progress.getValue() + 1);
if (progress.getValue() >= fDuration) {
timer.stop();
}
}
});
timer.start();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void createUI() {
progress = new JProgressBar();
progress.setPreferredSize(new Dimension(300, 10));
progress.setMaximumSize(new Dimension(300, 10));
progress.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
int tW = progress.getWidth();
int cW = e.getX();
int newProgress = progress.getMaximum() * cW / tW;
listener.play((int) newProgress * DEFAULT_FRAMES_PER_SECS);
setCurrentSongProgress(newProgress);
}
});
progress.setMaximum(0);
lblTime = new JLabel("-.-/-.-");
btnStartPause = new JToggleButton();
btnStartPause.setIcon(Utils.getIcon(ResourceConstants.PLAY_ICON));
btnStartPause.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (btnStartPause.isSelected()) {
// pause
setState(PlayState.PLAYING);
listener.play(pausedOnFrame);
} else {
// start
setState(PlayState.PAUSED);
listener.pause();
}
}
});
btnStop = new JButton(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
setState(PlayState.STOPPED);
pausedOnFrame = 0;
listener.stop();
}
});
btnStop.setIcon(Utils.getIcon(ResourceConstants.STOP_ICON));
btnNext = new JButton(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
listener.stop();
setState(PlayState.STOPPED);
listener.next();
}
});
btnNext.setIcon(Utils.getIcon(ResourceConstants.NEXT_ICON));
btnPrev = new JButton(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
listener.stop();
setState(PlayState.STOPPED);
listener.prev();
}
});
btnPrev.setIcon(Utils.getIcon(ResourceConstants.PREV_ICON));
btnInfin = new JToggleButton(
Utils.getIcon(ResourceConstants.INFINI_ICON));
btnInfin.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
listener.setInfinyPlay(btnInfin.isSelected());
}
});
final JPopupMenu popup = new SleepMenu(listener);
btnSleep = new JButton(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
popup.show(btnSleep, 0, 0);
}
});
btnSleep.setIcon(Utils.getIcon(ResourceConstants.SLEEP_ICON));
btnRandom = new JToggleButton(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
listener.setRandomize(btnRandom.isSelected());
}
});
btnRandom.setIcon(Utils.getIcon(ResourceConstants.SHUFFLE_ICON));
btnRandom.setSelected(false);
btnFillSettings = new JButton(new AbstractAction("") {
@Override
public void actionPerformed(ActionEvent e) {
showSettingsFrame();
}
});
btnFillSettings.setIcon(Utils.getIcon(ResourceConstants.SETTINGS_ICON));
cmbStrategy = new JComboBox();
List<PlaylistGenerator> list = StrategyFactory.getAllStrategies();
cmbStrategy.setModel(new DefaultComboBoxModel(list
.toArray(new PlaylistGenerator[list.size()])));
cmbStrategy.setRenderer(new ListCellRenderer() {
@Override
public Component getListCellRendererComponent(JList list,
Object value, int index, boolean isSelected,
boolean cellHasFocus) {
JLabel lbl = new JLabel(((PlaylistGenerator) value)
.getStrategyDisplayName());
return lbl;
}
});
cmbStrategy.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent event) {
if (event.getStateChange() == ItemEvent.SELECTED) {
PlaylistGenerator item = (PlaylistGenerator) event
.getItem();
onStrategySelectionChange(item);
}
}
});
volumeSlider = new JSlider(SwingConstants.HORIZONTAL, 0, 100, 50);
volumeSlider.setToolTipText("Volume control");
volumeSlider.setPreferredSize(new Dimension(60, 10));
// volumeSlider.setMaximumSize(new Dimension(60, 20));
// volumeSlider.setMinimumSize(new Dimension(60, 5));
volumeSlider.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
VolumeControl.setVolume((float) volumeSlider.getValue() / 100);
}
});
cmbStrategy.setSelectedIndex(0);
onStrategySelectionChange((PlaylistGenerator) cmbStrategy.getItemAt(0));
}
protected void onStrategySelectionChange(PlaylistGenerator newStrategy) {
currentStrategy = newStrategy;
currentStrategySettings = StrategyFactory
.getDefaultOrLastSettings(newStrategy);
}
public void setCurrentSongProgress(int val) {
progress.setValue(val);
lblTime.setText(getTimeFormattedString(val) + "/"
+ getTimeFormattedString(progress.getMaximum()));
}
private String getTimeFormattedString(int val) {
int mins = val / 60;
int secs = val % 60;
return mins + "." + ((secs < 10) ? "0" + secs : secs);
}
public void setPausedOnFrame(int frame) {
this.pausedOnFrame = frame;
}
public boolean getIsInfiniPlay() {
return btnInfin.isSelected();
}
@Override
public void setCurrentProfileSettings(StrategyConfiguration strategySettngs) {
currentStrategySettings = strategySettngs;
StrategyFactory.updateLastSettings(currentStrategy,
currentStrategySettings);
}
public void setInfiniPlay(boolean selected) {
btnInfin.setSelected(selected);
}
public void setStrategy(PlaylistGenerator strategy) {
currentStrategy = strategy;
cmbStrategy.setSelectedItem(currentStrategy);
}
public void updateSettings() {
AppSettingsManager.setProperty(AppSettingsManager.LS_FILL_STRATEGY,
((PlaylistGenerator) cmbStrategy.getSelectedItem()).getClass()
.getName());
AppSettingsManager.setProperty(AppSettingsManager.LS_INFINI_PLAY,
btnInfin.isSelected() ? "true" : "false");
AppSettingsManager.setProperty(AppSettingsManager.LS_VOLUME_LEVEL,
volumeSlider.getValue() + "");
}
public void setToolTips() {
btnStartPause.setToolTipText("Start/Pause");
btnStop.setToolTipText("Stop");
btnPrev.setToolTipText("Previous Song");
btnNext.setToolTipText("Next Song");
btnRandom.setToolTipText("Randomize");
btnSleep.setToolTipText("Sleep");
cmbStrategy
.setToolTipText("Fill strategy to use to generate the next songs for the playlist");
btnFillSettings.setToolTipText("Settings for the fill strategy");
btnInfin.setToolTipText("InfiniPlay Mode");
}
}