import java.awt.*; 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.Scanner; import com.formdev.flatlaf.FlatIntelliJLaf; import javax.swing.*; import javax.swing.text.DefaultCaret; import static UI.Modal.showTextFileChooser; public class Main extends JFrame { final static String BLACKLIST = "blacklist.txt"; private static String COMPLETED_DIR = "completed"; String textPath = ""; static JTextArea outputArea = new JTextArea(""); JPanel panel = new JPanel(); JScrollPane scrollPane; JButton songsGen = new JButton("Generate text file"); JButton editButton = new JButton("Edit Tags"); JButton startButton = new JButton("Set .txt File"); JButton configureDownloadButton = new JButton("Configure Download File Interactively"); JButton setOutputDirButton = new JButton("Set MP3 Output Directory"); JCheckBox defaultFileBox = new JCheckBox("Use location of last file"); JCheckBox useBlacklistBox = new JCheckBox("Use Blacklist.txt"); JProgressBar progressBar = new JProgressBar(); JLabel title = new JLabel("YouTube to MP3 Auto Tagging [CrossPlatform]"); Boolean useBlacklist = false; Boolean readyState = false; public Main() { initializeComponents(); initializeActionsListeners(); createDirectories(); } public static void main(String[] args) { FlatIntelliJLaf.setup(); new Main().setVisible(true); } /** * Calculate the percentage for progress bar * @param current The current number of songs downloaded * @param total The total number of songs to download * @return The percentage of songs downloaded */ private int calculatePercentage(int current, int total) { return (int) (((double) current / (double) total) * 100); } public void downloadAndTag(){ ArrayList songs = FileUtility.txtToList(textPath); int totalSongs = songs.size(); int songsProcessed = 0; for(String line: songs){ System.out.println(line); if(line.contains(",")){ String[] parts = line.split(","); String url = parts[0]; String stamp = parts[1]; Downloader downloader = new Downloader(COMPLETED_DIR, outputArea); if(!downloader.download(url, stamp)){ UI.Modal.showError("Error downloading song: " + url + " at timestamp: " + stamp); } } else{ Downloader downloader = new Downloader(COMPLETED_DIR, outputArea); if(!downloader.download(line)){ UI.Modal.showError("Error downloading song: " + line); } } songsProcessed++; progressBar.setValue(calculatePercentage(songsProcessed, totalSongs)); } } /** * Initialize all GUI components */ private void initializeComponents() {//Initiate GUI components this.setDefaultCloseOperation(EXIT_ON_CLOSE); this.setLocationRelativeTo(null); this.setIconImage(new ImageIcon("icon.png").getImage()); this.add(panel); panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS)); scrollPane = new JScrollPane(outputArea); scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); outputArea.setEditable(true); outputArea.setLineWrap(true); DefaultCaret caret = (DefaultCaret) outputArea.getCaret(); caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE); panel.add(Box.createRigidArea(new Dimension(0, 5))); panel.setBorder(BorderFactory.createEmptyBorder(25, 10, 20, 10)); startButton.setAlignmentX(CENTER_ALIGNMENT); startButton.setSize(new Dimension(300, 20)); title.setAlignmentX(Component.CENTER_ALIGNMENT); defaultFileBox.setAlignmentX(Component.CENTER_ALIGNMENT); useBlacklistBox.setAlignmentX(Component.CENTER_ALIGNMENT); editButton.setAlignmentX(Component.CENTER_ALIGNMENT); songsGen.setAlignmentX(Component.CENTER_ALIGNMENT); progressBar.setStringPainted(true); progressBar.setFont(new Font("Verdana", Font.PLAIN, 12)); title.setFont(new Font("Verdana", Font.BOLD, 16)); panel.add(title); panel.add(Box.createVerticalStrut(10)); panel.add(progressBar); panel.add(Box.createVerticalStrut(10)); panel.add(startButton); panel.add(defaultFileBox); panel.add(useBlacklistBox); panel.add(Box.createVerticalStrut(8)); panel.add(scrollPane); panel.add(Box.createVerticalStrut(5)); panel.add(editButton); panel.add(Box.createVerticalStrut(5)); outputArea.setEditable(false); configureDownloadButton.setAlignmentX(Component.CENTER_ALIGNMENT); panel.add(configureDownloadButton); this.setSize(550, 450); this.setTitle("YTMP3Tagger"); } /** * Initialize all action listeners for buttons */ private void initializeActionsListeners() { //Add all actionlisteners for buttons defaultFileBox.addActionListener(e -> useLastInputTextFileLocation()); useBlacklistBox.addActionListener(e -> useBlacklist = useBlacklistBox.isSelected()); startButton.addActionListener(e -> startDownloadTagJobs()); editButton.addActionListener(e -> new TagEditorScreen().setVisible(true)); configureDownloadButton.addActionListener(e -> new DownloadConfigPane().setVisible(true)); } private void writeFileContentsToOutputArea(String path){ File file = new File(path); try { Scanner scanner = new Scanner(file); while (scanner.hasNextLine()){ String line = scanner.nextLine(); outputArea.setText(outputArea.getText() + "\n" + line); } } catch (FileNotFoundException e) { UI.Modal.showError("Unable to display contents of input file? Did you delete it?"); } } /** * Create the directories for the downloaded and completed files */ public void createDirectories(){ Path completedDirPath = Paths.get(COMPLETED_DIR); try { Files.createDirectories(completedDirPath); } catch (IOException e) { UI.Modal.showError("Unable to create directories for completed files"); } } /** * Set the text file input path to the location that was used last time */ private void useLastInputTextFileLocation(){ if (defaultFileBox.isSelected()) { File file = new File("lastFile.txt"); if (!file.exists()) { defaultFileBox.setSelected(false); JOptionPane.showMessageDialog(null, "Unable to find the location of your previous file, please select a new one"); return; } BufferedReader br; try { br = new BufferedReader(new FileReader(file)); String line = br.readLine(); if (line == null) { defaultFileBox.setSelected(false); JOptionPane.showMessageDialog(null, "Unable to find the location of your previous file, please select a new one"); return; } textPath = line; COMPLETED_DIR = textPath.substring(0, textPath.lastIndexOf(File.separator)); readyState = true; startButton.setText("Start Download"); outputArea.setText(outputArea.getText() + "\n" + "Ready to begin downloading. Press the button"); writeFileContentsToOutputArea(textPath); System.out.println("Ready to begin downloading. Press the button"); } catch (Exception ex) { UI.Modal.showError("Unable to read the last file path. Please select a new file instead"); } } else { readyState = false; startButton.setText("Set .txt File"); textPath = ""; } } /** * Deletes any possible remaining files from previous jobs */ private void cleanRemainingFiles(){ FileUtility.deleteALlFileOfType(System.getProperty("user.dir"), "webm"); FileUtility.deleteALlFileOfType(System.getProperty("user.dir"), "json"); FileUtility.deleteALlFileOfType(System.getProperty("user.dir"), "mp3"); } /** * Starts the download and tagging process */ private void startDownloadTagJobs(){ cleanRemainingFiles(); if (!readyState) { outputArea.setText(outputArea.getText() + "\n" + "txt path has not been set. Launching chooserPane"); System.out.println(".txt path has not been set. Launching chooserPane"); String path = showTextFileChooser(); textPath = path; if(path == null){ UI.Modal.showWarning("No file has been selected... How did we get here?"); return; } COMPLETED_DIR = path.substring(0, path.lastIndexOf(File.separator)); try { if (!textPath.isEmpty()) { UI.Modal.showWarning("File has been set.\nMake sure you add a new line for each URL"); readyState = true; writeFileContentsToOutputArea(textPath); startButton.setText("Start Download"); outputArea.setText(outputArea.getText() + "\n" + "Ready to begin downloading. Press the button"); File file = new File("lastFile.txt"); if (!file.exists()) { file.createNewFile(); } FileWriter fw = new FileWriter(file); fw.write(textPath); fw.close(); System.out.println("Ready to begin downloading. Press the button"); } } catch (Exception ex) { } } else { Runnable runnable = () -> { outputArea.setText(""); startButton.setEnabled(false); downloadAndTag(); startButton.setEnabled(true); }; Thread thread = new Thread(runnable); thread.start(); } } }