Moved LibraryUtils to default implementations in ILibrary.
This commit is contained in:
parent
ac2ddda462
commit
4ffca843b4
@ -4,9 +4,13 @@ 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.
|
||||
* @param message Error message.
|
||||
*/
|
||||
void libraryUpdated(boolean successful);
|
||||
void libraryUpdated(String message);
|
||||
/**
|
||||
* Call this after performing library updates so the front-end knows that updating has completed.
|
||||
*/
|
||||
void libraryUpdated();
|
||||
|
||||
/**
|
||||
* Update the current display with the file/folder currently being parsed.
|
||||
|
@ -1,10 +1,67 @@
|
||||
package musicplayer.library;
|
||||
|
||||
import musicplayer.callbacks.LibraryCallbackInterface;
|
||||
import musicplayer.db.IDatabase;
|
||||
import musicplayer.model.ExtractedMetadata;
|
||||
import musicplayer.model.HasSongs;
|
||||
import org.jaudiotagger.audio.AudioFileIO;
|
||||
import org.jaudiotagger.audio.exceptions.CannotReadException;
|
||||
import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException;
|
||||
import org.jaudiotagger.audio.exceptions.ReadOnlyFileException;
|
||||
import org.jaudiotagger.tag.Tag;
|
||||
import org.jaudiotagger.tag.TagException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface ILibrary {
|
||||
void showSongs();
|
||||
<T extends HasSongs & Comparable<T>> void showGroupedSongs(Class<T> grouping);
|
||||
void updateLibrary();
|
||||
void refreshLibrary();
|
||||
|
||||
String musicFileExtensionRegex = "(?iu).*\\.(mp3|mp4|flac|ogg)";
|
||||
|
||||
/**
|
||||
* Add all songs contained with all paths in rootDirectory to the database.
|
||||
* @param rootDirectory Folder(s) containing music files to index.
|
||||
* @param callbackInterface Object to send callback data to, set to null if the application doesn't require update data.
|
||||
*/
|
||||
static void processSongsWithCallback(IDatabase database, List<Path> rootDirectory, LibraryCallbackInterface callbackInterface){
|
||||
boolean callbacksEnabled = callbackInterface != null;
|
||||
rootDirectory.forEach(dir -> {
|
||||
try {
|
||||
Files.walk(dir)
|
||||
.filter(f -> f.toString().matches(musicFileExtensionRegex)).map(ILibrary::autoParse)
|
||||
.forEach(x -> x.ifPresent(i -> {
|
||||
database.addSong(i);
|
||||
if (callbacksEnabled)
|
||||
callbackInterface.currentlyUpdating(i.toString());
|
||||
}));
|
||||
} catch (IOException e) {
|
||||
if(callbacksEnabled)
|
||||
callbackInterface.libraryUpdated(e.getMessage());
|
||||
}
|
||||
});
|
||||
if(callbacksEnabled)
|
||||
callbackInterface.libraryUpdated();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract music metadata from the target file.
|
||||
*
|
||||
* @param targetFile Path to file to extract metadata from.
|
||||
* @return Metadata contained in targetFile.
|
||||
*/
|
||||
static Optional<ExtractedMetadata> autoParse(Path targetFile) {
|
||||
Tag audioTags = null;
|
||||
try {
|
||||
audioTags = AudioFileIO.read(targetFile.toFile()).getTag();
|
||||
} catch (CannotReadException | IOException | ReadOnlyFileException | TagException | InvalidAudioFrameException ignored) {
|
||||
}
|
||||
return audioTags == null ? Optional.empty() : Optional.of(new ExtractedMetadata(audioTags, targetFile.toFile()));
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ import musicplayer.model.Artist;
|
||||
import musicplayer.model.HasSongs;
|
||||
import musicplayer.model.Song;
|
||||
import musicplayer.playlist.IPlaylist;
|
||||
import musicplayer.util.LibraryUtils;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
@ -137,7 +136,8 @@ public class JTreeLibrary extends JPanel implements ILibrary, LibraryCallbackInt
|
||||
addNodeToTreeModel(model, parentNode, updatingNode);
|
||||
libraryTree.setModel(model);
|
||||
List<Path> dirs = ConfigManager.getLibraryDirectories().stream().map(File::toPath).collect(Collectors.toList());
|
||||
LibraryUtils.processSongsWithCallback(database, dirs, this);
|
||||
Thread updaterThread = new Thread(() -> ILibrary.processSongsWithCallback(database, dirs, this), "updater");
|
||||
updaterThread.start();
|
||||
}
|
||||
}
|
||||
|
||||
@ -165,7 +165,12 @@ public class JTreeLibrary extends JPanel implements ILibrary, LibraryCallbackInt
|
||||
}
|
||||
|
||||
@Override
|
||||
public void libraryUpdated(boolean successful) {
|
||||
public void libraryUpdated(String message) {
|
||||
JOptionPane.showMessageDialog(this, message, "Update Error", JOptionPane.ERROR_MESSAGE);
|
||||
libraryUpdated();
|
||||
}
|
||||
|
||||
public void libraryUpdated() {
|
||||
libraryUpdating.set(false);
|
||||
refreshLibrary();
|
||||
}
|
||||
|
@ -1,75 +0,0 @@
|
||||
package musicplayer.util;
|
||||
|
||||
import musicplayer.callbacks.LibraryCallbackInterface;
|
||||
import musicplayer.db.IDatabase;
|
||||
import musicplayer.model.ExtractedMetadata;
|
||||
import org.jaudiotagger.audio.AudioFileIO;
|
||||
import org.jaudiotagger.audio.exceptions.CannotReadException;
|
||||
import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException;
|
||||
import org.jaudiotagger.audio.exceptions.ReadOnlyFileException;
|
||||
import org.jaudiotagger.tag.Tag;
|
||||
import org.jaudiotagger.tag.TagException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public final class LibraryUtils {
|
||||
|
||||
private static final String musicFileExtensionRegex = "(?iu).*\\.(mp3|mp4|flac|ogg)";
|
||||
private static Thread updaterThread;
|
||||
|
||||
/**
|
||||
* Add all songs contained with all paths in rootDirectory to the database.
|
||||
* @param rootDirectory Folder(s) containing music files to index.
|
||||
* @param callbackInterface Object to send callback data to, set to null if the application doesn't require update data.
|
||||
*/
|
||||
public static void processSongsWithCallback(IDatabase database, List<Path> rootDirectory, LibraryCallbackInterface callbackInterface){
|
||||
boolean callbacksEnabled = callbackInterface != null;
|
||||
updaterThread = new Thread(() -> {
|
||||
rootDirectory.forEach(dir -> {
|
||||
try {
|
||||
Files.walk(dir)
|
||||
.filter(f -> f.toString().matches(musicFileExtensionRegex)).map(LibraryUtils::autoParse)
|
||||
.forEach(x -> x.ifPresent(i -> {
|
||||
database.addSong(i);
|
||||
if (callbacksEnabled)
|
||||
callbackInterface.currentlyUpdating(i.toString());
|
||||
}));
|
||||
} catch (IOException e) {
|
||||
if(callbacksEnabled)
|
||||
callbackInterface.libraryUpdated(false);
|
||||
}
|
||||
});
|
||||
if(callbacksEnabled)
|
||||
callbackInterface.libraryUpdated(true);
|
||||
}, "libraryUpdater");
|
||||
updaterThread.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Halt execution of the library updater thread (if running)
|
||||
*/
|
||||
public static void cancelProcessing(){
|
||||
if(updaterThread.isAlive())
|
||||
updaterThread.interrupt();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract music metadata from the target file.
|
||||
*
|
||||
* @param targetFile Path to file to extract metadata from.
|
||||
* @return Metadata contained in targetFile.
|
||||
*/
|
||||
public static Optional<ExtractedMetadata> autoParse(Path targetFile) {
|
||||
Tag audioTags = null;
|
||||
try {
|
||||
audioTags = AudioFileIO.read(targetFile.toFile()).getTag();
|
||||
} catch (CannotReadException | IOException | ReadOnlyFileException | TagException | InvalidAudioFrameException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return audioTags == null ? Optional.empty() : Optional.of(new ExtractedMetadata(audioTags, targetFile.toFile()));
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package musicplayer.util;
|
||||
|
||||
import musicplayer.library.ILibrary;
|
||||
import musicplayer.model.Album;
|
||||
import musicplayer.model.Artist;
|
||||
import musicplayer.model.Song;
|
||||
@ -51,7 +52,7 @@ public final class PlaylistUtils {
|
||||
songPaths.set(i, Paths.get(targetFile.getParent(), songPaths.get(i).toString()));
|
||||
}
|
||||
}
|
||||
songPaths.stream().map(LibraryUtils::autoParse).filter(Optional::isPresent).map(Optional::get)
|
||||
songPaths.stream().map(ILibrary::autoParse).filter(Optional::isPresent).map(Optional::get)
|
||||
.forEach(x -> result.add(new Song(x.getTrackNumber(), x.getDiscNumber(), x.getTitle(), new Artist(x.getArtist()), new Album(x.getAlbum()), x.getGenre(), x.getSongFile())));
|
||||
}
|
||||
} catch (IOException ignored) { }
|
||||
|
79
src/test/java/musicplayer/library/ILibraryTest.java
Normal file
79
src/test/java/musicplayer/library/ILibraryTest.java
Normal file
@ -0,0 +1,79 @@
|
||||
package musicplayer.library;
|
||||
|
||||
import musicplayer.callbacks.LibraryCallbackInterface;
|
||||
import musicplayer.db.HibernateDatabase;
|
||||
import musicplayer.db.IDatabase;
|
||||
import musicplayer.model.ExtractedMetadata;
|
||||
import musicplayer.model.Song;
|
||||
import org.jaudiotagger.audio.AudioFileIO;
|
||||
import org.jaudiotagger.tag.FieldKey;
|
||||
import org.jaudiotagger.tag.Tag;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class ILibraryTest {
|
||||
|
||||
@Test
|
||||
public void testAutoParse() throws Exception {
|
||||
File inputFile = new File(ILibraryTest.class.getResource("/sample.mp3").getFile());
|
||||
Optional<ExtractedMetadata> data = ILibrary.autoParse(inputFile.toPath());
|
||||
Tag audioTags = AudioFileIO.read(inputFile).getTag();
|
||||
assertTrue(data.isPresent());
|
||||
ExtractedMetadata internal = data.get();
|
||||
assertEquals(audioTags.getFirst(FieldKey.ARTIST), internal.getArtist());
|
||||
assertEquals(audioTags.getFirst(FieldKey.GENRE), internal.getGenre());
|
||||
assertEquals(audioTags.getFirst(FieldKey.TITLE), internal.getTitle());
|
||||
assertEquals(audioTags.getFirst(FieldKey.ALBUM), internal.getAlbum());
|
||||
assertEquals(audioTags.getFirst(FieldKey.TRACK), internal.getTrackNumber());
|
||||
assertEquals(audioTags.getFirst(FieldKey.DISC_NO), internal.getDiscNumber());
|
||||
assertEquals(inputFile.getPath(), internal.getSongFile());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAutoParseInvalidFile() throws Exception {
|
||||
File inputFile = new File("");
|
||||
Optional<ExtractedMetadata> data = ILibrary.autoParse(inputFile.toPath());
|
||||
assertFalse(data.isPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessSongsWithCallback() throws Exception {
|
||||
CallbackInterface callbackInterface = new CallbackInterface();
|
||||
Path dir = new File(ILibraryTest.class.getResource("/sample.mp3").getFile()).getParentFile().toPath();
|
||||
List<Path> dirList = new ArrayList<>();
|
||||
dirList.add(dir);
|
||||
IDatabase database = new HibernateDatabase(true);
|
||||
ILibrary.processSongsWithCallback(database, dirList, callbackInterface);
|
||||
assertEquals(1, database.listAllT(Song.class).get().size());
|
||||
assertTrue(callbackInterface.status);
|
||||
assertFalse(callbackInterface.error);
|
||||
}
|
||||
|
||||
private class CallbackInterface implements LibraryCallbackInterface{
|
||||
public boolean status = false;
|
||||
public String update = "";
|
||||
public boolean error = false;
|
||||
|
||||
@Override
|
||||
public void libraryUpdated(String message) {
|
||||
error = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void libraryUpdated() {
|
||||
status = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void currentlyUpdating(String name) {
|
||||
update = name;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
package musicplayer.player;
|
||||
|
||||
import musicplayer.library.ILibrary;
|
||||
import musicplayer.model.Song;
|
||||
import musicplayer.playlist.IPlaylist;
|
||||
import musicplayer.playlist.JTablePlaylist;
|
||||
import musicplayer.util.LibraryUtils;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
@ -16,7 +16,7 @@ public class GStreamerPlayerTest {
|
||||
|
||||
GStreamerPlayer player;
|
||||
IPlaylist playlist;
|
||||
Song sampleSong = new Song(LibraryUtils.autoParse(
|
||||
Song sampleSong = new Song(ILibrary.autoParse(
|
||||
new File(GStreamerPlayerTest.class.getResource("/sample.mp3").getFile()).toPath()).get());
|
||||
|
||||
@Before
|
||||
|
Loading…
Reference in New Issue
Block a user