Implemented seek functionality.
This commit is contained in:
parent
587324d5ef
commit
bc53f088cf
@ -2,6 +2,7 @@ package musicplayer;
|
||||
|
||||
import musicplayer.callbacks.PlayerCallbackInterface;
|
||||
import musicplayer.model.Song;
|
||||
import org.gstreamer.ClockTime;
|
||||
import org.gstreamer.ElementFactory;
|
||||
import org.gstreamer.Gst;
|
||||
import org.gstreamer.State;
|
||||
@ -115,7 +116,7 @@ public class Player {
|
||||
* @return Current playback position in seconds.
|
||||
*/
|
||||
public int currentSongPosition(){
|
||||
return playBin.isPlaying() || playBin.getState() == State.PAUSED ? (int) (playBin.getClock().getTime().toSeconds() - playBin.getBaseTime().toSeconds()) : 0;
|
||||
return playBin.isPlaying() || playBin.getState() == State.PAUSED ? (int) playBin.queryPosition().toSeconds() : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -134,6 +135,14 @@ public class Player {
|
||||
return playBin.getVolumePercent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Seek to a position in the song.
|
||||
* @param position Position (in seconds) to seek to.
|
||||
*/
|
||||
public void seek(int position){
|
||||
playBin.seek(ClockTime.fromSeconds(position));
|
||||
}
|
||||
|
||||
private class InternalThread implements Runnable {
|
||||
|
||||
@Override
|
||||
|
@ -16,10 +16,12 @@ import java.awt.*;
|
||||
import java.awt.event.ItemEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseListener;
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class PlayerGUI implements PlayerCallbackInterface, LibraryCallbackInterface {
|
||||
@ -32,6 +34,7 @@ public class PlayerGUI implements PlayerCallbackInterface, LibraryCallbackInterf
|
||||
private PlaylistTableModel playlistTableModel = new PlaylistTableModel(new ArrayList<>());
|
||||
private static DefaultMutableTreeNode updatingNode = new DefaultMutableTreeNode();
|
||||
private boolean libraryUpdating = false;
|
||||
private AtomicBoolean seeking = new AtomicBoolean(false);
|
||||
|
||||
private Map<String, Runnable> libraryDisplayVariants = createDisplayVariantMap();
|
||||
|
||||
@ -69,7 +72,10 @@ public class PlayerGUI implements PlayerCallbackInterface, LibraryCallbackInterf
|
||||
* @param position New seekBar value.
|
||||
*/
|
||||
public void setSeekBarPosition(int position) {
|
||||
SwingUtilities.invokeLater(() -> seekBar.setValue(position));
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
if(!seeking.get())
|
||||
seekBar.setValue(position);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -153,6 +159,9 @@ public class PlayerGUI implements PlayerCallbackInterface, LibraryCallbackInterf
|
||||
player.playSong(playlistTableModel.nextSong(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));
|
||||
player.playSong(playlistTableModel.previous(player.getCurrentSong()));
|
||||
@ -222,6 +231,9 @@ public class PlayerGUI implements PlayerCallbackInterface, LibraryCallbackInterf
|
||||
((DefaultTreeModel)libraryView.getModel()).nodeChanged(updatingNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Map of display types for the library paired code to populate the library with data in the correct format.
|
||||
*/
|
||||
private Map<String, Runnable> createDisplayVariantMap() {
|
||||
Map<String, Runnable> value = new HashMap<>();
|
||||
value.put("Song", () -> Gateway.listAllSongs().ifPresent(this::populateLibrary));
|
||||
@ -272,11 +284,15 @@ public class PlayerGUI implements PlayerCallbackInterface, LibraryCallbackInterf
|
||||
seekBar = new JSlider();
|
||||
seekBar.setMinorTickSpacing(1);
|
||||
seekBar.setValue(0);
|
||||
seekBar.addMouseListener(new SeekbarMouseListener());
|
||||
controlPane.add(seekBar, BorderLayout.NORTH);
|
||||
controlPane.add(createControlButtons(), BorderLayout.SOUTH);
|
||||
mainPanel.add(createMenuBar(), BorderLayout.NORTH);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Area containing the library.
|
||||
*/
|
||||
private JTree createLibraryArea() {
|
||||
libraryView.setRootVisible(false);
|
||||
libraryView.setToggleClickCount(1);
|
||||
@ -285,6 +301,9 @@ public class PlayerGUI implements PlayerCallbackInterface, LibraryCallbackInterf
|
||||
return libraryView;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Area containing the playlist.
|
||||
*/
|
||||
private JScrollPane createPlaylistArea() {
|
||||
JScrollPane playlistScroll = new JScrollPane();
|
||||
playList.setRowSelectionAllowed(true);
|
||||
@ -308,6 +327,9 @@ public class PlayerGUI implements PlayerCallbackInterface, LibraryCallbackInterf
|
||||
return playlistScroll;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Playback control buttons (play, stop, etc.)
|
||||
*/
|
||||
private JToolBar createControlButtons() {
|
||||
JToolBar toolBar = new JToolBar();
|
||||
toolBar.setFloatable(false);
|
||||
@ -345,6 +367,9 @@ public class PlayerGUI implements PlayerCallbackInterface, LibraryCallbackInterf
|
||||
return toolBar;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Volume controls.
|
||||
*/
|
||||
private JPanel createVolumeControls() {
|
||||
JPanel panel = new JPanel();
|
||||
panel.setLayout(new FlowLayout());
|
||||
@ -410,4 +435,29 @@ public class PlayerGUI implements PlayerCallbackInterface, LibraryCallbackInterf
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* MouseListener implementation for the seekbar.
|
||||
* Using this instead of the ChangeListener so that the polling for the current song position
|
||||
* doesn't repeatedly fire seek events.
|
||||
*/
|
||||
private class SeekbarMouseListener implements MouseListener {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) { seeking.set(true); }
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) { seeking.set(true); }
|
||||
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
player.seek(seekBar.getValue());
|
||||
seeking.set(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent e) {}
|
||||
|
||||
@Override
|
||||
public void mouseExited(MouseEvent e) {}
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,15 @@ package musicplayer.callbacks;
|
||||
|
||||
public interface LibraryCallbackInterface {
|
||||
|
||||
/**
|
||||
* Call this after performing library updates so the front-end knows that updating has completed.
|
||||
* @param successful Was the update function successful.
|
||||
*/
|
||||
void libraryUpdated(boolean successful);
|
||||
|
||||
/**
|
||||
* Update the current display with the file/folder currently being parsed.
|
||||
* @param name Data about the file/folder to be shown to the user.
|
||||
*/
|
||||
void currentlyUpdating(String name);
|
||||
}
|
||||
|
@ -6,14 +6,32 @@ import java.util.Optional;
|
||||
|
||||
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();
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user