/* This file is part of Airsonic. Airsonic 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. Airsonic 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 Airsonic. If not, see . Copyright 2016 (C) Airsonic Authors Based upon Subsonic, Copyright 2009 (C) Sindre Mehus */ package org.airsonic.player.service.upnp; import com.google.common.collect.Lists; import org.airsonic.player.domain.MediaFile; import org.airsonic.player.domain.Player; import org.airsonic.player.service.JWTSecurityService; import org.airsonic.player.service.PlayerService; import org.airsonic.player.service.SettingsService; import org.airsonic.player.service.TranscodingService; import org.airsonic.player.util.StringUtil; import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang3.StringUtils; import org.fourthline.cling.support.contentdirectory.AbstractContentDirectoryService; import org.fourthline.cling.support.contentdirectory.ContentDirectoryException; import org.fourthline.cling.support.contentdirectory.DIDLParser; import org.fourthline.cling.support.model.BrowseResult; import org.fourthline.cling.support.model.DIDLContent; import org.fourthline.cling.support.model.Res; import org.fourthline.cling.support.model.SortCriterion; import org.seamless.util.MimeType; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.util.UriComponentsBuilder; /** * @author Sindre Mehus * @version $Id: TagBasedContentDirectory.java 3739 2013-12-03 11:55:01Z sindre_mehus $ */ public abstract class CustomContentDirectory extends AbstractContentDirectoryService { protected static final String CONTAINER_ID_ROOT = "0"; @Autowired protected SettingsService settingsService; @Autowired private PlayerService playerService; @Autowired private TranscodingService transcodingService; @Autowired protected JWTSecurityService jwtSecurityService; public CustomContentDirectory() { super(Lists.newArrayList("*"), Lists.newArrayList()); } protected Res createResourceForSong(MediaFile song) { Player player = playerService.getGuestPlayer(null); UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(getBaseUrl() + "/ext/stream") .queryParam("id", song.getId()) .queryParam("player", player.getId()); if (song.isVideo()) { builder.queryParam("format", TranscodingService.FORMAT_RAW); } jwtSecurityService.addJWTToken(builder); String url = builder.toUriString(); String suffix = song.isVideo() ? FilenameUtils.getExtension(song.getPath()) : transcodingService.getSuffix(player, song, null); String mimeTypeString = StringUtil.getMimeType(suffix); MimeType mimeType = mimeTypeString == null ? null : MimeType.valueOf(mimeTypeString); Res res = new Res(mimeType, null, url); res.setDuration(formatDuration(song.getDurationSeconds())); return res; } private String formatDuration(Integer seconds) { if (seconds == null) { return null; } return StringUtil.formatDurationHMMSS((int)seconds) + ".0"; } protected String getBaseUrl() { String dlnaBaseLANURL = settingsService.getDlnaBaseLANURL(); if (StringUtils.isBlank(dlnaBaseLANURL)) { throw new RuntimeException("DLNA Base LAN URL is not set correctly"); } return dlnaBaseLANURL; } protected BrowseResult createBrowseResult(DIDLContent didl, int count, int totalMatches) throws Exception { return new BrowseResult(new DIDLParser().generate(didl), count, totalMatches); } @Override public BrowseResult search(String containerId, String searchCriteria, String filter, long firstResult, long maxResults, SortCriterion[] orderBy) throws ContentDirectoryException { // You can override this method to implement searching! return super.search(containerId, searchCriteria, filter, firstResult, maxResults, orderBy); } public void setPlayerService(PlayerService playerService) { this.playerService = playerService; } public void setTranscodingService(TranscodingService transcodingService) { this.transcodingService = transcodingService; } public void setSettingsService(SettingsService settingsService) { this.settingsService = settingsService; } public void setJwtSecurityService(JWTSecurityService jwtSecurityService) { this.jwtSecurityService = jwtSecurityService; } }