https://github.com/maihde/roku_subsonic
Since the roku only support WMA and MP3 audio, I transcode m4a files, but the roku audio player would only play 10-15 seconds of audio before skipping to the next song.
After poking around, this Roku forum thread put me on the right path
http://forums.roku.com/viewtopic.php?f= ... 353162f4a8
Essentially, if the roku doesn't receive a content-length it will keep pulling from the URL until it receives a 416 response. WIth Subsonic transcoding, the entire file is transferred in the first GET and then the roku does a second GET with a range like this
Range: <end-of-file>-
As of Subsonic 4.4, instead of returning a 416 error code it will send a 0-length response. For whatever reason, ROKU interprets this to immediately stop playback of the song; but the correct behavior per HTTP/1.1 part 5 does seem to indicate that a 416 status should be returned.
The below patch appears to fix the problem for me without breaking anything else.
- Code: Select all
diff -ur release-4.4/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/StreamController.java release-4.4-patched/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/StreamController.java
--- release-4.4/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/StreamController.java 2011-02-06 03:43:41.000000000 -0500
+++ release-4.4-patched/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/StreamController.java 2011-06-05 15:36:59.273570620 -0400
@@ -202,6 +202,15 @@
int n = in.read(buf);
if (n == -1) {
if (isPodcast || isSingleFile) {
+ // If the range request was not satisfied return 416
+ if ((range != null) && (out instanceof RangeOutputStream)) {
+ if (!((RangeOutputStream) out).isSatisfied()) {
+ LOG.info("Range request not satisifed: " + range);
+ response.setStatus(416);
+ } else {
+ LOG.info("Range request satisifed: " + range);
+ }
+ }
break;
} else {
sendDummy(buf, out);
diff -ur release-4.4/subsonic-main/src/main/java/net/sourceforge/subsonic/io/RangeOutputStream.java release-4.4-patched/subsonic-main/src/main/java/net/sourceforge/subsonic/io/RangeOutputStream.java
--- release-4.4/subsonic-main/src/main/java/net/sourceforge/subsonic/io/RangeOutputStream.java 2011-02-06 03:43:41.000000000 -0500
+++ release-4.4-patched/subsonic-main/src/main/java/net/sourceforge/subsonic/io/RangeOutputStream.java 2011-06-05 15:58:12.613549299 -0400
@@ -48,6 +48,12 @@
protected long pos;
/**
+ * Range satisfied.
+ * true if the start of the range was reached
+ */
+ protected boolean satisfied;
+
+ /**
* Wraps the given output stream in a RangeOutputStream, using the values
* in the given range, unless the range is <code>null</code> in which case
* the original OutputStream is returned.
@@ -75,6 +81,7 @@
this.start = start;
this.end = end;
pos = 0;
+ satisfied = false;
}
/**
@@ -87,6 +94,7 @@
@Override
public void write(int b) throws IOException {
if ((pos >= start) && (pos <= end)) {
+ satisfied = true;
super.write(b);
}
pos++;
@@ -139,12 +147,17 @@
}
// If we have enabled writing, do the write!
- if (allowWrite) {
+ if ((allowWrite) && (newLen > 0)) {
+ satisfied = true;
out.write(b, (int) newOff, (int) newLen);
}
// Move the cursor along
pos += off + len;
}
+
+ public boolean isSatisfied() {
+ return satisfied;
+ }
}