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:
parent
89e8341686
commit
dabfb827ee
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -4,6 +4,7 @@
|
||||||
/Skins/
|
/Skins/
|
||||||
/SongPacks/
|
/SongPacks/
|
||||||
/Songs/
|
/Songs/
|
||||||
|
/Temp/
|
||||||
/.opsu.log
|
/.opsu.log
|
||||||
/.opsu.cfg
|
/.opsu.cfg
|
||||||
/.opsu.db*
|
/.opsu.db*
|
||||||
|
|
|
@ -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
|
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!.
|
the scores database. Replays can be imported from osu! as well as opsu!.
|
||||||
* `Natives/`: The native libraries directory.
|
* `Natives/`: The native libraries directory.
|
||||||
|
* `Temp/`: The temporary files directory. Deleted when opsu! exits.
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
opsu! is distributed as both a [Maven](https://maven.apache.org/) and
|
opsu! is distributed as both a [Maven](https://maven.apache.org/) and
|
||||||
|
|
|
@ -27,11 +27,15 @@ import itdelatrisu.opsu.downloads.Updater;
|
||||||
import itdelatrisu.opsu.render.CurveRenderState;
|
import itdelatrisu.opsu.render.CurveRenderState;
|
||||||
import itdelatrisu.opsu.ui.UI;
|
import itdelatrisu.opsu.ui.UI;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.codehaus.plexus.util.FileUtils;
|
||||||
import org.lwjgl.opengl.Display;
|
import org.lwjgl.opengl.Display;
|
||||||
import org.newdawn.slick.AppGameContainer;
|
import org.newdawn.slick.AppGameContainer;
|
||||||
import org.newdawn.slick.Game;
|
import org.newdawn.slick.Game;
|
||||||
import org.newdawn.slick.SlickException;
|
import org.newdawn.slick.SlickException;
|
||||||
import org.newdawn.slick.opengl.InternalTextureLoader;
|
import org.newdawn.slick.opengl.InternalTextureLoader;
|
||||||
|
import org.newdawn.slick.util.Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AppGameContainer extension that sends critical errors to ErrorHandler.
|
* AppGameContainer extension that sends critical errors to ErrorHandler.
|
||||||
|
@ -142,6 +146,15 @@ public class Container extends AppGameContainer {
|
||||||
if (!Options.isWatchServiceEnabled())
|
if (!Options.isWatchServiceEnabled())
|
||||||
BeatmapWatchService.destroy();
|
BeatmapWatchService.destroy();
|
||||||
BeatmapWatchService.removeListeners();
|
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
|
@Override
|
||||||
|
|
|
@ -94,6 +94,9 @@ public class Options {
|
||||||
/** Directory where natives are unpacked. */
|
/** Directory where natives are unpacked. */
|
||||||
public static final File NATIVE_DIR = new File(CACHE_DIR, "Natives/");
|
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. */
|
/** Font file name. */
|
||||||
public static final String FONT_NAME = "DroidSansFallback.ttf";
|
public static final String FONT_NAME = "DroidSansFallback.ttf";
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,9 @@ import itdelatrisu.opsu.ErrorHandler;
|
||||||
import itdelatrisu.opsu.Options;
|
import itdelatrisu.opsu.Options;
|
||||||
import itdelatrisu.opsu.audio.HitSound.SampleSet;
|
import itdelatrisu.opsu.audio.HitSound.SampleSet;
|
||||||
import itdelatrisu.opsu.beatmap.HitObject;
|
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.File;
|
||||||
import java.io.IOException;
|
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.
|
* 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 isMP3 true if MP3, false if WAV
|
||||||
* @param listener the line listener
|
* @param listener the line listener
|
||||||
* @return the MultiClip being played
|
* @return true if playing, false otherwise
|
||||||
* @throws SlickException if any error occurred
|
* @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();
|
stopTrack();
|
||||||
try {
|
|
||||||
AudioInputStream audioIn = AudioSystem.getAudioInputStream(url);
|
// download new track
|
||||||
currentTrack = loadClip(url.getFile(), audioIn, isMP3);
|
File dir = Options.TEMP_DIR;
|
||||||
playClip(currentTrack, Options.getMusicVolume() * Options.getMasterVolume(), listener);
|
if (!dir.isDirectory())
|
||||||
return currentTrack;
|
dir.mkdir();
|
||||||
} catch (Exception e) {
|
String filename = String.format("%s.%s", name, isMP3 ? "mp3" : "wav");
|
||||||
throw new SlickException(String.format("Failed to load clip '%s'.", url.getFile(), e));
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -167,12 +167,13 @@ public class Download {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts the download from the "waiting" status.
|
* 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)
|
if (status != Status.WAITING)
|
||||||
return;
|
return null;
|
||||||
|
|
||||||
new Thread() {
|
Thread t = new Thread() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
// open connection
|
// open connection
|
||||||
|
@ -274,7 +275,9 @@ public class Download {
|
||||||
listener.error();
|
listener.error();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.start();
|
};
|
||||||
|
t.start();
|
||||||
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -47,8 +47,6 @@ import itdelatrisu.opsu.ui.UI;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.MalformedURLException;
|
|
||||||
import java.net.URL;
|
|
||||||
|
|
||||||
import javax.sound.sampled.LineEvent;
|
import javax.sound.sampled.LineEvent;
|
||||||
import javax.sound.sampled.LineListener;
|
import javax.sound.sampled.LineListener;
|
||||||
|
@ -663,15 +661,18 @@ public class DownloadsMenu extends BasicGameState {
|
||||||
SoundController.stopTrack();
|
SoundController.stopTrack();
|
||||||
} else {
|
} else {
|
||||||
// play preview
|
// play preview
|
||||||
try {
|
final String url = serverMenu.getSelectedItem().getPreviewURL(node.getID());
|
||||||
final URL url = new URL(serverMenu.getSelectedItem().getPreviewURL(node.getID()));
|
MusicController.pause();
|
||||||
MusicController.pause();
|
new Thread() {
|
||||||
new Thread() {
|
@Override
|
||||||
@Override
|
public void run() {
|
||||||
public void run() {
|
try {
|
||||||
try {
|
previewID = -1;
|
||||||
previewID = -1;
|
boolean playing = SoundController.playTrack(
|
||||||
SoundController.playTrack(url, true, new LineListener() {
|
url,
|
||||||
|
Integer.toString(node.getID()),
|
||||||
|
true,
|
||||||
|
new LineListener() {
|
||||||
@Override
|
@Override
|
||||||
public void update(LineEvent event) {
|
public void update(LineEvent event) {
|
||||||
if (event.getType() == LineEvent.Type.STOP) {
|
if (event.getType() == LineEvent.Type.STOP) {
|
||||||
|
@ -681,18 +682,16 @@ public class DownloadsMenu extends BasicGameState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
if (playing)
|
||||||
previewID = node.getID();
|
previewID = node.getID();
|
||||||
} catch (SlickException e) {
|
} catch (SlickException e) {
|
||||||
UI.sendBarNotification("Failed to load track preview. See log for details.");
|
UI.sendBarNotification("Failed to load track preview. See log for details.");
|
||||||
Log.error(e);
|
Log.error(e);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}.start();
|
}
|
||||||
} catch (MalformedURLException e) {
|
}.start();
|
||||||
UI.sendBarNotification("Could not load track preview (bad URL).");
|
|
||||||
Log.error(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user