/*- * Copyright (C) 2011 Peter Baldwin * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.peterbaldwin.vlcremote.net.xml; import org.peterbaldwin.vlcremote.model.Status; import org.peterbaldwin.vlcremote.model.Track; import org.xml.sax.Attributes; import org.xml.sax.ContentHandler; import android.sax.Element; import android.sax.ElementListener; import android.sax.EndTextElementListener; import android.sax.RootElement; import android.sax.TextElementListener; import android.text.Html; import java.io.IOException; import java.net.URLConnection; public final class XmlStatusContentHandler extends XmlContentHandler<Status> { private static String unescape(String text) { // The response text is escaped twice so that it can be used in HTML. if (text.indexOf("&") != -1) { // TODO: Use more efficient unescaping return Html.fromHtml(text.toString()).toString(); } else { return text; } } private static boolean parseBoolean(String text) { try { // Booleans are represented as integers in VLC 1.0 return Integer.parseInt(text) != 0; } catch (NumberFormatException e) { // Booleans are represented as strings in VLC 1.1 return Boolean.parseBoolean(text); } } private Status mStatus = new Status(); private Track mTrack = mStatus.getTrack(); private String mCategoryName; private String mInfoName; public ContentHandler getContentHandler() { RootElement root = new RootElement("", "root"); root.getChild("", "volume").setEndTextElementListener(new EndTextElementListener() { /** {@inheritDoc} */ public void end(String body) { int volume = Integer.parseInt(body); mStatus.setVolume(volume); } }); root.getChild("", "length").setEndTextElementListener(new EndTextElementListener() { /** {@inheritDoc} */ public void end(String body) { int length = Integer.parseInt(body); mStatus.setLength(length); } }); root.getChild("", "time").setEndTextElementListener(new EndTextElementListener() { /** {@inheritDoc} */ public void end(String body) { int time = Integer.parseInt(body); mStatus.setTime(time); } }); root.getChild("", "state").setEndTextElementListener(new EndTextElementListener() { /** {@inheritDoc} */ public void end(String body) { mStatus.setState(body); } }); root.getChild("", "position").setEndTextElementListener(new EndTextElementListener() { /** {@inheritDoc} */ public void end(String body) { double position = Double.parseDouble(body); mStatus.setPosition(position); } }); root.getChild("", "fullscreen").setEndTextElementListener(new EndTextElementListener() { /** {@inheritDoc} */ public void end(String body) { boolean fullscreen = parseBoolean(body); mStatus.setFullscreen(fullscreen); } }); root.getChild("", "random").setEndTextElementListener(new EndTextElementListener() { /** {@inheritDoc} */ public void end(String body) { boolean random = parseBoolean(body); mStatus.setRandom(random); } }); root.getChild("", "loop").setEndTextElementListener(new EndTextElementListener() { /** {@inheritDoc} */ public void end(String body) { boolean loop = parseBoolean(body); mStatus.setLoop(loop); } }); root.getChild("", "repeat").setEndTextElementListener(new EndTextElementListener() { /** {@inheritDoc} */ public void end(String body) { boolean repeat = parseBoolean(body); mStatus.setRepeat(repeat); } }); Element information = root.getChild("", "information"); Element meta = information.getChild("", "meta-information"); meta.getChild("", "title").setEndTextElementListener(new EndTextElementListener() { /** {@inheritDoc} */ public void end(String body) { mTrack.setTitle(unescape(body)); } }); meta.getChild("", "artist").setEndTextElementListener(new EndTextElementListener() { /** {@inheritDoc} */ public void end(String body) { mTrack.setArtist(unescape(body)); } }); meta.getChild("", "genre").setEndTextElementListener(new EndTextElementListener() { /** {@inheritDoc} */ public void end(String body) { mTrack.setGenre(unescape(body)); } }); meta.getChild("", "copyright").setEndTextElementListener(new EndTextElementListener() { /** {@inheritDoc} */ public void end(String body) { mTrack.setCopyright(unescape(body)); } }); meta.getChild("", "album").setEndTextElementListener(new EndTextElementListener() { /** {@inheritDoc} */ public void end(String body) { mTrack.setAlbum(unescape(body)); } }); meta.getChild("", "track").setEndTextElementListener(new EndTextElementListener() { /** {@inheritDoc} */ public void end(String body) { mTrack.setTrack(unescape(body)); } }); meta.getChild("", "description").setEndTextElementListener(new EndTextElementListener() { /** {@inheritDoc} */ public void end(String body) { mTrack.setDescription(unescape(body)); } }); meta.getChild("", "rating").setEndTextElementListener(new EndTextElementListener() { /** {@inheritDoc} */ public void end(String body) { mTrack.setRating(unescape(body)); } }); meta.getChild("", "date").setEndTextElementListener(new EndTextElementListener() { /** {@inheritDoc} */ public void end(String body) { mTrack.setDate(unescape(body)); } }); meta.getChild("", "url").setEndTextElementListener(new EndTextElementListener() { /** {@inheritDoc} */ public void end(String body) { mTrack.setUrl(unescape(body)); } }); meta.getChild("", "language").setEndTextElementListener(new EndTextElementListener() { /** {@inheritDoc} */ public void end(String body) { mTrack.setLanguage(unescape(body)); } }); meta.getChild("", "now_playing").setEndTextElementListener(new EndTextElementListener() { /** {@inheritDoc} */ public void end(String body) { mTrack.setNowPlaying(unescape(body)); } }); meta.getChild("", "publisher").setEndTextElementListener(new EndTextElementListener() { /** {@inheritDoc} */ public void end(String body) { mTrack.setPublisher(unescape(body)); } }); meta.getChild("", "encoded_by").setEndTextElementListener(new EndTextElementListener() { /** {@inheritDoc} */ public void end(String body) { mTrack.setEncodedBy(unescape(body)); } }); meta.getChild("", "art_url").setEndTextElementListener(new EndTextElementListener() { /** {@inheritDoc} */ public void end(String body) { mTrack.setArtUrl(unescape(body)); } }); meta.getChild("", "track_id").setEndTextElementListener(new EndTextElementListener() { /** {@inheritDoc} */ public void end(String body) { mTrack.setTrackId(unescape(body)); } }); // VLC 1.1 Element category = information.getChild("", "category"); category.setElementListener(new ElementListener() { /** {@inheritDoc} */ public void start(Attributes attributes) { mCategoryName = attributes.getValue("", "name"); } /** {@inheritDoc} */ public void end() { mCategoryName = null; } }); Element info = category.getChild("", "info"); info.setTextElementListener(new TextElementListener() { /** {@inheritDoc} */ public void start(Attributes attributes) { mInfoName = attributes.getValue("", "name"); } /** {@inheritDoc} */ public void end(String body) { if ("meta".equalsIgnoreCase(mCategoryName)) { if ("artist".equalsIgnoreCase(mInfoName)) { mTrack.setArtist(unescape(body)); } else if ("title".equalsIgnoreCase(mInfoName)) { mTrack.setTitle(unescape(body)); } else if ("album".equalsIgnoreCase(mInfoName)) { mTrack.setAlbum(unescape(body)); } else if ("genre".equalsIgnoreCase(mInfoName)) { mTrack.setGenre(unescape(body)); } else if ("description".equalsIgnoreCase(mInfoName)) { mTrack.setDescription(unescape(body)); } else if ("filename".equalsIgnoreCase(mInfoName)) { mTrack.setName(unescape(body)); } else if ("artwork_url".equalsIgnoreCase(mInfoName)) { mTrack.setArtUrl(unescape(body)); } } if (mCategoryName != null && mCategoryName.startsWith("Stream")) { if ("Type".equalsIgnoreCase(mInfoName)) { mTrack.addStreamType(unescape(body)); } } mInfoName = null; } }); return root.getContentHandler(); } @Override public Object getContent(URLConnection connection) throws IOException { parse(connection, getContentHandler()); return mStatus; } }