Java tutorial
/** * Xtreme Media Player a cross-platform media player. * Copyright (C) 2005-2014 Besmir Beqiri * * 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 2 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, write to the Free Software Foundation, Inc., 51 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package xtrememp; import java.awt.CardLayout; import java.awt.Desktop; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.InputEvent; import java.awt.event.ItemEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseWheelEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.File; import java.io.FileNotFoundException; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.concurrent.TimeUnit; import net.miginfocom.swing.MigLayout; import xtrememp.player.audio.AudioPlayer; import xtrememp.player.audio.PlaybackEvent; import xtrememp.player.audio.PlaybackListener; import xtrememp.player.audio.PlayerException; import xtrememp.playlist.Playlist; import xtrememp.playlist.PlaylistEvent; import xtrememp.playlist.PlaylistException; import xtrememp.playlist.PlaylistIO; import xtrememp.playlist.PlaylistItem; import xtrememp.playlist.PlaylistListener; import xtrememp.tag.TagInfo; import xtrememp.ui.button.NextButton; import xtrememp.ui.button.PlayPauseButton; import xtrememp.ui.button.PreviousButton; import xtrememp.ui.button.StopButton; import xtrememp.ui.button.VolumeButton; import xtrememp.ui.label.BusyLabel; import xtrememp.ui.skin.GFXUIListener; import xtrememp.ui.slider.SeekSlider; import xtrememp.update.SoftwareUpdate; import xtrememp.update.Version; import xtrememp.util.AbstractSwingWorker; import xtrememp.util.LanguageBundle; import xtrememp.util.OSUtils; import xtrememp.util.Utilities; import static xtrememp.util.Utilities.tr; import xtrememp.util.file.AudioFileFilter; import xtrememp.util.file.PlaylistFileFilter; import javax.sound.sampled.AudioSystem; import javax.swing.Box; import javax.swing.ButtonGroup; import javax.swing.JCheckBox; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JRadioButtonMenuItem; import javax.swing.JSeparator; import javax.swing.JSlider; import javax.swing.JTable; import javax.swing.KeyStroke; import javax.swing.SwingConstants; import javax.swing.UIManager; import javax.swing.event.ChangeEvent; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.Option; import org.apache.commons.cli.OptionBuilder; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import org.apache.commons.cli.PosixParser; import org.pushingpixels.lafwidget.animation.AnimationConfigurationManager; import org.pushingpixels.lafwidget.animation.AnimationFacet; import org.pushingpixels.substance.api.DecorationAreaType; import org.pushingpixels.substance.api.SubstanceConstants; import org.pushingpixels.substance.api.SubstanceLookAndFeel; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.melloware.jintellitype.IntellitypeListener; import com.melloware.jintellitype.JIntellitype; import java.awt.Rectangle; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.io.IOException; import java.net.URISyntaxException; import java.util.concurrent.ExecutionException; /** * XtremeMP main class. Special thanks to rom1dep for the changes applied to * this class. * * @author Besmir Beqiri */ public final class XtremeMP implements ActionListener, ControlListener, PlaybackListener, PlaylistListener, IntellitypeListener, GFXUIListener { private static final Logger logger = LoggerFactory.getLogger(XtremeMP.class); private final AudioFileFilter audioFileFilter = AudioFileFilter.INSTANCE; private final PlaylistFileFilter playlistFileFilter = PlaylistFileFilter.INSTANCE; private final Version currentVersion = Version.getCurrentVersion(); private static XtremeMP instance; private JFrame mainFrame; private JMenuBar menuBar; private JMenu fileMenu; private JMenu playerMenu; private JMenu playModeSubMenu; private JMenu viewMenu; private JMenu helpMenu; private JMenuItem openMenuItem; private JMenuItem openURLMenuItem; private JMenuItem openPlaylistMenuItem; private JMenuItem savePlaylistMenuItem; private JMenuItem preferencesMenuItem; private JMenuItem exitMenuItem; private JMenuItem nextMenuItem; private JMenuItem playPauseMenuItem; private JMenuItem stopMenuItem; private JMenuItem previousMenuItem; private JMenuItem randomizePlaylistMenuItem; private JRadioButtonMenuItem playlistManagerMenuItem; private JRadioButtonMenuItem visualizationMenuItem; private JRadioButtonMenuItem playModeRepeatNoneMenuItem; private JRadioButtonMenuItem playModeRepeatOneMenuItem; private JRadioButtonMenuItem playModeRepeatAllMenuItem; private JRadioButtonMenuItem playModeShuffleMenuItem; private JMenuItem updateMenuItem; private JMenuItem aboutMenuItem; private BusyLabel busyLabel; private JPanel mainPanel; private VisualizationManager visualizationManager; private JPanel controlPanel; private AudioPlayer audioPlayer; private Playlist playlist; private PlaylistManager playlistManager; private StopButton stopButton; private PreviousButton previousButton; private PlayPauseButton playPauseButton; private NextButton nextButton; private VolumeButton volumeButton; private JSlider volumeSlider; private JLabel timeLabel; private JLabel statusLabel; private JLabel playModeLabel; private SeekSlider seekSlider; private PlaylistItem currentPli; private XtremeMP() { } public static XtremeMP getInstance() { if (instance == null) { instance = new XtremeMP(); } return instance; } public JFrame getMainFrame() { return mainFrame; } public BusyLabel getBusyLabel() { return busyLabel; } public AudioPlayer getAudioPlayer() { return audioPlayer; } public void init(String[] args) { // Process arguments Option urlOption = OptionBuilder.withArgName("URL").hasArg().withDescription("Open from URL").create("url"); Options options = new Options(); options.addOption("help", false, "print help information"); options.addOption("version", false, "print the version information"); options.addOption(urlOption); CommandLineParser parser = new PosixParser(); try { final CommandLine line = parser.parse(options, args); if (line.hasOption("h") || line.hasOption("help")) { HelpFormatter formatter = new HelpFormatter(); formatter.printHelp("xtrememp", options); System.exit(0); } if (line.hasOption("version")) { StringBuilder appVersion = new StringBuilder(tr("Application.title")); appVersion.append(" ").append(currentVersion); appVersion.append(" [").append(tr("Dialog.About.Codename")); appVersion.append(" ").append(tr("Application.version.codename")); appVersion.append("]"); System.out.println(appVersion.toString()); System.exit(0); } // Initialize JIntellitype if (OSUtils.IS_OS_WINDOWS) { String libraryLocation = (OSUtils.IS_ARCH_X64) ? "\\native\\JIntellitype64.dll" : "\\native\\JIntellitype.dll"; JIntellitype.setLibraryLocation(OSUtils.USER_DIR + libraryLocation); if (JIntellitype.isJIntellitypeSupported()) { JIntellitype.getInstance().addIntellitypeListener(this); } } // Initialize audio engine audioPlayer = new AudioPlayer(); audioPlayer.addPlaybackListener(this); String mixerName = Settings.getMixerName(); if (!Utilities.isNullOrEmpty(mixerName)) { audioPlayer.setMixerName(mixerName); } // Launch gui EventQueue.invokeLater(() -> { if (!OSUtils.IS_OS_WINDOWS_7 && !OSUtils.IS_OS_WINDOWS_VISTA) { JFrame.setDefaultLookAndFeelDecorated(true); JDialog.setDefaultLookAndFeelDecorated(true); } UIManager.put(SubstanceLookAndFeel.FOCUS_KIND, SubstanceConstants.FocusKind.NONE); SubstanceLookAndFeel.setSkin(Settings.getSkin()); //Turn on Substance animations if required guiEffectsStateChanged(Settings.isUIEffectsEnabled()); StringBuilder appTitle = new StringBuilder(tr("Application.title")); appTitle.append(" ").append(currentVersion); mainFrame = new JFrame(appTitle.toString()); mainFrame.setIconImages(Utilities.getIconImages()); Rectangle boundsRect = Settings.getMainFrameBounds(); if (boundsRect.x <= 0 || boundsRect.y <= 0) { mainFrame.setSize(boundsRect.width, boundsRect.height); // Center the frame. mainFrame.setLocationRelativeTo(null); } else { mainFrame.setBounds(boundsRect); } mainFrame.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent ev) { exit(); } // @Override // public void windowIconified(WindowEvent e) { // if (Toolkit.getDefaultToolkit().isFrameStateSupported(JFrame.ICONIFIED)) { // getMainFrame().setExtendedState(JFrame.ICONIFIED); // } // getMainFrame().setVisible(false); // } // // @Override // public void windowDeiconified(WindowEvent e) { // if (Toolkit.getDefaultToolkit().isFrameStateSupported(JFrame.NORMAL)) { // getMainFrame().setExtendedState(JFrame.NORMAL); // } // getMainFrame().setVisible(true); // } }); createMenuBar(); createPanels(); // Set a minimum size for this frame. mainFrame.setMinimumSize(new Dimension(532, 244)); playlist = playlistManager.getPlaylist(); playlist.addPlaylistListener(XtremeMP.this); // Restore playlist settings : play mode playlist.setPlayMode(Settings.getPlayMode()); List<String> argList = Arrays.asList(line.getArgs()); List<File> fileList = new ArrayList<>(); if (argList.isEmpty()) { File playlistFile = new File(Settings.getCacheDir(), Utilities.DEFAULT_PLAYLIST); if (playlistFile.exists()) { playlistManager.loadPlaylist(playlistFile.getAbsolutePath()); } } else { playlistManager.setFirstLoad(true); if (argList.size() == 1) { File file = new File(argList.get(0)); if (audioFileFilter.accept(file)) { fileList.add(file); playlistManager.addFiles(fileList, true); } else if (playlistFileFilter.accept(file)) { playlistManager.loadPlaylist(file.getAbsolutePath()); } } else { for (String arg : argList) { File file = new File(arg); if (audioFileFilter.accept(file)) { fileList.add(file); } } playlistManager.addFiles(fileList, true); } } mainFrame.setVisible(true); }); } catch (ParseException exp) { logger.error("Parsing failed.", exp.getMessage()); } } public static void main(String... args) throws Exception { // Load Settings Settings.loadSettings(); // Configure logback Settings.configureLogback(); // Enable uncaught exception catching. Thread.setDefaultUncaughtExceptionHandler((Thread t, Throwable e) -> { logger.error(t.getName(), e); }); // Close error stream System.err.close(); // First, look up for other instances running if (!MultipleInstancesHandler.getInstance().isFirstInstance()) { MultipleInstancesHandler.getInstance().sendArgumentsToFirstInstance(args); } else { // NORMAL APPLICATION STARTUP // Set language Locale locale = Utilities.getLanguages()[Settings.getLanguageIndex()]; Locale.setDefault(locale); LanguageBundle.setLanguage(locale); // Animation configurations AnimationConfigurationManager.getInstance().disallowAnimations(AnimationFacet.ICON_GLOW, JTable.class); AnimationConfigurationManager.getInstance().disallowAnimations(AnimationFacet.ROLLOVER, JTable.class); AnimationConfigurationManager.getInstance().disallowAnimations(AnimationFacet.SELECTION, JTable.class); // Init getInstance().init(args); // Check for updates if (Settings.isAutomaticUpdatesEnabled()) { // wait 5 sec SoftwareUpdate.scheduleCheckForUpdates(5 * 1000); } } } protected void exit() { // Save current settings Settings.setMainFrameBounds(mainFrame.getBounds()); Settings.setPlaylistPosition(playlist.getCursorPosition()); Settings.setPlaylistColumns(playlistManager.getPlaylistColumns()); Settings.storeSettings(); try { File playlistFile = new File(Settings.getCacheDir(), Utilities.DEFAULT_PLAYLIST); PlaylistIO.saveXSPF(playlist, playlistFile.getAbsolutePath()); } catch (PlaylistException ex) { logger.error("Can't save default playlist", ex); } // Release audio engine resources audioPlayer.stop(); // Clean up all resources used by JIntellitype if (JIntellitype.isJIntellitypeSupported()) { JIntellitype.getInstance().cleanUp(); } MultipleInstancesHandler.getInstance().dispose(); logger.info("Exit application..."); System.exit(0); } protected void createMenuBar() { menuBar = new JMenuBar(); // File Menu String fileMenuStr = tr("MainFrame.Menu.File"); fileMenu = new JMenu(fileMenuStr); fileMenu.setMnemonic(fileMenuStr.charAt(0)); openMenuItem = new JMenuItem(tr("MainFrame.Menu.File.OpenFile")); openMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_DOWN_MASK)); openMenuItem.setIcon(Utilities.FOLDER_ICON); openMenuItem.addActionListener(this); fileMenu.add(openMenuItem); openURLMenuItem = new JMenuItem(tr("MainFrame.Menu.File.OpenURL")); openURLMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_U, InputEvent.CTRL_DOWN_MASK)); openURLMenuItem.setIcon(Utilities.FOLDER_REMOTE_ICON); openURLMenuItem.addActionListener(this); fileMenu.add(openURLMenuItem); fileMenu.addSeparator(); openPlaylistMenuItem = new JMenuItem(tr("MainFrame.Menu.File.OpenPlaylist")); openPlaylistMenuItem.setAccelerator( KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK)); openPlaylistMenuItem.setIcon(Utilities.DOCUMENT_OPEN_ICON); openPlaylistMenuItem.addActionListener(this); fileMenu.add(openPlaylistMenuItem); savePlaylistMenuItem = new JMenuItem(tr("MainFrame.Menu.File.SavePlaylist")); savePlaylistMenuItem.setAccelerator( KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK)); savePlaylistMenuItem.setIcon(Utilities.DOCUMENT_SAVE_ICON); savePlaylistMenuItem.addActionListener(this); fileMenu.add(savePlaylistMenuItem); fileMenu.addSeparator(); preferencesMenuItem = new JMenuItem(tr("MainFrame.Menu.File.Preferences")); preferencesMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_P, InputEvent.CTRL_DOWN_MASK)); preferencesMenuItem.addActionListener(this); fileMenu.add(preferencesMenuItem); fileMenu.addSeparator(); exitMenuItem = new JMenuItem(tr("MainFrame.Menu.File.Exit")); exitMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, InputEvent.CTRL_DOWN_MASK)); exitMenuItem.addActionListener(this); fileMenu.add(exitMenuItem); menuBar.add(fileMenu); // Player Menu String playerMenuStr = tr("MainFrame.Menu.Player"); playerMenu = new JMenu(playerMenuStr); playerMenu.setMnemonic(playerMenuStr.charAt(0)); playPauseMenuItem = new JMenuItem(tr("MainFrame.Menu.Player.Play")); playPauseMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.CTRL_DOWN_MASK)); playPauseMenuItem.addActionListener(this); playerMenu.add(playPauseMenuItem); stopMenuItem = new JMenuItem(tr("MainFrame.Menu.Player.Stop")); stopMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_B, InputEvent.CTRL_DOWN_MASK)); // stopMenuItem.setIcon(Utilities.MEDIA_STOP_ICON); stopMenuItem.setEnabled(false); stopMenuItem.addActionListener(this); playerMenu.add(stopMenuItem); previousMenuItem = new JMenuItem(tr("MainFrame.Menu.Player.Previous")); previousMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_DOWN_MASK)); // previousMenuItem.setIcon(Utilities.MEDIA_PREVIOUS_ICON); previousMenuItem.setEnabled(false); previousMenuItem.addActionListener(this); playerMenu.add(previousMenuItem); nextMenuItem = new JMenuItem(tr("MainFrame.Menu.Player.Next")); nextMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.CTRL_DOWN_MASK)); // nextMenuItem.setIcon(Utilities.MEDIA_NEXT_ICON); nextMenuItem.setEnabled(false); nextMenuItem.addActionListener(this); playerMenu.add(nextMenuItem); playerMenu.addSeparator(); //PlayMode submenu String playModeSubMenuStr = tr("MainFrame.Menu.Player.PlayMode"); playModeSubMenu = new JMenu(playModeSubMenuStr); playModeRepeatNoneMenuItem = new JRadioButtonMenuItem(tr("MainFrame.Menu.Player.PlayMode.RepeatNone")); playModeRepeatNoneMenuItem.setIcon(Utilities.PLAYLIST_REPEAT_NONE_ICON); playModeRepeatNoneMenuItem.addActionListener(this); playModeSubMenu.add(playModeRepeatNoneMenuItem); playModeRepeatOneMenuItem = new JRadioButtonMenuItem(tr("MainFrame.Menu.Player.PlayMode.RepeatOne")); playModeRepeatOneMenuItem.setIcon(Utilities.PLAYLIST_REPEAT_ONE_ICON); playModeRepeatOneMenuItem.addActionListener(this); playModeSubMenu.add(playModeRepeatOneMenuItem); playModeRepeatAllMenuItem = new JRadioButtonMenuItem(tr("MainFrame.Menu.Player.PlayMode.RepeatAll")); playModeRepeatAllMenuItem.setIcon(Utilities.PLAYLIST_REPEAT_ALL_ICON); playModeRepeatAllMenuItem.addActionListener(this); playModeSubMenu.add(playModeRepeatAllMenuItem); playModeShuffleMenuItem = new JRadioButtonMenuItem(tr("MainFrame.Menu.Player.PlayMode.Shuffle")); playModeShuffleMenuItem.setIcon(Utilities.PLAYLIST_SHUFFLE_ICON); playModeShuffleMenuItem.addActionListener(this); playModeSubMenu.add(playModeShuffleMenuItem); ButtonGroup playModeBG = new ButtonGroup(); playModeBG.add(playModeRepeatNoneMenuItem); playModeBG.add(playModeRepeatOneMenuItem); playModeBG.add(playModeRepeatAllMenuItem); playModeBG.add(playModeShuffleMenuItem); playerMenu.add(playModeSubMenu); playerMenu.addSeparator(); randomizePlaylistMenuItem = new JMenuItem(tr("MainFrame.Menu.Player.Randomize")); randomizePlaylistMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.CTRL_DOWN_MASK)); randomizePlaylistMenuItem.setEnabled(false); randomizePlaylistMenuItem.addActionListener(this); playerMenu.add(randomizePlaylistMenuItem); menuBar.add(playerMenu); // View Menu String viewMenuStr = tr("MainFrame.Menu.View"); viewMenu = new JMenu(viewMenuStr); viewMenu.setMnemonic(viewMenuStr.charAt(0)); playlistManagerMenuItem = new JRadioButtonMenuItem(tr("MainFrame.Menu.View.PlaylistManager")); playlistManagerMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_L, InputEvent.CTRL_DOWN_MASK)); playlistManagerMenuItem.addActionListener(this); viewMenu.add(playlistManagerMenuItem); visualizationMenuItem = new JRadioButtonMenuItem(tr("MainFrame.Menu.View.Visualizations")); visualizationMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_K, InputEvent.CTRL_DOWN_MASK)); visualizationMenuItem.addActionListener(this); viewMenu.add(visualizationMenuItem); ButtonGroup viewBG = new ButtonGroup(); viewBG.add(playlistManagerMenuItem); viewBG.add(visualizationMenuItem); menuBar.add(viewMenu); // Help menu String helpMenuStr = tr("MainFrame.Menu.Help"); helpMenu = new JMenu(helpMenuStr); helpMenu.setMnemonic(helpMenuStr.charAt(0)); updateMenuItem = new JMenuItem(tr("MainFrame.Menu.Help.CheckForUpdates")); updateMenuItem.addActionListener(this); helpMenu.add(updateMenuItem); helpMenu.addSeparator(); aboutMenuItem = new JMenuItem(tr("MainFrame.Menu.Help.About")); aboutMenuItem.addActionListener(this); helpMenu.add(aboutMenuItem); menuBar.add(helpMenu); menuBar.add(Box.createHorizontalGlue()); busyLabel = new BusyLabel(new Dimension(20, 20)); menuBar.add(busyLabel); menuBar.add(Box.createHorizontalStrut(8)); mainFrame.setJMenuBar(menuBar); } protected void createPanels() { JPanel framePanel = new JPanel(new MigLayout("fill")); mainPanel = new JPanel(new CardLayout()); playlistManager = new PlaylistManager(this); visualizationManager = new VisualizationManager(audioPlayer.getDSS()); if (Settings.getLastView().equals(Utilities.VISUALIZATION_PANEL)) { visualizationManager.setDssEnabled(true); mainPanel.add(visualizationManager, Utilities.VISUALIZATION_PANEL); mainPanel.add(playlistManager, Utilities.PLAYLIST_MANAGER); visualizationMenuItem.setSelected(true); } else { mainPanel.add(playlistManager, Utilities.PLAYLIST_MANAGER); mainPanel.add(visualizationManager, Utilities.VISUALIZATION_PANEL); playlistManagerMenuItem.setSelected(true); } framePanel.add(mainPanel, "grow"); JPanel southPanel = new JPanel(new MigLayout("fill", "[center]")); SubstanceLookAndFeel.setDecorationType(southPanel, DecorationAreaType.TOOLBAR); seekSlider = new SeekSlider(this); seekSlider.setEnabled(false); southPanel.add(seekSlider, "north, gap 4 4 1 0"); controlPanel = new JPanel(new MigLayout("gap 0, ins 0", "[center]")); controlPanel.setOpaque(false); stopButton = new StopButton(); stopButton.setEnabled(false); stopButton.addActionListener(this); controlPanel.add(stopButton); previousButton = new PreviousButton(); previousButton.setEnabled(false); previousButton.addActionListener(this); controlPanel.add(previousButton); playPauseButton = new PlayPauseButton(); playPauseButton.addActionListener(this); controlPanel.add(playPauseButton, "height pref!"); nextButton = new NextButton(); nextButton.setEnabled(false); nextButton.addActionListener(this); controlPanel.add(nextButton); volumeButton = new VolumeButton(Utilities.MIN_GAIN, Utilities.MAX_GAIN, Settings.getGain(), Settings.isMuted()); volumeButton.addMouseWheelListener((MouseWheelEvent e) -> { try { int volumeValue = volumeSlider.getValue() - 5 * e.getWheelRotation(); int volumeMin = volumeSlider.getMinimum(); int volumeMax = volumeSlider.getMaximum(); if (volumeValue < volumeMin) { volumeValue = volumeMin; } else if (volumeValue > volumeMax) { volumeValue = volumeMax; } volumeButton.setVolumeIcon(volumeValue); volumeSlider.setValue(volumeValue); audioPlayer.setGain(volumeValue / 100.0F); Settings.setGain(volumeValue); } catch (PlayerException ex) { logger.debug(ex.getMessage(), ex); } }); JPopupMenu volumePopupMenu = volumeButton.getPopupMenu(); volumeSlider = new JSlider(JSlider.VERTICAL, Utilities.MIN_GAIN, Utilities.MAX_GAIN, Settings.getGain()); volumeSlider.setMajorTickSpacing(25); volumeSlider.setMinorTickSpacing(5); volumeSlider.setPaintTicks(true); volumeSlider.setPaintLabels(true); volumeSlider.addChangeListener((ChangeEvent e) -> { if (volumeSlider.getValueIsAdjusting()) { try { int volumeValue = volumeSlider.getValue(); volumeButton.setVolumeIcon(volumeValue); audioPlayer.setGain(volumeValue / 100.0F); Settings.setGain(volumeValue); } catch (PlayerException ex) { logger.debug(ex.getMessage(), ex); } } }); volumeSlider.setEnabled(!Settings.isMuted()); JPanel volumePanel = new JPanel(new MigLayout("fill")); JLabel volumeLabel = new JLabel(tr("MainFrame.Menu.Player.Volume"), JLabel.CENTER); volumeLabel.setFont(volumeLabel.getFont().deriveFont(Font.BOLD)); volumePanel.add(volumeLabel, "north"); volumePanel.add(volumeSlider); JCheckBox muteCheckBox = new JCheckBox(tr("MainFrame.Menu.Player.Mute")); muteCheckBox.setSelected(Settings.isMuted()); muteCheckBox.addItemListener((ItemEvent e) -> { try { if (e.getStateChange() == ItemEvent.SELECTED) { volumeSlider.setEnabled(false); volumeButton.setVolumeMutedIcon(); audioPlayer.setMuted(true); Settings.setMuted(true); } else { volumeSlider.setEnabled(true); volumeButton.setVolumeIcon(Settings.getGain()); audioPlayer.setMuted(false); Settings.setMuted(false); } } catch (PlayerException ex) { logger.debug(ex.getMessage(), ex); } }); volumePanel.add(muteCheckBox, "south"); volumePopupMenu.add(volumePanel); controlPanel.add(volumeButton); southPanel.add(controlPanel, "gap 0 0 2 5"); JPanel statusBar = new JPanel(new MigLayout("ins 2 0 2 0")); SubstanceLookAndFeel.setDecorationType(statusBar, DecorationAreaType.FOOTER); timeLabel = new JLabel(Utilities.ZERO_TIMER); timeLabel.setFont(timeLabel.getFont().deriveFont(Font.BOLD)); statusBar.add(timeLabel, "gap 6 6 0 0, west"); statusBar.add(new JSeparator(SwingConstants.VERTICAL), "hmin 16"); statusLabel = new JLabel(); statusBar.add(statusLabel, "gap 0 2 0 0, wmin 0, push"); statusBar.add(new JSeparator(SwingConstants.VERTICAL), "hmin 16"); playModeLabel = new JLabel(); playModeLabel.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { Playlist.PlayMode[] playModes = Playlist.PlayMode.values(); Playlist.PlayMode playMode = playlist.getPlayMode(); int ordinal = playMode.ordinal(); playlist.setPlayMode(playModes[(ordinal == playModes.length - 1) ? 0 : ordinal + 1]); } }); statusBar.add(playModeLabel, "east, gap 2 2 2 2, width 18!, height 18!"); southPanel.add(statusBar, "south"); framePanel.add(southPanel, "south"); mainFrame.setContentPane(framePanel); } protected void addToPlaylistAndPlay(List<PlaylistItem> pliList) { playlistManager.clearPlaylist(); playlistManager.add(pliList); playlist.begin(); acOpenAndPlay(); } protected void setStatus(String text) { final String status = (text != null) ? text : ""; if (EventQueue.isDispatchThread()) { statusLabel.setText(status); } else { EventQueue.invokeLater(() -> { statusLabel.setText(status); }); } } protected void enableControlButtons(boolean flag) { previousButton.setEnabled(flag); previousMenuItem.setEnabled(flag); nextButton.setEnabled(flag); nextMenuItem.setEnabled(flag); randomizePlaylistMenuItem.setEnabled(flag); } @Override public void actionPerformed(ActionEvent e) { Object source = e.getSource(); if (source == openMenuItem) { playlistManager.addFilesDialog(true); } else if (source == openURLMenuItem) { String url = JOptionPane.showInputDialog(mainFrame, tr("Dialog.OpenURL.Message"), tr("Dialog.OpenURL"), JOptionPane.INFORMATION_MESSAGE); if (url != null && Utilities.startWithProtocol(url)) { boolean isPlaylistFile = false; for (String ext : PlaylistFileFilter.PlaylistFileExt) { if (url.endsWith(ext)) { isPlaylistFile = true; } } if (isPlaylistFile) { playlistManager.clearPlaylist(); playlistManager.loadPlaylist(url); playlist.begin(); } else { PlaylistItem newPli = new PlaylistItem(url, url, -1, false); playlistManager.add(newPli); playlist.setCursor(newPli); } acOpenAndPlay(); } } else if (source == openPlaylistMenuItem) { playlistManager.openPlaylistDialog(); } else if (source == savePlaylistMenuItem) { playlistManager.savePlaylistDialog(); } else if (source == preferencesMenuItem) { PreferencesDialog preferencesDialog = new PreferencesDialog(audioPlayer, this); preferencesDialog.setVisible(true); } else if (source == exitMenuItem) { exit(); } else if (source == playPauseMenuItem || source == playPauseButton) { acPlayPause(); } else if (source == previousMenuItem || source == previousButton) { acPrevious(); } else if (source == nextMenuItem || source == nextButton) { acNext(); } else if (source == randomizePlaylistMenuItem) { playlistManager.randomizePlaylist(); } else if (source == stopMenuItem || source == stopButton) { acStop(); } else if (source == playlistManagerMenuItem) { if (visualizationManager.isVisible()) { visualizationManager.setDssEnabled(false); CardLayout cardLayout = (CardLayout) (mainPanel.getLayout()); cardLayout.show(mainPanel, Utilities.PLAYLIST_MANAGER); playlistManagerMenuItem.setSelected(true); Settings.setLastView(Utilities.PLAYLIST_MANAGER); } } else if (source == visualizationMenuItem) { if (playlistManager.isVisible()) { visualizationManager.setDssEnabled(true); CardLayout cardLayout = (CardLayout) (mainPanel.getLayout()); cardLayout.show(mainPanel, Utilities.VISUALIZATION_PANEL); visualizationMenuItem.setSelected(true); Settings.setLastView(Utilities.VISUALIZATION_PANEL); } } else if (source == updateMenuItem) { SoftwareUpdate.checkForUpdates(true); SoftwareUpdate.showCheckForUpdatesDialog(); } else if (source == aboutMenuItem) { Object[] options = { tr("Button.Close") }; Desktop desktop = null; if (Desktop.isDesktopSupported()) { desktop = Desktop.getDesktop(); if (desktop.isSupported(Desktop.Action.BROWSE)) { options = new Object[] { tr("Button.Close"), tr("Button.Website") }; } } StringBuffer message = new StringBuffer(); message.append("<html><b><font color='red' size='5'>").append(tr("Application.title")); message.append("</font></b><br>").append(tr("Application.description")); message.append("<br>Copyright 2005-2014 The Xtreme Media Player Project"); message.append("<br><br><b>").append(tr("Dialog.About.Authors")).append(": </b>") .append(tr("Application.authors")); message.append("<br><b>").append(tr("Dialog.About.Version")).append(": </b>").append(currentVersion); message.append("<br><b>").append(tr("Dialog.About.Codename")).append(": </b>") .append(currentVersion.getCodename()); message.append("<br><b>").append(tr("Dialog.About.ReleaseDate")).append(": </b>") .append(currentVersion.getReleaseDate()); message.append("<br><b>").append(tr("Dialog.About.Homepage")).append(": </b>") .append(tr("Application.homepage")); message.append("<br><br><b>").append(tr("Dialog.About.JavaVersion")).append(": </b>") .append(System.getProperty("java.version")); message.append("<br><b>").append(tr("Dialog.About.JavaVendor")).append(": </b>") .append(System.getProperty("java.vendor")); message.append("<br><b>").append(tr("Dialog.About.JavaHome")).append(": </b>") .append(System.getProperty("java.home")); message.append("<br><b>").append(tr("Dialog.About.OSName")).append(": </b>") .append(System.getProperty("os.name")); message.append("<br><b>").append(tr("Dialog.About.OSArch")).append(": </b>") .append(System.getProperty("os.arch")); message.append("<br><b>").append(tr("Dialog.About.UserName")).append(": </b>") .append(System.getProperty("user.name")); message.append("<br><b>").append(tr("Dialog.About.UserHome")).append(": </b>") .append(System.getProperty("user.home")); message.append("<br><b>").append(tr("Dialog.About.UserDir")).append(": </b>") .append(System.getProperty("user.dir")); message.append("</html>"); int n = JOptionPane.showOptionDialog(mainFrame, message, tr("Dialog.About"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, Utilities.APP_256_ICON, options, options[0]); if (n == 1 && desktop != null) { try { URL url = new URL(tr("Application.homepage")); desktop.browse(url.toURI()); } catch (IOException | URISyntaxException ex) { logger.error(ex.getMessage(), ex); } } } else if (source.equals(playModeRepeatNoneMenuItem)) { playlist.setPlayMode(Playlist.PlayMode.REPEAT_NONE); } else if (source.equals(playModeRepeatOneMenuItem)) { playlist.setPlayMode(Playlist.PlayMode.REPEAT_ONE); } else if (source.equals(playModeRepeatAllMenuItem)) { playlist.setPlayMode(Playlist.PlayMode.REPEAT_ALL); } else if (source.equals(playModeShuffleMenuItem)) { playlist.setPlayMode(Playlist.PlayMode.SHUFFLE); } } @Override public void playbackBuffering(PlaybackEvent pe) { setStatus(tr("MainFrame.StatusBar.Buffering")); } @Override public void playbackOpened(PlaybackEvent pe) { try { audioPlayer.setGain(Settings.getGain() / 100.0F); audioPlayer.setMuted(Settings.isMuted()); } catch (PlayerException ex) { logger.error(ex.getMessage(), ex); } finally { if (currentPli != null) { if (!currentPli.isFile()) { currentPli.getTagInfo(); } setStatus(currentPli.getFormattedName()); } } EventQueue.invokeLater(() -> { stopButton.setEnabled(true); stopMenuItem.setEnabled(true); }); } @Override public void playbackEndOfMedia(PlaybackEvent pe) { if (playlist.isEmpty()) { acStop(); } else { switch (playlist.getPlayMode()) { case REPEAT_NONE: if (playlist.getCursorPosition() == playlist.size() - 1) { acStop(); } else { acNext(); } break; case REPEAT_ONE: acStop(); acPlayPause(); break; case REPEAT_ALL: acNext(); break; case SHUFFLE: acNext(); break; } } } @Override public void playbackPlaying(PlaybackEvent pe) { EventQueue.invokeLater(() -> { playPauseButton.setPauseIcon(); playPauseMenuItem.setText(tr("MainFrame.Menu.Player.Pause")); }); } @Override public void playbackProgress(PlaybackEvent pe) { if (currentPli != null && !seekSlider.getValueIsAdjusting() && !seekSlider.isPressed() && mainFrame.isVisible()) { acUpdateTime(seekSlider.getOldValue() + Math.round(pe.getPosition() / 1000F)); // Shoutcast stream title. Map properties = pe.getProperties(); String streamTitleKey = "mp3.shoutcast.metadata.StreamTitle"; if (!currentPli.isFile() && properties.containsKey(streamTitleKey)) { String streamTitle = ((String) properties.get(streamTitleKey)).trim(); TagInfo tagInfo = currentPli.getTagInfo(); if (!streamTitle.isEmpty() && (tagInfo != null)) { String sTitle = Utilities.isNullOrEmpty(tagInfo.getTitle()) ? "" : " (" + tagInfo.getTitle() + ")"; if (!currentPli.getFormattedName().equals(streamTitle + sTitle)) { currentPli.setFormattedName(streamTitle + sTitle); EventQueue.invokeLater(() -> { playlistManager.refreshRow(playlist.indexOf(currentPli)); setStatus(currentPli.getFormattedName()); }); } } } } } @Override public void playbackPaused(PlaybackEvent pe) { EventQueue.invokeLater(() -> { playPauseButton.setPlayIcon(); playPauseMenuItem.setText(tr("MainFrame.Menu.Player.Play")); }); } @Override public void playbackStopped(PlaybackEvent pe) { currentPli = null; EventQueue.invokeLater(() -> { playPauseButton.setPlayIcon(); stopButton.setEnabled(false); playPauseMenuItem.setText(tr("MainFrame.Menu.Player.Play")); stopMenuItem.setEnabled(false); acUpdateTime(0); statusLabel.setText(""); }); } @Override public void acOpen() { PlayerLauncher playerLauncher = new PlayerLauncher(false); playerLauncher.execute(); } @Override public void acOpenAndPlay() { PlayerLauncher playerLauncher = new PlayerLauncher(true); playerLauncher.execute(); } @Override public void acPrevious() { if (!playlist.isEmpty()) { playlist.previousCursor(); acOpenAndPlay(); } } @Override public void acNext() { if (!playlist.isEmpty()) { playlist.nextCursor(); acOpenAndPlay(); } } @Override public void acPlayPause() { try { if (playlist.isEmpty()) { if ((audioPlayer.getState() == AudioSystem.NOT_SPECIFIED) || (audioPlayer.getState() == AudioPlayer.STOP)) { playlistManager.addFilesDialog(true); } } else { if ((audioPlayer.getState() != AudioPlayer.PLAY) && (audioPlayer.getState() != AudioPlayer.PAUSE) && (playlist.getCursorPosition() == -1)) { playlist.begin(); } } switch (audioPlayer.getState()) { case AudioPlayer.PLAY: audioPlayer.pause(); break; case AudioPlayer.INIT: audioPlayer.play(); break; case AudioPlayer.PAUSE: audioPlayer.play(); break; default: acOpenAndPlay(); break; } } catch (PlayerException ex) { logger.error(ex.getMessage()); // String msg = "<html><b>An exeption was generated:</b><br><br>" + ex.getMessage() + "<html>"; // JOptionPane.showMessageDialog(mainFrame, msg, "Error", JOptionPane.ERROR_MESSAGE); } } @Override public void acStop() { audioPlayer.stop(); } @Override public void acUpdateTime(int value) { StringBuilder timeText = new StringBuilder(); if (currentPli != null) { String formattedLength = currentPli.getFormattedLength(); long duration = TimeUnit.MILLISECONDS.toSeconds(value); if (Utilities.isNullOrEmpty(formattedLength)) { timeText.append(currentPli.getFormattedLength(duration)); } else { timeText.append(currentPli.getFormattedLength(duration)); timeText.append(" / "); timeText.append(formattedLength); } } else { timeText.append(Utilities.ZERO_TIMER); } final String timeStr = timeText.toString(); final int seekValue = (currentPli == null) ? 0 : value; if (EventQueue.isDispatchThread()) { seekSlider.setValue(seekValue); timeLabel.setText(timeStr); } else { EventQueue.invokeLater(() -> { seekSlider.setValue(seekValue); timeLabel.setText(timeStr); }); } } @Override public void acSeek() { try { if (seekSlider.isEnabled()) { audioPlayer.seek(Math.round( audioPlayer.getByteLength() * (double) seekSlider.getValue() / seekSlider.getMaximum())); } } catch (PlayerException ex) { logger.error(ex.getMessage(), ex); } } @Override public void playlistItemAdded(PlaylistEvent e) { if (!playlist.isEmpty() && !previousButton.isEnabled()) { enableControlButtons(true); } } @Override public void playlistItemRemoved(PlaylistEvent e) { if (playlist.isEmpty()) { if (audioPlayer.getState() != AudioPlayer.PLAY && audioPlayer.getState() != AudioPlayer.PAUSE) { audioPlayer.stop(); } enableControlButtons(false); } } @Override public void playModeChanged(PlaylistEvent e) { Playlist.PlayMode playMode = playlist.getPlayMode(); Settings.setPlayMode(playMode); StringBuilder toolTipMessage = new StringBuilder("<html><b>"); toolTipMessage.append(tr("MainFrame.Menu.Player.PlayMode")); toolTipMessage.append("</b><br>"); switch (playMode) { case REPEAT_NONE: playModeLabel.setIcon(Utilities.PLAYLIST_REPEAT_NONE_ICON); playModeRepeatNoneMenuItem.setSelected(true); toolTipMessage.append(tr("MainFrame.Menu.Player.PlayMode.RepeatNone")); break; case REPEAT_ONE: playModeLabel.setIcon(Utilities.PLAYLIST_REPEAT_ONE_ICON); playModeRepeatOneMenuItem.setSelected(true); toolTipMessage.append(tr("MainFrame.Menu.Player.PlayMode.RepeatOne")); break; case REPEAT_ALL: playModeLabel.setIcon(Utilities.PLAYLIST_REPEAT_ALL_ICON); playModeRepeatAllMenuItem.setSelected(true); toolTipMessage.append(tr("MainFrame.Menu.Player.PlayMode.RepeatAll")); break; case SHUFFLE: playModeLabel.setIcon(Utilities.PLAYLIST_SHUFFLE_ICON); playModeShuffleMenuItem.setSelected(true); toolTipMessage.append(tr("MainFrame.Menu.Player.PlayMode.Shuffle")); break; default: playModeLabel.setIcon(null); } toolTipMessage.append("</html>"); playModeLabel.setToolTipText(toolTipMessage.toString()); } @Override public void onIntellitype(int command) { switch (command) { case JIntellitype.APPCOMMAND_MEDIA_PLAY_PAUSE: logger.debug("APPCOMMAND_MEDIA_PLAY_PAUSE command received: " + Integer.toString(command)); acPlayPause(); break; case JIntellitype.APPCOMMAND_MEDIA_PREVIOUSTRACK: logger.debug("APPCOMMAND_MEDIA_PREVIOUSTRACK command received: " + Integer.toString(command)); acPrevious(); break; case JIntellitype.APPCOMMAND_MEDIA_NEXTTRACK: logger.debug("APPCOMMAND_MEDIA_NEXTTRACK command received: " + Integer.toString(command)); acNext(); break; case JIntellitype.APPCOMMAND_MEDIA_STOP: logger.debug("APPCOMMAND_MEDIA_STOP command received: " + Integer.toString(command)); acStop(); break; default: logger.debug("Undefined INTELLITYPE command received: " + Integer.toString(command)); break; } } @Override public void guiEffectsStateChanged(boolean flag) { if (flag) { // AnimationConfigurationManager.getInstance().allowAnimations(AnimationFacet.ARM); // AnimationConfigurationManager.getInstance().allowAnimations(AnimationFacet.FOCUS); // AnimationConfigurationManager.getInstance().allowAnimations(AnimationFacet.FOCUS_LOOP_ANIMATION); AnimationConfigurationManager.getInstance().allowAnimations(AnimationFacet.GHOSTING_BUTTON_PRESS); AnimationConfigurationManager.getInstance().allowAnimations(AnimationFacet.GHOSTING_ICON_ROLLOVER); AnimationConfigurationManager.getInstance().allowAnimations(AnimationFacet.ICON_GLOW); // AnimationConfigurationManager.getInstance().allowAnimations(AnimationFacet.PRESS); // AnimationConfigurationManager.getInstance().allowAnimations(AnimationFacet.ROLLOVER); // AnimationConfigurationManager.getInstance().allowAnimations(AnimationFacet.SELECTION); } else { // AnimationConfigurationManager.getInstance().disallowAnimations(AnimationFacet.ARM); // AnimationConfigurationManager.getInstance().disallowAnimations(AnimationFacet.FOCUS); // AnimationConfigurationManager.getInstance().disallowAnimations(AnimationFacet.FOCUS_LOOP_ANIMATION); AnimationConfigurationManager.getInstance().disallowAnimations(AnimationFacet.GHOSTING_BUTTON_PRESS); AnimationConfigurationManager.getInstance().disallowAnimations(AnimationFacet.GHOSTING_ICON_ROLLOVER); AnimationConfigurationManager.getInstance().disallowAnimations(AnimationFacet.ICON_GLOW); // AnimationConfigurationManager.getInstance().disallowAnimations(AnimationFacet.PRESS); // AnimationConfigurationManager.getInstance().disallowAnimations(AnimationFacet.ROLLOVER); // AnimationConfigurationManager.getInstance().disallowAnimations(AnimationFacet.SELECTION); } } private class PlayerLauncher extends AbstractSwingWorker<Boolean, Void> { private boolean play = false; private boolean isFile = false; private int duration = -1; public PlayerLauncher(boolean play) { this.play = play; } @Override protected Boolean doInBackground() throws PlayerException, MalformedURLException { PlaylistItem pli = playlist.getCursor(); if (pli != null) { currentPli = pli; isFile = pli.isFile(); if (isFile) { audioPlayer.open(new File(pli.getLocation())); duration = Math.round(audioPlayer.getDuration() / 1000); } else { audioPlayer.open(new URL(pli.getLocation())); } if (play) { audioPlayer.play(); } return Boolean.TRUE; } currentPli = null; return Boolean.FALSE; } @Override protected void done() { if (currentPli != null) { try { if (get()) { seekSlider.reset(); playlistManager.colorizeRow(); if (isFile) { if (duration > 0) { seekSlider.setMaximum(duration); seekSlider.setEnabled(true); } else { seekSlider.setMaximum((int) (currentPli.getDuration() * 1000)); seekSlider.setEnabled(false); } } else { seekSlider.setEnabled(false); } } } catch (InterruptedException | ExecutionException ex) { if (ex.getCause() instanceof PlayerException) { acStop(); setStatus("An error occurred..."); logger.error(ex.getMessage(), ex); if (ex.getCause().getCause() instanceof FileNotFoundException) { String msg = "<html><b>" + currentPli.getFormattedLength() + "</b> could not be used<br>because the original file could not be found.<html>"; JOptionPane.showMessageDialog(mainFrame, msg, "Message", JOptionPane.ERROR_MESSAGE); } // String msg = "<html><b>An exeption was generated:</b><br><br>" + ex.getMessage() + "<html>"; // JOptionPane.showMessageDialog(mainFrame, msg, "Error", JOptionPane.ERROR_MESSAGE); } } } } } }