Back ported last.fm coverart service from Subsonic 6.0_beta1
None of this code is mine, I just integrated it.
This commit is contained in:
@@ -123,14 +123,8 @@
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava-base</artifactId>
|
||||
<version>r03</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava-collections</artifactId>
|
||||
<version>r03</version>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>18.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
||||
@@ -23,6 +23,7 @@ import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
@@ -32,7 +33,9 @@ import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
|
||||
import org.libresonic.player.Logger;
|
||||
import org.libresonic.player.domain.LastFmCoverArt;
|
||||
import org.libresonic.player.domain.MediaFile;
|
||||
import org.libresonic.player.service.LastFmService;
|
||||
import org.libresonic.player.service.MediaFileService;
|
||||
import org.libresonic.player.service.SecurityService;
|
||||
import org.libresonic.player.util.StringUtil;
|
||||
@@ -50,6 +53,11 @@ public class CoverArtService {
|
||||
|
||||
private SecurityService securityService;
|
||||
private MediaFileService mediaFileService;
|
||||
private LastFmService lastFmService;
|
||||
|
||||
public List<LastFmCoverArt> searchCoverArt(String artist, String album) {
|
||||
return lastFmService.searchCoverArt(artist, album);
|
||||
}
|
||||
|
||||
/**
|
||||
* Downloads and saves the cover art at the given URL.
|
||||
@@ -162,4 +170,8 @@ public class CoverArtService {
|
||||
public void setMediaFileService(MediaFileService mediaFileService) {
|
||||
this.mediaFileService = mediaFileService;
|
||||
}
|
||||
|
||||
public void setLastFmService(LastFmService lastFmService) {
|
||||
this.lastFmService = lastFmService;
|
||||
}
|
||||
}
|
||||
+3
-2
@@ -25,6 +25,7 @@ import java.util.Map;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.web.bind.ServletRequestUtils;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.mvc.ParameterizableViewController;
|
||||
@@ -49,10 +50,10 @@ public class ChangeCoverArtController extends ParameterizableViewController {
|
||||
String album = request.getParameter("album");
|
||||
MediaFile dir = mediaFileService.getMediaFile(id);
|
||||
|
||||
if (artist == null) {
|
||||
if (StringUtils.isBlank(artist)) {
|
||||
artist = dir.getArtist();
|
||||
}
|
||||
if (album == null) {
|
||||
if (StringUtils.isBlank(album)) {
|
||||
album = dir.getAlbumName();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* This file is part of Libresonic.
|
||||
*
|
||||
* Libresonic 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.
|
||||
*
|
||||
* Libresonic 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 Libresonic. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Copyright 2016 (C) Libresonic Authors
|
||||
* Based upon Subsonic, Copyright 2009 (C) Sindre Mehus
|
||||
*/
|
||||
|
||||
package org.libresonic.player.domain;
|
||||
|
||||
/**
|
||||
* @author Sindre Mehus
|
||||
* @version $Id$
|
||||
*/
|
||||
public class AlbumNotes {
|
||||
|
||||
private final String notes;
|
||||
private final String musicBrainzId;
|
||||
private final String lastFmUrl;
|
||||
private final String smallImageUrl;
|
||||
private final String mediumImageUrl;
|
||||
private final String largeImageUrl;
|
||||
|
||||
public AlbumNotes(String notes, String musicBrainzId, String lastFmUrl, String smallImageUrl,
|
||||
String mediumImageUrl, String largeImageUrl) {
|
||||
this.notes = notes;
|
||||
this.musicBrainzId = musicBrainzId;
|
||||
this.lastFmUrl = lastFmUrl;
|
||||
this.smallImageUrl = smallImageUrl;
|
||||
this.mediumImageUrl = mediumImageUrl;
|
||||
this.largeImageUrl = largeImageUrl;
|
||||
}
|
||||
|
||||
public String getNotes() {
|
||||
return notes;
|
||||
}
|
||||
|
||||
public String getMusicBrainzId() {
|
||||
return musicBrainzId;
|
||||
}
|
||||
|
||||
public String getLastFmUrl() {
|
||||
return lastFmUrl;
|
||||
}
|
||||
|
||||
public String getSmallImageUrl() {
|
||||
return smallImageUrl;
|
||||
}
|
||||
|
||||
public String getMediumImageUrl() {
|
||||
return mediumImageUrl;
|
||||
}
|
||||
|
||||
public String getLargeImageUrl() {
|
||||
return largeImageUrl;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* This file is part of Libresonic.
|
||||
*
|
||||
* Libresonic 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.
|
||||
*
|
||||
* Libresonic 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 Libresonic. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Copyright 2014 (C) Sindre Mehus
|
||||
*/
|
||||
|
||||
package org.libresonic.player.domain;
|
||||
|
||||
/**
|
||||
* @author Sindre Mehus
|
||||
* @version $Id$
|
||||
*/
|
||||
public class LastFmCoverArt {
|
||||
|
||||
private final String imageUrl;
|
||||
private final String artist;
|
||||
private final String album;
|
||||
|
||||
public LastFmCoverArt(String imageUrl, String artist, String album) {
|
||||
this.imageUrl = imageUrl;
|
||||
this.artist = artist;
|
||||
this.album = album;
|
||||
}
|
||||
|
||||
public String getImageUrl() {
|
||||
return imageUrl;
|
||||
}
|
||||
|
||||
public String getArtist() {
|
||||
return artist;
|
||||
}
|
||||
|
||||
public String getAlbum() {
|
||||
return album;
|
||||
}
|
||||
}
|
||||
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* This file is part of Libresonic.
|
||||
*
|
||||
* Libresonic 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.
|
||||
*
|
||||
* Libresonic 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 Libresonic. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Copyright 2014 (C) Sindre Mehus
|
||||
*/
|
||||
|
||||
package org.libresonic.player.service;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import de.umass.lastfm.cache.ExpirationPolicy;
|
||||
|
||||
/**
|
||||
* Artist and album info is cached permanently. Everything else is cached one year.
|
||||
*
|
||||
* @author Sindre Mehus
|
||||
* @version $Id$
|
||||
*/
|
||||
public class LastFmExpirationPolicy implements ExpirationPolicy {
|
||||
|
||||
private final static long ONE_YEAR = 12 * 30 * 24 * 3600 * 1000L;
|
||||
|
||||
private final Map<String, Long> methodToExpirationTime = new LinkedHashMap<String, Long>() {{
|
||||
put("artist.getInfo", Long.MAX_VALUE); // Cache forever
|
||||
put("album.getInfo", Long.MAX_VALUE); // Cache forever
|
||||
put("album.search", -1L); // Don't cache
|
||||
}};
|
||||
|
||||
@Override
|
||||
public long getExpirationTime(String method, Map<String, String> params) {
|
||||
Long expirationTime = methodToExpirationTime.get(method);
|
||||
return expirationTime == null ? ONE_YEAR : expirationTime;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ package org.libresonic.player.service;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -30,13 +31,23 @@ import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.FluentIterable;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import de.umass.lastfm.Album;
|
||||
import de.umass.lastfm.Artist;
|
||||
import de.umass.lastfm.Caller;
|
||||
import de.umass.lastfm.ImageSize;
|
||||
import de.umass.lastfm.Track;
|
||||
import de.umass.lastfm.cache.Cache;
|
||||
|
||||
import org.libresonic.player.Logger;
|
||||
import org.libresonic.player.dao.ArtistDao;
|
||||
import org.libresonic.player.dao.MediaFileDao;
|
||||
import org.libresonic.player.domain.LastFmCoverArt;
|
||||
import org.libresonic.player.domain.AlbumNotes;
|
||||
import org.libresonic.player.domain.ArtistBio;
|
||||
import org.libresonic.player.domain.MediaFile;
|
||||
import org.libresonic.player.domain.MusicFolder;
|
||||
@@ -273,6 +284,96 @@ public class LastFmService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns album notes and images.
|
||||
*
|
||||
* @param mediaFile The media file (song or album).
|
||||
* @return Album notes.
|
||||
*/
|
||||
public AlbumNotes getAlbumNotes(MediaFile mediaFile) {
|
||||
return getAlbumNotes(getCanonicalArtistName(getArtistName(mediaFile)), mediaFile.getAlbumName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns album notes and images.
|
||||
*
|
||||
* @param album The album.
|
||||
* @return Album notes.
|
||||
*/
|
||||
public AlbumNotes getAlbumNotes(org.libresonic.player.domain.Album album) {
|
||||
return getAlbumNotes(getCanonicalArtistName(album.getArtist()), album.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns album notes and images.
|
||||
*
|
||||
* @param artist The artist name.
|
||||
* @param album The album name.
|
||||
* @return Album notes.
|
||||
*/
|
||||
private AlbumNotes getAlbumNotes(String artist, String album) {
|
||||
if (artist == null || album == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
Album info = Album.getInfo(artist, album, LAST_FM_KEY);
|
||||
if (info == null) {
|
||||
return null;
|
||||
}
|
||||
return new AlbumNotes(processWikiText(info.getWikiSummary()),
|
||||
info.getMbid(),
|
||||
info.getUrl(),
|
||||
info.getImageURL(ImageSize.MEDIUM),
|
||||
info.getImageURL(ImageSize.LARGE),
|
||||
info.getImageURL(ImageSize.MEGA));
|
||||
} catch (Throwable x) {
|
||||
LOG.warn("Failed to find album notes for " + artist + " - " + album, x);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public List<LastFmCoverArt> searchCoverArt(String artist, String album) {
|
||||
if (artist == null && album == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
try {
|
||||
StringBuilder query = new StringBuilder();
|
||||
if (artist != null) {
|
||||
query.append(artist).append(" ");
|
||||
}
|
||||
if (album != null) {
|
||||
query.append(album);
|
||||
}
|
||||
|
||||
Collection<Album> matches = Album.search(query.toString(), LAST_FM_KEY);
|
||||
return FluentIterable.from(matches)
|
||||
.transform(new Function<Album, LastFmCoverArt>() {
|
||||
@Override
|
||||
public LastFmCoverArt apply(Album album) {
|
||||
return convert(album);
|
||||
}
|
||||
})
|
||||
.filter(Predicates.notNull())
|
||||
.toList();
|
||||
} catch (Throwable x) {
|
||||
LOG.warn("Failed to search for cover art for " + artist + " - " + album, x);
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
private LastFmCoverArt convert(Album album) {
|
||||
String imageUrl = null;
|
||||
for (ImageSize imageSize : Lists.reverse(Arrays.asList(ImageSize.values()))) {
|
||||
imageUrl = StringUtils.trimToNull(album.getImageURL(imageSize));
|
||||
if (imageUrl != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return imageUrl == null ? null : new LastFmCoverArt(imageUrl, album.getArtist(), album.getName());
|
||||
}
|
||||
|
||||
|
||||
private ArtistBio getArtistBio(String artistName) {
|
||||
try {
|
||||
if (artistName == null) {
|
||||
|
||||
+2
-1
@@ -666,11 +666,12 @@ changecoverart.title = Change cover art
|
||||
changecoverart.address = Or enter image address
|
||||
changecoverart.artist = Artist
|
||||
changecoverart.album = Album
|
||||
changecoverart.search = Google Image Search
|
||||
changecoverart.search = Search Last.fm
|
||||
changecoverart.wait = Please wait...
|
||||
changecoverart.success = Image was successfully downloaded.
|
||||
changecoverart.error = Failed to download image.
|
||||
changecoverart.noimagesfound = No images found.
|
||||
changecoverart.courtesy = Images courtesy of Last.fm
|
||||
|
||||
# changeCoverArtConfirm.jsp
|
||||
changeCoverArtConfirm.failed = Failed to change cover art:<br><b>"{0}"</b>
|
||||
|
||||
@@ -274,6 +274,7 @@
|
||||
<bean id="ajaxCoverArtService" class="org.libresonic.player.ajax.CoverArtService">
|
||||
<property name="securityService" ref="securityService"/>
|
||||
<property name="mediaFileService" ref="mediaFileService"/>
|
||||
<property name="lastFmService" ref="lastFmService"/>
|
||||
</bean>
|
||||
|
||||
<bean id="ajaxStarService" class="org.libresonic.player.ajax.StarService">
|
||||
|
||||
@@ -53,6 +53,8 @@
|
||||
<convert converter="bean" match="org.libresonic.player.ajax.PlaylistInfo$Entry"/>
|
||||
<convert converter="bean" match="org.libresonic.player.domain.Playlist"/>
|
||||
<convert converter="bean" match="org.libresonic.player.domain.ArtistBio"/>
|
||||
<convert converter="bean" match="org.libresonic.player.domain.LastFmCoverArt"/>
|
||||
|
||||
<convert converter="bean" match="org.libresonic.player.ajax.UploadInfo"/>
|
||||
<convert converter="bean" match="org.libresonic.player.ajax.LyricsInfo"/>
|
||||
<convert converter="bean" match="org.libresonic.player.ajax.CoverArtInfo"/>
|
||||
|
||||
@@ -6,13 +6,14 @@
|
||||
<script type="text/javascript" src="<c:url value="/dwr/engine.js"/>"></script>
|
||||
<script type="text/javascript" src="<c:url value="/dwr/util.js"/>"></script>
|
||||
<script type="text/javascript" src="<c:url value="/script/prototype.js"/>"></script>
|
||||
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
|
||||
|
||||
<script type="text/javascript" language="javascript">
|
||||
|
||||
dwr.engine.setErrorHandler(null);
|
||||
google.load('search', '1');
|
||||
var imageSearch;
|
||||
dwr.engine.setErrorHandler(function() {
|
||||
$("wait").hide();
|
||||
dwr.util.setValue("errorDetails", "Sorry, an error occurred while searching for cover art.");
|
||||
$("errorDetails").show();
|
||||
});
|
||||
|
||||
function setImage(imageUrl) {
|
||||
$("wait").show();
|
||||
@@ -21,14 +22,13 @@
|
||||
$("error").hide();
|
||||
$("errorDetails").hide();
|
||||
$("noImagesFound").hide();
|
||||
var id = dwr.util.getValue("id");
|
||||
coverArtService.setCoverArtImage(id, imageUrl, setImageComplete);
|
||||
coverArtService.setCoverArtImage(${model.id}, imageUrl, setImageComplete);
|
||||
}
|
||||
|
||||
function setImageComplete(errorDetails) {
|
||||
$("wait").hide();
|
||||
if (errorDetails != null) {
|
||||
dwr.util.setValue("errorDetails", "<br/>" + errorDetails, { escapeHtml:false });
|
||||
dwr.util.setValue("errorDetails", errorDetails, { escapeHtml:false });
|
||||
$("error").show();
|
||||
$("errorDetails").show();
|
||||
} else {
|
||||
@@ -36,37 +36,29 @@
|
||||
}
|
||||
}
|
||||
|
||||
function searchComplete() {
|
||||
|
||||
function searchComplete(searchResults) {
|
||||
$("wait").hide();
|
||||
|
||||
if (imageSearch.results && imageSearch.results.length > 0) {
|
||||
if (searchResults.length > 0) {
|
||||
|
||||
var images = $("images");
|
||||
images.innerHTML = "";
|
||||
|
||||
var results = imageSearch.results;
|
||||
for (var i = 0; i < results.length; i++) {
|
||||
var result = results[i];
|
||||
for (var i = 0; i < searchResults.length; i++) {
|
||||
var result = searchResults[i];
|
||||
var node = $("template").cloneNode(true);
|
||||
|
||||
// Rename results to https to avoid mixed contents.
|
||||
result.tbUrl = result.tbUrl.replace('http://', 'https://');
|
||||
|
||||
var link = node.getElementsByClassName("search-result-link")[0];
|
||||
link.href = "javascript:setImage('" + result.url + "');";
|
||||
link.href = "javascript:setImage('" + result.imageUrl + "');";
|
||||
|
||||
var thumbnail = node.getElementsByClassName("search-result-thumbnail")[0];
|
||||
thumbnail.src = result.tbUrl;
|
||||
var thumbnail = node.getElementsByClassName("search-result-image")[0];
|
||||
thumbnail.src = result.imageUrl;
|
||||
|
||||
var title = node.getElementsByClassName("search-result-title")[0];
|
||||
title.innerHTML = result.contentNoFormatting.truncate(30);
|
||||
var title = node.getElementsByClassName("search-result-artist")[0];
|
||||
title.innerHTML = result.artist;
|
||||
|
||||
var dimension = node.getElementsByClassName("search-result-dimension")[0];
|
||||
dimension.innerHTML = result.width + " × " + result.height;
|
||||
|
||||
var url = node.getElementsByClassName("search-result-url")[0];
|
||||
url.innerHTML = result.visibleUrl;
|
||||
var dimension = node.getElementsByClassName("search-result-album")[0];
|
||||
dimension.innerHTML = result.album;
|
||||
|
||||
node.show();
|
||||
images.appendChild(node);
|
||||
@@ -74,50 +66,12 @@
|
||||
|
||||
$("result").show();
|
||||
|
||||
addPaginationLinks(imageSearch);
|
||||
|
||||
} else {
|
||||
$("noImagesFound").show();
|
||||
}
|
||||
}
|
||||
|
||||
function addPaginationLinks() {
|
||||
|
||||
// To paginate search results, use the cursor function.
|
||||
var cursor = imageSearch.cursor;
|
||||
var curPage = cursor.currentPageIndex; // check what page the app is on
|
||||
var pagesDiv = document.createElement("div");
|
||||
for (var i = 0; i < cursor.pages.length; i++) {
|
||||
var page = cursor.pages[i];
|
||||
var label;
|
||||
if (curPage == i) {
|
||||
// If we are on the current page, then don"t make a link.
|
||||
label = document.createElement("b");
|
||||
} else {
|
||||
|
||||
// Create links to other pages using gotoPage() on the searcher.
|
||||
label = document.createElement("a");
|
||||
label.href = "javascript:imageSearch.gotoPage(" + i + ");";
|
||||
}
|
||||
label.innerHTML = page.label;
|
||||
label.style.marginRight = "1em";
|
||||
pagesDiv.appendChild(label);
|
||||
}
|
||||
|
||||
// Create link to next page.
|
||||
if (curPage < cursor.pages.length - 1) {
|
||||
var next = document.createElement("a");
|
||||
next.href = "javascript:imageSearch.gotoPage(" + (curPage + 1) + ");";
|
||||
next.innerHTML = "<fmt:message key="common.next"/>";
|
||||
next.style.marginLeft = "1em";
|
||||
pagesDiv.appendChild(next);
|
||||
}
|
||||
|
||||
var pages = $("pages");
|
||||
pages.innerHTML = "";
|
||||
pages.appendChild(pagesDiv);
|
||||
}
|
||||
|
||||
function search() {
|
||||
|
||||
$("wait").show();
|
||||
@@ -127,40 +81,25 @@
|
||||
$("errorDetails").hide();
|
||||
$("noImagesFound").hide();
|
||||
|
||||
var query = dwr.util.getValue("query");
|
||||
imageSearch.execute(query);
|
||||
var artist = dwr.util.getValue("artist");
|
||||
var album = dwr.util.getValue("album");
|
||||
coverArtService.searchCoverArt(artist, album, searchComplete);
|
||||
}
|
||||
|
||||
function onLoad() {
|
||||
|
||||
imageSearch = new google.search.ImageSearch();
|
||||
imageSearch.setSearchCompleteCallback(this, searchComplete, null);
|
||||
imageSearch.setNoHtmlGeneration();
|
||||
imageSearch.setResultSetSize(8);
|
||||
|
||||
google.search.Search.getBranding("branding");
|
||||
|
||||
$("template").hide();
|
||||
|
||||
search();
|
||||
}
|
||||
google.setOnLoadCallback(onLoad);
|
||||
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body class="mainframe bgcolor1">
|
||||
<body class="mainframe bgcolor1" onload="search()">
|
||||
<h1><fmt:message key="changecoverart.title"/></h1>
|
||||
<form action="javascript:search()">
|
||||
<table class="indent"><tr>
|
||||
<td><input id="query" name="query" size="70" type="text" value="${model.artist} ${model.album}" onclick="select()"/></td>
|
||||
<td><input id="artist" name="artist" placeholder="<fmt:message key="changecoverart.artist"/>" size="35" type="text" value="${model.artist}" onclick="select()"/></td>
|
||||
<td><input id="album" name="album" placeholder="<fmt:message key="changecoverart.album"/>" size="35" type="text" value="${model.album}" onclick="select()"/></td>
|
||||
<td style="padding-left:0.5em"><input type="submit" value="<fmt:message key="changecoverart.search"/>"/></td>
|
||||
</tr></table>
|
||||
</form>
|
||||
|
||||
<form action="javascript:setImage(dwr.util.getValue('url'))">
|
||||
<table><tr>
|
||||
<input id="id" type="hidden" name="id" value="${model.id}"/>
|
||||
<td><label for="url"><fmt:message key="changecoverart.address"/></label></td>
|
||||
<td style="padding-left:0.5em"><input type="text" name="url" size="50" id="url" value="http://" onclick="select()"/></td>
|
||||
<td style="padding-left:0.5em"><input type="submit" value="<fmt:message key="common.ok"/>"></td>
|
||||
@@ -178,32 +117,21 @@
|
||||
<div id="errorDetails" class="warning" style="display:none">
|
||||
</div>
|
||||
|
||||
<div id="result">
|
||||
|
||||
<div id="pages" style="float:left;padding-left:0.5em;padding-top:0.5em">
|
||||
<div id="result" style="padding-top:2em">
|
||||
<div style="clear:both;"></div>
|
||||
<div id="images"></div>
|
||||
<div style="clear:both;"></div>
|
||||
<a href="http://last.fm/" target="_blank"><img src="<c:url value="/icons/lastfm.gif"/>"></a>
|
||||
<span class="detail" style="padding-left:1em"><fmt:message key="changecoverart.courtesy"/></span>
|
||||
</div>
|
||||
|
||||
<div id="branding" style="float:right;padding-right:1em;padding-top:0.5em">
|
||||
</div>
|
||||
|
||||
<div style="clear:both;">
|
||||
</div>
|
||||
|
||||
<div id="images" style="width:100%;padding-bottom:2em">
|
||||
</div>
|
||||
|
||||
<div style="clear:both;">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="template" style="float:left; height:190px; width:220px;padding:0.5em;position:relative">
|
||||
<div style="position:absolute;bottom:0">
|
||||
<a class="search-result-link"><img class="search-result-thumbnail" style="padding:1px; border:1px solid #021a40; background-color:white;"></a>
|
||||
<div class="search-result-title"></div>
|
||||
<div class="search-result-dimension detail"></div>
|
||||
<div class="search-result-url detail"></div>
|
||||
<div id="template" class="coverart dropshadow" style="float:left;margin-right:2.0em;margin-bottom:2.0em;width:250px;display:none">
|
||||
<div>
|
||||
<a class="search-result-link"><img class="search-result-image" style="width:250px;height:250px"></a>
|
||||
<div class="search-result-artist caption1"></div>
|
||||
<div class="search-result-album caption2"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body></html>
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@ PARAMETERS
|
||||
showZoom: Whether to display a link for zooming the cover art.
|
||||
showChange: Whether to display a link for changing the cover art.
|
||||
appearAfter: Fade in after this many milliseconds, or nil if no fading in should happen.
|
||||
hideOverflow: Hide cover art overflow when height is greater than width
|
||||
--%>
|
||||
<c:choose>
|
||||
<c:when test="${empty param.coverArtSize}">
|
||||
@@ -33,7 +32,7 @@ PARAMETERS
|
||||
<str:randomString count="5" type="alphabet" var="playId"/>
|
||||
|
||||
<div class="coverart dropshadow">
|
||||
<div style="width:${size};max-width:${size};height:${size};max-height:${size};cursor:pointer;<c:if test="${param.hideOverflow}">overflow:hidden</c:if>;" title="${param.caption1}" id="${divId}">
|
||||
<div style="width:${size};max-width:${size};height:${size};max-height:${size};cursor:pointer" title="${param.caption1}" id="${divId}">
|
||||
|
||||
<c:if test="${not empty param.albumId}">
|
||||
<c:url value="main.view" var="targetUrl">
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
Reference in New Issue
Block a user