I've been struggling for a while with a new project. As it turns out the PMS lacked some functions (for this project at least), and it can't be like that can it? So I rolled up my shirt and got my hands all dirty.
Below are two patches (actually there are four files patched). One which allows the "Search" primitive to be used (not just XBOX), and one which allows remote controls to "push" media to renders.
The remote control feature is simple and only requires a config option "remote_control=true" in the PMS.conf. The remote control is a device that will browse the server and the push the data to a render. Without this patch the PMS was a bit confused when the redner asked for media it had not browsed itself.
The second patch enables searching. It is no rocket science here all chil discovering is done as normal and the it filters in the requset base on name, media info etc. However the saerch is prepared to be more intelligent than that. The search strin is passed down to the discoverChildren function (which now comes in two variants on with and one withou argument), by default the search string is just dropped and everything works as normal. But if you hav a search engine on the other side (like grooveshark,spotify,you tube etc.) you can override the discoverchildren(str) and send the string directly to the search engine. If you do override this method you must also override the isSearched function which then must return true. This function disables the output filter in request.
Questions?
- Code: Select all
diff -rupN old/DLNAResource.java new/DLNAResource.java
--- old/DLNAResource.java 2010-12-02 08:17:12.407360200 +0100
+++ new/DLNAResource.java 2010-11-21 21:34:21.499845500 +0100
@@ -329,7 +329,13 @@ public abstract class DLNAResource exten
}
}
- public synchronized ArrayList<DLNAResource> getDLNAResources(String objectId, boolean children, int start, int count, RendererConfiguration renderer) throws IOException {
+ public synchronized ArrayList<DLNAResource> getDLNAResources(String objectId, boolean children, int start, int count,
+ RendererConfiguration renderer) throws IOException {
+ return getDLNAResources(objectId,children,start,count,renderer,null);
+ }
+
+ public synchronized ArrayList<DLNAResource> getDLNAResources(String objectId, boolean children, int start, int count,
+ RendererConfiguration renderer,String searchStr) throws IOException {
PMS.debug("Searching for objectId: " + objectId + " with children option: " +children);
ArrayList<DLNAResource> resources = new ArrayList<DLNAResource>();
DLNAResource resource = search(objectId);
@@ -361,7 +367,7 @@ public abstract class DLNAResource exten
else {
// Discovering if not already done.
if (!resource.discovered) {
- resource.discoverChildren();
+ resource.discoverChildren(searchStr);
boolean ready = true;
if (renderer.isMediaParserV2())
ready = resource.analyzeChildren(count);
@@ -434,6 +440,15 @@ public abstract class DLNAResource exten
}
+ // Sharkpatch
+ public void discoverChildren(String str) {
+ discoverChildren();
+ }
+
+ public boolean isSearched() {
+ return false;
+ }
+
public boolean analyzeChildren(int count) {
return true;
}
@@ -1023,6 +1038,16 @@ public abstract class DLNAResource exten
return player;
}
+ ////////////////////////////////////
+ // Shark patch
+ ////////////////////////////////////
+ public void setPlayer(Player p) {
+ player=p;
+ }
+ //////////////////////////////////////
+ // End patch
+ //////////////////////////////////////
+
public String mimeType() {
if (player != null)
return player.mimeType();
diff -rupN old/PMS.java new/PMS.java
--- old/PMS.java 2010-12-02 08:16:46.600884100 +0100
+++ new/PMS.java 2010-12-02 08:20:24.373340000 +0100
@@ -164,6 +164,14 @@ public class PMS {
}
+ //////////////////////////////////////////////////////
+ // SharkHunter
+ //////////////////////////////////////////////////////
+
+ public ArrayList<RendererConfiguration> getRenders() {
+ return foundRenderers;
+ }
+
//private RootFolder rootFolder;
private HTTPServer server;
private String serverName;
diff -rupN old/Request.java new/Request.java
--- old/Request.java 2010-12-02 08:16:22.108483300 +0100
+++ new/Request.java 2010-12-01 21:20:24.510357400 +0100
@@ -187,6 +187,27 @@ public class Request extends HTTPResourc
String id = argument.substring(argument.indexOf("get/") + 4, argument.lastIndexOf("/"));
id = id.replace("%24", "$"); // popcorn hour ?
ArrayList<DLNAResource> files = PMS.get().getRootFolder(mediaRenderer).getDLNAResources(id, false, 0, 0, mediaRenderer);
+ ///////////////////////////////////////////////
+ // Sharkpatch
+ ///////////////////////////////////////////////
+ if(files==null||files.size()==0) { // nothing found
+ String tmp=(String)PMS.getConfiguration().getCustomProperty("remote_control");
+ if(tmp!=null&&!tmp.equalsIgnoreCase("false")) {
+ ArrayList<RendererConfiguration> renders=PMS.get().getRenders();
+ for(int i=0;i<renders.size();i++) {
+ RendererConfiguration r=renders.get(i);
+ if(r.equals(mediaRenderer))
+ continue;
+ files = PMS.get().getRootFolder(r).getDLNAResources(id, false, 0, 0, r);
+ if(files!=null&&files.size()!=0) {
+ break;
+ }
+ }
+ }
+ }
+ //////////////////////////////////////
+ // End patch
+ //////////////////////////////////////
if (transferMode != null) {
output(output, "TransferMode.DLNA.ORG: " + transferMode);
}
@@ -342,7 +363,7 @@ public class Request extends HTTPResourc
//PMS.debug(content);
objectID = getEnclosingValue(content, "<ObjectID>", "</ObjectID>");
String containerID = null;
- if ((objectID == null || objectID.length() == 0) && xbox) {
+ if ((objectID == null || objectID.length() == 0) /*&& xbox*/) {
containerID = getEnclosingValue(content, "<ContainerID>", "</ContainerID>");
if (!containerID.contains("$")) {
objectID = "0";
@@ -396,13 +417,36 @@ public class Request extends HTTPResourc
}
}
}
-
- ArrayList<DLNAResource> files = PMS.get().getRootFolder(mediaRenderer).getDLNAResources(objectID, browseFlag!=null&&browseFlag.equals("BrowseDirectChildren"), startingIndex, requestCount, mediaRenderer);
+ // Sharkpatch
+ else if (soapaction.contains("ContentDirectory:1#Search"))
+ searchCriteria=getEnclosingValue(content,"<SearchCriteria>","</SearchCriteria>");
+
+ ArrayList<DLNAResource> files = PMS.get().getRootFolder(mediaRenderer).getDLNAResources(objectID, browseFlag!=null&&browseFlag.equals("BrowseDirectChildren"), startingIndex, requestCount,
+ mediaRenderer,searchCriteria);
if (searchCriteria != null && files != null) {
for(int i=files.size()-1;i>=0;i--) {
- if (!files.get(i).getName().equals(searchCriteria))
+ searchCriteria=searchCriteria.toLowerCase();
+ for(int i=files.size()-1;i>=0;i--) {
+ /*if (!files.get(i).getName().equals(searchCriteria))
+ files.remove(i);*/
+ DLNAResource res=files.get(i);
+ if(res.isSearched())
+ continue;
+ boolean keep=res.getName().toLowerCase().indexOf(searchCriteria)!=-1;
+ if(res.media!=null) {
+ for(int j=0;j<res.media.audioCodes.size();j++) {
+ DLNAMediaAudio audio=res.media.audioCodes.get(j);
+ keep|=audio.album.toLowerCase().indexOf(searchCriteria)!=-1;
+ keep|=audio.artist.toLowerCase().indexOf(searchCriteria)!=-1;
+ keep|=audio.songname.toLowerCase().indexOf(searchCriteria)!=-1;
+ }
+ }
+ if(!keep) // dump it
files.remove(i);
}
+ if(xbox)
+ // Patch end
+ }
if (files.size() > 0) {
files = files.get(0).getChildren();
}
diff -rupN old/RequestV2.java new/RequestV2.java
--- old/RequestV2.java 2010-12-02 08:15:59.135169300 +0100
+++ new/RequestV2.java 2010-11-21 21:35:26.598568900 +0100
@@ -30,6 +30,7 @@ import java.util.TimeZone;
import net.pms.PMS;
import net.pms.configuration.RendererConfiguration;
+import net.pms.dlna.DLNAMediaAudio;
import net.pms.dlna.DLNAMediaInfo;
import net.pms.dlna.DLNAResource;
@@ -180,6 +181,27 @@ public class RequestV2 extends HTTPResou
String id = argument.substring(argument.indexOf("get/") + 4, argument.lastIndexOf("/"));
id = id.replace("%24", "$"); // popcorn hour ?
ArrayList<DLNAResource> files = PMS.get().getRootFolder(mediaRenderer).getDLNAResources(id, false, 0, 0, mediaRenderer);
+ ///////////////////////////////////////////////
+ // Sharkpatch
+ ///////////////////////////////////////////////
+ if(files==null||files.size()==0) { // nothing found
+ String tmp=(String)PMS.getConfiguration().getCustomProperty("remote_control");
+ if(tmp!=null&&!tmp.equalsIgnoreCase("false")) {
+ ArrayList<RendererConfiguration> renders=PMS.get().getRenders();
+ for(int i=0;i<renders.size();i++) {
+ RendererConfiguration r=renders.get(i);
+ if(r.equals(mediaRenderer))
+ continue;
+ files = PMS.get().getRootFolder(r).getDLNAResources(id, false, 0, 0, r);
+ if(files!=null&&files.size()!=0) {
+ break;
+ }
+ }
+ }
+ }
+ //////////////////////////////////////
+ // End patch
+ //////////////////////////////////////
if (transferMode != null) {
output.setHeader("TransferMode.DLNA.ORG", transferMode);
}
@@ -350,7 +372,8 @@ public class RequestV2 extends HTTPResou
//PMS.debug(content);
objectID = getEnclosingValue(content, "<ObjectID>", "</ObjectID>");
String containerID = null;
- if ((objectID == null || objectID.length() == 0) && xbox) {
+ // Sharkpatch
+ if ((objectID == null || objectID.length() == 0) /*&& xbox*/) {
containerID = getEnclosingValue(content, "<ContainerID>", "</ContainerID>");
if (!containerID.contains("$")) {
objectID = "0";
@@ -380,7 +403,8 @@ public class RequestV2 extends HTTPResou
response.append(HTTPXMLHelper.DIDL_HEADER);
- if (soapaction.contains("ContentDirectory:1#Search"))
+
+ if (soapaction.contains("ContentDirectory:1#Search"))
browseFlag = "BrowseDirectChildren";
//XBOX virtual containers ... doh
@@ -405,12 +429,34 @@ public class RequestV2 extends HTTPResou
}
}
- ArrayList<DLNAResource> files = PMS.get().getRootFolder(mediaRenderer).getDLNAResources(objectID, browseFlag!=null&&browseFlag.equals("BrowseDirectChildren"), startingIndex, requestCount, mediaRenderer);
+ // Sharkpatch
+ else if (soapaction.contains("ContentDirectory:1#Search"))
+ searchCriteria=getEnclosingValue(content,"<SearchCriteria>","</SearchCriteria>");
+
+ ArrayList<DLNAResource> files = PMS.get().getRootFolder(mediaRenderer).getDLNAResources(objectID, browseFlag!=null&&browseFlag.equals("BrowseDirectChildren"), startingIndex, requestCount,
+ mediaRenderer,searchCriteria);
if (searchCriteria != null && files != null) {
+ searchCriteria=searchCriteria.toLowerCase();
for(int i=files.size()-1;i>=0;i--) {
- if (!files.get(i).getName().equals(searchCriteria))
+ /*if (!files.get(i).getName().equals(searchCriteria))
+ files.remove(i);*/
+ DLNAResource res=files.get(i);
+ if(res.isSearched())
+ continue;
+ boolean keep=res.getName().toLowerCase().indexOf(searchCriteria)!=-1;
+ if(res.media!=null) {
+ for(int j=0;j<res.media.audioCodes.size();j++) {
+ DLNAMediaAudio audio=res.media.audioCodes.get(j);
+ keep|=audio.album.toLowerCase().indexOf(searchCriteria)!=-1;
+ keep|=audio.artist.toLowerCase().indexOf(searchCriteria)!=-1;
+ keep|=audio.songname.toLowerCase().indexOf(searchCriteria)!=-1;
+ }
+ }
+ if(!keep) // dump it
files.remove(i);
}
+ if(xbox)
+ // Patch end
if (files.size() > 0) {
files = files.get(0).getChildren();
}
