diff --git a/interface/src/main/java/edu/regis/universeplayer/player/Collections.java b/interface/src/main/java/edu/regis/universeplayer/player/Collections.java index 3961711..2668d8f 100644 --- a/interface/src/main/java/edu/regis/universeplayer/player/Collections.java +++ b/interface/src/main/java/edu/regis/universeplayer/player/Collections.java @@ -45,37 +45,15 @@ public class Collections extends JPanel this.setFocusable(true); this.setFocusCycleRoot(true); - this.add(defaultLabel = label = this.createButton(langs.getString("collections.all"))); - label.setMnemonic('A'); - label.addActionListener(mouseEvent -> this - .triggerSongDisplayListeners(new ArrayList<>(SongProvider.INSTANCE.getSongs()))); - this.add(label = this.createButton(langs.getString("collections.artists"))); - label.setMnemonic('T'); - label.addActionListener(mouseEvent -> this - .triggerCollectionDisplayListeners(CollectionType.albumArtist, SongProvider.INSTANCE - .getAlbumArtists())); - this.add(label = this.createButton(langs.getString("collections.albums"))); - label.setMnemonic('B'); - label.addActionListener(mouseEvent -> this - .triggerCollectionDisplayListeners(CollectionType.album, SongProvider.INSTANCE - .getAlbums())); - this.add(label = this.createButton(langs.getString("collections.genres"))); - label.setMnemonic('G'); - label.addActionListener(mouseEvent -> this - .triggerCollectionDisplayListeners(CollectionType.genre, SongProvider.INSTANCE - .getGenres())); - this.add(label = this.createButton(langs.getString("collections.years"))); - label.setMnemonic('Y'); - label.addActionListener(mouseEvent -> this - .triggerCollectionDisplayListeners(CollectionType.year, SongProvider.INSTANCE - .getYears())); + this.add(defaultLabel = label = this.createButton(Interface.getInstance().actions.get("view.all"))); + this.add(label = this.createButton(Interface.getInstance().actions.get("view.artists"))); + this.add(label = this.createButton(Interface.getInstance().actions.get("view.albums"))); + this.add(label = this.createButton(Interface.getInstance().actions.get("view.genres"))); + this.add(label = this.createButton(Interface.getInstance().actions.get("view.years"))); this.add(new JLabel("\u23AF".repeat(6))); - this.add(label = this.createButton(langs.getString("collections.playlists"))); - label.setMnemonic('P'); + this.add(label = this.createButton(Interface.getInstance().actions.get("view.playlists"))); this.add(new JLabel("\u23AF".repeat(6))); - this.add(label = this.createButton(langs.getString("actions.external.add.title"))); - label.setMnemonic('E'); - label.addActionListener(mouseEvent -> this.addNewSong()); + this.add(label = this.createButton(Interface.getInstance().actions.get("addExternal"))); addMouseListener(new MouseAdapter() { @@ -123,7 +101,16 @@ public class Collections extends JPanel private JButton createButton(String text) { - JButton label = new JButton(text); + return setButton(new JButton(text)); + } + + private JButton createButton(Action action) + { + return setButton(new JButton(action)); + } + + private JButton setButton(JButton label) + { label.setFocusPainted(true); label.setMargin(new Insets(0, 0, 0, 0)); label.setContentAreaFilled(false); diff --git a/interface/src/main/java/edu/regis/universeplayer/player/Interface.java b/interface/src/main/java/edu/regis/universeplayer/player/Interface.java index 8e33fb8..b5e24e2 100644 --- a/interface/src/main/java/edu/regis/universeplayer/player/Interface.java +++ b/interface/src/main/java/edu/regis/universeplayer/player/Interface.java @@ -13,10 +13,12 @@ import edu.regis.universeplayer.data.*; import edu.regis.universeplayer.localPlayer.LocalPlayer; import net.harawata.appdirs.AppDirsFactory; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.swing.*; + import java.awt.*; import java.awt.event.*; import java.io.File; @@ -35,16 +37,21 @@ import java.util.Set; */ public class Interface extends JFrame implements SongDisplayListener, ComponentListener, WindowListener, UpdateListener, FocusListener { -// static { + // static { // Locale.setDefault(new Locale("es", "ES")); // } private static final Logger logger = LoggerFactory.getLogger(Interface.class); - private static final ResourceBundle langs = ResourceBundle.getBundle("lang.interface", Locale.getDefault()); - + private static final ResourceBundle langs = ResourceBundle + .getBundle("lang.interface", Locale.getDefault()); + + private static Interface INSTANCE; + private static File dataDir; private static File commDir; private static File configDir; - + + public final ActionMap actions = new ActionMap(); + /** * A reference to the panel containing links to different collection views. */ @@ -69,13 +76,18 @@ public class Interface extends JFrame implements SongDisplayListener, ComponentL * A reference to the player controls pane. */ private final PlayerControls controls; - + /** * A link to the browser. */ private final ArrayList> players = new ArrayList<>(); private int currentPlayer = -1; - + + public static Interface getInstance() + { + return INSTANCE; + } + public static void main(String[] args) { Thread browserThread; @@ -90,18 +102,18 @@ public class Interface extends JFrame implements SongDisplayListener, ComponentL * otherwise. */ logger.info("Starting application"); - - browser = Browser.createBrowser(); - browserThread = new Thread(browser); - browserThread.start(); - + inter = new Interface(); inter.setSize(700, 500); SongProvider.INSTANCE.addUpdateListener(inter); inter.setVisible(true); + browser = Browser.createBrowser(); + browserThread = new Thread(browser); + browserThread.start(); + Player.REGISTERED_PLAYERS.put(LocalSong.class, new LocalPlayer()); - + try { inter.players.add(browserPlayer = new BrowserPlayer()); @@ -109,7 +121,7 @@ public class Interface extends JFrame implements SongDisplayListener, ComponentL browser.sendObject("ping"); Runtime.getRuntime().addShutdownHook(new Thread(browserPlayer::close)); Player.REGISTERED_PLAYERS.put(InternetSong.class, browserPlayer); - + // LinkedList> pingRequests = new LinkedList<>(); // for (int i = 0; i < 20; i++) // { @@ -135,26 +147,31 @@ public class Interface extends JFrame implements SongDisplayListener, ComponentL catch (IOException e) { logger.error("Could not open browser background", e); - JOptionPane.showMessageDialog(inter, e, langs.getString("error.browser.launch"), JOptionPane.ERROR_MESSAGE); + JOptionPane.showMessageDialog(inter, e, langs + .getString("error.browser.launch"), JOptionPane.ERROR_MESSAGE); } } catch (Throwable e) { logger.error("Could not open browser background", e); - JOptionPane.showMessageDialog(inter != null && inter.isVisible() ? inter : null, e, langs.getString("error.generic"), JOptionPane.ERROR_MESSAGE); + JOptionPane + .showMessageDialog(inter != null && inter.isVisible() ? inter : null, e, langs + .getString("error.generic"), JOptionPane.ERROR_MESSAGE); } } - + /** * Obtains the data storage directory for the application, creating it if * needed. + * * @return The data storage directory. */ public static File getDataDir() { if (dataDir == null) { - dataDir = new File(AppDirsFactory.getInstance().getUserDataDir("universalmusic", null, null, true)); + dataDir = new File(AppDirsFactory.getInstance() + .getUserDataDir("universalmusic", null, null, true)); if (!dataDir.exists()) { if (!dataDir.mkdir()) @@ -165,17 +182,19 @@ public class Interface extends JFrame implements SongDisplayListener, ComponentL } return dataDir; } - + /** * Obtains the configuration directory for the application, creating it if * needed. + * * @return The configuration directory. */ public static File getConfigDir() { if (configDir == null) { - configDir = new File(AppDirsFactory.getInstance().getUserConfigDir("universalmusic", null, null, true)); + configDir = new File(AppDirsFactory.getInstance() + .getUserConfigDir("universalmusic", null, null, true)); if (!configDir.exists()) { if (!configDir.mkdir()) @@ -186,16 +205,18 @@ public class Interface extends JFrame implements SongDisplayListener, ComponentL } return configDir; } - + /** * Obtains the directory for memory mapped files + * * @return The communications storage directory. */ public static File getCommDir() { if (commDir == null) { - commDir = new File(AppDirsFactory.getInstance().getSharedDir("universalmusic", null, null), "comm"); + commDir = new File(AppDirsFactory.getInstance() + .getSharedDir("universalmusic", null, null), "comm"); if (!commDir.getParentFile().exists()) { if (!commDir.getParentFile().mkdir()) @@ -213,57 +234,385 @@ public class Interface extends JFrame implements SongDisplayListener, ComponentL } return commDir; } - + /** * Creates an interface */ public Interface() { super(); - + INSTANCE = this; + + this.initActions(); + + this.collectionTypes = new Collections(); + this.controls = new PlayerControls(); + this.queueList = new QueueList(); + this.songList = new SongList(); + this.collectionList = new CollectionList(); + this.centerView = new JScrollPane(this.songList); + + this.constructWindow(); + this.setFocusManager(); + + this.updateSongs(SongProvider.INSTANCE.getSongs()); + } + + protected void initActions() + { + AbstractAction action; + + this.actions.put("refresh", action = new AbstractAction(langs.getString("actions.refresh")) + { + @Override + public void actionPerformed(ActionEvent e) + { + if (this.isEnabled()) + { + + } + } + }); + action.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_R); + + this.actions.put("addExternal", action = new AbstractAction(langs + .getString("actions.addExternal")) + { + @Override + public void actionPerformed(ActionEvent e) + { + if (this.isEnabled()) + { + InternetSongDialog dialog = new InternetSongDialog(Interface.this); + dialog.addWindowListener(new WindowAdapter() + { + /** + * Invoked when a window has been closed. + * + * @param e + */ + @Override + public void windowClosed(WindowEvent e) + { + } + }); + dialog.setVisible(true); + } + } + }); + action.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_E); + + this.actions.put("exit", action = new AbstractAction(langs.getString("actions.exit")) + { + @Override + public void actionPerformed(ActionEvent e) + { + if (this.isEnabled()) + { + Interface.this + .dispatchEvent(new WindowEvent(Interface.this, WindowEvent.WINDOW_CLOSING)); + } + } + }); + action.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_X); + + this.actions.put("logs", action = new AbstractAction(langs.getString("actions.logs")) + { + @Override + public void actionPerformed(ActionEvent e) + { + if (this.isEnabled()) + { + + } + } + }); + + this.actions.put("about", action = new AbstractAction(langs.getString("actions.about")) + { + @Override + public void actionPerformed(ActionEvent e) + { + if (this.isEnabled()) + { + + } + } + }); + + this.actions + .put("view.all", action = new AbstractAction(langs.getString("actions.view.all")) + { + @Override + public void actionPerformed(ActionEvent e) + { + if (this.isEnabled()) + { + collectionTypes + .triggerSongDisplayListeners(new ArrayList<>(SongProvider.INSTANCE + .getSongs())); + } + } + }); + action.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_A); + + this.actions.put("view.artists", action = new AbstractAction(langs + .getString("actions.view.artists")) + { + @Override + public void actionPerformed(ActionEvent e) + { + if (this.isEnabled()) + { + collectionTypes + .triggerCollectionDisplayListeners(CollectionType.albumArtist, SongProvider.INSTANCE + .getAlbumArtists()); + } + } + }); + action.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_T); + + this.actions.put("view.albums", action = new AbstractAction(langs + .getString("actions.view.albums")) + { + @Override + public void actionPerformed(ActionEvent e) + { + if (this.isEnabled()) + { + collectionTypes + .triggerCollectionDisplayListeners(CollectionType.album, SongProvider.INSTANCE + .getAlbums()); + } + } + }); + action.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_B); + + this.actions.put("view.genres", action = new AbstractAction(langs + .getString("actions.view.genres")) + { + @Override + public void actionPerformed(ActionEvent e) + { + if (this.isEnabled()) + { + collectionTypes + .triggerCollectionDisplayListeners(CollectionType.genre, SongProvider.INSTANCE + .getGenres()); + } + } + }); + action.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_G); + + this.actions.put("view.years", action = new AbstractAction(langs + .getString("actions.view.years")) + { + @Override + public void actionPerformed(ActionEvent e) + { + if (this.isEnabled()) + { + collectionTypes + .triggerCollectionDisplayListeners(CollectionType.year, SongProvider.INSTANCE + .getYears()); + } + } + }); + action.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_Y); + + this.actions.put("view.playlists", action = new AbstractAction(langs + .getString("actions.view.playlists")) + { + @Override + public void actionPerformed(ActionEvent e) + { + if (this.isEnabled()) + { + + } + } + }); + action.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_L); + + this.actions.put("playback.clear", action = new AbstractAction(langs + .getString("actions.playback.clear")) + { + @Override + public void actionPerformed(ActionEvent e) + { + if (this.isEnabled()) + { + Queue.getInstance().clear(); + } + } + }); + action.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_R); + + this.actions.put("playback.play", action = new AbstractAction(langs + .getString("actions.playback.play")) + { + @Override + public void actionPerformed(ActionEvent e) + { + if (this.isEnabled()) + { + controls.play(); + } + } + }); + + this.actions.put("playback.pause", action = new AbstractAction(langs + .getString("actions.playback.pause")) + { + @Override + public void actionPerformed(ActionEvent e) + { + if (this.isEnabled()) + { + controls.pause(); + } + } + }); + + this.actions.put("playback.toggle", action = new AbstractAction(langs + .getString("actions.playback.toggle")) + { + @Override + public void actionPerformed(ActionEvent e) + { + if (this.isEnabled()) + { + controls.togglePlayback(); + } + } + }); + + this.actions.put("playback.skipPrev", action = new AbstractAction(langs + .getString("actions.playback.skipPrev")) + { + @Override + public void actionPerformed(ActionEvent e) + { + if (this.isEnabled()) + { + controls.previousSong(); + } + } + }); + + this.actions.put("playback.skipNext", action = new AbstractAction(langs + .getString("actions.playback.skipNext")) + { + @Override + public void actionPerformed(ActionEvent e) + { + if (this.isEnabled()) + { + controls.nextSong(); + } + } + }); + } + + protected void constructWindow() + { + JMenuBar toolbar; + JMenu fileMenu, viewMenu, collectionsMenu, playbackMenu, helpMenu; + this.setTitle(langs.getString("title")); this.getContentPane().setLayout(new BorderLayout()); this.setFocusable(true); this.setFocusCycleRoot(true); - + this.getContentPane() - .add(this.collectionTypes = new Collections(), BorderLayout.LINE_START); + .add(this.collectionTypes, BorderLayout.LINE_START); this.collectionTypes.addFocusListener(this); this.collectionTypes.addSongDisplayListener(this); - - this.controls = new PlayerControls(); + this.controls.addFocusListener(this); this.getContentPane().add(controls, BorderLayout.PAGE_END); - - this.queueList = new QueueList(); + this.queueList.addFocusListener(this); Queue.getInstance().addQueueChangeListener(this.queueList); Queue.getInstance().addSongChangeListener(this.queueList); this.getContentPane().add(queueList, BorderLayout.LINE_END); - - this.songList = new SongList(); + this.songList.addFocusListener(this); - this.collectionList = new CollectionList(); this.collectionList.addSongDisplayListener(this); - - this.centerView = new JScrollPane(this.songList); + this.getContentPane().add(this.centerView, BorderLayout.CENTER); this.componentResized(null); - + + toolbar = new JMenuBar(); + + fileMenu = new JMenu(langs.getString("menu.file.title")); + fileMenu.setMnemonic(KeyEvent.VK_F); + toolbar.add(fileMenu); + + viewMenu = new JMenu(langs.getString("menu.view.title")); + viewMenu.setMnemonic(KeyEvent.VK_V); + toolbar.add(viewMenu); + + collectionsMenu = new JMenu(langs.getString("menu.view.collections")); + collectionsMenu.setMnemonic(KeyEvent.VK_C); + viewMenu.add(collectionsMenu); + + playbackMenu = new JMenu(langs.getString("menu.playback.title")); + playbackMenu.setMnemonic(KeyEvent.VK_P); + toolbar.add(playbackMenu); + + helpMenu = new JMenu(langs.getString("menu.help.title")); + helpMenu.setMnemonic(KeyEvent.VK_H); + toolbar.add(helpMenu); + + fileMenu.add(new JMenuItem(actions.get("refresh"))); + + fileMenu.add(actions.get("addExternal")); + + fileMenu.add(new JMenuItem(actions.get("exit"))); + + collectionsMenu.add(new JMenuItem(actions.get("view.all"))); + collectionsMenu.add(new JMenuItem(actions.get("view.artists"))); + collectionsMenu.add(new JMenuItem(actions.get("view.albums"))); + collectionsMenu.add(new JMenuItem(actions.get("view.genres"))); + collectionsMenu.add(new JMenuItem(actions.get("view.years"))); + collectionsMenu.add(new JMenuItem(actions.get("view.playlists"))); + + playbackMenu.add(new JMenuItem(actions.get("playback.clear"))); + playbackMenu.addSeparator(); + playbackMenu.add(new JMenuItem(actions.get("playback.toggle"))); + playbackMenu.add(new JMenuItem(actions.get("playback.skipPrev"))); + playbackMenu.add(new JMenuItem(actions.get("playback.skipNext"))); + + helpMenu.add(new JMenuItem(actions.get("logs"))); + + helpMenu.add(new JMenuItem(actions.get("about"))); + + this.setJMenuBar(toolbar); + + this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + this.addComponentListener(this); this.addWindowListener(this); this.addFocusListener(this); - - ((SortingFocusTraversalPolicy) this.getFocusTraversalPolicy()).setImplicitDownCycleTraversal(true); - this.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, Set.of(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_DOWN, 0), AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_RIGHT, 0))); - this.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, Set.of(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_UP, 0), AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_LEFT, 0))); - this.setFocusTraversalKeys(KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, Set.of(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, 0))); - this.setFocusTraversalKeys(KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS, Set.of(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, KeyEvent.SHIFT_DOWN_MASK))); - this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - - this.updateSongs(SongProvider.INSTANCE.getSongs()); } - + + protected void setFocusManager() + { + ((SortingFocusTraversalPolicy) this.getFocusTraversalPolicy()) + .setImplicitDownCycleTraversal(true); + this.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, Set + .of(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_DOWN, 0), AWTKeyStroke + .getAWTKeyStroke(KeyEvent.VK_RIGHT, 0))); + this.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, Set + .of(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_UP, 0), AWTKeyStroke + .getAWTKeyStroke(KeyEvent.VK_LEFT, 0))); + this.setFocusTraversalKeys(KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, Set + .of(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, 0))); + this.setFocusTraversalKeys(KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS, Set + .of(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, KeyEvent.SHIFT_DOWN_MASK))); + } + @Override public void updateSongs(Collection songs) { @@ -272,7 +621,7 @@ public class Interface extends JFrame implements SongDisplayListener, ComponentL this.songList.revalidate(); this.centerView.revalidate(); } - + @Override public void updateCollections(CollectionType type, Collection collections) { @@ -281,71 +630,70 @@ public class Interface extends JFrame implements SongDisplayListener, ComponentL this.collectionList.revalidate(); this.centerView.revalidate(); } - + @Override public void componentResized(ComponentEvent event) { } - + @Override public void componentMoved(ComponentEvent event) { - + } - + @Override public void componentShown(ComponentEvent event) { - + } - + @Override public void componentHidden(ComponentEvent event) { - + } - + @Override public void windowOpened(WindowEvent windowEvent) { logger.info("Interface opened"); } - + @Override public void windowClosing(WindowEvent windowEvent) { this.players.forEach(Player::close); } - + @Override public void windowClosed(WindowEvent windowEvent) { } - + @Override public void windowIconified(WindowEvent windowEvent) { - + } - + @Override public void windowDeiconified(WindowEvent windowEvent) { - + } - + @Override public void windowActivated(WindowEvent windowEvent) { - + } - + @Override public void windowDeactivated(WindowEvent windowEvent) { - } - + @Override public void onUpdate(int updated, int totalUpdate, String updating) { @@ -359,7 +707,7 @@ public class Interface extends JFrame implements SongDisplayListener, ComponentL this.updateSongs(SongProvider.INSTANCE.getSongs()); } } - + @Override public void focusGained(FocusEvent e) { @@ -435,7 +783,7 @@ public class Interface extends JFrame implements SongDisplayListener, ComponentL } } } - + @Override public void focusLost(FocusEvent e) { diff --git a/interface/src/main/java/edu/regis/universeplayer/player/InternetSongDialog.java b/interface/src/main/java/edu/regis/universeplayer/player/InternetSongDialog.java index bf17a73..66a07a7 100644 --- a/interface/src/main/java/edu/regis/universeplayer/player/InternetSongDialog.java +++ b/interface/src/main/java/edu/regis/universeplayer/player/InternetSongDialog.java @@ -51,7 +51,7 @@ public class InternetSongDialog extends JDialog c.anchor = GridBagConstraints.WEST; c.insets = new Insets(0, 2, 5, 2); - this.getContentPane().add(label = new JLabel(langs.getString("actions.external.add.url")), c); + this.getContentPane().add(label = new JLabel(langs.getString("actions.addExternal.url")), c); this.urlBox = new JTextField(); this.urlBox.addFocusListener(new FocusAdapter() { @@ -76,7 +76,7 @@ public class InternetSongDialog extends JDialog c.gridx = 0; c.gridy = ++y; - this.getContentPane().add(label = new JLabel(langs.getString("actions.external.add.song")), c); + this.getContentPane().add(label = new JLabel(langs.getString("actions.addExternal.song")), c); this.titleBox = new JTextField(); c.gridy = ++y; this.getContentPane().add(this.titleBox, c); @@ -84,7 +84,7 @@ public class InternetSongDialog extends JDialog c.gridx = 0; c.gridy = ++y; - this.getContentPane().add(label = new JLabel(langs.getString("actions.external.add.album")), c); + this.getContentPane().add(label = new JLabel(langs.getString("actions.addExternal.album")), c); this.albumBox = new JTextField(); c.gridy = ++y; this.getContentPane().add(this.albumBox, c); @@ -92,7 +92,7 @@ public class InternetSongDialog extends JDialog c.gridx = 0; c.gridy = ++y; - this.getContentPane().add(label = new JLabel(langs.getString("actions.external.add.artists")), c); + this.getContentPane().add(label = new JLabel(langs.getString("actions.addExternal.artists")), c); this.artistBox = new JTextField(); c.gridy = ++y; this.getContentPane().add(this.artistBox, c); @@ -100,7 +100,7 @@ public class InternetSongDialog extends JDialog c.gridx = 0; c.gridy = ++y; - this.getContentPane().add(label = new JLabel(langs.getString("actions.external.add.genre")), c); + this.getContentPane().add(label = new JLabel(langs.getString("actions.addExternal.genre")), c); this.genreBox = new JTextField(); c.gridy = ++y; this.getContentPane().add(this.genreBox, c); diff --git a/interface/src/main/java/edu/regis/universeplayer/player/PlayerControls.java b/interface/src/main/java/edu/regis/universeplayer/player/PlayerControls.java index 169de8e..a0d056b 100644 --- a/interface/src/main/java/edu/regis/universeplayer/player/PlayerControls.java +++ b/interface/src/main/java/edu/regis/universeplayer/player/PlayerControls.java @@ -72,31 +72,31 @@ public class PlayerControls extends JPanel implements Queue.SongChangeListener, buttonCont = new JPanel(buttonLayout); this.add(buttonCont); - this.prevButton = new JButton(); + this.prevButton = new JButton(Interface.getInstance().actions.get("playback.skipPrev")); + this.prevButton.setText(""); icon = new ImageIcon(this.getClass() .getResource("/gui/icons/skipPrev.png"), "Previous Button"); icon.setImage(icon.getImage().getScaledInstance(ICON_SIZE.width, ICON_SIZE.height, 0)); this.prevButton.setIcon(icon); this.prevButton.setPreferredSize(BUTTON_SIZE); - this.prevButton.addActionListener(actionEvent -> this.previousSong()); buttonCont.add(this.prevButton); - this.playButton = new JButton(); + this.playButton = new JButton(Interface.getInstance().actions.get("playback.toggle")); + this.playButton.setText(""); PAUSE_ICON = icon = new ImageIcon(this.getClass().getResource("/gui/icons/pause.png"), "Pause Button"); icon.setImage(icon.getImage().getScaledInstance(ICON_SIZE.width, ICON_SIZE.height, 0)); PLAY_ICON = icon = new ImageIcon(this.getClass().getResource("/gui/icons/play.png"), "Play Button"); icon.setImage(icon.getImage().getScaledInstance(ICON_SIZE.width, ICON_SIZE.height, 0)); this.playButton.setIcon(icon); this.playButton.setPreferredSize(BUTTON_SIZE); - this.playButton.addActionListener(actionEvent -> this.togglePlayback()); buttonCont.add(this.playButton); - this.nextButton = new JButton(); + this.nextButton = new JButton(Interface.getInstance().actions.get("playback.skipNext")); + this.nextButton.setText(""); icon = new ImageIcon(this.getClass().getResource("/gui/icons/skipNext.png"), "Next Button"); icon.setImage(icon.getImage().getScaledInstance(ICON_SIZE.width, ICON_SIZE.height, 0)); this.nextButton.setIcon(icon); this.nextButton.setPreferredSize(BUTTON_SIZE); - this.nextButton.addActionListener(actionEvent -> this.nextSong()); buttonCont.add(this.nextButton); progressLayout = new SpringLayout(); @@ -171,11 +171,66 @@ public class PlayerControls extends JPanel implements Queue.SongChangeListener, }); this.triggerCommandListeners(PlaybackCommand.SEEK, value); } + + protected void play() + { + this.service.execute(() -> { + try + { + if (this.currentPlayer != null) + { + switch ((PlaybackStatus) this.currentPlayer.getStatus().get()) + { + case PAUSED -> this.currentPlayer.play(); + case STOPPED, EMPTY -> { + if (Queue.getInstance().size() > 0) + { + if (Queue.getInstance().getCurrentSong() == null) + { + Queue.getInstance().skipToSong(0); + } + else + { + this.currentPlayer.play(); + } + } + } + } + } + } + catch (ExecutionException | InterruptedException e) + { + logger.error("Could not get current playback status", e); + } + }); + this.triggerCommandListeners(PlaybackCommand.PLAY, null); + } + + protected void pause() + { + this.service.execute(() -> { + try + { + if (this.currentPlayer != null) + { + switch ((PlaybackStatus) this.currentPlayer.getStatus().get()) + { + case PLAYING -> this.currentPlayer.pause(); + } + } + } + catch (ExecutionException | InterruptedException e) + { + logger.error("Could not get current playback status", e); + } + }); + this.triggerCommandListeners(PlaybackCommand.PAUSE, null); + } /** * Toggles the playback of the current song. */ - private void togglePlayback() + protected void togglePlayback() { this.service.execute(() -> { try @@ -213,7 +268,7 @@ public class PlayerControls extends JPanel implements Queue.SongChangeListener, /** * Skips to the next song. */ - private void previousSong() + protected void previousSong() { Queue.getInstance().skipPrev(); this.triggerCommandListeners(PlaybackCommand.PREVIOUS, null); @@ -222,7 +277,7 @@ public class PlayerControls extends JPanel implements Queue.SongChangeListener, /** * Skips to the next song. */ - private void nextSong() + protected void nextSong() { Queue.getInstance().skipNext(); this.triggerCommandListeners(PlaybackCommand.NEXT, null); diff --git a/interface/src/main/java/edu/regis/universeplayer/player/QueueList.java b/interface/src/main/java/edu/regis/universeplayer/player/QueueList.java index c85f822..b279bf7 100644 --- a/interface/src/main/java/edu/regis/universeplayer/player/QueueList.java +++ b/interface/src/main/java/edu/regis/universeplayer/player/QueueList.java @@ -46,8 +46,7 @@ public class QueueList extends JPanel implements Queue.SongChangeListener, Queue c.gridy = 0; c.gridwidth = 1; header.add(new JLabel(" ".repeat(20) + langs.getString("interface.queue.title") + " ".repeat(20)), c); - this.clearButton = new JButton(langs.getString("actions.clear")); - this.clearButton.addActionListener(e -> Queue.getInstance().clear()); + this.clearButton = new JButton(Interface.getInstance().actions.get("playback.clear")); c.gridy = 1; c.gridwidth = 1; header.add(clearButton, c); diff --git a/interface/src/main/resources/lang/interface.properties b/interface/src/main/resources/lang/interface.properties index 87e2545..0d77f71 100644 --- a/interface/src/main/resources/lang/interface.properties +++ b/interface/src/main/resources/lang/interface.properties @@ -1,16 +1,16 @@ title=Universal Music Player +menu.file.title=File +menu.view.title=View +menu.view.collections=Collections +menu.playback.title=Playback +menu.help.title=Help + albumInfo.album=Album albumInfo.artists=Artists albumInfo.genres=Genres albumInfo.year=Year -collections.all=All Songs -collections.artists=Artists -collections.albums=Albums -collections.genres=Genres -collections.years=Years -collections.playlists=Playlists interface.queue.title=Queue @@ -19,19 +19,37 @@ actions.confirm=O.K. actions.add=Add actions.remove=Remove actions.cancel=Cancel -actions.clear=Clear actions.play=Play -actions.pause=Pause -actions.skipNext=Next -actions.skipPrev=Previous -actions.stop=Stop -actions.external.add.title=Add External Song -actions.external.add.url=URL -actions.external.add.song=Song Title -actions.external.add.album=Album -actions.external.add.artists=Artists -actions.external.add.genre=Genre +actions.addExternal=Add External Song +actions.addExternal.url=URL +actions.addExternal.song=Song Title +actions.addExternal.album=Album +actions.addExternal.artists=Artists +actions.addExternal.genre=Genre + +actions.refresh=Refresh Song Cache + +actions.exit=Exit + +actions.logs=Show Logs + +actions.about=About + +actions.view.all=All Songs +actions.view.artists=Artists +actions.view.albums=Albums +actions.view.genres=Genres +actions.view.years=Years +actions.view.playlists=Playlists + +actions.playback.clear=Clear Queue +actions.playback.play=Play +actions.playback.pause=Pause +actions.playback.toggle=Toggle Playback +actions.playback.stop=Stop +actions.playback.skipPrev=Skip Previously +actions.playback.skipNext=Skip Next error.generic=Error! error.browser.launch=Could not open browser background \ No newline at end of file diff --git a/interface/src/main/resources/lang/interface_es.properties b/interface/src/main/resources/lang/interface_es.properties index 16cee58..939ff6b 100644 --- a/interface/src/main/resources/lang/interface_es.properties +++ b/interface/src/main/resources/lang/interface_es.properties @@ -1,16 +1,20 @@ title=Reproductor de música universal +menu.file.title=Archivo + +menu.help.title=Ayuda + albumInfo.album=Álbum albumInfo.artists=Artistas albumInfo.genres=Géneros albumInfo.year=Año -collections.all=Todas las canciones -collections.artists=Artistas -collections.albums=Álbums -collections.genres=Géneros -collections.years=Años -collections.playlists=Listas +actions.view.all=Todas las canciones +actions.view.artists=Artistas +actions.view.albums=Álbums +actions.view.genres=Géneros +actions.view.years=Años +actions.view.playlists=Listas interface.queue.title=Queue @@ -26,12 +30,20 @@ actions.skipNext=Siguiente actions.skipPrev=Anteriormente actions.stop=Detener -actions.external.add.title=Añadir canción externa -actions.external.add.url=URL -actions.external.add.song=Título -actions.external.add.album=Álbum -actions.external.add.artists=Artistas -actions.external.add.genre=Género +actions.addExternal=Añadir canción externa +actions.addExternal.url=URL +actions.addExternal.song=Título +actions.addExternal.album=Álbum +actions.addExternal.artists=Artistas +actions.addExternal.genre=Género + +actions.refresh=Actualizar la caché de canciones + +actions.exit=Salir + +actions.logs=Mostrar registros + +actions.about=Sobre nosotros error.generic=¡Error! error.browser.launch=No se puede abrir el fondo del navegador \ No newline at end of file