GStreamerPlayer no longer proxies via PlayerGUI to interact with a playlist.

This commit is contained in:
neviyn 2016-03-19 23:06:28 +00:00
parent 974ff2c8c1
commit 41e7de065e
5 changed files with 99 additions and 106 deletions

View File

@ -47,18 +47,6 @@ public class PlayerGUI extends JPanel implements PlayerCallbackInterface {
this.playlist = playlist; this.playlist = playlist;
this.library = library; this.library = library;
createUI(); 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 { try {
Logger logger = Logger.getLogger(GlobalScreen.class.getPackage().getName()); Logger logger = Logger.getLogger(GlobalScreen.class.getPackage().getName());
logger.setLevel(Level.WARNING); 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> 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. * Set the maximum value of the seekBar.
* *
@ -151,14 +104,9 @@ public class PlayerGUI extends JPanel implements PlayerCallbackInterface {
SwingUtilities.invokeLater(() -> seekBar.setMaximum(seconds)); SwingUtilities.invokeLater(() -> seekBar.setMaximum(seconds));
} }
@Override private void showError(StartPlayingException ex){
public void removeInvalidSong(Song invalidSong) { JOptionPane.showMessageDialog(this, "Failed to play " + ex.getSong().toString() + ".\n" +
playlist.delete(invalidSong); "If file path contains non-ASCII characters, please restart the application with UTF-8 encoding.");
}
public void playerStopped(){
setSongHighlighting(player.getCurrentSong());
playlist.setPlayingSong(null);
} }
/* /*
@ -204,15 +152,18 @@ public class PlayerGUI extends JPanel implements PlayerCallbackInterface {
playButton.setName("playButton"); playButton.setName("playButton");
playButton.setIcon(Icons.playIcon); playButton.setIcon(Icons.playIcon);
playButton.setMnemonic('P'); playButton.setMnemonic('P');
playButton.addActionListener(e -> playSong(playlist.getActive())); playButton.addActionListener(e -> {
try {
player.play();
} catch (StartPlayingException e1) {
showError(e1);
}
});
controlBar.add(playButton); controlBar.add(playButton);
JButton pauseButton = new JButton(); JButton pauseButton = new JButton();
pauseButton.setIcon(Icons.pauseIcon); pauseButton.setIcon(Icons.pauseIcon);
pauseButton.setMnemonic('E'); pauseButton.setMnemonic('E');
pauseButton.addActionListener(e -> { pauseButton.addActionListener(e -> player.pause());
player.pause();
setSongHighlighting(player.getCurrentSong()); // Resume won't function if a different song is selected.
});
controlBar.add(pauseButton); controlBar.add(pauseButton);
JButton stopButton = new JButton(); JButton stopButton = new JButton();
stopButton.setIcon(Icons.stopIcon); stopButton.setIcon(Icons.stopIcon);
@ -222,12 +173,24 @@ public class PlayerGUI extends JPanel implements PlayerCallbackInterface {
JButton previousButton = new JButton(); JButton previousButton = new JButton();
previousButton.setIcon(Icons.prevIcon); previousButton.setIcon(Icons.prevIcon);
previousButton.setMnemonic('R'); previousButton.setMnemonic('R');
previousButton.addActionListener(e -> playPreviousSong()); previousButton.addActionListener(e -> {
try {
player.previous();
} catch (StartPlayingException e1) {
showError(e1);
}
});
controlBar.add(previousButton); controlBar.add(previousButton);
JButton nextButton = new JButton(); JButton nextButton = new JButton();
nextButton.setIcon(Icons.nextIcon); nextButton.setIcon(Icons.nextIcon);
nextButton.setMnemonic('N'); nextButton.setMnemonic('N');
nextButton.addActionListener(e -> playNextSong()); nextButton.addActionListener(e -> {
try {
player.next();
} catch (StartPlayingException e1) {
showError(e1);
}
});
controlBar.add(nextButton); controlBar.add(nextButton);
toolBar.add(controlBar); toolBar.add(controlBar);
toolBar.add(createVolumeControls()); toolBar.add(createVolumeControls());
@ -399,22 +362,27 @@ public class PlayerGUI extends JPanel implements PlayerCallbackInterface {
@Override @Override
public void nativeKeyTyped(NativeKeyEvent nativeKeyEvent) { public void nativeKeyTyped(NativeKeyEvent nativeKeyEvent) {
if(modified){ if(modified){
switch(nativeKeyEvent.getRawCode()){ try {
switch (nativeKeyEvent.getRawCode()) {
case playPause: case playPause:
if(player.isPlaying()){ if (player.isPlaying()) {
player.pause(); player.pause();
setSongHighlighting(player.getCurrentSong()); // Resume won't function if a different song is selected. } else {
} player.play();
else{
playSong(playlist.getActive());
} }
break; break;
case stop: case stop:
player.stop(); break; player.stop();
break;
case previous: case previous:
playPreviousSong(); break; player.previous();
break;
case next: case next:
playNextSong(); break; player.next();
break;
}
}catch (StartPlayingException ex){
showError(ex);
} }
} }
} }

View File

@ -9,4 +9,8 @@ public class StartPlayingException extends Exception {
public StartPlayingException(Song song){ public StartPlayingException(Song song){
this.song = song; this.song = song;
} }
public Song getSong() {
return song;
}
} }

View File

@ -7,32 +7,13 @@ import musicplayer.model.Song;
@ImplementedBy(PlayerGUI.class) @ImplementedBy(PlayerGUI.class)
public interface PlayerCallbackInterface { 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. * Set the seekbar position.
*
* @param seconds Position to set the seekbar to. * @param seconds Position to set the seekbar to.
*/ */
void setSeekBarDuration(int seconds); void setSeekBarDuration(int seconds);
/** void setSeekBarPosition(int position);
* 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();
} }

View File

@ -4,6 +4,7 @@ import com.google.inject.Inject;
import musicplayer.StartPlayingException; import musicplayer.StartPlayingException;
import musicplayer.callbacks.PlayerCallbackInterface; import musicplayer.callbacks.PlayerCallbackInterface;
import musicplayer.model.Song; import musicplayer.model.Song;
import musicplayer.playlist.IPlaylist;
import org.gstreamer.ClockTime; import org.gstreamer.ClockTime;
import org.gstreamer.ElementFactory; import org.gstreamer.ElementFactory;
import org.gstreamer.Gst; import org.gstreamer.Gst;
@ -22,14 +23,16 @@ public class GStreamerPlayer implements IPlayer{
private Song currentSong; private Song currentSong;
private final PlayerCallbackInterface callbackInterface; private final PlayerCallbackInterface callbackInterface;
private int currentVolume = 100; private int currentVolume = 100;
private final IPlaylist playlist;
/** /**
* Manages GStreamer based playback operations. * Manages GStreamer based playback operations.
* @param callbackInterface Interface on which UI updates can be called. * @param callbackInterface Interface on which UI updates can be called.
*/ */
@Inject @Inject
public GStreamerPlayer(PlayerCallbackInterface callbackInterface) { public GStreamerPlayer(PlayerCallbackInterface callbackInterface, IPlaylist playlist) {
this.callbackInterface = callbackInterface; this.callbackInterface = callbackInterface;
this.playlist = playlist;
Gst.init(); Gst.init();
playBin = new PlayBin2("BusMessages"); playBin = new PlayBin2("BusMessages");
playBin.setVideoSink(ElementFactory.make("fakesink", "videosink")); playBin.setVideoSink(ElementFactory.make("fakesink", "videosink"));
@ -38,16 +41,39 @@ public class GStreamerPlayer implements IPlayer{
Thread callbackThing = new Thread(() -> { Thread callbackThing = new Thread(() -> {
try { try {
Thread.sleep(1000); // Song is about to finish, wait so we don't cut it off early. 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(); e.printStackTrace();
} }
callbackInterface.playNextSong();
}); });
callbackThing.start(); 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(); 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. * Set a source Song file and start playing it via GStreamer.
* @param inputSong Song to play. * @param inputSong Song to play.
@ -60,13 +86,14 @@ public class GStreamerPlayer implements IPlayer{
resume(); resume();
return; return;
} }
resetSeek();
playBin.setState(State.READY); playBin.setState(State.READY);
currentSong = inputSong.get(); currentSong = inputSong.get();
callbackInterface.setSongHighlighting(currentSong); playlist.setPlayingSong(currentSong);
File songFile = currentSong.getSongFile(); File songFile = currentSong.getSongFile();
if (!songFile.exists()) { if (!songFile.exists()) {
callbackInterface.playNextSong(); playlist.delete(currentSong);
callbackInterface.removeInvalidSong(currentSong); next();
return; return;
} }
playBin.setURI(songFile.toURI()); playBin.setURI(songFile.toURI());
@ -95,7 +122,8 @@ public class GStreamerPlayer implements IPlayer{
playBin.stop(); playBin.stop();
internalThread.stop(); internalThread.stop();
thread = null; thread = null;
callbackInterface.playerStopped(); resetSeek();
playlist.setPlayingSong(currentSong);
} }
} }
@ -110,9 +138,18 @@ public class GStreamerPlayer implements IPlayer{
* Pause the currently playing song. * Pause the currently playing song.
*/ */
public void pause() { public void pause() {
playlist.setPlayingSong(currentSong);
playBin.pause(); 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. * @return The Song currently being played or ready to be played.
*/ */

View File

@ -6,10 +6,13 @@ import musicplayer.model.Song;
import java.util.Optional; import java.util.Optional;
public interface IPlayer { public interface IPlayer {
void play() throws StartPlayingException;
void playSong(Optional<Song> inputSong) throws StartPlayingException; void playSong(Optional<Song> inputSong) throws StartPlayingException;
void stop(); void stop();
void resume(); void resume();
void pause(); void pause();
void next() throws StartPlayingException;
void previous() throws StartPlayingException;
Song getCurrentSong(); Song getCurrentSong();
int currentSongPosition(); int currentSongPosition();
void setVolume(int volume); void setVolume(int volume);