Library now shows the current file being indexed when the library is updating. Disabled view mode switching while updating the library.

This commit is contained in:
neviyn 2016-02-26 15:16:54 +00:00
parent 45efd42793
commit ecc789a556
8 changed files with 65 additions and 50 deletions

View File

@ -21,7 +21,7 @@ import java.util.stream.Collectors;
public final class LibraryUtils { public final class LibraryUtils {
static final String musicFileExtensionRegex = ".*\\.(mp3|mp4|flac|ogg)"; static final String musicFileExtensionRegex = "(?iu).*\\.(mp3|mp4|flac|ogg)";
static final Properties librarySettings = new Properties(); static final Properties librarySettings = new Properties();
static final String settingsFilename = "settings.cfg"; static final String settingsFilename = "settings.cfg";
static final File propertiesFile = new File(settingsFilename); static final File propertiesFile = new File(settingsFilename);
@ -59,44 +59,23 @@ public final class LibraryUtils {
public static void processSongsWithCallback(List<Path> rootDirectory, LibraryCallbackInterface callbackInterface){ public static void processSongsWithCallback(List<Path> rootDirectory, LibraryCallbackInterface callbackInterface){
Thread thread = new Thread(() -> { Thread thread = new Thread(() -> {
try { rootDirectory.forEach(dir -> {
processSongs(rootDirectory); try {
callbackInterface.libraryUpdated(true); Files.walk(dir)
} catch (IOException e) { .filter(f -> f.toString().matches(musicFileExtensionRegex)).map(LibraryUtils::autoParse)
callbackInterface.libraryUpdated(false); .forEach(x -> x.ifPresent(i -> {
} Gateway.addSong(i);
callbackInterface.currentlyUpdating(i.toString());
}));
} catch (IOException e) {
callbackInterface.libraryUpdated(false);
}
});
callbackInterface.libraryUpdated(true);
}); });
thread.start(); thread.start();
} }
public static void processSongsWithCallback(Path rootDirectory, LibraryCallbackInterface callbackInterface){
Thread thread = new Thread(() -> {
try {
processSongs(rootDirectory);
callbackInterface.libraryUpdated(true);
} catch (IOException e) {
callbackInterface.libraryUpdated(false);
}
});
thread.start();
}
public static void processSongs(List<Path> rootDirectories) throws IOException {
for(Path rootDirectory: rootDirectories)
processSongs(rootDirectory);
}
/**
* Walk through all files and directories recursively and index any music files with a correct extension
*
* @param rootDirectory Directory from which to start searching
*/
public static void processSongs(Path rootDirectory) throws IOException {
Files.walk(rootDirectory)
.filter(f -> f.toString().matches(musicFileExtensionRegex))
.map(LibraryUtils::autoParse).forEach(x -> x.ifPresent(Gateway::addSong));
}
/** /**
* Extract music metadata from the target file. * Extract music metadata from the target file.
* *

View File

@ -82,6 +82,7 @@ public class Player {
playBin.stop(); playBin.stop();
internalThread.stop(); internalThread.stop();
thread = null; thread = null;
callbackInterface.playerStopped();
} }
} }

View File

@ -30,6 +30,8 @@ public class PlayerGUI implements PlayerCallbackInterface, LibraryCallbackInterf
private JComboBox libraryDisplayType = new JComboBox(); private JComboBox libraryDisplayType = new JComboBox();
private Player player = new Player(this); private Player player = new Player(this);
private PlaylistTableModel playlistTableModel = new PlaylistTableModel(new ArrayList<>()); private PlaylistTableModel playlistTableModel = new PlaylistTableModel(new ArrayList<>());
private static DefaultMutableTreeNode updatingNode = new DefaultMutableTreeNode();
private boolean libraryUpdating = false;
private Map<String, Runnable> libraryDisplayVariants = createDisplayVariantMap(); private Map<String, Runnable> libraryDisplayVariants = createDisplayVariantMap();
@ -91,7 +93,8 @@ public class PlayerGUI implements PlayerCallbackInterface, LibraryCallbackInterf
sortedData.forEach((k, v) -> { sortedData.forEach((k, v) -> {
DefaultMutableTreeNode albumNode = new DefaultMutableTreeNode(k); DefaultMutableTreeNode albumNode = new DefaultMutableTreeNode(k);
addNodeToTreeModel(model, parentNode, albumNode); addNodeToTreeModel(model, parentNode, albumNode);
new TreeSet<>(v).forEach(x -> addNodeToTreeModel(model, albumNode, new DefaultMutableTreeNode(x))); Collections.sort(v);
v.forEach(x -> addNodeToTreeModel(model, albumNode, new DefaultMutableTreeNode(x)));
}); });
libraryView.setModel(model); libraryView.setModel(model);
} }
@ -152,6 +155,7 @@ public class PlayerGUI implements PlayerCallbackInterface, LibraryCallbackInterf
public void setSongHighlighting(Song playingSong) { public void setSongHighlighting(Song playingSong) {
int index = playlistTableModel.getSongIndex(playingSong); int index = playlistTableModel.getSongIndex(playingSong);
playList.setRowSelectionInterval(index, index); playList.setRowSelectionInterval(index, index);
playlistTableModel.setPlayingRow(index);
} }
/** /**
@ -176,6 +180,8 @@ public class PlayerGUI implements PlayerCallbackInterface, LibraryCallbackInterf
playlistTableModel.removeSong(invalidSong); playlistTableModel.removeSong(invalidSong);
} }
public void playerStopped(){ playlistTableModel.setPlayingRow(-1); }
/** /**
* Refresh the library with songs in the currently selected display format. * Refresh the library with songs in the currently selected display format.
*/ */
@ -200,10 +206,12 @@ public class PlayerGUI implements PlayerCallbackInterface, LibraryCallbackInterf
} }
private void updateLibrary(){ private void updateLibrary(){
libraryUpdating = true;
DefaultTreeModel model = new DefaultTreeModel(new DefaultMutableTreeNode()); DefaultTreeModel model = new DefaultTreeModel(new DefaultMutableTreeNode());
DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) model.getRoot(); DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) model.getRoot();
DefaultMutableTreeNode newNode = new DefaultMutableTreeNode("Updating Library..."); DefaultMutableTreeNode newNode = new DefaultMutableTreeNode("Updating Library...");
addNodeToTreeModel(model, parentNode, newNode); addNodeToTreeModel(model, parentNode, newNode);
addNodeToTreeModel(model, parentNode, updatingNode);
libraryView.setModel(model); libraryView.setModel(model);
List<Path> dirs = LibraryUtils.getLibraryDirectories().stream().map(File::toPath).collect(Collectors.toList()); List<Path> dirs = LibraryUtils.getLibraryDirectories().stream().map(File::toPath).collect(Collectors.toList());
LibraryUtils.processSongsWithCallback(dirs, this); LibraryUtils.processSongsWithCallback(dirs, this);
@ -213,6 +221,13 @@ public class PlayerGUI implements PlayerCallbackInterface, LibraryCallbackInterf
public void libraryUpdated(boolean successful) { public void libraryUpdated(boolean successful) {
if (successful) if (successful)
refreshLibrary(); refreshLibrary();
libraryUpdating = false;
}
@Override
public void currentlyUpdating(String name) {
updatingNode.setUserObject(name);
((DefaultTreeModel)libraryView.getModel()).nodeChanged(updatingNode);
} }
private Map<String, Runnable> createDisplayVariantMap() { private Map<String, Runnable> createDisplayVariantMap() {
@ -247,7 +262,7 @@ public class PlayerGUI implements PlayerCallbackInterface, LibraryCallbackInterf
libraryAndComboboxPane.setLayout(new BorderLayout(0, 0)); libraryAndComboboxPane.setLayout(new BorderLayout(0, 0));
libraryAndPlaylistPane.setLeftComponent(libraryAndComboboxPane); libraryAndPlaylistPane.setLeftComponent(libraryAndComboboxPane);
libraryDisplayType.addItemListener(e -> { libraryDisplayType.addItemListener(e -> {
if (e.getStateChange() == ItemEvent.SELECTED) if (!libraryUpdating && e.getStateChange() == ItemEvent.SELECTED)
libraryDisplayVariants.get(libraryDisplayType.getSelectedItem().toString()).run(); libraryDisplayVariants.get(libraryDisplayType.getSelectedItem().toString()).run();
}); });
libraryAndComboboxPane.add(libraryDisplayType, BorderLayout.NORTH); libraryAndComboboxPane.add(libraryDisplayType, BorderLayout.NORTH);
@ -278,6 +293,9 @@ public class PlayerGUI implements PlayerCallbackInterface, LibraryCallbackInterf
JScrollPane playlistScroll = new JScrollPane(); JScrollPane playlistScroll = new JScrollPane();
playList.setRowSelectionAllowed(true); playList.setRowSelectionAllowed(true);
playList.setModel(playlistTableModel); playList.setModel(playlistTableModel);
playList.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
playList.getColumnModel().getColumn(0).setPreferredWidth(10);
playList.getColumnModel().getColumn(0).setMaxWidth(10);
JPopupMenu popupMenu = new JPopupMenu(); JPopupMenu popupMenu = new JPopupMenu();
JMenuItem menuItem = new JMenuItem("Remove"); JMenuItem menuItem = new JMenuItem("Remove");
menuItem.addActionListener((e) -> playlistTableModel.removeSong(playList.getSelectedRows())); menuItem.addActionListener((e) -> playlistTableModel.removeSong(playList.getSelectedRows()));

View File

@ -3,4 +3,6 @@ package musicplayer.callbacks;
public interface LibraryCallbackInterface { public interface LibraryCallbackInterface {
void libraryUpdated(boolean successful); void libraryUpdated(boolean successful);
void currentlyUpdating(String name);
} }

View File

@ -14,4 +14,6 @@ public interface PlayerCallbackInterface {
void removeInvalidSong(Song invalidSong); void removeInvalidSong(Song invalidSong);
void playerStopped();
} }

View File

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

View File

@ -84,4 +84,9 @@ public class ExtractedMetadata {
g.dispose(); g.dispose();
return newImage; return newImage;
} }
@Override
public String toString() {
return title + " - " + artist;
}
} }

