GStreamerPlayer no longer proxies via PlayerGUI to interact with a playlist.
This commit is contained in:
parent
974ff2c8c1
commit
41e7de065e
@ -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 {
|
||||||
case playPause:
|
switch (nativeKeyEvent.getRawCode()) {
|
||||||
if(player.isPlaying()){
|
case playPause:
|
||||||
player.pause();
|
if (player.isPlaying()) {
|
||||||
setSongHighlighting(player.getCurrentSong()); // Resume won't function if a different song is selected.
|
player.pause();
|
||||||
}
|
} else {
|
||||||
else{
|
player.play();
|
||||||
playSong(playlist.getActive());
|
}
|
||||||
}
|
break;
|
||||||
break;
|
case stop:
|
||||||
case stop:
|
player.stop();
|
||||||
player.stop(); break;
|
break;
|
||||||
case previous:
|
case previous:
|
||||||
playPreviousSong(); break;
|
player.previous();
|
||||||
case next:
|
break;
|
||||||
playNextSong(); break;
|
case next:
|
||||||
|
player.next();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}catch (StartPlayingException ex){
|
||||||
|
showError(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user