From 41e7de065e1f1b521d3b5bd4c9c8d27a84fee393 Mon Sep 17 00:00:00 2001 From: Nathan Cannon Date: Sat, 19 Mar 2016 23:06:28 +0000 Subject: [PATCH] GStreamerPlayer no longer proxies via PlayerGUI to interact with a playlist. --- src/main/java/musicplayer/PlayerGUI.java | 124 +++++++----------- .../musicplayer/StartPlayingException.java | 4 + .../callbacks/PlayerCallbackInterface.java | 23 +--- .../musicplayer/player/GStreamerPlayer.java | 51 ++++++- src/main/java/musicplayer/player/IPlayer.java | 3 + 5 files changed, 99 insertions(+), 106 deletions(-) diff --git a/src/main/java/musicplayer/PlayerGUI.java b/src/main/java/musicplayer/PlayerGUI.java index 29a51e9..b8f74a1 100644 --- a/src/main/java/musicplayer/PlayerGUI.java +++ b/src/main/java/musicplayer/PlayerGUI.java @@ -47,18 +47,6 @@ public class PlayerGUI extends JPanel implements PlayerCallbackInterface { this.playlist = playlist; this.library = library; createUI(); - Thread seekBarUpdater = new Thread(() -> { - boolean running = true; - while (running) { - try { - Thread.sleep(1000); - setSeekBarPosition(player.currentSongPosition()); - } catch (InterruptedException e) { - running = false; - } - } - }, "seekbar"); - seekBarUpdater.start(); try { Logger logger = Logger.getLogger(GlobalScreen.class.getPackage().getName()); logger.setLevel(Level.WARNING); @@ -107,41 +95,6 @@ public class PlayerGUI extends JPanel implements PlayerCallbackInterface { }); } - /** - * Set the highlighted song in the playlist to this song. - * - * @param playingSong Song to be highlighted in the playlist. - */ - @Override - public void setSongHighlighting(Song playingSong) { - playlist.setPlayingSong(playingSong); - } - - private void playSong(Optional song){ - try { - player.playSong(song); - } catch (StartPlayingException e) { - JOptionPane.showMessageDialog(this, "Failed to play " + song.get().toString() + ".\n" + - "If file path contains non-ASCII characters, please restart the application with UTF-8 encoding."); - } - } - - /** - * Get the next song in the playlist and dispatch it to the Player to be played. - */ - public void playNextSong() { - SwingUtilities.invokeLater(() -> seekBar.setValue(0)); - playSong(playlist.getNext(player.getCurrentSong())); - } - - /** - * Get the previous song in the playlist and dispatch it to the Player to be played. - */ - public void playPreviousSong() { - SwingUtilities.invokeLater(() -> seekBar.setValue(0)); - playSong(playlist.getPrevious(player.getCurrentSong())); - } - /** * Set the maximum value of the seekBar. * @@ -151,14 +104,9 @@ public class PlayerGUI extends JPanel implements PlayerCallbackInterface { SwingUtilities.invokeLater(() -> seekBar.setMaximum(seconds)); } - @Override - public void removeInvalidSong(Song invalidSong) { - playlist.delete(invalidSong); - } - - public void playerStopped(){ - setSongHighlighting(player.getCurrentSong()); - playlist.setPlayingSong(null); + private void showError(StartPlayingException ex){ + JOptionPane.showMessageDialog(this, "Failed to play " + ex.getSong().toString() + ".\n" + + "If file path contains non-ASCII characters, please restart the application with UTF-8 encoding."); } /* @@ -204,15 +152,18 @@ public class PlayerGUI extends JPanel implements PlayerCallbackInterface { playButton.setName("playButton"); playButton.setIcon(Icons.playIcon); playButton.setMnemonic('P'); - playButton.addActionListener(e -> playSong(playlist.getActive())); + playButton.addActionListener(e -> { + try { + player.play(); + } catch (StartPlayingException e1) { + showError(e1); + } + }); controlBar.add(playButton); JButton pauseButton = new JButton(); pauseButton.setIcon(Icons.pauseIcon); pauseButton.setMnemonic('E'); - pauseButton.addActionListener(e -> { - player.pause(); - setSongHighlighting(player.getCurrentSong()); // Resume won't function if a different song is selected. - }); + pauseButton.addActionListener(e -> player.pause()); controlBar.add(pauseButton); JButton stopButton = new JButton(); stopButton.setIcon(Icons.stopIcon); @@ -222,12 +173,24 @@ public class PlayerGUI extends JPanel implements PlayerCallbackInterface { JButton previousButton = new JButton(); previousButton.setIcon(Icons.prevIcon); previousButton.setMnemonic('R'); - previousButton.addActionListener(e -> playPreviousSong()); + previousButton.addActionListener(e -> { + try { + player.previous(); + } catch (StartPlayingException e1) { + showError(e1); + } + }); controlBar.add(previousButton); JButton nextButton = new JButton(); nextButton.setIcon(Icons.nextIcon); nextButton.setMnemonic('N'); - nextButton.addActionListener(e -> playNextSong()); + nextButton.addActionListener(e -> { + try { + player.next(); + } catch (StartPlayingException e1) { + showError(e1); + } + }); controlBar.add(nextButton); toolBar.add(controlBar); toolBar.add(createVolumeControls()); @@ -399,22 +362,27 @@ public class PlayerGUI extends JPanel implements PlayerCallbackInterface { @Override public void nativeKeyTyped(NativeKeyEvent nativeKeyEvent) { if(modified){ - switch(nativeKeyEvent.getRawCode()){ - case playPause: - if(player.isPlaying()){ - player.pause(); - setSongHighlighting(player.getCurrentSong()); // Resume won't function if a different song is selected. - } - else{ - playSong(playlist.getActive()); - } - break; - case stop: - player.stop(); break; - case previous: - playPreviousSong(); break; - case next: - playNextSong(); break; + try { + switch (nativeKeyEvent.getRawCode()) { + case playPause: + if (player.isPlaying()) { + player.pause(); + } else { + player.play(); + } + break; + case stop: + player.stop(); + break; + case previous: + player.previous(); + break; + case next: + player.next(); + break; + } + }catch (StartPlayingException ex){ + showError(ex); } } } diff --git a/src/main/java/musicplayer/StartPlayingException.java b/src/main/java/musicplayer/StartPlayingException.java index 3408877..58f9661 100644 --- a/src/main/java/musicplayer/StartPlayingException.java +++ b/src/main/java/musicplayer/StartPlayingException.java @@ -9,4 +9,8 @@ public class StartPlayingException extends Exception { public StartPlayingException(Song song){ this.song = song; } + + public Song getSong() { + return song; + } } diff --git a/src/main/java/musicplayer/callbacks/PlayerCallbackInterface.java b/src/main/java/musicplayer/callbacks/PlayerCallbackInterface.java index 63a830b..a0ad802 100644 --- a/src/main/java/musicplayer/callbacks/PlayerCallbackInterface.java +++ b/src/main/java/musicplayer/callbacks/PlayerCallbackInterface.java @@ -7,32 +7,13 @@ import musicplayer.model.Song; @ImplementedBy(PlayerGUI.class) public interface PlayerCallbackInterface { - /** - * Set the song currently shown to the user as playing. - * @param playingSong Song currently playing. - */ - void setSongHighlighting(Song playingSong); - /** * Set the seekbar position. + * * @param seconds Position to set the seekbar to. */ void setSeekBarDuration(int seconds); - /** - * Remove a song from the current playlist. - * @param invalidSong Song to remove. - */ - void removeInvalidSong(Song invalidSong); - - /** - * Playback has ceased. - */ - void playerStopped(); - - /** - * Start playing the next song. - */ - void playNextSong(); + void setSeekBarPosition(int position); } diff --git a/src/main/java/musicplayer/player/GStreamerPlayer.java b/src/main/java/musicplayer/player/GStreamerPlayer.java index 484012e..e4b206c 100644 --- a/src/main/java/musicplayer/player/GStreamerPlayer.java +++ b/src/main/java/musicplayer/player/GStreamerPlayer.java @@ -4,6 +4,7 @@ import com.google.inject.Inject; import musicplayer.StartPlayingException; import musicplayer.callbacks.PlayerCallbackInterface; import musicplayer.model.Song; +import musicplayer.playlist.IPlaylist; import org.gstreamer.ClockTime; import org.gstreamer.ElementFactory; import org.gstreamer.Gst; @@ -22,14 +23,16 @@ public class GStreamerPlayer implements IPlayer{ private Song currentSong; private final PlayerCallbackInterface callbackInterface; private int currentVolume = 100; + private final IPlaylist playlist; /** * Manages GStreamer based playback operations. * @param callbackInterface Interface on which UI updates can be called. */ @Inject - public GStreamerPlayer(PlayerCallbackInterface callbackInterface) { + public GStreamerPlayer(PlayerCallbackInterface callbackInterface, IPlaylist playlist) { this.callbackInterface = callbackInterface; + this.playlist = playlist; Gst.init(); playBin = new PlayBin2("BusMessages"); playBin.setVideoSink(ElementFactory.make("fakesink", "videosink")); @@ -38,16 +41,39 @@ public class GStreamerPlayer implements IPlayer{ Thread callbackThing = new Thread(() -> { try { Thread.sleep(1000); // Song is about to finish, wait so we don't cut it off early. - } catch (InterruptedException e) { + playSong(playlist.getNext(currentSong)); + } catch (InterruptedException | StartPlayingException e) { e.printStackTrace(); } - callbackInterface.playNextSong(); }); callbackThing.start(); }); + if (callbackInterface != null) { + Thread seekBarUpdater = new Thread(() -> { + boolean running = true; + while (running) { + try { + Thread.sleep(1000); + if (isPlaying()) + callbackInterface.setSeekBarPosition(currentSongPosition()); + } catch (InterruptedException e) { + running = false; + } + } + }, "seekbar"); + seekBarUpdater.start(); + } currentVolume = getVolume(); } + private void resetSeek(){ + callbackInterface.setSeekBarPosition(0); + } + + public void play() throws StartPlayingException { + playSong(playlist.getActive()); + } + /** * Set a source Song file and start playing it via GStreamer. * @param inputSong Song to play. @@ -60,13 +86,14 @@ public class GStreamerPlayer implements IPlayer{ resume(); return; } + resetSeek(); playBin.setState(State.READY); currentSong = inputSong.get(); - callbackInterface.setSongHighlighting(currentSong); + playlist.setPlayingSong(currentSong); File songFile = currentSong.getSongFile(); if (!songFile.exists()) { - callbackInterface.playNextSong(); - callbackInterface.removeInvalidSong(currentSong); + playlist.delete(currentSong); + next(); return; } playBin.setURI(songFile.toURI()); @@ -95,7 +122,8 @@ public class GStreamerPlayer implements IPlayer{ playBin.stop(); internalThread.stop(); thread = null; - callbackInterface.playerStopped(); + resetSeek(); + playlist.setPlayingSong(currentSong); } } @@ -110,9 +138,18 @@ public class GStreamerPlayer implements IPlayer{ * Pause the currently playing song. */ public void pause() { + playlist.setPlayingSong(currentSong); playBin.pause(); } + public void next() throws StartPlayingException { + playSong(playlist.getNext(currentSong)); + } + + public void previous() throws StartPlayingException{ + playSong(playlist.getPrevious(currentSong)); + } + /** * @return The Song currently being played or ready to be played. */ diff --git a/src/main/java/musicplayer/player/IPlayer.java b/src/main/java/musicplayer/player/IPlayer.java index 063a430..83b4ae8 100644 --- a/src/main/java/musicplayer/player/IPlayer.java +++ b/src/main/java/musicplayer/player/IPlayer.java @@ -6,10 +6,13 @@ import musicplayer.model.Song; import java.util.Optional; public interface IPlayer { + void play() throws StartPlayingException; void playSong(Optional inputSong) throws StartPlayingException; void stop(); void resume(); void pause(); + void next() throws StartPlayingException; + void previous() throws StartPlayingException; Song getCurrentSong(); int currentSongPosition(); void setVolume(int volume);