use of net.pms.dlna.RootFolder in project UniversalMediaServer by UniversalMediaServer.
the class RemotePlayHandler method mkPage.
private String mkPage(String id, HttpExchange t) throws IOException {
HashMap<String, Object> vars = new HashMap<>();
vars.put("serverName", configuration.getServerDisplayName());
LOGGER.debug("Make play page " + id);
RootFolder root = parent.getRoot(RemoteUtil.userName(t), t);
if (root == null) {
LOGGER.debug("root not found");
throw new IOException("Unknown root");
}
WebRender renderer = (WebRender) root.getDefaultRenderer();
renderer.setBrowserInfo(RemoteUtil.getCookie("UMSINFO", t), t.getRequestHeaders().getFirst("User-agent"));
// List<DLNAResource> res = root.getDLNAResources(id, false, 0, 0, renderer);
DLNAResource r = root.getDLNAResource(id, renderer);
if (r == null) {
LOGGER.debug("Bad web play id: " + id);
throw new IOException("Bad Id");
}
if (!r.isCodeValid(r)) {
LOGGER.debug("coded object with invalid code");
throw new IOException("Bad code");
}
if (r instanceof VirtualVideoAction) {
// waste of resource to play dummy video
if (((VirtualVideoAction) r).enable()) {
renderer.notify(renderer.INFO, r.getName() + " enabled");
} else {
renderer.notify(renderer.INFO, r.getName() + " disabled");
}
return returnPage();
}
Format format = r.getFormat();
boolean isImage = format.isImage();
boolean isVideo = format.isVideo();
boolean isAudio = format.isAudio();
String query = t.getRequestURI().getQuery();
boolean forceFlash = StringUtils.isNotEmpty(RemoteUtil.getQueryVars(query, "flash"));
boolean forcehtml5 = StringUtils.isNotEmpty(RemoteUtil.getQueryVars(query, "html5"));
boolean flowplayer = isVideo && (forceFlash || (!forcehtml5 && configuration.getWebFlash()));
// hack here to ensure we got a root folder to use for recently played etc.
root.getDefaultRenderer().setRootFolder(root);
String id1 = URLEncoder.encode(id, "UTF-8");
String name = StringEscapeUtils.escapeHtml(r.resumeName());
String mime = root.getDefaultRenderer().getMimeType(r.mimeType(), r.getMedia());
String mediaType = isVideo ? "video" : isAudio ? "audio" : isImage ? "image" : "";
String auto = "autoplay";
@SuppressWarnings("unused") String coverImage = "";
if (isVideo) {
if (mime.equals(FormatConfiguration.MIMETYPE_AUTO)) {
if (r.getMedia() != null && r.getMedia().getMimeType() != null) {
mime = r.getMedia().getMimeType();
}
}
if (!flowplayer) {
if (!RemoteUtil.directmime(mime) || RemoteUtil.transMp4(mime, r.getMedia()) || r.isResume()) {
WebRender render = (WebRender) r.getDefaultRenderer();
mime = render != null ? render.getVideoMimeType() : RemoteUtil.transMime();
}
}
}
vars.put("isVideo", isVideo);
vars.put("name", name);
vars.put("id1", id1);
vars.put("autoContinue", configuration.getWebAutoCont(format));
if (configuration.isDynamicPls()) {
if (r.getParent() instanceof Playlist) {
vars.put("plsOp", "del");
vars.put("plsSign", "-");
vars.put("plsAttr", RemoteUtil.getMsgString("Web.4", t));
} else {
vars.put("plsOp", "add");
vars.put("plsSign", "+");
vars.put("plsAttr", RemoteUtil.getMsgString("Web.5", t));
}
}
addNextByType(r, vars);
if (isImage) {
// do this like this to simplify the code
// skip all player crap since img tag works well
int delay = configuration.getWebImgSlideDelay() * 1000;
if (delay > 0 && configuration.getWebAutoCont(format)) {
vars.put("delay", delay);
}
} else {
vars.put("mediaType", mediaType);
vars.put("auto", auto);
vars.put("mime", mime);
if (flowplayer) {
if (RemoteUtil.directmime(mime) && !RemoteUtil.transMp4(mime, r.getMedia()) && !r.isResume() && !forceFlash) {
vars.put("src", true);
}
} else {
vars.put("width", renderer.getVideoWidth());
vars.put("height", renderer.getVideoHeight());
}
}
if (configuration.useWebControl()) {
vars.put("push", true);
}
if (isVideo && configuration.getWebSubs()) {
// only if subs are requested as <track> tags
// otherwise we'll transcode them in
boolean isFFmpegFontConfig = configuration.isFFmpegFontConfig();
if (isFFmpegFontConfig) {
// do not apply fontconfig to flowplayer subs
configuration.setFFmpegFontConfig(false);
}
OutputParams p = new OutputParams(configuration);
p.sid = r.getMediaSubtitle();
Player.setAudioAndSubs(r.getName(), r.getMedia(), p);
if (p.sid != null && p.sid.getType().isText()) {
try {
File subFile = SubtitleUtils.getSubtitles(r, r.getMedia(), p, configuration, SubtitleType.WEBVTT);
LOGGER.debug("subFile " + subFile);
if (subFile != null) {
vars.put("sub", parent.getResources().add(subFile));
}
} catch (Exception e) {
LOGGER.debug("error when doing sub file " + e);
}
}
// return back original fontconfig value
configuration.setFFmpegFontConfig(isFFmpegFontConfig);
}
return parent.getResources().getTemplate(isImage ? "image.html" : flowplayer ? "flow.html" : "play.html").execute(vars);
}
use of net.pms.dlna.RootFolder in project UniversalMediaServer by UniversalMediaServer.
the class RemoteWeb method getRoot.
public RootFolder getRoot(String user, boolean create, HttpExchange t) {
String groupTag = getTag(user);
String cookie = RemoteUtil.getCookie("UMS", t);
RootFolder root;
synchronized (roots) {
root = roots.get(cookie);
if (root == null) {
// Double-check for cookie errors
WebRender valid = RemoteUtil.matchRenderer(user, t);
if (valid != null) {
// A browser of the same type and user is already connected at
// this ip but for some reason we didn't get a cookie match.
RootFolder validRoot = valid.getRootFolder();
// Do a reverse lookup to see if it's been registered
for (Map.Entry<String, RootFolder> entry : roots.entrySet()) {
if (entry.getValue() == validRoot) {
// Found
root = validRoot;
cookie = entry.getKey();
LOGGER.debug("Allowing browser connection without cookie match: {}: {}", valid.getRendererName(), t.getRemoteAddress().getAddress());
break;
}
}
}
}
if (!create || (root != null)) {
t.getResponseHeaders().add("Set-Cookie", "UMS=" + cookie + ";Path=/");
return root;
}
ArrayList<String> tag = new ArrayList<>();
tag.add(user);
if (!groupTag.equals(user)) {
tag.add(groupTag);
}
tag.add(t.getRemoteAddress().getHostString());
tag.add("web");
root = new RootFolder(tag);
try {
WebRender render = new WebRender(user);
root.setDefaultRenderer(render);
render.setRootFolder(root);
render.associateIP(t.getRemoteAddress().getAddress());
render.associatePort(t.getRemoteAddress().getPort());
if (configuration.useWebSubLang()) {
render.setSubLang(StringUtils.join(RemoteUtil.getLangs(t), ","));
}
// render.setUA(t.getRequestHeaders().getFirst("User-agent"));
render.setBrowserInfo(RemoteUtil.getCookie("UMSINFO", t), t.getRequestHeaders().getFirst("User-agent"));
PMS.get().setRendererFound(render);
} catch (ConfigurationException e) {
root.setDefaultRenderer(RendererConfiguration.getDefaultConf());
}
// root.setDefaultRenderer(RendererConfiguration.getRendererConfigurationByName("web"));
root.discoverChildren();
cookie = UUID.randomUUID().toString();
t.getResponseHeaders().add("Set-Cookie", "UMS=" + cookie + ";Path=/");
roots.put(cookie, root);
}
return root;
}
use of net.pms.dlna.RootFolder in project UniversalMediaServer by UniversalMediaServer.
the class RemoteBrowseHandler method mkBrowsePage.
private String mkBrowsePage(String id, HttpExchange t) throws IOException {
LOGGER.debug("Make browse page " + id);
String user = RemoteUtil.userName(t);
RootFolder root = parent.getRoot(user, true, t);
String search = RemoteUtil.getQueryVars(t.getRequestURI().getQuery(), "str");
List<DLNAResource> resources = root.getDLNAResources(id, true, 0, 0, root.getDefaultRenderer(), search);
boolean upnpAllowed = RemoteUtil.bumpAllowed(t);
boolean upnpControl = RendererConfiguration.hasConnectedControlPlayers();
if (!resources.isEmpty() && resources.get(0).getParent() != null && (resources.get(0).getParent() instanceof CodeEnter)) {
// this is a code folder the search string is entered code
CodeEnter ce = (CodeEnter) resources.get(0).getParent();
ce.setEnteredCode(search);
if (!ce.validCode(ce)) {
// invalid code throw error
throw new IOException("Auth error");
}
DLNAResource real = ce.getResource();
if (!real.isFolder()) {
// no folder -> redirect
Headers hdr = t.getResponseHeaders();
hdr.add("Location", "/play/" + real.getId());
RemoteUtil.respond(t, "", 302, "text/html");
// return null here to avoid multiple responses
return null;
}
// redirect to ourself
Headers hdr = t.getResponseHeaders();
hdr.add("Location", "/browse/" + real.getResourceId());
RemoteUtil.respond(t, "", 302, "text/html");
return null;
}
if (StringUtils.isNotEmpty(search) && !(resources instanceof CodeEnter)) {
UMSUtils.postSearch(resources, search);
}
boolean hasFile = false;
ArrayList<String> folders = new ArrayList<>();
ArrayList<HashMap<String, String>> media = new ArrayList<>();
StringBuilder sb = new StringBuilder();
sb.setLength(0);
sb.append("<a href=\"javascript:history.back()\" title=\"").append(RemoteUtil.getMsgString("Web.10", t)).append("\">");
sb.append("<span>").append(RemoteUtil.getMsgString("Web.10", t)).append("</span>");
sb.append("</a>");
folders.add(sb.toString());
// Generate innerHtml snippets for folders and media items
for (DLNAResource resource : resources) {
String newId = resource.getResourceId();
String idForWeb = URLEncoder.encode(newId, "UTF-8");
String thumb = "/thumb/" + idForWeb;
String name = StringEscapeUtils.escapeHtml(resource.resumeName());
if (resource instanceof VirtualVideoAction) {
// Let's take the VVA real early
sb.setLength(0);
HashMap<String, String> item = new HashMap<>();
sb.append("<a href=\"#\" onclick=\"umsAjax('/play/").append(idForWeb).append("', true);return false;\" title=\"").append(name).append("\">").append("<img class=\"thumb\" src=\"").append(thumb).append("\" alt=\"").append(name).append("\">").append("</a>");
item.put("thumb", sb.toString());
sb.setLength(0);
sb.append("<a href=\"#\" onclick=\"umsAjax('/play/").append(idForWeb).append("', true);return false;\" title=\"").append(name).append("\">").append("<span class=\"caption\">").append(name).append("</span>").append("</a>");
item.put("caption", sb.toString());
item.put("bump", "<span class=\"floatRight\"></span>");
media.add(item);
hasFile = true;
continue;
}
if (resource.isFolder()) {
sb.setLength(0);
// The resource is a folder
String p = "/browse/" + idForWeb;
boolean code = (resource instanceof CodeEnter);
String txt = RemoteUtil.getMsgString("Web.8", t);
if (code) {
txt = RemoteUtil.getMsgString("Web.9", t);
}
if (resource.getClass().getName().contains("SearchFolder") || code) {
// search folder add a prompt
// NOTE!!!
// Yes doing getClass.getname is REALLY BAD, but this
// is to make legacy plugins utilize this function as well
sb.append("<a href=\"javascript:void(0);\" onclick=\"searchFun('").append(p).append("','").append(txt).append("');\" title=\"").append(name).append("\">");
} else {
sb.append("<a href=\"").append(p).append("\" oncontextmenu=\"searchFun('").append(p).append("','").append(txt).append("');\" title=\"").append(name).append("\">");
}
sb.append("<span>").append(name).append("</span>");
sb.append("</a>");
folders.add(sb.toString());
} else {
// The resource is a media file
sb.setLength(0);
HashMap<String, String> item = new HashMap<>();
if (upnpAllowed) {
if (upnpControl) {
sb.append("<a class=\"bumpIcon\" href=\"javascript:bump.start('//").append(parent.getAddress()).append("','/play/").append(idForWeb).append("','").append(name.replace("'", "\\'")).append("')\" title=\"").append(RemoteUtil.getMsgString("Web.1", t)).append("\"></a>");
} else {
sb.append("<a class=\"bumpIcon icondisabled\" href=\"javascript:notify('warn','").append(RemoteUtil.getMsgString("Web.2", t)).append("')\" title=\"").append(RemoteUtil.getMsgString("Web.3", t)).append("\"></a>");
}
if (resource.getParent() instanceof Playlist) {
sb.append("\n<a class=\"playlist_del\" href=\"#\" onclick=\"umsAjax('/playlist/del/").append(idForWeb).append("', true);return false;\" title=\"").append(RemoteUtil.getMsgString("Web.4", t)).append("\"></a>");
} else {
sb.append("\n<a class=\"playlist_add\" href=\"#\" onclick=\"umsAjax('/playlist/add/").append(idForWeb).append("', false);return false;\" title=\"").append(RemoteUtil.getMsgString("Web.5", t)).append("\"></a>");
}
} else {
// ensure that we got a string
sb.append("");
}
item.put("bump", sb.toString());
sb.setLength(0);
if (WebRender.supports(resource) || resource.isResume() || resource.getType() == Format.IMAGE) {
sb.append("<a href=\"/play/").append(idForWeb).append("\" title=\"").append(name).append("\">").append("<img class=\"thumb\" src=\"").append(thumb).append("\" alt=\"").append(name).append("\">").append("</a>");
item.put("thumb", sb.toString());
sb.setLength(0);
sb.append("<a href=\"/play/").append(idForWeb).append("\" title=\"").append(name).append("\">").append("<span class=\"caption\">").append(name).append("</span>").append("</a>");
item.put("caption", sb.toString());
} else if (upnpControl && upnpAllowed) {
// Include it as a web-disabled item so it can be thrown via upnp
sb.append("<a class=\"webdisabled\" href=\"javascript:notify('warn','").append(RemoteUtil.getMsgString("Web.6", t)).append("')\"").append(" title=\"").append(name).append(' ').append(RemoteUtil.getMsgString("Web.7", t)).append("\">").append("<img class=\"thumb\" src=\"").append(thumb).append("\" alt=\"").append(name).append("\">").append("</a>");
item.put("thumb", sb.toString());
sb.setLength(0);
sb.append("<span class=\"webdisabled caption\">").append(name).append("</span>");
item.put("caption", sb.toString());
}
media.add(item);
hasFile = true;
}
}
HashMap<String, Object> vars = new HashMap<>();
vars.put("name", id.equals("0") ? configuration.getServerDisplayName() : StringEscapeUtils.escapeHtml(root.getDLNAResource(id, null).getDisplayName()));
vars.put("hasFile", hasFile);
vars.put("folders", folders);
vars.put("media", media);
if (configuration.useWebControl()) {
vars.put("push", true);
}
return parent.getResources().getTemplate("browse.html").execute(vars);
}
use of net.pms.dlna.RootFolder in project UniversalMediaServer by UniversalMediaServer.
the class RemotePlayHandler method handle.
@Override
public void handle(HttpExchange t) throws IOException {
if (RemoteUtil.deny(t)) {
throw new IOException("Access denied");
}
String p = t.getRequestURI().getPath();
if (p.contains("/play/")) {
LOGGER.debug("got a play request " + t.getRequestURI());
String id = RemoteUtil.getId("play/", t);
String response = mkPage(id, t);
// LOGGER.trace("play page " + response);
RemoteUtil.respond(t, response, 200, "text/html");
} else if (p.contains("/playerstatus/")) {
String json = IOUtils.toString(t.getRequestBody(), "UTF-8");
LOGGER.trace("got player status: " + json);
RemoteUtil.respond(t, "", 200, "text/html");
RootFolder root = parent.getRoot(RemoteUtil.userName(t), t);
if (root == null) {
LOGGER.debug("root not found");
throw new IOException("Unknown root");
}
WebRender renderer = (WebRender) root.getDefaultRenderer();
((WebRender.WebPlayer) renderer.getPlayer()).setData(json);
} else if (p.contains("/playlist/")) {
String[] tmp = p.split("/");
// sanity
if (tmp.length < 3) {
throw new IOException("Bad request");
}
String op = tmp[tmp.length - 2];
String id = tmp[tmp.length - 1];
DLNAResource r = PMS.getGlobalRepo().get(id);
if (r != null) {
RootFolder root = parent.getRoot(RemoteUtil.userName(t), t);
if (root == null) {
LOGGER.debug("root not found");
throw new IOException("Unknown root");
}
WebRender renderer = (WebRender) root.getDefaultRenderer();
if (op.equals("add")) {
PMS.get().getDynamicPls().add(r);
renderer.notify(renderer.OK, "Added '" + r.getDisplayName() + "' to dynamic playlist");
} else if (op.equals("del") && (r.getParent() instanceof Playlist)) {
((Playlist) r.getParent()).remove(r);
renderer.notify(renderer.INFO, "Removed '" + r.getDisplayName() + "' from playlist");
}
}
RemoteUtil.respond(t, returnPage(), 200, "text/html");
}
}
use of net.pms.dlna.RootFolder in project UniversalMediaServer by UniversalMediaServer.
the class RemoteRawHandler method handle.
@Override
public void handle(HttpExchange t) throws IOException {
LOGGER.debug("got a raw request " + t.getRequestURI());
if (RemoteUtil.deny(t)) {
throw new IOException("Access denied");
}
RootFolder root = parent.getRoot(RemoteUtil.userName(t), t);
if (root == null) {
throw new IOException("Unknown root");
}
String id;
id = RemoteUtil.strip(RemoteUtil.getId("raw/", t));
LOGGER.debug("raw id " + id);
List<DLNAResource> res = root.getDLNAResources(id, false, 0, 0, root.getDefaultRenderer());
if (res.size() != 1) {
// another error
LOGGER.debug("media unkonwn");
throw new IOException("Bad id");
}
DLNAResource dlna = res.get(0);
long len;
String mime = null;
InputStream in;
Range.Byte range;
if (dlna.getMedia() != null && dlna.getMedia().isImage() && dlna.getMedia().getImageInfo() != null) {
boolean supported = false;
ImageInfo imageInfo = dlna.getMedia().getImageInfo();
if (root.getDefaultRenderer() instanceof WebRender) {
WebRender renderer = (WebRender) root.getDefaultRenderer();
supported = renderer.isImageFormatSupported(imageInfo.getFormat());
}
mime = dlna.getFormat() != null ? dlna.getFormat().mimeType() : root.getDefaultRenderer().getMimeType(dlna.mimeType(), dlna.getMedia());
len = supported && imageInfo.getSize() != ImageInfo.SIZE_UNKNOWN ? imageInfo.getSize() : dlna.length();
range = new Range.Byte(0l, len);
if (supported) {
in = dlna.getInputStream();
} else {
InputStream imageInputStream;
if (dlna.getPlayer() instanceof ImagePlayer) {
ProcessWrapper transcodeProcess = dlna.getPlayer().launchTranscode(dlna, dlna.getMedia(), new OutputParams(PMS.getConfiguration()));
imageInputStream = transcodeProcess != null ? transcodeProcess.getInputStream(0) : null;
} else {
imageInputStream = dlna.getInputStream();
}
Image image = Image.toImage(imageInputStream, 3840, 2400, ScaleType.MAX, ImageFormat.JPEG, false);
len = image.getBytes(false).length;
in = image == null ? null : new ByteArrayInputStream(image.getBytes(false));
}
} else {
len = dlna.length();
dlna.setPlayer(null);
range = RemoteUtil.parseRange(t.getRequestHeaders(), len);
in = dlna.getInputStream(range, root.getDefaultRenderer());
if (len == 0) {
// For web resources actual length may be unknown until we open the stream
len = dlna.length();
}
mime = root.getDefaultRenderer().getMimeType(dlna.mimeType(), dlna.getMedia());
}
Headers hdr = t.getResponseHeaders();
LOGGER.debug("Sending media \"{}\" with mime type \"{}\"", dlna, mime);
hdr.add("Content-Type", mime);
hdr.add("Accept-Ranges", "bytes");
hdr.add("Server", PMS.get().getServerName());
hdr.add("Connection", "keep-alive");
hdr.add("Transfer-Encoding", "chunked");
if (in.available() != len) {
hdr.add("Content-Range", "bytes " + range.getStart() + "-" + in.available() + "/" + len);
t.sendResponseHeaders(206, in.available());
} else {
t.sendResponseHeaders(200, 0);
}
OutputStream os = new BufferedOutputStream(t.getResponseBody(), 512 * 1024);
LOGGER.debug("start raw dump");
RemoteUtil.dump(in, os);
}
Aggregations