diff --git a/src/main/java/moe/nekojimi/chords/Downloader.java b/src/main/java/moe/nekojimi/chords/Downloader.java index 9f5c0a5..f030efd 100644 --- a/src/main/java/moe/nekojimi/chords/Downloader.java +++ b/src/main/java/moe/nekojimi/chords/Downloader.java @@ -6,8 +6,12 @@ package moe.nekojimi.chords; import java.io.File; +import java.io.IOException; import java.io.InputStream; import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.attribute.FileAttribute; +import java.nio.file.attribute.PosixFilePermission; import java.util.LinkedList; import java.util.List; import java.util.Queue; @@ -20,6 +24,9 @@ import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; +import javax.json.Json; +import javax.json.JsonObject; +import javax.json.JsonReader; /** * @@ -33,6 +40,8 @@ public class Downloader implements Consumer private Consumer next; private BiConsumer messageHandler; + private File downloadDir = null; + public Downloader() { @@ -42,6 +51,7 @@ public class Downloader implements Consumer public void accept(Song song) { downloadQueue.add(song); + getInfo(song); exec.submit(new Runnable() { @Override @@ -57,29 +67,49 @@ public class Downloader implements Consumer this.next = next; } + private void getInfo(Song song) + { + try + { + String cmd = "/usr/bin/youtube-dl --skip-download --print-json " + song.getUrl().toString(); + Process exec = runCommand(cmd, 5); + InputStream input = exec.getInputStream(); + JsonReader reader = Json.createReader(input); + JsonObject object = reader.readObject(); + if (song.getTitle() == null) + song.setTitle(object.getString("title", null)); + if (song.getArtist() == null) + song.setArtist(object.getString("uploader", null)); + } catch (Exception ex) + { + Logger.getLogger(Downloader.class.getName()).log(Level.SEVERE, null, ex); + } + } + + private File getDownloadDir() throws IOException + { + if (downloadDir == null || !downloadDir.exists() || !downloadDir.canWrite()) + downloadDir = Files.createTempDirectory("chords").toFile(); + return downloadDir; + } + private void download(Song song) { try { + messageHandler.accept(song, null); - String cmd = "/usr/bin/youtube-dl -x -f=worstaudio/worst --audio-format=wav --no-playlist --write-info-json " + song.getUrl().toString(); - System.out.println("Running command: " + cmd); -// Process exec = Runtime.getRuntime().exec().split(" ")); - Process exec = new ProcessBuilder(cmd.split(" ")).redirectOutput(ProcessBuilder.Redirect.PIPE).start(); - boolean done = exec.waitFor(300, TimeUnit.SECONDS); - if (!done) - { - exec.destroyForcibly(); - throw new RuntimeException("Took too long to download, giving up."); - } + String cmd = "/usr/bin/youtube-dl -x -f=worstaudio/worst --audio-format=wav --no-playlist -o " + getDownloadDir().getAbsolutePath() + "/%(title)s.%(ext)s " + song.getUrl().toString(); + Process exec = runCommand(cmd, 300); InputStream in = exec.getInputStream(); String output = new String(in.readAllBytes(), Charset.defaultCharset()); + String error = new String(exec.getErrorStream().readAllBytes(), Charset.defaultCharset()); System.out.println(output); Matcher matcher = Pattern.compile("Destination: (.*\\.wav)").matcher(output); if (matcher.find()) song.setLocation(new File(matcher.group(1))); else if (exec.exitValue() != 0) - throw new RuntimeException("youtube-dl failed with error " + exec.exitValue()); + throw new RuntimeException("youtube-dl failed with error " + exec.exitValue() + ", output:\n" + error); // return true; if (next != null) @@ -95,6 +125,20 @@ public class Downloader implements Consumer } } + private Process runCommand(String cmd, int timeoutSecs) throws RuntimeException, IOException, InterruptedException + { + System.out.println("Running command: " + cmd); + // Process exec = Runtime.getRuntime().exec().split(" ")); + Process exec = new ProcessBuilder(cmd.split(" ")).redirectOutput(ProcessBuilder.Redirect.PIPE).redirectError(ProcessBuilder.Redirect.PIPE).start(); + boolean done = exec.waitFor(timeoutSecs, TimeUnit.SECONDS); + if (!done) + { + exec.destroyForcibly(); + throw new RuntimeException("Took too long, giving up."); + } + return exec; + } + public BiConsumer getMessageHandler() { return messageHandler;