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:
parent
45efd42793
commit
ecc789a556
@ -21,7 +21,7 @@ import java.util.stream.Collectors;
|
||||
|
||||
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 String settingsFilename = "settings.cfg";
|
||||
static final File propertiesFile = new File(settingsFilename);
|
||||
@ -59,44 +59,23 @@ public final class LibraryUtils {
|
||||
|
||||
public static void processSongsWithCallback(List<Path> rootDirectory, LibraryCallbackInterface callbackInterface){
|
||||
Thread thread = new Thread(() -> {
|
||||
rootDirectory.forEach(dir -> {
|
||||
try {
|
||||
processSongs(rootDirectory);
|
||||
callbackInterface.libraryUpdated(true);
|
||||
Files.walk(dir)
|
||||
.filter(f -> f.toString().matches(musicFileExtensionRegex)).map(LibraryUtils::autoParse)
|
||||
.forEach(x -> x.ifPresent(i -> {
|
||||
Gateway.addSong(i);
|
||||
callbackInterface.currentlyUpdating(i.toString());
|
||||
}));
|
||||
} catch (IOException e) {
|
||||
callbackInterface.libraryUpdated(false);
|
||||
}
|
||||
});
|
||||
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.
|
||||
*
|
||||
|
@ -82,6 +82,7 @@ public class Player {
|
||||
playBin.stop();
|
||||
internalThread.stop();
|
||||
thread = null;
|
||||
callbackInterface.playerStopped();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,8 @@ public class PlayerGUI implements PlayerCallbackInterface, LibraryCallbackInterf
|
||||
private JComboBox libraryDisplayType = new JComboBox();
|
||||
private Player player = new Player(this);
|
||||
private PlaylistTableModel playlistTableModel = new PlaylistTableModel(new ArrayList<>());
|
||||
private static DefaultMutableTreeNode updatingNode = new DefaultMutableTreeNode();
|
||||
private boolean libraryUpdating = false;
|
||||
|
||||
private Map<String, Runnable> libraryDisplayVariants = createDisplayVariantMap();
|
||||
|
||||
@ -91,7 +93,8 @@ public class PlayerGUI implements PlayerCallbackInterface, LibraryCallbackInterf
|
||||
sortedData.forEach((k, v) -> {
|
||||
DefaultMutableTreeNode albumNode = new DefaultMutableTreeNode(k);
|
||||
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);
|
||||
}
|
||||
@ -152,6 +155,7 @@ public class PlayerGUI implements PlayerCallbackInterface, LibraryCallbackInterf
|
||||
public void setSongHighlighting(Song playingSong) {
|
||||
int index = playlistTableModel.getSongIndex(playingSong);
|
||||
playList.setRowSelectionInterval(index, index);
|
||||
playlistTableModel.setPlayingRow(index);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -176,6 +180,8 @@ public class PlayerGUI implements PlayerCallbackInterface, LibraryCallbackInterf
|
||||
playlistTableModel.removeSong(invalidSong);
|
||||
}
|
||||
|
||||
public void playerStopped(){ playlistTableModel.setPlayingRow(-1); }
|
||||
|
||||
/**
|
||||
* Refresh the library with songs in the currently selected display format.
|
||||
*/
|
||||
@ -200,10 +206,12 @@ public class PlayerGUI implements PlayerCallbackInterface, LibraryCallbackInterf
|
||||
}
|
||||
|
||||
private void updateLibrary(){
|
||||
libraryUpdating = true;
|
||||
DefaultTreeModel model = new DefaultTreeModel(new DefaultMutableTreeNode());
|
||||
DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) model.getRoot();
|
||||
DefaultMutableTreeNode newNode = new DefaultMutableTreeNode("Updating Library...");
|
||||
addNodeToTreeModel(model, parentNode, newNode);
|
||||
addNodeToTreeModel(model, parentNode, updatingNode);
|
||||
libraryView.setModel(model);
|
||||
List<Path> dirs = LibraryUtils.getLibraryDirectories().stream().map(File::toPath).collect(Collectors.toList());
|
||||
LibraryUtils.processSongsWithCallback(dirs, this);
|
||||
@ -213,6 +221,13 @@ public class PlayerGUI implements PlayerCallbackInterface, LibraryCallbackInterf
|
||||
public void libraryUpdated(boolean successful) {
|
||||
if (successful)
|
||||
refreshLibrary();
|
||||
libraryUpdating = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void currentlyUpdating(String name) {
|
||||
updatingNode.setUserObject(name);
|
||||
((DefaultTreeModel)libraryView.getModel()).nodeChanged(updatingNode);
|
||||
}
|
||||
|
||||
private Map<String, Runnable> createDisplayVariantMap() {
|
||||
@ -247,7 +262,7 @@ public class PlayerGUI implements PlayerCallbackInterface, LibraryCallbackInterf
|
||||
libraryAndComboboxPane.setLayout(new BorderLayout(0, 0));
|
||||
libraryAndPlaylistPane.setLeftComponent(libraryAndComboboxPane);
|
||||
libraryDisplayType.addItemListener(e -> {
|
||||
if (e.getStateChange() == ItemEvent.SELECTED)
|
||||
if (!libraryUpdating && e.getStateChange() == ItemEvent.SELECTED)
|
||||
libraryDisplayVariants.get(libraryDisplayType.getSelectedItem().toString()).run();
|
||||
});
|
||||
libraryAndComboboxPane.add(libraryDisplayType, BorderLayout.NORTH);
|
||||
@ -278,6 +293,9 @@ public class PlayerGUI implements PlayerCallbackInterface, LibraryCallbackInterf
|
||||
JScrollPane playlistScroll = new JScrollPane();
|
||||
playList.setRowSelectionAllowed(true);
|
||||
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();
|
||||
JMenuItem menuItem = new JMenuItem("Remove");
|
||||
menuItem.addActionListener((e) -> playlistTableModel.removeSong(playList.getSelectedRows()));
|
||||
|
@ -3,4 +3,6 @@ package musicplayer.callbacks;
|
||||
public interface LibraryCallbackInterface {
|
||||
|
||||
void libraryUpdated(boolean successful);
|
||||
|
||||
void currentlyUpdating(String name);
|
||||
}
|
||||
|
@ -14,4 +14,6 @@ public interface PlayerCallbackInterface {
|
||||
|
||||
void removeInvalidSong(Song invalidSong);
|
||||
|
||||
void playerStopped();
|
||||
|
||||
}
|
||||
|
@ -19,7 +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")
|
||||
@OrderBy("discNumber ASC, trackNumber ASC")
|
||||
private Set<Song> songs;
|
||||
@Lob
|
||||
@Column(name = "art", nullable = true, length = 10000)
|
||||
|
@ -84,4 +84,9 @@ public class ExtractedMetadata {
|
||||
g.dispose();
|
||||
return newImage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return title + " - " + artist;
|
||||
}
|
||||
}
|
||||
|
@ -3,15 +3,14 @@ package musicplayer.swingmodels;
|
||||
import musicplayer.model.Song;
|
||||
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class PlaylistTableModel extends AbstractTableModel {
|
||||
|
||||
private List<Song> songList;
|
||||
private int playingRow = -1;
|
||||
|
||||
public PlaylistTableModel(List<Song> songList){
|
||||
this.songList = songList;
|
||||
@ -24,7 +23,7 @@ public class PlaylistTableModel extends AbstractTableModel {
|
||||
|
||||
@Override
|
||||
public int getColumnCount() {
|
||||
return 4;
|
||||
return 6;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -32,10 +31,12 @@ public class PlaylistTableModel extends AbstractTableModel {
|
||||
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;
|
||||
case 0: o = (playingRow == rowIndex) ? "▶" : " "; break;
|
||||
case 1: o = song.getTrackNumber(); break;
|
||||
case 2: o = song.getTitle(); break;
|
||||
case 3: o = song.getArtist(); break;
|
||||
case 4: o = song.getAlbum(); break;
|
||||
case 5: o = song.getDiscNumber(); break;
|
||||
}
|
||||
return o;
|
||||
}
|
||||
@ -49,10 +50,12 @@ public class PlaylistTableModel extends AbstractTableModel {
|
||||
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;
|
||||
case 0 : name = " "; break;
|
||||
case 1: name = "Track"; break;
|
||||
case 2: name = "Title"; break;
|
||||
case 3: name = "Artist"; break;
|
||||
case 4: name = "Album"; break;
|
||||
case 5: name = "DiscNo"; break;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
@ -108,4 +111,9 @@ public class PlaylistTableModel extends AbstractTableModel {
|
||||
public Optional<Song> getSong(int index){
|
||||
return songList.size() > 0 && index >= 0 && index < songList.size() ? Optional.of(songList.get(index)) : Optional.empty();
|
||||
}
|
||||
|
||||
public void setPlayingRow(int index){
|
||||
playingRow = index;
|
||||
fireTableDataChanged();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user