Refactor output streaming for readability

The core loop was put together confusingly; this encapsulates the
process of constructing an OutputStream and reformats some.
master
Peter Marheine 5 years ago
parent cae8f8b4e5
commit 47eefc1369
  1. 78
      airsonic-main/src/main/java/org/airsonic/player/controller/StreamController.java

@ -208,49 +208,32 @@ public class StreamController {
status = statusService.createStreamStatus(player);
in = new PlayQueueInputStream(player, status, maxBitRate, preferredTargetFormat, videoTranscodingSettings, transcodingService,
audioScrobblerService, mediaFileService, searchService);
OutputStream out = RangeOutputStream.wrap(response.getOutputStream(), range);
// Enabled SHOUTcast, if requested.
boolean isShoutCastRequested = "1".equals(request.getHeader("icy-metadata"));
if (isShoutCastRequested && !isSingleFile) {
response.setHeader("icy-metaint", "" + ShoutCastOutputStream.META_DATA_INTERVAL);
response.setHeader("icy-notice1", "This stream is served using Airsonic");
response.setHeader("icy-notice2", "Airsonic - Free media streamer");
response.setHeader("icy-name", "Airsonic");
response.setHeader("icy-genre", "Mixed");
response.setHeader("icy-url", "https://airsonic.github.io/");
out = new ShoutCastOutputStream(out, player.getPlayQueue(), settingsService);
}
final int BUFFER_SIZE = 2048;
byte[] buf = new byte[BUFFER_SIZE];
while (true) {
in = new PlayQueueInputStream(player, status, maxBitRate, preferredTargetFormat, videoTranscodingSettings,
transcodingService, audioScrobblerService, mediaFileService, searchService);
// Check if stream has been terminated.
if (status.terminated()) {
return;
}
if (player.getPlayQueue().getStatus() == PlayQueue.Status.STOPPED) {
if (isPodcast || isSingleFile) {
break;
} else {
sendDummy(buf, out);
}
} else {
try (OutputStream out = makeOutputStream(request, response, range, isSingleFile, player, settingsService)) {
final int BUFFER_SIZE = 2048;
byte[] buf = new byte[BUFFER_SIZE];
int n = in.read(buf);
if (n == -1) {
while (!status.terminated()) {
if (player.getPlayQueue().getStatus() == PlayQueue.Status.STOPPED) {
if (isPodcast || isSingleFile) {
break;
} else {
sendDummy(buf, out);
}
} else {
out.write(buf, 0, n);
int n = in.read(buf);
if (n == -1) {
if (isPodcast || isSingleFile) {
break;
} else {
sendDummy(buf, out);
}
} else {
out.write(buf, 0, n);
}
}
}
}
@ -283,6 +266,31 @@ public class StreamController {
return;
}
/**
* Construct an appropriate output stream based on the request.
* <p>
* This is responsible for limiting the output to the given range (if not null) and injecting Shoutcast metadata
* into the stream if requested.
*/
private OutputStream makeOutputStream(HttpServletRequest request, HttpServletResponse response, HttpRange range,
boolean isSingleFile, Player player, SettingsService settingsService)
throws IOException {
OutputStream out = RangeOutputStream.wrap(response.getOutputStream(), range);
// Enabled SHOUTcast, if requested.
boolean isShoutCastRequested = "1".equals(request.getHeader("icy-metadata"));
if (isShoutCastRequested && !isSingleFile) {
response.setHeader("icy-metaint", "" + ShoutCastOutputStream.META_DATA_INTERVAL);
response.setHeader("icy-notice1", "This stream is served using Airsonic");
response.setHeader("icy-notice2", "Airsonic - Free media streamer");
response.setHeader("icy-name", "Airsonic");
response.setHeader("icy-genre", "Mixed");
response.setHeader("icy-url", "https://airsonic.github.io/");
out = new ShoutCastOutputStream(out, player.getPlayQueue(), settingsService);
}
return out;
}
private void setContentDuration(HttpServletResponse response, MediaFile file) {
if (file.getDurationSeconds() != null) {
response.setHeader("X-Content-Duration", String.format("%.1f", file.getDurationSeconds().doubleValue()));

Loading…
Cancel
Save