sonos

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

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:
Mnet/frotz/sonos/SoapRPC.java | 6++++--
Mnet/frotz/sonos/Sonos.java | 141++++++++++++++++++++++++++++++++++++++++++-------------------------------------
Anet/frotz/sonos/SonosItem.java | 18++++++++++++++++++
Anet/frotz/sonos/SonosListener.java | 5+++++
Mnet/frotz/sonos/XML.java | 4++--
Mnet/frotz/sonos/app.java | 24+++++++++++++++++-------
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); + } }