package me.aurous.utils.playlist; import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE; import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE; import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY; import java.awt.GridLayout; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.nio.file.FileSystems; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.WatchEvent; import java.nio.file.WatchKey; import java.nio.file.WatchService; import java.util.LinkedList; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import javax.swing.DefaultListModel; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JTable; import javax.swing.JTextField; import javax.swing.SwingConstants; import javax.swing.table.DefaultTableModel; import me.aurous.player.Settings; import me.aurous.services.PlaylistService; import me.aurous.services.impl.RedditService; import me.aurous.services.impl.SoundCloudService; import me.aurous.services.impl.YouTubeService; import me.aurous.swinghacks.GhostText; import me.aurous.tools.DiscoMixer; import me.aurous.tools.PlayListBuilder; import me.aurous.tools.PlayListImporter; import me.aurous.ui.listeners.ContextMenuMouseListener; import me.aurous.utils.media.MediaUtils; /** * @author Andrew * */ public class Playlist { private static final Playlist INSTANCE = new Playlist(); public static Playlist getPlaylist() { return INSTANCE; // TODO Find a better place to place the playlist instance } public boolean builderOpen; public boolean importerOpen; public boolean settingsOpen; public boolean discoOpen; public boolean aboutOpen; private List<PlaylistService> platforms = new LinkedList<>(); private ExecutorService executorService = Executors.newCachedThreadPool(); private Playlist() { platforms.add(new YouTubeService()); platforms.add(new RedditService()); platforms.add(new SoundCloudService()); } /** * @author Andrew * * Removes a row from the JTable while deleting the line from the * playlist */ public void removeSelectedRows(final JTable table) { final DefaultTableModel model = (DefaultTableModel) table.getModel(); final int[] rows = table.getSelectedRows(); removeLineFromPlayList(Settings.getLastPlayList(), (String) table.getValueAt(rows[0], 7)); for (int i = 0; i < rows.length; i++) { model.removeRow(rows[i] - i); } } public void disableDiscoInterface() { DiscoMixer.discoBuildButton.setEnabled(false); DiscoMixer.queryField.setEnabled(false); DiscoMixer.top100Button.setEnabled(false); } public void resetDiscoInterface() { DiscoMixer.discoProgressBar.setValue(0); DiscoMixer.discoProgressBar.setVisible(false); DiscoMixer.discoBuildButton.setEnabled(true); DiscoMixer.queryField.setEnabled(true); DiscoMixer.top100Button.setEnabled(true); } public void resetImporterInterface() { PlayListImporter.importProgressBar.setValue(0); PlayListImporter.importProgressBar.setVisible(false); PlayListImporter.importInstrucLabel.setText("Import Playlist"); PlayListImporter.lblEnterAPlaylist.setText("Enter a Playlist Name"); PlayListImporter.importPlayListButton.setEnabled(true); } public void disableImporterInterface() { PlayListImporter.importProgressBar.setVisible(true); PlayListImporter.importPlayListButton.setEnabled(false); PlayListImporter.importInstrucLabel.setText("Importing Playlist"); PlayListImporter.lblEnterAPlaylist.setText(""); } public void buildPlaylistFor(String name, String url, String playlistName) { PlaylistService service = getPlaylistService(name); if (service != null) { executorService.execute(() -> service.buildPlaylist(url, playlistName)); } } public void getImportRules(final String sourceURL, final String playListName) { PlaylistService service = getPlaylistService(sourceURL); if (service != null) { executorService.execute(() -> service.buildPlaylist(sourceURL, playListName)); } else { JOptionPane.showMessageDialog(null, "No importer found!", "Error", JOptionPane.ERROR_MESSAGE); PlayListImporter.importProgressBar.setVisible(false); } } public String getAddRules(final String sourceURL) { PlaylistService service = getPlaylistService(sourceURL); if (service != null) { return service.buildPlayListLine(sourceURL); } JOptionPane.showMessageDialog(null, "No importer found!", "Error", JOptionPane.ERROR_MESSAGE); return ""; } /** * popup panel to add url to playlist */ public void additionToPlayListPrompt() { if ((Settings.getLastPlayList() == null) || Settings.getLastPlayList().isEmpty()) { JOptionPane.showMessageDialog(new JFrame(), "You do not have any playlist loaded!", "Uh oh", JOptionPane.ERROR_MESSAGE); return; } final JTextField urlField = new JTextField(); urlField.addMouseListener(new ContextMenuMouseListener()); urlField.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(final MouseEvent e) { } }); new GhostText("https://www.youtube.com/watch?v=TU3b1qyEGsE", urlField); urlField.setHorizontalAlignment(SwingConstants.CENTER); final JPanel panel = new JPanel(new GridLayout(0, 1)); panel.add(new JLabel("Paste media url")); panel.add(urlField); final int result = JOptionPane.showConfirmDialog(null, panel, "Add to Playlist", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE); if (result == JOptionPane.OK_OPTION) { addUrlToPlayList(urlField.getText()); } else { } } private void addUrlToPlayList(final String url) { if (url.isEmpty()) { return; } if (url.contains("&list=")) { return; } else { try { final String filename = Settings.getLastPlayList(); final FileWriter fw = new FileWriter(filename, true); // the // true final String data = getAddRules(url); fw.write("\n" + data);// appends fw.close(); } catch (final IOException ioe) { System.err.println("IOException: " + ioe); } } } /** * popup panel to create a playlist */ public String importPlayListPrompt() { final JTextField urlField = new JTextField(); final GhostText gText = new GhostText("Enter service url", urlField); urlField.addMouseListener(new ContextMenuMouseListener()); urlField.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(final MouseEvent e) { } }); urlField.setHorizontalAlignment(SwingConstants.CENTER); gText.setHorizontalAlignment(SwingConstants.CENTER); final JPanel panel = new JPanel(new GridLayout(0, 1)); panel.add(new JLabel("Enter a PlayList URL")); panel.add(urlField); final int result = JOptionPane.showConfirmDialog(null, panel, "Add to Service", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE); if (result == JOptionPane.OK_OPTION) { if (!urlField.getText().isEmpty()) { return urlField.getText(); } } else { } return ""; } public void buildPlayList(final String playListItems, final String playListName) { final Thread thread = new Thread() { @Override public void run() { try { final String name = "data/playlist/" + playListName + ".plist"; final String header = "Title, Artist, Time, Date Added, User, Album, ALBUMART_INDEX, link"; final File file = new File(name); final PrintWriter printWriter = new PrintWriter(file); final String[] lines = playListItems.split("\n"); printWriter.println(header); for (final String line : lines) { if (builderOpen) { final String playListItem = MediaUtils.getBuiltString(line.trim()); if (!playListItem.isEmpty()) { printWriter.println(playListItem); } else { continue; } } else { printWriter.close(); deletePlayList(name); return; } } printWriter.close(); PlayListBuilder.loadingIcon.setVisible(false); PlayListBuilder.playListTextArea.setEditable(true); PlayListBuilder.buildListButton.setEnabled(true); PlayListBuilder.playListNameTextField.setEditable(true); } catch (final FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }; thread.start(); } public void deletePlayList(final JList<?> list) { final String path = list.getSelectedValue().toString(); try { final File file = new File(path); if (file.delete()) { System.out.println(file.getName() + " is deleted!"); } else { System.out.println("Delete operation is failed."); } } catch (final Exception e) { e.printStackTrace(); } } public void deletePlayList(final String path) { try { final File file = new File(path); if (file.delete()) { System.out.println(file.getName() + " is deleted!"); } else { System.out.println("Delete operation is failed."); } } catch (final Exception e) { e.printStackTrace(); } } @SuppressWarnings({ "rawtypes", "unchecked" }) public void watchPlayListDirectory(final JList<?> displayList) { try { final WatchService watcher = FileSystems.getDefault() .newWatchService(); final Path dir = Paths.get("data/playlist/"); dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY); System.out.println("Watch Service registered for dir: " + dir.getFileName()); while (true) { WatchKey key; try { key = watcher.take(); } catch (final InterruptedException ex) { return; } for (final WatchEvent<?> event : key.pollEvents()) { final WatchEvent.Kind<?> kind = event.kind(); final WatchEvent<Path> ev = (WatchEvent<Path>) event; final Path fileName = ev.context(); System.out.println(kind.name() + ": " + fileName); java.awt.EventQueue // i dont question the Java API, it works now. .invokeLater(() -> { final DefaultListModel playListModel = new DefaultListModel(); final File[] playListFolder = new File( "data/playlist/").listFiles(); if ((kind == ENTRY_CREATE) || ((kind == ENTRY_DELETE) && (playListModel != null) && (playListFolder != null))) { for (final File file : playListFolder) { playListModel.addElement(file); } displayList.setModel(playListModel); displayList.updateUI(); System.out .println("Playlist change detected"); } }); } final boolean valid = key.reset(); if (!valid) { break; } } } catch (final IOException ex) { System.err.println(ex); } } /** * @author Andrew * * Deletes line from PlayList */ public void removeLineFromPlayList(final String file, final String lineToRemove) { try { final File inFile = new File(file); if (!inFile.isFile()) { System.out.println("Parameter is not an existing file"); return; } // Construct the new file that will later be renamed to the original // filename. final File tempFile = new File(inFile.getAbsolutePath() + ".tmp"); final BufferedReader br = new BufferedReader(new FileReader(file)); final PrintWriter pw = new PrintWriter(new FileWriter(tempFile)); String line = null; // Read from the original file and write to the new // unless content matches data to be removed. while ((line = br.readLine()) != null) { if (!line.contains(lineToRemove)) { pw.println(line); pw.flush(); } } pw.close(); br.close(); // Delete the original file if (!inFile.delete()) { System.out.println("Could not delete file"); return; } // Rename the new file to the filename the original file had. if (!tempFile.renameTo(inFile)) { System.out.println("Could not rename file"); } // loadPlayList(PlayerUtils.currentPlayList); } catch (final FileNotFoundException ex) { ex.printStackTrace(); } catch (final IOException ex) { ex.printStackTrace(); } } public PlaylistService getPlaylistService(String context) { for (PlaylistService service : platforms) { if (context.contains(service.getName())) { return service; } } return null; } }