Added functionality to add from library to playlist and play (currently automatic) songs.

This commit is contained in:
neviyn 2016-02-11 04:54:36 +00:00
parent 6344e9dbe9
commit de860fad1f
11 changed files with 228 additions and 27 deletions

View File

@ -29,7 +29,7 @@ public class Application {
List<Song> songs = Gateway.listAllSongs().get();
boolean running = true;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
Player player = new Player();
Player player = new Player(null);
while (running) {
try {
System.out.println("Ready to read");
@ -37,7 +37,7 @@ public class Application {
System.out.println(input);
switch (input) {
case "play":
player.playSong(songs.get(0).getSongFile());
player.playSong(songs.get(0));
break;
case "stop":
player.stop();

View File

@ -1,5 +1,6 @@
package musicplayer;
import musicplayer.model.Song;
import org.gstreamer.ElementFactory;
import org.gstreamer.Gst;
import org.gstreamer.State;
@ -13,14 +14,32 @@ public class Player {
private InternalThread internalThread;
private Thread thread;
private Song currentSong;
private PlayerCallbackInterface callbackInterface;
public Player() {
public Player(PlayerCallbackInterface callbackInterface) {
this.callbackInterface = callbackInterface;
Gst.init();
playBin = new PlayBin2("BusMessages");
playBin.setVideoSink(ElementFactory.make("fakesink", "videosink"));
playBin.connect((PlayBin2.ABOUT_TO_FINISH) playBin2 -> {
Thread callbackThing = new Thread(() -> {
try {
Thread.sleep(1500); // Song is about to finish, wait so we don't cut it off early.
} catch (InterruptedException e) {
e.printStackTrace();
}
playSong(callbackInterface.getNextSong(currentSong));
});
callbackThing.start();
});
}
public void playSong(File songFile) {
public void playSong(Song song) {
callbackInterface.setSongHighlighting(song);
currentSong = song;
File songFile = song.getSongFile();
if (playBin.getState() == State.PLAYING)
stop();
playBin.setURI(songFile.toURI());
@ -47,6 +66,10 @@ public class Player {
playBin.pause();
}
public Song getCurrentSong(){
return currentSong;
}
private class InternalThread implements Runnable {
@Override

View File

@ -0,0 +1,10 @@
package musicplayer;
import musicplayer.model.Song;
public interface PlayerCallbackInterface {
Song getNextSong(Song currentSong);
void setSongHighlighting(Song playingSong);
}

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="musicplayer.PlayerGUI">
<grid id="27dc6" binding="mainPanel" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<grid id="27dc6" binding="mainPanel" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="500" height="400"/>
@ -10,7 +10,7 @@
<children>
<scrollpane id="2b209">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="7" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
<grid row="0" column="0" row-span="2" col-span="1" vsize-policy="7" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
@ -28,12 +28,45 @@
<properties/>
<border type="none"/>
<children>
<component id="b8fb" class="javax.swing.JList" binding="list1" default-binding="true">
<component id="c10f" class="javax.swing.JTable" binding="playList">
<constraints/>
<properties/>
<properties>
<rowSelectionAllowed value="true"/>
</properties>
</component>
</children>
</scrollpane>
<toolbar id="56df">
<constraints>
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="-1" height="20"/>
</grid>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="a01e9" class="javax.swing.JButton" binding="playButton">
<constraints/>
<properties>
<label value="Play"/>
<text value="&amp;Play"/>
</properties>
</component>
<component id="c0e85" class="javax.swing.JButton" binding="stopButton" default-binding="true">
<constraints/>
<properties>
<label value="Stop"/>
<text value="&amp;Stop"/>
</properties>
</component>
<component id="5cfc3" class="javax.swing.JButton" binding="nextButton">
<constraints/>
<properties>
<text value="&amp;Next"/>
</properties>
</component>
</children>
</toolbar>
</children>
</grid>
</form>

View File

@ -9,15 +9,18 @@ import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.TreeSet;
import java.awt.event.*;
import java.util.*;
public class PlayerGUI {
public class PlayerGUI implements PlayerCallbackInterface{
private JTree libraryView;
private JList list1;
private JTable playList;
private JPanel mainPanel;
private JButton playButton;
private JButton stopButton;
private JButton nextButton;
private Player player = new Player(this);
private PlaylistTableModel playlistTableModel = new PlaylistTableModel(new ArrayList<>());
public static void main(String[] args) {
@ -35,6 +38,18 @@ public class PlayerGUI {
libraryView.setRootVisible(false);
libraryView.setToggleClickCount(1);
libraryView.setCellRenderer(new LibraryTreeCellRenderer());
MouseListener mouseListener = new libraryMouseAdapter();
libraryView.addMouseListener(mouseListener);
playList.setModel(playlistTableModel);
playButton.addActionListener(e -> {
if (playList.getSelectedColumn() == -1) {
player.playSong(playlistTableModel.getFirst().get());
}
});
stopButton.addActionListener(e -> player.stop());
nextButton.addActionListener(e -> playNextSong());
}
private void resetTree() {
@ -69,4 +84,44 @@ public class PlayerGUI {
}
}
private void addToPlaylist(Song song){
playlistTableModel.addSong(song);
playList.revalidate();
}
@Override
public Song getNextSong(Song currentSong) {
return playlistTableModel.nextSong(currentSong);
}
@Override
public void setSongHighlighting(Song playingSong) {
int index = playlistTableModel.getSongIndex(playingSong);
playList.setRowSelectionInterval(index, index);
}
public void playNextSong(){
player.playSong(getNextSong(player.getCurrentSong()));
}
private class libraryMouseAdapter extends MouseAdapter {
@Override
public void mousePressed(MouseEvent e) {
int selRow = libraryView.getRowForLocation(e.getX(), e.getY());
try {
Object selectedItem = ((DefaultMutableTreeNode) libraryView.getPathForLocation(e.getX(), e.getY()).getLastPathComponent()).getUserObject();
if (selRow != -1) {
if (e.getClickCount() == 2) {
if (selectedItem != null) {
if (selectedItem instanceof Song) {
addToPlaylist((Song) selectedItem);
} else if (selectedItem instanceof Album) {
((Album) selectedItem).getSongs().forEach(PlayerGUI.this::addToPlaylist);
}
}
}
}
} catch (NullPointerException ignored) {}
}
}
}

View File

@ -0,0 +1,76 @@
package musicplayer;
import musicplayer.model.Song;
import javax.swing.table.AbstractTableModel;
import java.util.List;
import java.util.Optional;
public class PlaylistTableModel extends AbstractTableModel {
private List<Song> songList;
public PlaylistTableModel(List<Song> songList){
this.songList = songList;
}
@Override
public int getRowCount() {
return songList.size();
}
@Override
public int getColumnCount() {
return 4;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
Object o = "?";
Song song = songList.get(rowIndex);
switch (columnIndex){
case 0: o = song.getTrackNumber(); break;
case 1: o = song.getTitle(); break;
case 2: o = song.getArtist(); break;
case 3: o = song.getAlbum(); break;
}
return o;
}
@Override
public Class<?> getColumnClass(int columnIndex) {
return Song.class;
}
@Override
public String getColumnName(int column) {
String name = "";
switch (column){
case 0: name = "Track"; break;
case 1: name = "Title"; break;
case 2: name = "Artist"; break;
case 3: name = "Album"; break;
}
return name;
}
public void addSong(Song song){
System.out.println("Adding " + song.toString());
songList.add(song);
fireTableDataChanged();
}
public Optional<Song> getFirst(){
return songList.size() > 0 ? Optional.of(songList.get(0)) : Optional.<Song>empty();
}
public Song nextSong(Song song){
int index = songList.indexOf(song) + 1;
if(index >= songList.size()) index = 0;
return songList.get(index);
}
public int getSongIndex(Song song){
return songList.indexOf(song);
}
}

View File

@ -19,6 +19,7 @@ public class Album implements Comparable<Album> {
@Column(name = "name")
private String name;
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "album")
@OrderBy("trackNumber ASC")
private Set<Song> songs;
@Lob
@Column(name = "art", nullable = true, length = 10000)

View File

@ -23,7 +23,7 @@ public class ExtractedMetadata {
public final String trackNumber;
public final byte[] artwork;
static final String albumArtRegex = ".*(Cover|Folder|cover|folder)\\.(jpg|png)";
private static final String albumArtRegex = ".*(Cover|Folder|cover|folder)\\.(jpg|png)";
/**
* @param audioTags jaudiotagger tag data.
@ -64,7 +64,7 @@ public class ExtractedMetadata {
return null;
}
public static BufferedImage convertToBufferedImage(Image image) {
private static BufferedImage convertToBufferedImage(Image image) {
BufferedImage newImage = new BufferedImage(
image.getWidth(null), image.getHeight(null),
BufferedImage.TYPE_INT_ARGB);

View File

@ -30,13 +30,15 @@ public class Song implements Comparable<Song> {
@Column(name = "songFile")
private String songFile;
@Column(name = "trackNumber")
private String trackNumber;
private int trackNumber;
protected Song() {
}
public Song(String trackNumber, String title, Artist artist, Album album, String genre, String songFile) {
this.trackNumber = trackNumber;
try {
this.trackNumber = Integer.parseInt(trackNumber);
} catch (NumberFormatException e){ this.trackNumber = 0; }
this.title = title;
this.artist = artist;
this.genre = genre;
@ -58,7 +60,7 @@ public class Song implements Comparable<Song> {
Song song = (Song) o;
return id == song.id && artist.equals(song.artist) && genre.equals(song.genre) && title.equals(song.title)
&& album.equals(song.album) && songFile.equals(song.songFile) && trackNumber.equals(song.trackNumber);
&& album.equals(song.album) && songFile.equals(song.songFile) && trackNumber == song.trackNumber;
}
@ -70,7 +72,7 @@ public class Song implements Comparable<Song> {
result = 31 * result + title.hashCode();
result = 31 * result + album.hashCode();
result = 31 * result + songFile.hashCode();
result = 31 * result + trackNumber.hashCode();
result = 31 * result + trackNumber;
return result;
}
@ -112,14 +114,12 @@ public class Song implements Comparable<Song> {
return new File(songFile);
}
public String getTrackNumber() {
public Integer getTrackNumber() {
return trackNumber;
}
@Override
public int compareTo(Song o) {
if (trackNumber != null && o.getTrackNumber() != null && !trackNumber.isEmpty() && !o.getTrackNumber().isEmpty())
return Integer.parseInt(getTrackNumber()) - Integer.parseInt(o.getTrackNumber());
return (int) (id - o.getId());
return trackNumber - o.getTrackNumber();
}
}

View File

@ -20,5 +20,8 @@
<property name="hibernate.hbm2ddl.auto">
update
</property>
<property name="hibernate.enable_lazy_load_no_trans">
true
</property>
</session-factory>
</hibernate-configuration>

View File

@ -7,7 +7,7 @@ import musicplayer.model.Song;
import org.hibernate.Session;
import org.jaudiotagger.tag.FieldKey;
import org.jaudiotagger.tag.Tag;
import org.jaudiotagger.tag.id3.ID3v1Tag;
import org.jaudiotagger.tag.id3.ID3v11Tag;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@ -120,7 +120,7 @@ public class GatewayTest {
@Test
public void testAddSong() throws Exception {
Tag tags = new ID3v1Tag();
Tag tags = new ID3v11Tag();
tags.addField(FieldKey.ALBUM, "Test Album");
tags.addField(FieldKey.ARTIST, "Test Artist");
tags.addField(FieldKey.TRACK, "1");
@ -131,7 +131,7 @@ public class GatewayTest {
Song song = (Song)session.createCriteria(Song.class).uniqueResult();
assertEquals(song.getAlbum().getName(), metadata.album);
assertEquals(song.getArtist().getName(), metadata.artist);
assertEquals(song.getTrackNumber(), metadata.trackNumber);
assertEquals(song.getTrackNumber(), Integer.valueOf(1));
assertEquals(song.getTitle(), metadata.title);
assertEquals(song.getGenre(), metadata.genre);
}