rendered paste bodyFrom 3a6d4d6e584b1680440e26769bce6267c8f6cfd6 Mon Sep 17 00:00:00 2001From: Mook <mook@songbirdnest.com>Date: Fri, 20 Mar 2009 12:06:24 -0700Subject: [PATCH 2/2] playlist stuff--- extensions/httpserv/components/src/sbhttpserv.js | 75 +++++++++++++++++---- 1 files changed, 60 insertions(+), 15 deletions(-)diff --git extensions/httpserv/components/src/sbhttpserv.js extensions/httpserv/components/src/sbhttpserv.jsindex 7127e52..31a21ad 100644--- extensions/httpserv/components/src/sbhttpserv.js+++ extensions/httpserv/components/src/sbhttpserv.js@@ -110,17 +110,17 @@ SBHttpServ.prototype.handle = function SBHttpServ_handle(aMetadata, aResponse) for (let idx = 0; idx < pathParts.length; idx += 2) { let dirName = decodeURIComponent(pathParts[idx]); let dirValue = decodeURIComponent(pathParts[idx + 1]); if (dirName === "") { break; } if (["albums", "artists", "genres", "playlists"].indexOf(dirName) != -1) { if (typeof(dirValue) == "undefined" || dirValue === "") {- this.generateFilterListing(aMetadata, context, dirName, aResponse);+ this._generateFilterListing(aMetadata, context, dirName, aResponse); context = null; break; } else { context = context[dirName][dirValue]; if (!context) { dd(<>can't find {dirName} / {dirValue}</>); throw new HttpError(404, "Not Found"); }@@ -130,96 +130,141 @@ SBHttpServ.prototype.handle = function SBHttpServ_handle(aMetadata, aResponse) break; } else { context = context[dirName][dirValue]; if (!context) { dd(<>can't find {dirName} / {dirValue}</>); throw new HttpError(404, "Not Found"); } }+ } else if (dirName == "pls") {+ if (!("items" in context)) {+ dd(<>context {context} is not a media list</>);+ throw new HttpError(404, "Playlist not found");+ }+ this._generatePlaylistListing(aMetadata, context, aResponse);+ context = null;+ break; } else { dd(<>ignoring unknown directory [{dirName}]</>); throw new HttpError(404, "Not Found");; } } if ((context instanceof Ci.sbIMediaItem) && !(context instanceof Ci.sbIMediaList)) { const BUFFER_SIZE = 0x80000; aResponse.setHeader("Content-Type", this._getContentType(context.contentSrc)); let ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); let channel = ios.newChannelFromURI(context.contentSrc); aResponse.bodyOutputStream.writeFrom(channel.open(), -1); } else if (context && ("items" in context)) {- this.generateItemListing(aMetadata, context, aResponse);+ this._generateItemListing(aMetadata, context, aResponse); } } catch (e) { Components.utils.reportError(e); throw e; } }; -SBHttpServ.prototype.generateFilterListing =-function SBHttpServ_generateFilterListing(aMetadata, aContext, aType, aResponse) {- aResponse.setHeader("Content-Type", "text/html");+SBHttpServ.prototype._generateFilterListing =+function SBHttpServ__generateFilterListing(aMetadata, aContext, aType, aResponse) {+ aResponse.setHeader("Content-Type", "text/html; charset=utf-8"); aResponse.write(String(<><![CDATA[ <html> <head>- <title>Directory listing for {aMetadata.path}</title>+ <title>Directory listing for {aMetadata.path.split('/').map(unescape).join('/')}</title> </head> <body>- <h1>Directory listing for {aMetadata.path}</h1>+ <h1>Directory listing for {aMetadata.path.split('/').map(unescape).join('/')}</h1> <ul> ]]></>).replace(/\{[^}]*\}/g, function(c) eval(c.substr(1,c.length-2)))); for (let item in aContext[aType]) {- aResponse.write('<li><a href="' + item + '/">' + item + '</a></li>');+ aResponse.write('<li><a href="' + encodeURIComponent(item) + '/">' ++ unescape(encodeURIComponent(item)) + '</a></li>'); } aResponse.write(<><![CDATA[ </ul></body></html> ]]></>); } -SBHttpServ.prototype.generateItemListing =-function SBHttpServ_generateItemListing(aMetadata, aContext, aResponse) {- aResponse.setHeader("Content-Type", "text/html");+SBHttpServ.prototype._generateItemListing =+function SBHttpServ__generateItemListing(aMetadata, aContext, aResponse) {+ aResponse.setHeader("Content-Type", "text/html; charset=utf-8"); aResponse.write(String(<><![CDATA[ <html> <head>- <title>Directory listing for {aMetadata.path}</title>+ <title>Directory listing for {aMetadata.path.split('/').map(unescape).join('/')}</title> </head> <body>- <h1>Directory listing for {aMetadata.path}</h1>+ <h1>Directory listing for {aMetadata.path.split('/').map(unescape).join('/')}</h1> <ul> ]]></>).replace(/\{[^}]*\}/g, function(c) eval(c.substr(1,c.length-2)))); + aResponse.write('<li><a href="pls/index.pls">[playlist]</a></li>'); for each (let type in ["artists", "albums", "genres"]) { if ((type in aContext) && (aContext[type].length > 1)) { aResponse.write('<li><a href="' + type + '/">' + type + '/</a></li>'); } } if ("items" in aContext) { for each (let item in aContext.items) { if (item && (item instanceof Ci.sbIMediaItem)) { if (item instanceof Ci.sbIMediaList) { continue; } aResponse.write(- '<li><a href="items/' + item.guid + '">' +- item.getProperty(SBProperties.trackName) ++ '<li><a href="items/' + item.guid + '?type=' ++ item.contentSrc.spec.replace(/.*\./, '.') + '">' ++ unescape(encodeURIComponent(item.getProperty(SBProperties.trackName))) + '</a></li>' ); } else { aResponse.write("<li> item" + item + " is no good</li>"); } } } aResponse.write('</ul></body></html>'); } +SBHttpServ.prototype._generatePlaylistListing =+function SBHttpServ__generatePlaylistListing(aMetadata, aContext, aResponse) {+ function ToUTF8(str) {+ return unescape(encodeURIComponent(str));+ }+ if (!("items" in aContext)) {+ Components.utils.reportError("context has no items");+ throw new HttpError(500, "not a playlist");+ }+ aResponse.setHeader("Content-Type", "audio/x-scpls; charset=utf-8");++ aResponse.write("[playlist]\n");+ let length = 0;+ for each (let item in aContext.items) {+ if (!item || !(item instanceof Ci.sbIMediaItem)) {+ continue;+ }+ if (item instanceof Ci.sbIMediaList) {+ continue;+ }+ ++length;+ aResponse.write("File" + length + "=/contents/items/" + item.guid + "\n");+ aResponse.write("Title" + length + "=" + ToUTF8(item.getProperty(SBProperties.trackName)) + "\n");+ try {+ aResponse.write("Length" + length + "=" + ToUTF8(item.getProperty(SBProperties.contentLength)) + "\n");+ } catch (e) {+ aResponse.write("Length" + length + "=-1\n");+ }+ }+ + aResponse.write("NumberOfEntries=" + length + "\n");+ aResponse.write("Version=2\n");+}+ /** * nsISupports implementation */ SBHttpServ.prototype.QueryInterface = XPCOMUtils.generateQI([ Ci.nsIHttpRequestHandler, Ci.nsIObserver ]); SBHttpServ.prototype.classDescription = "Songbird HTTP Library Server";-- 1.5.5.1015.g9d258