Added functionality for reading m3u playlists.

This commit is contained in:
neviyn 2016-03-09 01:58:19 +00:00
parent 1eceab8227
commit 68aca0d416
4 changed files with 90 additions and 23 deletions

View File

@ -10,6 +10,8 @@ import musicplayer.db.Gateway;
import musicplayer.model.Album; import musicplayer.model.Album;
import musicplayer.model.Song; import musicplayer.model.Song;
import musicplayer.swingmodels.PlaylistTableModel; import musicplayer.swingmodels.PlaylistTableModel;
import musicplayer.util.LibraryUtils;
import musicplayer.util.PlaylistUtils;
import javax.swing.*; import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter; import javax.swing.filechooser.FileNameExtensionFilter;
@ -17,7 +19,10 @@ import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode; import javax.swing.tree.TreeNode;
import java.awt.*; import java.awt.*;
import java.awt.event.*; 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.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Path; import java.nio.file.Path;
@ -432,19 +437,20 @@ public class PlayerGUI implements PlayerCallbackInterface, LibraryCallbackInterf
}); });
playlistTools.add(menuItem); playlistTools.add(menuItem);
FileNameExtensionFilter m3uExtensionFilter = new FileNameExtensionFilter("m3u playlist", "m3u");
menuItem = new JMenuItem("Save Playlist"); menuItem = new JMenuItem("Save Playlist");
menuItem.addActionListener(e -> { menuItem.addActionListener(e -> {
if(!playlistTableModel.isEmpty()) { if(!playlistTableModel.isEmpty()) {
JFileChooser fileChooser = new JFileChooser(); JFileChooser fileChooser = new JFileChooser();
fileChooser.setDialogType(JFileChooser.SAVE_DIALOG); fileChooser.setDialogType(JFileChooser.SAVE_DIALOG);
fileChooser.setSelectedFile(new File("playlist.m3u")); fileChooser.setSelectedFile(new File("playlist.m3u"));
fileChooser.setFileFilter(new FileNameExtensionFilter("m3u playlist", "m3u")); fileChooser.setFileFilter(m3uExtensionFilter);
if (fileChooser.showSaveDialog(mainPanel) == JFileChooser.APPROVE_OPTION) { if (fileChooser.showSaveDialog(mainPanel) == JFileChooser.APPROVE_OPTION) {
String filename = fileChooser.getSelectedFile().toString(); String filename = fileChooser.getSelectedFile().toString();
if (!filename.endsWith(".m3u")) if (!filename.endsWith(".m3u"))
filename += ".m3u"; filename += ".m3u";
try { try {
playlistTableModel.writePlaylistToFile(new File(filename)); PlaylistUtils.writePlaylistToFile(playlistTableModel.getSongList(), new File(filename));
} catch (IOException e1) { } catch (IOException e1) {
JOptionPane.showMessageDialog(null, e1.getMessage() + "\n" + Arrays.toString(e1.getStackTrace()), "Error", JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(null, e1.getMessage() + "\n" + Arrays.toString(e1.getStackTrace()), "Error", JOptionPane.ERROR_MESSAGE);
} }
@ -453,6 +459,17 @@ public class PlayerGUI implements PlayerCallbackInterface, LibraryCallbackInterf
}); });
playlistTools.add(menuItem); playlistTools.add(menuItem);
menuItem = new JMenuItem("Open Playlist");
menuItem.addActionListener(e -> {
JFileChooser fileChooser = new JFileChooser();
fileChooser.setDialogType(JFileChooser.OPEN_DIALOG);
fileChooser.setFileFilter(m3uExtensionFilter);
if(fileChooser.showOpenDialog(mainPanel) == JFileChooser.APPROVE_OPTION){
PlaylistUtils.readPlaylistFromFile(fileChooser.getSelectedFile()).stream().forEach(playlistTableModel::addSong);
}
});
playlistTools.add(menuItem);
// Add everything to the menu bar itself // Add everything to the menu bar itself
menuBar.add(playlistTools); menuBar.add(playlistTools);
return menuBar; return menuBar;

View File

@ -3,7 +3,6 @@ package musicplayer.swingmodels;
import musicplayer.model.Song; import musicplayer.model.Song;
import javax.swing.table.AbstractTableModel; import javax.swing.table.AbstractTableModel;
import java.io.*;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
@ -170,20 +169,10 @@ public class PlaylistTableModel extends AbstractTableModel {
fireTableDataChanged(); fireTableDataChanged();
} }
public String getM3UPlaylist(){ /**
StringBuilder output = new StringBuilder("#EXTM3U\n"); * @return Songs currently in the playlist.
songList.forEach(x -> output.append(x.getM3UFormatString())); */
return output.toString(); public List<Song> getSongList(){
} return songList;
public void writePlaylistToFile(File targetFile) throws IOException {
if(!targetFile.exists())
targetFile.createNewFile();
try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(targetFile), "utf-8"))) {
writer.write("#EXTM3U\n");
for(Song song : songList){
writer.write(song.getM3UFormatString());
}
}
} }
} }

