commit d0f1188775e47c906acfd34a40a655ab222c971a
parent 8fdeea99071b52c24354dd8ae273114b0b1b81fd
Author: Brian Swetland <swetland@frotz.net>
Date: Sun, 24 Jul 2011 20:23:52 -0700
update Sonos.browse() to use SonosListener interface and SonosItem container
- browse 100 items at a time, issue as many requests as needed
- use callback to pass items up the stack
- remove some debug chatter
- update commandline app for new interface
Signed-off-by: Brian Swetland <swetland@frotz.net>
Diffstat:
6 files changed, 121 insertions(+), 77 deletions(-)
diff --git a/net/frotz/sonos/SoapRPC.java b/net/frotz/sonos/SoapRPC.java
@@ -32,6 +32,7 @@ import java.nio.charset.CoderResult;
class SoapRPC {
static Charset cs = Charset.forName("UTF-8");
+ static final int MAXIO = 256*1024;
public boolean trace_io;
public boolean trace_reply;
@@ -67,8 +68,8 @@ class SoapRPC {
encoder = cs.newEncoder();
- bb = ByteBuffer.wrap(new byte[32768]);
- xml = new XML(32768);
+ bb = ByteBuffer.wrap(new byte[MAXIO]);
+ xml = new XML(MAXIO);
hdr = new StringBuilder(2048);
msg = new StringBuilder(8192);
}
@@ -137,6 +138,7 @@ class SoapRPC {
xpath = ept.path;
msg.setLength(0);
+ hdr.setLength(0);
/* setup message envelope/prefix */
msg.append("<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><s:Body><u:");
diff --git a/net/frotz/sonos/Sonos.java b/net/frotz/sonos/Sonos.java
@@ -23,14 +23,18 @@ public class Sonos {
SoapRPC.Endpoint media;
SoapRPC.Endpoint render;
SoapRPC rpc;
- XML result;
+ XMLSequence name, value;
+ SonosItem item;
public Sonos(byte[] ip) {
init(ip);
}
void init(byte[] ip) {
- result = new XML(32768);
+ name = new XMLSequence();
+ value = new XMLSequence();
+ item = new SonosItem();
+
rpc = new SoapRPC(ip, 1400);
xport = new SoapRPC.Endpoint(
@@ -136,79 +140,84 @@ public class Sonos {
}
/* content service calls */
- public void list(String _id, boolean d) {
+ public void browse(String _id, SonosListener cb) {
+ int total, count, updateid;
int n = 0;
XML xml;
- rpc.prepare(media,"Browse");
- rpc.simpleTag("ObjectID",_id);
- rpc.simpleTag("BrowseFlag",
- (d ? "BrowseDirectChildren" : "BrowseMetadata"));
- rpc.simpleTag("Filter","");
- rpc.simpleTag("StartingIndex", n);
- rpc.simpleTag("RequestedCount",25);
- rpc.simpleTag("SortCriteria","");
- xml = rpc.invoke();
+ do {
+ rpc.prepare(media,"Browse");
+ rpc.simpleTag("ObjectID",_id);
+ rpc.simpleTag("BrowseFlag","BrowseDirectChildren"); // BrowseMetadata
+ rpc.simpleTag("Filter","");
+ rpc.simpleTag("StartingIndex", n);
+ rpc.simpleTag("RequestedCount",100);
+ rpc.simpleTag("SortCriteria","");
- try {
- XMLSequence name = new XMLSequence();
- XMLSequence value = new XMLSequence();
- xml.open("u:BrowseResponse");
- XMLSequence tmp = xml.read("Result");
- tmp.unescape();
- //System.out.println(tmp);
- result.init(tmp);
+ xml = rpc.invoke();
+ try {
+ xml.open("u:BrowseResponse");
+ value.init(xml.read("Result"));
- if (trace_browse) {
- System.out.println("--------- list -----------");
- result.print(System.out,1024);
- result.rewind();
- }
- System.err.println("Count = " + xml.read("NumberReturned"));
- System.err.println("Total = " + xml.read("TotalMatches"));
- System.err.println("UpdID = " + xml.read("UpdateID"));
+ // Eww, toString()? really? surely there's
+ // a non-allocating Int parser somewhere
+ // in the bloat that is java standard libraries?
+ count = Integer.parseInt(xml.read("NumberReturned").toString());
+ total = Integer.parseInt(xml.read("TotalMatches").toString());
+ updateid = Integer.parseInt(xml.read("UpdateID").toString());
- result.open("DIDL-Lite");
- while (result.more()) {
- n++;
- CharSequence id = result.getAttr("id").copy();
- CharSequence title = "";
- CharSequence album = "";
- CharSequence res = "";
- String thing = "item";
- try {
- result.open("item");
- } catch (XML.Oops x) {
- result.open("container"); // yuck!
- thing = "container";
+ /* descend in to the contained results */
+ value.unescape();
+ xml.init(value);
+ n += processBrowseResults(xml,_id,cb);
+ } catch (Exception x) {
+ System.err.println("OOPS " + x);
+ x.printStackTrace();
+ break;
+ }
+ } while (n < total);
+ }
+ int processBrowseResults(XML result, String _id, SonosListener cb) throws XML.Oops {
+ SonosItem item = this.item;
+ int n = 0;
+ if (trace_browse) {
+ System.out.println("--------- list -----------");
+ result.print(System.out,1024);
+ result.rewind();
+ }
+ result.open("DIDL-Lite");
+ while (result.more()) {
+ String thing;
+ n++;
+ item.idURI = result.getAttr("id").copy();
+ try {
+ result.open("item");
+ thing = "item";
+ } catch (XML.Oops x) {
+ result.open("container"); // yuck!
+ thing = "container";
+ }
+ while (result.tryRead(name,value)) {
+ if ("dc:title".contentEquals(name)) {
+ item.title = value.unescape().copy();
+ continue;
+ }
+ if ("dc:creator".contentEquals(name)) {
+ item.artist = value.unescape().copy();
+ continue;
+ }
+ if ("upnp:album".contentEquals(name)) {
+ item.album = value.unescape().copy();
+ continue;
}
- while (result.tryRead(name,value)) {
- if ("dc:title".contentEquals(name)) {
- title = value.unescape().copy();
- continue;
- }
- if ("upnp:album".contentEquals(name)) {
- album = value.unescape().copy();
- continue;
- }
- if ("res".contentEquals(name)) {
- res = value.copy();
- continue;
- }
+ if ("res".contentEquals(name)) {
+ item.playURI = value.unescape().copy();
+ continue;
}
- if (thing == "item")
- System.err.println("Item: " + n);
- else
- System.err.println("Item: " + id);
- System.out.println(" Title: " + title);
- if (album.length() > 0)
- System.out.println(" Album: " + album);
- System.out.println(" Resource: " + res);
- result.close(thing);
}
- } catch (XML.Oops x) {
- System.err.println("OOPS: " + x.getMessage());
- x.printStackTrace();
+ cb.updateItem(_id, n, item);
+ result.close(thing);
}
+ return n;
}
}
diff --git a/net/frotz/sonos/SonosItem.java b/net/frotz/sonos/SonosItem.java
@@ -0,0 +1,18 @@
+package net.frotz.sonos;
+
+
+public class SonosItem {
+ public CharSequence title;
+ public CharSequence album;
+ public CharSequence artist;
+ public CharSequence playURI; /* to enqueue */
+ public CharSequence idURI; /* for browse/list */
+
+ public void reset() {
+ title = null;
+ album = null;
+ artist = null;
+ playURI = null;
+ idURI= null;
+ }
+}
diff --git a/net/frotz/sonos/SonosListener.java b/net/frotz/sonos/SonosListener.java
@@ -0,0 +1,5 @@
+package net.frotz.sonos;
+
+public interface SonosListener {
+ public void updateItem(String parent, int index, SonosItem item);
+}
diff --git a/net/frotz/sonos/XML.java b/net/frotz/sonos/XML.java
@@ -63,7 +63,7 @@ public class XML {
public void init(ByteBuffer in) {
buf.clear();
CoderResult cr = decoder.decode(in, buf, true);
- System.err.println("cr = " + cr);
+ // TODO: error handling
buf.flip();
reset();
}
@@ -79,7 +79,7 @@ public class XML {
tmp.init(xml, 0, 0);
offset = 0;
nextTag();
- System.err.println("XML reset, "+buf.length()+" bytes.");
+ //System.err.println("XML reset, "+buf.length()+" bytes.");
}
public void rewind() {
offset = 0;
diff --git a/net/frotz/sonos/app.java b/net/frotz/sonos/app.java
@@ -16,17 +16,20 @@
package net.frotz.sonos;
-public class app {
+public class app implements SonosListener {
public static void main(String args[]) {
+ app a = new app();
Sonos sonos = new Sonos(new byte[] { 10, 0, 0, (byte) 199});
String cmd = args[0];
- sonos.trace_io(true);
- sonos.trace_reply(true);
- sonos.trace_browse(true);
+ //sonos.trace_io(true);
+ //sonos.trace_reply(true);
+ //sonos.trace_browse(true);
if (cmd.equals("play")) {
sonos.play();
+ sonos.play();
+ sonos.play();
} else if (cmd.equals("pause")) {
sonos.pause();
} else if (cmd.equals("next")) {
@@ -34,9 +37,7 @@ public class app {
} else if (cmd.equals("prev")) {
sonos.prev();
} else if (cmd.equals("list")) {
- sonos.list(args[1],true);
- } else if (cmd.equals("dump")) {
- sonos.list(args[1],false);
+ sonos.browse(args[1],a);
} else if (cmd.equals("add")) {
sonos.add(args[1]);
} else if (cmd.equals("remove")) {
@@ -57,4 +58,13 @@ public class app {
System.exit(-1);
}
}
+ public void updateItem(String id, int idx, SonosItem item) {
+ System.out.println("("+idx+")\t id: " + item.idURI);
+ System.out.println("\t res: " + item.playURI);
+ System.out.println("\t title: " + item.title);
+ if (item.album != null)
+ System.out.println("\t album: " + item.album);
+ if (item.artist != null)
+ System.out.println("\tartist: " + item.artist);
+ }
}