View File

@ -3,15 +3,14 @@ package musicplayer.swingmodels;
import musicplayer.model.Song; import musicplayer.model.Song;
import javax.swing.table.AbstractTableModel; import javax.swing.table.AbstractTableModel;
import java.util.Collections; import java.util.*;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.IntStream; import java.util.stream.IntStream;
public class PlaylistTableModel extends AbstractTableModel { public class PlaylistTableModel extends AbstractTableModel {
private List<Song> songList; private List<Song> songList;
private int playingRow = -1;
public PlaylistTableModel(List<Song> songList){ public PlaylistTableModel(List<Song> songList){
this.songList = songList; this.songList = songList;
@ -24,7 +23,7 @@ public class PlaylistTableModel extends AbstractTableModel {
@Override @Override
public int getColumnCount() { public int getColumnCount() {
return 4; return 6;
} }
@Override @Override
@ -32,10 +31,12 @@ public class PlaylistTableModel extends AbstractTableModel {
Object o = "?"; Object o = "?";
Song song = songList.get(rowIndex); Song song = songList.get(rowIndex);
switch (columnIndex){ switch (columnIndex){
case 0: o = song.getTrackNumber(); break; case 0: o = (playingRow == rowIndex) ? "" : " "; break;
case 1: o = song.getTitle(); break; case 1: o = song.getTrackNumber(); break;
case 2: o = song.getArtist(); break; case 2: o = song.getTitle(); break;
case 3: o = song.getAlbum(); break; case 3: o = song.getArtist(); break;
case 4: o = song.getAlbum(); break;
case 5: o = song.getDiscNumber(); break;
} }
return o; return o;
} }
@ -49,10 +50,12 @@ public class PlaylistTableModel extends AbstractTableModel {
public String getColumnName(int column) { public String getColumnName(int column) {
String name = ""; String name = "";
switch (column){ switch (column){
case 0: name = "Track"; break; case 0 : name = " "; break;
case 1: name = "Title"; break; case 1: name = "Track"; break;
case 2: name = "Artist"; break; case 2: name = "Title"; break;
case 3: name = "Album"; break; case 3: name = "Artist"; break;
case 4: name = "Album"; break;
case 5: name = "DiscNo"; break;
} }
return name; return name;
} }
@ -108,4 +111,9 @@ public class PlaylistTableModel extends AbstractTableModel {
public Optional<Song> getSong(int index){ public Optional<Song> getSong(int index){
return songList.size() > 0 && index >= 0 && index < songList.size() ? Optional.of(songList.get(index)) : Optional.empty(); return songList.size() > 0 && index >= 0 && index < songList.size() ? Optional.of(songList.get(index)) : Optional.empty();
} }
public void setPlayingRow(int index){
playingRow = index;
fireTableDataChanged();
}
} }