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/
|
||||
/SongPacks/
|
||||
/Songs/
|
||||
/Temp/
|
||||
/.opsu.log
|
||||
/.opsu.cfg
|
||||
/.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
|
||||
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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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";
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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()));
|
||||
final String url = serverMenu.getSelectedItem().getPreviewURL(node.getID());
|
||||
MusicController.pause();
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
previewID = -1;
|
||||
SoundController.playTrack(url, true, new LineListener() {
|
||||
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,7 +682,9 @@ public class DownloadsMenu extends BasicGameState {
|
|||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
if (playing)
|
||||
previewID = node.getID();
|
||||
} catch (SlickException e) {
|
||||
UI.sendBarNotification("Failed to load track preview. See log for details.");
|
||||
|
@ -689,10 +692,6 @@ public class DownloadsMenu extends BasicGameState {
|
|||
}
|
||||
}
|
||||
}.start();
|
||||
} catch (MalformedURLException e) {
|
||||
UI.sendBarNotification("Could not load track preview (bad URL).");
|
||||
Log.error(e);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user