Use Download class to download track previews into a Temp/ directory.

AudioSystem.getAudioInputStream(URL) was causing issues, so just download the files using the more robust Download class.

Signed-off-by: Jeffrey Han <itdelatrisu@gmail.com>
This commit is contained in:
Jeffrey Han 2016-10-13 04:12:47 -04:00
parent 89e8341686
commit dabfb827ee
7 changed files with 93 additions and 36 deletions

1
.gitignore vendored
View File

@ -4,6 +4,7 @@
/Skins/
/SongPacks/
/Songs/
/Temp/
/.opsu.log
/.opsu.cfg
/.opsu.db*

View File

@ -63,6 +63,7 @@ The following files and folders will be created by opsu! as needed:
files within this directory to the replay directory and saves the scores in
the scores database. Replays can be imported from osu! as well as opsu!.
* `Natives/`: The native libraries directory.
* `Temp/`: The temporary files directory. Deleted when opsu! exits.
## Building
opsu! is distributed as both a [Maven](https://maven.apache.org/) and

View File

@ -27,11 +27,15 @@ import itdelatrisu.opsu.downloads.Updater;
import itdelatrisu.opsu.render.CurveRenderState;
import itdelatrisu.opsu.ui.UI;
import java.io.IOException;
import org.codehaus.plexus.util.FileUtils;
import org.lwjgl.opengl.Display;
import org.newdawn.slick.AppGameContainer;
import org.newdawn.slick.Game;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.opengl.InternalTextureLoader;
import org.newdawn.slick.util.Log;
/**
* AppGameContainer extension that sends critical errors to ErrorHandler.
@ -142,6 +146,15 @@ public class Container extends AppGameContainer {
if (!Options.isWatchServiceEnabled())
BeatmapWatchService.destroy();
BeatmapWatchService.removeListeners();
// delete temporary directory
if (Options.TEMP_DIR.isDirectory()) {
try {
FileUtils.deleteDirectory(Options.TEMP_DIR);
} catch (IOException e) {
Log.warn(String.format("Failed to delete temp dir: %s", Options.TEMP_DIR.getAbsolutePath()), e);
}
}
}
@Override

View File

@ -94,6 +94,9 @@ public class Options {
/** Directory where natives are unpacked. */
public static final File NATIVE_DIR = new File(CACHE_DIR, "Natives/");
/** Directory where temporary files are stored (deleted on exit). */
public static final File TEMP_DIR = new File(CACHE_DIR, "Temp/");
/** Font file name. */
public static final String FONT_NAME = "DroidSansFallback.ttf";

View File

@ -22,6 +22,9 @@ import itdelatrisu.opsu.ErrorHandler;
import itdelatrisu.opsu.Options;
import itdelatrisu.opsu.audio.HitSound.SampleSet;
import itdelatrisu.opsu.beatmap.HitObject;
import itdelatrisu.opsu.downloads.Download;
import itdelatrisu.opsu.downloads.Download.DownloadListener;
import itdelatrisu.opsu.ui.UI;
import java.io.File;
import java.io.IOException;
@ -345,24 +348,58 @@ public class SoundController {
}
/**
* Plays a track from a URL.
* Plays a track from a remote URL.
* If a track is currently playing, it will be stopped.
* @param url the resource URL
* @param url the remote URL
* @param name the track file name
* @param isMP3 true if MP3, false if WAV
* @param listener the line listener
* @return the MultiClip being played
* @return true if playing, false otherwise
* @throws SlickException if any error occurred
*/
public static synchronized MultiClip playTrack(URL url, boolean isMP3, LineListener listener) throws SlickException {
public static synchronized boolean playTrack(String url, String name, boolean isMP3, LineListener listener)
throws SlickException {
// stop previous track
stopTrack();
try {
AudioInputStream audioIn = AudioSystem.getAudioInputStream(url);
currentTrack = loadClip(url.getFile(), audioIn, isMP3);
playClip(currentTrack, Options.getMusicVolume() * Options.getMasterVolume(), listener);
return currentTrack;
} catch (Exception e) {
throw new SlickException(String.format("Failed to load clip '%s'.", url.getFile(), e));
// download new track
File dir = Options.TEMP_DIR;
if (!dir.isDirectory())
dir.mkdir();
String filename = String.format("%s.%s", name, isMP3 ? "mp3" : "wav");
final File downloadFile = new File(dir, filename);
boolean complete;
if (downloadFile.isFile()) {
complete = true; // file already downloaded
} else {
Download download = new Download(url, downloadFile.getAbsolutePath());
download.setListener(new DownloadListener() {
@Override
public void completed() {}
@Override
public void error() {
UI.sendBarNotification("Failed to download track preview.");
}
});
try {
download.start().join();
} catch (InterruptedException e) {}
complete = (download.getStatus() == Download.Status.COMPLETE);
}
// play the track
if (complete) {
try {
AudioInputStream audioIn = AudioSystem.getAudioInputStream(downloadFile);
currentTrack = loadClip(filename, audioIn, isMP3);
playClip(currentTrack, Options.getMusicVolume() * Options.getMasterVolume(), listener);
return true;
} catch (Exception e) {
throw new SlickException(String.format("Failed to load clip '%s'.", url));
}
}
return false;
}
/**

View File

@ -167,12 +167,13 @@ public class Download {
/**
* Starts the download from the "waiting" status.
* @return the started download thread, or {@code null} if none started
*/
public void start() {
public Thread start() {
if (status != Status.WAITING)
return;
return null;
new Thread() {
Thread t = new Thread() {
@Override
public void run() {
// open connection
@ -274,7 +275,9 @@ public class Download {
listener.error();
}
}
}.start();
};
t.start();
return t;
}
/**

View File

@ -47,8 +47,6 @@ import itdelatrisu.opsu.ui.UI;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineListener;
@ -663,15 +661,18 @@ public class DownloadsMenu extends BasicGameState {
SoundController.stopTrack();
} else {
// play preview
try {
final URL url = new URL(serverMenu.getSelectedItem().getPreviewURL(node.getID()));
MusicController.pause();
new Thread() {
@Override
public void run() {
try {
previewID = -1;
SoundController.playTrack(url, true, new LineListener() {
final String url = serverMenu.getSelectedItem().getPreviewURL(node.getID());
MusicController.pause();
new Thread() {
@Override
public void run() {
try {
previewID = -1;
boolean playing = SoundController.playTrack(
url,
Integer.toString(node.getID()),
true,
new LineListener() {
@Override
public void update(LineEvent event) {
if (event.getType() == LineEvent.Type.STOP) {
@ -681,18 +682,16 @@ public class DownloadsMenu extends BasicGameState {
}
}
}
});
}
);
if (playing)
previewID = node.getID();
} catch (SlickException e) {
UI.sendBarNotification("Failed to load track preview. See log for details.");
Log.error(e);
}
} catch (SlickException e) {
UI.sendBarNotification("Failed to load track preview. See log for details.");
Log.error(e);
}
}.start();
} catch (MalformedURLException e) {
UI.sendBarNotification("Could not load track preview (bad URL).");
Log.error(e);
}
}
}.start();
}
return;
}