View File

@ -1,4 +1,4 @@
package musicplayer; package musicplayer.util;
import musicplayer.callbacks.LibraryCallbackInterface; import musicplayer.callbacks.LibraryCallbackInterface;
import musicplayer.db.Gateway; import musicplayer.db.Gateway;
@ -16,7 +16,7 @@ import java.nio.file.Path;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
final class LibraryUtils { public final class LibraryUtils {
private static final String musicFileExtensionRegex = "(?iu).*\\.(mp3|mp4|flac|ogg)"; private static final String musicFileExtensionRegex = "(?iu).*\\.(mp3|mp4|flac|ogg)";
private static Thread updaterThread; private static Thread updaterThread;
@ -35,7 +35,7 @@ final class LibraryUtils {
.filter(f -> f.toString().matches(musicFileExtensionRegex)).map(LibraryUtils::autoParse) .filter(f -> f.toString().matches(musicFileExtensionRegex)).map(LibraryUtils::autoParse)
.forEach(x -> x.ifPresent(i -> { .forEach(x -> x.ifPresent(i -> {
Gateway.addSong(i); Gateway.addSong(i);
if(callbacksEnabled) if (callbacksEnabled)
callbackInterface.currentlyUpdating(i.toString()); callbackInterface.currentlyUpdating(i.toString());
})); }));
} catch (IOException e) { } catch (IOException e) {
@ -63,7 +63,7 @@ final class LibraryUtils {
* @param targetFile Path to file to extract metadata from. * @param targetFile Path to file to extract metadata from.
* @return Metadata contained in targetFile. * @return Metadata contained in targetFile.
*/ */
private static Optional<ExtractedMetadata> autoParse(Path targetFile) { public static Optional<ExtractedMetadata> autoParse(Path targetFile) {
Tag audioTags = null; Tag audioTags = null;
try { try {
audioTags = AudioFileIO.read(targetFile.toFile()).getTag(); audioTags = AudioFileIO.read(targetFile.toFile()).getTag();

View File

@ -0,0 +1,61 @@
package musicplayer.util;
import musicplayer.model.Album;
import musicplayer.model.Artist;
import musicplayer.model.Song;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
public final class PlaylistUtils {
/**
* Write a list of songs to a file as an m3u format playlist file.
* @param playlist Playlist of songs to write.
* @param targetFile File to write playlist into.
* @throws IOException
*/
public static void writePlaylistToFile(List<Song> playlist, File targetFile) throws IOException {
if(!targetFile.exists())
targetFile.createNewFile();
try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(targetFile), "utf-8"))) {
writer.write("#EXTM3U\n");
for(Song song : playlist){
writer.write(song.getM3UFormatString());
}
}
}
/**
* Read songs in from an m3u playlist.
* Songs in the playlist with files that don't actually exists will be dropped.
* @param targetFile File to read m3u playlist data from.
* @return List of songs contained in the playlist.
*/
public static List<Song> readPlaylistFromFile(File targetFile){
List<Song> result = new ArrayList<>();
if(targetFile.exists()){
try {
List<String> playlistData = Files.lines(targetFile.toPath()).filter(x -> !x.isEmpty() && !x.contains("#EXTINF")).collect(Collectors.toList());
if(playlistData.get(0).equals("#EXTM3U")){
playlistData.remove(0);
List<Path> songPaths = playlistData.stream().map(Paths::get).collect(Collectors.toList());
for(int i = 0; i < songPaths.size(); i++){
if(!Files.exists(songPaths.get(i))){ // If song file doesn't exists, try treating it as relative
songPaths.set(i, Paths.get(targetFile.getParent(), songPaths.get(i).toString()));
}
}
songPaths.stream().map(LibraryUtils::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) { }
}
return result;
}
}